11<script setup lang="ts">
2- const props = defineProps <{
2+ defineProps <{
33 label: string
44 description? : string
55}>()
@@ -10,69 +10,65 @@ const id = useId()
1010 </script >
1111
1212<template >
13- <label :for =" id" >
14- <span class =" label-text" >{{ label }}</span >
15- <input role =" switch" type =" checkbox" :id class =" checkbox" v-model =" checked" />
16- <span class =" background" ></span >
13+ <label :for =" id" class =" grid" style =" grid-template-areas : ' label-text . toggle-background' " >
14+ <span class =" text-sm text-fg font-medium text-start" style =" grid-area : label-text" >{{
15+ label
16+ }}</span >
17+ <input
18+ role =" switch"
19+ type =" checkbox"
20+ :id
21+ class =" opacity-0"
22+ style =" grid-row : 1 ; grid-column : 3 ; justify-self : end "
23+ v-model =" checked"
24+ />
25+ <span
26+ class =" toggle-background h-6 w-11 rounded-full border border-fg relative flex"
27+ style =" grid-area : toggle-background; justify-self : end "
28+ ></span >
1729 </label >
1830 <p v-if =" description" class =" text-sm text-fg-muted mt-2" >
1931 {{ description }}
2032 </p >
2133</template >
2234
2335<style scoped>
24- .label-text {
25- grid-area : label-text;
26- }
27-
28- .background {
29- grid-area : toggle-background;
30- justify-self : end ;
31- }
32-
33- .checkbox {
34- opacity : 0 ;
35- }
36-
37- label {
38- display : grid ;
39- grid-template-areas : ' label-text . toggle-background' ;
40- }
41-
42- input {
43- grid-row : 1 ;
44- grid-column : 3 ;
45- justify-self : end ;
36+ /* Track background */
37+ .toggle-background {
38+ background : var (--fg-subtle );
39+ transition :
40+ background-color 100ms ease-in ,
41+ border-color 100ms ease-in ;
4642}
4743
48- /* background */
49- .background {
50- width : 44px ;
51- height : 24px ;
52- background : var (--fg-subtle );
53- border-radius : 9999px ;
54- border : 1px solid var (--fg );
55- display : flex ;
56- position : relative ;
44+ @media (prefers-reduced-motion: reduce) {
45+ .toggle-background {
46+ transition : none ;
47+ }
5748}
5849
59- label :has (input :focus-visible ) .background {
50+ label :has (input :focus-visible ) .toggle- background {
6051 outline : solid 2px var (--fg );
6152 outline-offset : 2px ;
6253}
6354
64- label :has (input :checked ) .background {
55+ label :has (input :checked ) .toggle- background {
6556 background : var (--fg );
6657 border-color : var (--fg );
6758}
6859
69- label :has (input :hover ) .background {
60+ label :has (input :hover:not (:checked )) .toggle-background {
61+ background : var (--fg-muted );
62+ }
63+
64+ label :has (input :checked:hover ) .toggle-background {
7065 background : var (--fg-muted );
66+ border-color : var (--fg-muted );
7167}
7268
7369/* Circle that moves */
74- .background ::before {
75- transition : transform 200ms ease-in-out ;
70+ .toggle- background ::before {
71+ transition : translate 200ms ease-in-out ;
7672 content : ' ' ;
7773 width : 20px ;
7874 height : 20px ;
@@ -83,12 +79,18 @@ label:has(input:hover) .background {
8379 background : var (--bg );
8480}
8581
82+ @media (prefers-reduced-motion: reduce) {
83+ .toggle-background ::before {
84+ transition : none ;
85+ }
86+ }
87+
8688/* Support rtl locales */
87- :dir (ltr ) .checkbox :checked + .background ::before {
88- transform : translate ( 20px ) ;
89+ :dir (ltr ) input :checked + .toggle- background ::before {
90+ translate : 20px ;
8991}
9092
91- :dir (rtl ) .checkbox :checked + .background ::before {
92- transform : translate ( -20px ) ;
93+ :dir (rtl ) input :checked + .toggle- background ::before {
94+ translate : -20px ;
9395}
9496 </style >
0 commit comments