Skip to content

Commit

Permalink
Add switch component
Browse files Browse the repository at this point in the history
  • Loading branch information
jeannemas committed Apr 17, 2024
1 parent 82d925f commit 7d90579
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 25 deletions.
5 changes: 5 additions & 0 deletions .changeset/early-clocks-talk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@jeanne-mas/svelte-ui': minor
---

Added switch component
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@
"types": "./dist/components/select/index.d.ts",
"svelte": "./dist/components/select/index.js"
},
"./components/switch": {
"types": "./dist/components/switch/index.d.ts",
"svelte": "./dist/components/switch/index.js"
},
"./package.json": "./package.json",
"./transition/flyAndScale": {
"types": "./dist/transition/flyAndScale.d.ts",
Expand Down
69 changes: 69 additions & 0 deletions src/lib/components/switch/Switch.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<script context="module" lang="ts">
import { Switch as SwitchPrimitive } from 'bits-ui';
import type { SvelteHTMLElements } from 'svelte/elements';
import { cn } from '$lib/utils/cn.js';
import type { ComponentSlots } from '$lib/utils/types.js';
export type Attributes = Omit<SvelteHTMLElements['button'], 'disabled' | 'name' | 'value'>;
export type Events = Pick<SwitchPrimitive.Props, 'onCheckedChange'>;
export type Props = Omit<SwitchPrimitive.Props, keyof Attributes | keyof Events>;
export type Slots = ComponentSlots<SwitchPrimitive.Root>;
</script>

<script lang="ts">
type $$Events = SwitchPrimitive.Events;
type $$Props = Attributes & Events & Props;
type $$Slots = Slots;
export let asChild: Props['asChild'] = undefined;
export let checked: Props['checked'] = undefined;
export let disabled: Props['disabled'] = undefined;
export let el: Props['el'] = undefined;
export let includeInput: Props['includeInput'] = undefined;
export let inputAttrs: Props['inputAttrs'] = undefined;
export let name: Props['name'] = undefined;
export let onCheckedChange: Events['onCheckedChange'] = undefined;
export let required: Props['required'] = undefined;
export let value: Props['value'] = undefined;
$: attributes = $$restProps as Attributes;
</script>

<!-- <style lang="postcss">
</style> -->

<SwitchPrimitive.Root
{...attributes}
asChild="{asChild}"
class="{cn(
'peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background',
'disabled:cursor-not-allowed disabled:opacity-50',
'data-[state=checked]:bg-primary',
'data-[state=unchecked]:bg-input',
attributes.class,
)}"
disabled="{disabled}"
el="{el}"
includeInput="{includeInput}"
inputAttrs="{inputAttrs}"
name="{name}"
onCheckedChange="{onCheckedChange}"
required="{required}"
value="{value}"
bind:checked="{checked}"
let:builder
on:click
on:keydown
>
<slot builder="{builder}">
<SwitchPrimitive.Thumb
class="{cn(
'pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform',
'data-[state=checked]:translate-x-5',
'data-[state=unchecked]:translate-x-0',
)}"
/>
</slot>
</SwitchPrimitive.Root>
1 change: 1 addition & 0 deletions src/lib/components/switch/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default, type Attributes, type Events, type Props, type Slots } from './Switch.svelte';
9 changes: 4 additions & 5 deletions src/routes/button/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import Button, { variants, type Size, type Variant } from '$lib/components/button/index.js';
import Label from '$lib/components/label/index.js';
import * as Select from '$lib/components/select/index.js';
import Switch from '$lib/components/switch/index.js';
const disabledKey = 'disabled';
const sizeKey = 'size';
Expand Down Expand Up @@ -36,16 +37,14 @@
<div data-form>
<Label for="{disabledKey}">Disabled</Label>

<input
<Switch
checked="{$disabled}"
id="{disabledKey}"
name="{disabledKey}"
type="checkbox"
data-control
on:change="{({ currentTarget }) => {
onCheckedChange="{(checked) => {
const url = new URL($page.url);

if (currentTarget.checked) {
if (checked) {
url.searchParams.set(disabledKey, '');
} else {
url.searchParams.delete(disabledKey);
Expand Down
9 changes: 4 additions & 5 deletions src/routes/calendar/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import * as Calendar from '$lib/components/calendar/index.js';
import Label from '$lib/components/label/index.js';
import * as Select from '$lib/components/select/index.js';
import Switch from '$lib/components/switch/index.js';
const calendarLabelKey = 'calendarLabel';
const disabledKey = 'disabled';
Expand Down Expand Up @@ -58,16 +59,14 @@
<div data-form>
<Label for="{disabledKey}">Disabled</Label>

<input
<Switch
checked="{$disabled}"
id="{disabledKey}"
name="{disabledKey}"
type="checkbox"
data-control
on:change="{({ currentTarget }) => {
onCheckedChange="{(checked) => {
const url = new URL($page.url);

if (currentTarget.checked) {
if (checked) {
url.searchParams.set(disabledKey, '');
} else {
url.searchParams.delete(disabledKey);
Expand Down
17 changes: 7 additions & 10 deletions src/routes/container/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import { page } from '$app/stores';
import Container from '$lib/components/container/index.js';
import Label from '$lib/components/label/index.js';
import Switch from '$lib/components/switch/index.js';
const xAxisKey = 'xAxis';
const yAxisKey = 'yAxis';
Expand All @@ -21,16 +22,14 @@
<div data-form>
<Label for="{xAxisKey}">X axis</Label>

<input
<Switch
checked="{$xAxis}"
id="{xAxisKey}"
name="{xAxisKey}"
type="checkbox"
data-control
on:change="{({ currentTarget }) => {
onCheckedChange="{(checked) => {
const url = new URL($page.url);

if (currentTarget.checked) {
if (checked) {
url.searchParams.set(xAxisKey, '');
} else {
url.searchParams.delete(xAxisKey);
Expand All @@ -42,16 +41,14 @@

<Label for="{yAxisKey}">Y axis</Label>

<input
<Switch
checked="{$yAxis}"
id="{yAxisKey}"
name="{yAxisKey}"
type="checkbox"
data-control
on:change="{({ currentTarget }) => {
onCheckedChange="{(checked) => {
const url = new URL($page.url);

if (currentTarget.checked) {
if (checked) {
url.searchParams.set(yAxisKey, '');
} else {
url.searchParams.delete(yAxisKey);
Expand Down
9 changes: 4 additions & 5 deletions src/routes/input/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import Input, { type Variant } from '$lib/components/input/index.js';
import Label from '$lib/components/label/index.js';
import * as Select from '$lib/components/select/index.js';
import Switch from '$lib/components/switch/index.js';
const disabledKey = 'disabled';
const placeholderKey = 'placeholder';
Expand Down Expand Up @@ -34,16 +35,14 @@
<div data-form>
<Label for="{disabledKey}">Disabled</Label>

<input
<Switch
checked="{$disabled}"
id="{disabledKey}"
name="{disabledKey}"
type="checkbox"
data-control
on:change="{({ currentTarget }) => {
onCheckedChange="{(checked) => {
const url = new URL($page.url);

if (currentTarget.checked) {
if (checked) {
url.searchParams.set(disabledKey, '');
} else {
url.searchParams.delete(disabledKey);
Expand Down
42 changes: 42 additions & 0 deletions src/routes/switch/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<script context="module" lang="ts">
import { derived } from 'svelte/store';
import { goto } from '$app/navigation';
import { page } from '$app/stores';
import Label from '$lib/components/label/index.js';
import Switch from '$lib/components/switch/index.js';
const disabledKey = 'disabled';
</script>

<script lang="ts">
const disabled = derived(page, ($page) => $page.url.searchParams.has(disabledKey));
</script>

<!-- <style lang="postcss">
</style> -->

<div data-form>
<Label for="{disabledKey}">Disabled</Label>

<Switch
checked="{$disabled}"
id="{disabledKey}"
name="{disabledKey}"
onCheckedChange="{(checked) => {
const url = new URL($page.url);

if (checked) {
url.searchParams.set(disabledKey, '');
} else {
url.searchParams.delete(disabledKey);
}

goto(url);
}}"
/>
</div>

<hr class="my-4 border-y border-border" />

<Switch disabled="{$disabled}" />

0 comments on commit 7d90579

Please sign in to comment.