diff --git a/src/components/Switch/Switch.stories.mdx b/src/components/Switch/Switch.stories.mdx
new file mode 100644
index 0000000..b745aa2
--- /dev/null
+++ b/src/components/Switch/Switch.stories.mdx
@@ -0,0 +1,133 @@
+import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs';
+
+import Switch from './Switch.vue';
+
+
+
+export const Default = (args) => {
+ return {
+ components: { Switch },
+ setup() {
+ return {
+ args,
+ };
+ },
+ template: '',
+ };
+};
+
+# All the sizes
+
+
+
+
+
+# Reference
+
+
+
+
+
+# Notes
+
+
+
+ This component is a wrapper around the input
element.
+
+
+ The value
prop is passed to the input
element.
+
+
+ The disabled
prop is passed to the input
element.
+
+
+ The size
prop is passed to the input
element.
+
+
+# Installation
+
+
+
+Install the component with:
+
+```js
+import { Switch } from '@/components/Switch';
+```
+
+# Examples
+
+
+
+Basic using
+
+```html
+
+```
+
+Advance using
+
+```html
+
+```
diff --git a/src/components/Switch/Switch.vue b/src/components/Switch/Switch.vue
new file mode 100644
index 0000000..890ecf3
--- /dev/null
+++ b/src/components/Switch/Switch.vue
@@ -0,0 +1,39 @@
+
+
+
+
diff --git a/src/components/Switch/switch.css b/src/components/Switch/switch.css
new file mode 100644
index 0000000..cb3be02
--- /dev/null
+++ b/src/components/Switch/switch.css
@@ -0,0 +1,56 @@
+@tailwind components;
+
+fieldset {
+ @apply font-sans border-none m-0 p-0;
+}
+.switch {
+ @apply relative inline-block w-16 h-9;
+}
+.switch--small {
+ @apply w-12 h-6;
+}
+.switch--large {
+ @apply w-20 h-11;
+}
+.switch input {
+ @apply opacity-0 w-0 h-0 -z-10;
+}
+.slider {
+ @apply absolute top-0 left-0 right-0 bottom-0 bg-gray-300 transition duration-200 ease-in-out;
+}
+.switch--small > .slider::before {
+ @apply w-4 h-4;
+}
+.switch--large > .slider::before {
+ @apply w-9 h-9;
+}
+.slider:before {
+ content: '';
+ @apply absolute h-7 w-7 left-1 bottom-1 bg-white transition duration-200 ease-in-out;
+}
+input:checked + .slider {
+ @apply bg-teal-400;
+}
+input:focus + .slider {
+ box-shadow: 0 0 1px;
+ @apply shadow-teal-400;
+}
+input:checked + .slider:before {
+ -webkit-transform: translateX(26px);
+ -ms-transform: translateX(26px);
+ transform: translateX(26px);
+}
+.switch--large > input:checked + .slider:before {
+ -webkit-transform: translateX(34px);
+ -ms-transform: translateX(34px);
+ transform: translateX(34px);
+}
+.slider.round {
+ @apply rounded-full;
+}
+.slider.round:before {
+ @apply rounded-full;
+}
+.switch--disabled {
+ @apply opacity-50 cursor-not-allowed;
+}
diff --git a/src/components/Switch/switch.spec.ts b/src/components/Switch/switch.spec.ts
new file mode 100644
index 0000000..fb409f1
--- /dev/null
+++ b/src/components/Switch/switch.spec.ts
@@ -0,0 +1,23 @@
+import { describe, it, expect } from 'vitest';
+
+import { mount } from '@vue/test-utils';
+import Switch from './Switch.vue';
+
+describe('Switch', () => {
+ it('renders properly', () => {
+ const wrapper = mount(Switch, {
+ props: {
+ id: 'switch-id',
+ disabled: false,
+ size: 'small',
+ },
+ });
+ expect(wrapper.exists()).toBe(true);
+ expect(wrapper.find('label').exists()).toBe(true);
+ expect(wrapper.find('label').element.getAttribute('for')).toBe('switch-id');
+ expect(wrapper.find('input').exists()).toBe(true);
+ expect(wrapper.find('input').element.getAttribute('id')).toBe('switch-id');
+ expect(wrapper.find('input').element.getAttribute('type')).toBe('checkbox');
+ expect(wrapper.find('input').element.getAttribute('disabled')).toBe(null);
+ });
+});