Skip to content

Commit

Permalink
feat(v2)/switch components (#707)
Browse files Browse the repository at this point in the history
* feat(v2): add switch component

* style(v2): update border style in switch component

* feat(v2): add storybook for switch component

* style(v2): update `aria-label` for accessibility of checkbox

* style(v2): update disable color and `aria-label` for accessibility in switch

* style(v2): rewrite args in switch storybook

---------

Co-authored-by: Nutthapat Pongtanyavichai <[email protected]>
  • Loading branch information
phongit-kha and leomotors authored Oct 27, 2024
1 parent e905a6d commit d5788d6
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 0 deletions.
7 changes: 7 additions & 0 deletions packages/ui/src/components/switch/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Root from './switch.svelte'

export {
Root,
//
Root as Switch,
}
92 changes: 92 additions & 0 deletions packages/ui/src/components/switch/switch.stories.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<script context="module" lang="ts">
import type { Meta } from '@storybook/svelte'
import { Switch } from './index.js'
export const meta = {
title: 'Atom/Switch',
component: Switch,
tags: ['autodocs'],
argTypes: {
'aria-label': {
control: 'text',
description: 'string value that labels an interactive element',
},
checked: {
control: 'boolean',
description: 'Whether the switch is checked or not.',
defaultValue: false,
},
label: {
control: 'text',
description: 'The label associated with the switch.',
defaultValue: 'Switch Label',
},
id: {
control: 'text',
description: 'ID for the switch element and its label.',
defaultValue: 'switch',
},
class: {
control: false,
},
'on:click': {
action: 'onClick',
},
'on:keydown': {
action: 'onKeyDown',
},
},
} satisfies Meta<Switch>
</script>

<script lang="ts">
import { Story, Template } from '@storybook/addon-svelte-csf'
</script>

<!-- Define the template for the switch component -->
<Template let:args>
<Switch {...args} />
</Template>

<!-- Define the stories with different states -->
<Story
name="Default"
args="{{
checked: false,
label: 'Switch Label',
id: 'switch',
'aria-label': 'for example of default switch',
}}"
/>

<Story
name="Checked"
args="{{
checked: true,
label: 'Checked Switch',
id: 'checked-switch',
'aria-label': 'for example of checked switch ',
}}"
/>

<Story
name="With Custom Label"
args="{{
checked: false,
label: 'Custom Label',
id: 'custom-switch',
'aria-label': 'for example of custom label switch ',
}}"
/>

<Story
name="Disabled"
args="{{
checked: false,
label: 'Disabled Switch',
id: 'disabled-switch',
disabled: true,
'aria-label': 'for example of disable switch ',
}}"
/>
44 changes: 44 additions & 0 deletions packages/ui/src/components/switch/switch.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<script lang="ts">
import { Label, Switch as SwitchPrimitive } from 'bits-ui'
import { cn } from '../../utils'
type $$Props = SwitchPrimitive.Props & {
label?: string | undefined | null
}
type $$Events = SwitchPrimitive.Events
let className: $$Props['class'] = undefined
export let checked: $$Props['checked'] = undefined
export let id: $$Props['id'] = null
export let label: $$Props['label'] = 'label'
export { className as class }
</script>

<div class="flex items-center space-x-2">
<SwitchPrimitive.Root
bind:checked
class="{cn(
'focus-visible:ring-ring focus-visible:ring-offset-background data-[state=checked]:border-primary data-[state=checked]:bg-primary-low data-[state=unchecked]:bg-surface-container-lowest peer inline-flex h-[18px] w-[32px] shrink-0 cursor-pointer items-center rounded-full border border-surface-container-high transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
className,
)}"
{...$$restProps}
on:click
on:keydown
{id}
>
<SwitchPrimitive.Thumb
class="{cn(
'p-1 bg-surface-container-high data-[state=checked]:bg-primary pointer-events-none block h-3.5 w-3.5 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-[14.5px] data-[state=unchecked]:translate-x-[1px]',
)}"
/>
</SwitchPrimitive.Root>
{#if label}
<Label.Root
for="{id}"
class="text-button2 font-normal leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
{label}
</Label.Root>
{/if}
</div>

0 comments on commit d5788d6

Please sign in to comment.