Skip to content

Commit c498289

Browse files
committed
fix: settings toggle should use input
1 parent a729534 commit c498289

File tree

1 file changed

+113
-33
lines changed

1 file changed

+113
-33
lines changed
Lines changed: 113 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,134 @@
11
<script setup lang="ts">
2-
defineProps<{
3-
label?: string
2+
const props = defineProps<{
3+
label: string
44
description?: string
55
class?: string
66
}>()
77
88
const checked = defineModel<boolean>({
99
default: false,
1010
})
11+
const id = 'toggle-' + props.label
1112
</script>
1213

1314
<template>
14-
<button
15-
type="button"
16-
class="w-full flex items-center justify-between gap-4 group focus-visible:outline-none py-1 -my-1"
17-
role="switch"
18-
:aria-checked="checked"
19-
@click="checked = !checked"
20-
:class="class"
21-
>
22-
<span v-if="label" class="text-sm text-fg font-medium text-start">
23-
{{ label }}
24-
</span>
25-
<span
26-
class="inline-flex items-center h-6 w-11 shrink-0 rounded-full border p-0.25 transition-colors duration-200 shadow-sm ease-in-out motion-reduce:transition-none cursor-pointer group-focus-visible:(outline-accent/70 outline-offset-2 outline-solid)"
27-
:class="
28-
checked
29-
? 'bg-accent border-accent group-hover:bg-accent/80'
30-
: 'bg-fg/50 border-fg/50 group-hover:bg-fg/70'
31-
"
32-
aria-hidden="true"
33-
>
34-
<span
35-
class="block h-5 w-5 rounded-full bg-bg shadow-sm transition-transform duration-200 ease-in-out motion-reduce:transition-none"
36-
/>
37-
</span>
38-
</button>
15+
<label :for="id">
16+
<span class="toggle--label-text">{{ label }}</span>
17+
<input
18+
role="switch"
19+
type="checkbox"
20+
:id
21+
class="toggle--checkbox"
22+
:aria-checked="checked"
23+
:checked="checked"
24+
@click="checked = !checked"
25+
/>
26+
<span class="toggle--background"></span>
27+
</label>
3928
<p v-if="description" class="text-sm text-fg-muted mt-2">
4029
{{ description }}
4130
</p>
4231
</template>
4332

4433
<style scoped>
45-
button[aria-checked='false'] > span:last-of-type > span {
46-
translate: 0;
34+
@keyframes reverse {
35+
0% {
36+
left: 20px;
37+
width: 20px;
38+
}
39+
60% {
40+
left: 3px;
41+
width: 40px;
42+
}
43+
100% {
44+
left: 3px;
45+
}
4746
}
48-
button[aria-checked='true'] > span:last-of-type > span {
49-
translate: calc(100%);
47+
48+
@keyframes switch {
49+
0% {
50+
left: 3px;
51+
}
52+
60% {
53+
left: 3px;
54+
width: 40px;
55+
}
56+
100% {
57+
left: 20px;
58+
width: 20px;
59+
}
60+
}
61+
62+
.toggle--label-text {
63+
grid-area: label-text;
64+
}
65+
66+
.toggle--background {
67+
grid-area: toggle-background;
68+
justify-self: end;
69+
}
70+
71+
.toggle--checkbox {
72+
opacity: 0;
73+
}
74+
75+
label {
76+
display: grid;
77+
grid-template-areas: 'label-text . toggle-background';
78+
}
79+
80+
input {
81+
grid-row: 1;
82+
grid-column: 3;
83+
justify-self: end;
5084
}
51-
html[dir='rtl'] button[aria-checked='true'] > span:last-of-type > span {
52-
translate: calc(-100%);
85+
86+
label:has(input:focus) .toggle--background {
87+
outline: solid 1px #030712;
88+
outline-offset: 2px;
89+
transition: outline 100ms ease-in;
90+
}
91+
label:has(input:hover) .toggle--background {
92+
background: #6b7280;
93+
}
94+
95+
/* background */
96+
.toggle--background {
97+
width: 44px;
98+
height: 24px;
99+
background: #9ca3af;
100+
border-radius: 100px;
101+
border: 1px solid #030712;
102+
display: flex;
103+
position: relative;
104+
transition: all 350ms ease-in;
105+
}
106+
107+
label:has(input:checked) .toggle--background {
108+
background: #030712;
109+
border-color: #030712;
110+
}
111+
112+
/* Circle that moves */
113+
.toggle--checkbox:checked + .toggle--background:before {
114+
animation-name: reverse;
115+
animation-duration: 350ms;
116+
animation-fill-mode: forwards;
117+
transition: all 360ms ease-in;
118+
background: #f9fafb;
119+
}
120+
121+
.toggle--background:before {
122+
animation-name: switch;
123+
animation-duration: 350ms;
124+
animation-fill-mode: forwards;
125+
content: '';
126+
width: 20px;
127+
height: 20px;
128+
top: 1px;
129+
left: 3px;
130+
position: absolute;
131+
border-radius: 20px;
132+
background: #f9fafb;
53133
}
54134
</style>

0 commit comments

Comments
 (0)