aboutsummaryrefslogtreecommitdiffstats
path: root/code/app/src/lib/components/switch.svelte
blob: 16da23aa001e5f6d18f35a10952b1c5ad918b575 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<script context="module" lang="ts">
    export type SwitchType = "short" | "icon" | "default";
</script>

<script lang="ts">
    import pwKey from "$actions/pwKey";


    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;
    export let _pwKey:string|undefined = undefined;

    $: 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={enabled}
            use:pwKey={_pwKey}
            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={enabled}
            use:pwKey={_pwKey}
            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={enabled}
            use:pwKey={_pwKey}
            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>