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
| <script lang="ts">
| interface Props {
| checked: boolean
| onchange?: (checked: boolean) => void
| disabled?: boolean
| }
|
| let { checked = $bindable(), onchange, disabled = false }: Props = $props()
|
| function toggle() {
| if (disabled) return
| checked = !checked
| onchange?.(checked)
| }
| </script>
|
| <button
| class="toggle"
| class:active={checked}
| class:disabled
| onclick={toggle}
| role="switch"
| aria-checked={checked}
| >
| <div class="knob"></div>
| </button>
|
| <style>
| /* WPF: 36x20, macOS-style toggle */
| .toggle {
| position: relative;
| width: 36px;
| height: 20px;
| border-radius: 10px;
| background: #D1D1D6;
| border: none;
| cursor: pointer;
| transition: background var(--transition-fast);
| padding: 0;
| flex-shrink: 0;
| }
|
| .toggle.active {
| background: var(--color-green);
| }
|
| .toggle.disabled {
| opacity: 0.5;
| cursor: not-allowed;
| }
|
| .knob {
| position: absolute;
| top: 2px;
| left: 2px;
| width: 16px;
| height: 16px;
| border-radius: 8px;
| background: white;
| box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
| transition: transform var(--transition-fast);
| }
|
| .toggle.active .knob {
| transform: translateX(16px);
| }
| </style>
|
|