Skip to content

Commit cca112e

Browse files
committed
Implement a switch component
1 parent b6d5764 commit cca112e

File tree

4 files changed

+68
-8
lines changed

4 files changed

+68
-8
lines changed

src/components/features/bottom/BottomPanel.svelte

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import { stores } from '../../../lib/stores/Stores';
2020
import LiveDataFingerprint from './LiveDataFingerprint.svelte';
2121
import { Feature, hasFeature } from '../../../lib/FeatureToggles';
22+
import Switch from '../../ui/Switch.svelte';
2223
2324
const devices = stores.getDevices();
2425
const enableFingerprint = stores.getEnableFingerprint();
@@ -91,11 +92,10 @@
9192
<div class="absolute right-0 bottom-0 h-full w-45 flex flex-col justify-between">
9293
<div class="pt-2 pr-2 justify-end flex flex-row gap-2">
9394
<p>Fingerprint:</p>
94-
<input
95-
type="checkbox"
96-
checked={$enableFingerprint}
97-
on:change={e => toggleEnabled(e)}
98-
on:click|stopPropagation />
95+
<Switch
96+
size="sm"
97+
bind:checked={$enableFingerprint}
98+
on:change={e => enableFingerprint.set(e.detail.checked)} />
9999
</div>
100100

101101
{#if isFingerprintEnabled}

src/components/ui/Switch.svelte

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<!--
2+
(c) 2023-2025, Center for Computational Thinking and Design at Aarhus University and contributors
3+
4+
SPDX-License-Identifier: MIT
5+
-->
6+
7+
<script lang="ts">
8+
import { createEventDispatcher } from 'svelte';
9+
export let checked: boolean = false;
10+
export let disabled: boolean = false;
11+
export let label: string = '';
12+
export let size: 'sm' | 'md' | 'lg' = 'md';
13+
const dispatch = createEventDispatcher();
14+
15+
function toggle() {
16+
if (disabled) return;
17+
checked = !checked;
18+
dispatch('change', { checked });
19+
}
20+
21+
// Size classes
22+
const sizeMap = {
23+
sm: { btn: 'w-8 h-5', knob: 'w-4 h-4', translate: '0.9rem' },
24+
md: { btn: 'w-12 h-7', knob: 'w-6 h-6', translate: '1.25rem' },
25+
lg: { btn: 'w-16 h-9', knob: 'w-8 h-8', translate: '1.75rem' },
26+
};
27+
$: btnSize = sizeMap[size]?.btn || sizeMap.md.btn;
28+
$: knobSize = sizeMap[size]?.knob || sizeMap.md.knob;
29+
$: knobTranslate = sizeMap[size]?.translate || sizeMap.md.translate;
30+
</script>
31+
32+
<div class="flex items-center space-x-3 select-none">
33+
{#if label}
34+
<label class="text-base cursor-pointer" on:click={toggle}>{label}</label>
35+
{/if}
36+
<button
37+
type="button"
38+
class="relative focus:outline-none transition-colors duration-200 rounded-full border-2 border-gray-300 bg-gray-200 flex items-center {btnSize} {disabled
39+
? 'opacity-50 cursor-not-allowed'
40+
: 'cursor-pointer'}"
41+
aria-checked={checked}
42+
on:click|stopPropagation
43+
aria-label={label}
44+
{disabled}
45+
on:click={toggle}
46+
role="switch"
47+
tabindex="0">
48+
<span
49+
class="absolute left-0 top-0 w-full h-full rounded-full transition-colors duration-200"
50+
class:bg-primary={checked && !disabled}
51+
class:bg-gray-200={!checked || disabled}
52+
class:border-primary={checked && !disabled}
53+
class:border-gray-300={!checked || disabled}></span>
54+
<span
55+
class="inline-block bg-white rounded-full shadow transform transition-transform duration-200 z-10 border border-gray-300 {knobSize}"
56+
style="transform: translateX({checked ? knobTranslate : '0rem'});"></span>
57+
</button>
58+
</div>

src/pages/validation/ValidationPageActionContent.svelte

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import { tr } from '../../i18n';
1313
import Tooltip from '../../components/ui/Tooltip.svelte';
1414
import StandardButton from '../../components/ui/buttons/StandardButton.svelte';
15+
import Switch from '../../components/ui/Switch.svelte';
1516
1617
const classifier = stores.getClassifier();
1718
const model = classifier.getModel();
@@ -29,12 +30,12 @@
2930
</script>
3031

3132
<div class="bg-white h-full flex flex-row justify-evenly">
32-
<div class="pl-2 flex flex-col justify-center">
33+
<div class="flex flex-col justify-center">
3334
<div class="flex flex-row gap-2 justify-center">
3435
<p>
3536
{$tr('content.validation.testButton.autoUpdate')}:
3637
</p>
37-
<input type="checkbox" bind:checked={$autoUpdate} />
38+
<Switch size="sm" bind:checked={$autoUpdate} />
3839
</div>
3940
<Tooltip
4041
disabled={$model.isTrained}

src/pages/validation/ValidationpageActionContentMinimized.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
<script lang="ts">
88
import StandardButton from '../../components/ui/buttons/StandardButton.svelte';
9+
import Switch from '../../components/ui/Switch.svelte';
910
import Tooltip from '../../components/ui/Tooltip.svelte';
1011
import { tr } from '../../i18n';
1112
import { stores } from '../../lib/stores/Stores';
@@ -26,7 +27,7 @@
2627
<p class="text-sm self-center">
2728
{$tr('content.validation.testButton.autoUpdate')}:
2829
</p>
29-
<input type="checkbox" bind:checked={$autoUpdate} />
30+
<Switch size="sm" bind:checked={$autoUpdate} />
3031
<Tooltip
3132
disabled={$model.isTrained}
3233
offset={{ x: 230, y: 0 }}

0 commit comments

Comments
 (0)