forked from
npmx.dev/npmx.dev
[READ-ONLY]
a fast, modern browser for the npm registry
1<script setup lang="ts">
2const props = withDefaults(
3 defineProps<{
4 label: string
5 description?: string
6 justify?: 'between' | 'start'
7 reverseOrder?: boolean
8 }>(),
9 {
10 justify: 'between',
11 reverseOrder: false,
12 },
13)
14</script>
15
16<template>
17 <div
18 class="grid items-center gap-4 py-1 -my-1 grid-cols-[auto_1fr_auto]"
19 :class="[justify === 'start' ? 'justify-start' : '']"
20 :style="
21 props.reverseOrder
22 ? 'grid-template-areas: \'toggle . label-text\''
23 : 'grid-template-areas: \'label-text . toggle\''
24 "
25 >
26 <template v-if="props.reverseOrder">
27 <SkeletonBlock class="h-6 w-11 shrink-0 rounded-full" style="grid-area: toggle" />
28 <span
29 v-if="label"
30 class="text-sm text-fg font-medium text-start"
31 style="grid-area: label-text"
32 >
33 {{ label }}
34 </span>
35 </template>
36 <template v-else>
37 <span
38 v-if="label"
39 class="text-sm text-fg font-medium text-start"
40 style="grid-area: label-text"
41 >
42 {{ label }}
43 </span>
44 <SkeletonBlock
45 class="h-6 w-11 shrink-0 rounded-full"
46 style="grid-area: toggle; justify-self: end"
47 />
48 </template>
49 </div>
50 <p v-if="description" class="text-sm text-fg-muted mt-2">
51 {{ description }}
52 </p>
53</template>
54
55<style scoped>
56/* Thumb position: logical property for RTL support */
57.toggle::before {
58 inset-inline-start: 1px;
59}
60
61/* Track transition */
62.toggle {
63 transition:
64 background-color 200ms ease-in-out,
65 border-color 100ms ease-in-out;
66}
67
68.toggle::before {
69 transition:
70 background-color 200ms ease-in-out,
71 translate 200ms ease-in-out;
72}
73
74/* Hover states */
75.toggle:hover:not(:checked) {
76 background: var(--fg-muted);
77}
78
79.toggle:checked:hover {
80 background: var(--fg-muted);
81 border-color: var(--fg-muted);
82}
83
84/* RTL-aware checked thumb position */
85:dir(ltr) .toggle:checked::before {
86 translate: 20px;
87}
88
89:dir(rtl) .toggle:checked::before {
90 translate: -20px;
91}
92
93@media (prefers-reduced-motion: reduce) {
94 .toggle,
95 .toggle::before {
96 transition: none;
97 }
98}
99
100/* Support forced colors */
101@media (forced-colors: active) {
102 label > span {
103 background: Canvas;
104 color: Highlight;
105 forced-color-adjust: none;
106 }
107
108 label:has(.toggle:checked) > span {
109 background: Highlight;
110 color: Canvas;
111 }
112
113 .toggle::before {
114 forced-color-adjust: none;
115 background-color: Highlight;
116 }
117
118 .toggle,
119 .toggle:hover {
120 background: Canvas;
121 border-color: CanvasText;
122 }
123
124 .toggle:checked,
125 .toggle:checked:hover {
126 background: Highlight;
127 border-color: CanvasText;
128 }
129
130 .toggle:checked::before {
131 background: Canvas;
132 }
133}
134</style>