aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorivarlovlie <git@ivarlovlie.no>2022-09-28 15:31:41 +0200
committerivarlovlie <git@ivarlovlie.no>2022-09-28 15:31:41 +0200
commit3a9975ce230a892a8af0286ffa81776d03a8361b (patch)
tree46df0328e95eb88144e7802819fe3e74ce9eb028
parent803c2ff0581e761c5175e1a04b006e1f6a997c6e (diff)
downloadgreatoffice-3a9975ce230a892a8af0286ffa81776d03a8361b.tar.xz
greatoffice-3a9975ce230a892a8af0286ffa81776d03a8361b.zip
feat: Add switch component
-rw-r--r--apps/kit/src/lib/components/switch.svelte135
-rw-r--r--apps/kit/src/routes/book/+layout.svelte6
-rw-r--r--apps/kit/src/routes/book/toggles/+page.svelte27
3 files changed, 168 insertions, 0 deletions
diff --git a/apps/kit/src/lib/components/switch.svelte b/apps/kit/src/lib/components/switch.svelte
new file mode 100644
index 0000000..8a90dba
--- /dev/null
+++ b/apps/kit/src/lib/components/switch.svelte
@@ -0,0 +1,135 @@
+<script context="module" lang="ts">
+ export type SwitchType = "short" | "icon" | "default";
+</script>
+
+<script lang="ts">
+ export let enabled = false;
+ export let type: SwitchType = "default";
+ export let srText = "Use setting";
+ export let label: string | undefined = undefined;
+ export let description: string | undefined = undefined;
+ export let rightAlignedLabelDescription = false;
+ $: colorClass = enabled
+ ? "bg-teal-600 focus:ring-teal-500"
+ : "bg-gray-200 focus:ring-teal-500";
+ $: translateClass = enabled ? "translate-x-5" : "translate-x-0";
+ $: hasLabelOrDescription = label || description;
+
+ function toggle() {
+ enabled = !enabled;
+ }
+</script>
+
+<div
+ class="{hasLabelOrDescription
+ ? 'flex items-center'
+ : ''} {rightAlignedLabelDescription ? '' : 'justify-between'}"
+>
+ {#if hasLabelOrDescription && !rightAlignedLabelDescription}
+ <span class="flex flex-grow flex-col">
+ {#if label}
+ <span class="text-sm font-medium text-gray-900">{label}</span>
+ {/if}
+ {#if description}
+ <span class="text-sm text-gray-500">{description}</span>
+ {/if}
+ </span>
+ {/if}
+ {#if type === "short"}
+ <button
+ type="button"
+ class="group relative inline-flex h-5 w-10 flex-shrink-0 cursor-pointer items-center justify-center rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2"
+ role="switch"
+ aria-checked="false"
+ on:click={toggle}
+ >
+ <span class="sr-only">{srText}</span>
+ <span
+ aria-hidden="true"
+ class="pointer-events-none absolute h-full w-full rounded-md"
+ />
+ <span
+ aria-hidden="true"
+ class="{colorClass} pointer-events-none absolute mx-auto h-4 w-9 rounded-full transition-colors duration-200 ease-in-out"
+ />
+ <span
+ aria-hidden="true"
+ class="{translateClass} pointer-events-none absolute left-0 inline-block h-5 w-5 transform rounded-full border border-gray-200 bg-white shadow ring-0 transition-transform duration-200 ease-in-out"
+ />
+ </button>
+ {:else if type === "icon"}
+ <button
+ type="button"
+ class="{colorClass} relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-offset-2"
+ role="switch"
+ aria-checked="false"
+ on:click={toggle}
+ >
+ <span class="sr-only">{srText}</span>
+ <span
+ class="{translateClass} pointer-events-none relative inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"
+ >
+ <span
+ class="{enabled
+ ? 'opacity-0 ease-out duration-100'
+ : 'opacity-100 ease-in duration-200'} absolute inset-0 flex h-full w-full items-center justify-center transition-opacity"
+ aria-hidden="true"
+ >
+ <svg
+ class="h-3 w-3 text-gray-400"
+ fill="none"
+ viewBox="0 0 12 12"
+ >
+ <path
+ d="M4 8l2-2m0 0l2-2M6 6L4 4m2 2l2 2"
+ stroke="currentColor"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ </svg>
+ </span>
+ <span
+ class="{enabled
+ ? 'opacity-100 ease-in duration-200'
+ : 'opacity-0 ease-out duration-100'} absolute inset-0 flex h-full w-full items-center justify-center transition-opacity"
+ aria-hidden="true"
+ >
+ <svg
+ class="h-3 w-3 text-indigo-600"
+ fill="currentColor"
+ viewBox="0 0 12 12"
+ >
+ <path
+ d="M3.707 5.293a1 1 0 00-1.414 1.414l1.414-1.414zM5 8l-.707.707a1 1 0 001.414 0L5 8zm4.707-3.293a1 1 0 00-1.414-1.414l1.414 1.414zm-7.414 2l2 2 1.414-1.414-2-2-1.414 1.414zm3.414 2l4-4-1.414-1.414-4 4 1.414 1.414z"
+ />
+ </svg>
+ </span>
+ </span>
+ </button>
+ {:else if type === "default"}
+ <button
+ type="button"
+ class="{colorClass} relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-offset-2"
+ role="switch"
+ aria-checked="false"
+ on:click={toggle}
+ >
+ <span class="sr-only">{srText}</span>
+ <span
+ aria-hidden="true"
+ class="{translateClass} pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"
+ />
+ </button>
+ {/if}
+ {#if hasLabelOrDescription && rightAlignedLabelDescription}
+ <span class="ml-3">
+ {#if label}
+ <span class="text-sm font-medium text-gray-900">{label}</span>
+ {/if}
+ {#if description}
+ <span class="text-sm text-gray-500">{description}</span>
+ {/if}
+ </span>
+ {/if}
+</div>
diff --git a/apps/kit/src/routes/book/+layout.svelte b/apps/kit/src/routes/book/+layout.svelte
index fc55d9d..02d03b6 100644
--- a/apps/kit/src/routes/book/+layout.svelte
+++ b/apps/kit/src/routes/book/+layout.svelte
@@ -17,6 +17,12 @@
class:active={$page.url.pathname.startsWith("/book/buttons")}
>Buttons</a
>
+ <a
+ href="/book/toggles"
+ class="link"
+ class:active={$page.url.pathname.startsWith("/book/toggles")}
+ >Toggles</a
+ >
</nav>
<main>
<slot />
diff --git a/apps/kit/src/routes/book/toggles/+page.svelte b/apps/kit/src/routes/book/toggles/+page.svelte
new file mode 100644
index 0000000..94228b4
--- /dev/null
+++ b/apps/kit/src/routes/book/toggles/+page.svelte
@@ -0,0 +1,27 @@
+<script>
+ import Switch from "$lib/components/switch.svelte";
+</script>
+
+<section>
+ <h2>Default</h2>
+ <Switch />
+</section>
+<section>
+ <h2>Short</h2>
+ <Switch type="short" />
+</section>
+<section>
+ <h2>Icon</h2>
+ <Switch type="icon" />
+</section>
+<section>
+ <h2>Label / Description</h2>
+ <div class="max-w-md">
+ <Switch label="Label" description="Some text" />
+ </div>
+</section>
+
+<section>
+ <h2>Label / Description (right aligned)</h2>
+ <Switch label="Label" description="Some text" rightAlignedLabelDescription />
+</section> \ No newline at end of file