[READ-ONLY] a fast, modern browser for the npm registry
at main 179 lines 4.3 kB view raw
1<script setup lang="ts"> 2import TooltipApp from '~/components/Tooltip/App.vue' 3 4const props = withDefaults( 5 defineProps<{ 6 label: string 7 description?: string 8 justify?: 'between' | 'start' 9 tooltip?: string 10 tooltipPosition?: 'top' | 'bottom' | 'left' | 'right' 11 tooltipTo?: string 12 tooltipOffset?: number 13 reverseOrder?: boolean 14 }>(), 15 { 16 justify: 'between', 17 reverseOrder: false, 18 }, 19) 20 21const checked = defineModel<boolean>({ 22 required: true, 23}) 24const id = useId() 25</script> 26 27<template> 28 <label 29 :for="id" 30 class="grid items-center gap-4 py-1 -my-1 grid-cols-[auto_1fr_auto]" 31 :class="[justify === 'start' ? 'justify-start' : '']" 32 :style=" 33 props.reverseOrder 34 ? 'grid-template-areas: \'toggle . label-text\'' 35 : 'grid-template-areas: \'label-text . toggle\'' 36 " 37 > 38 <template v-if="props.reverseOrder"> 39 <input 40 role="switch" 41 type="checkbox" 42 :id 43 v-model="checked" 44 class="toggle appearance-none h-6 w-11 rounded-full border border-fg relative shrink-0 bg-fg-subtle checked:bg-fg checked:border-fg focus-visible:(outline-2 outline-fg outline-offset-2) before:content-[''] before:absolute before:h-5 before:w-5 before:top-1px before:rounded-full before:bg-bg" 45 style="grid-area: toggle" 46 /> 47 <TooltipApp 48 v-if="tooltip && label" 49 :text="tooltip" 50 :position="tooltipPosition ?? 'top'" 51 :to="tooltipTo" 52 :offset="tooltipOffset" 53 > 54 <span class="text-sm text-fg font-medium text-start" style="grid-area: label-text"> 55 {{ label }} 56 </span> 57 </TooltipApp> 58 <span 59 v-else-if="label" 60 class="text-sm text-fg font-medium text-start" 61 style="grid-area: label-text" 62 > 63 {{ label }} 64 </span> 65 </template> 66 <template v-else> 67 <TooltipApp 68 v-if="tooltip && label" 69 :text="tooltip" 70 :position="tooltipPosition ?? 'top'" 71 :to="tooltipTo" 72 :offset="tooltipOffset" 73 > 74 <span class="text-sm text-fg font-medium text-start" style="grid-area: label-text"> 75 {{ label }} 76 </span> 77 </TooltipApp> 78 <span 79 v-else-if="label" 80 class="text-sm text-fg font-medium text-start" 81 style="grid-area: label-text" 82 > 83 {{ label }} 84 </span> 85 <input 86 role="switch" 87 type="checkbox" 88 :id 89 v-model="checked" 90 class="toggle appearance-none h-6 w-11 rounded-full border border-fg relative shrink-0 bg-fg-subtle checked:bg-fg checked:border-fg focus-visible:(outline-2 outline-fg outline-offset-2) before:content-[''] before:absolute before:h-5 before:w-5 before:top-1px before:rounded-full before:bg-bg" 91 style="grid-area: toggle; justify-self: end" 92 /> 93 </template> 94 </label> 95 <p v-if="description" class="text-sm text-fg-muted mt-2"> 96 {{ description }} 97 </p> 98</template> 99 100<style scoped> 101/* Thumb position: logical property for RTL support */ 102.toggle::before { 103 inset-inline-start: 1px; 104} 105 106/* Track transition */ 107.toggle { 108 transition: 109 background-color 200ms ease-in-out, 110 border-color 100ms ease-in-out; 111} 112 113.toggle::before { 114 transition: 115 background-color 200ms ease-in-out, 116 translate 200ms ease-in-out; 117} 118 119/* Hover states */ 120.toggle:hover:not(:checked) { 121 background: var(--fg-muted); 122} 123 124.toggle:checked:hover { 125 background: var(--fg-muted); 126 border-color: var(--fg-muted); 127} 128 129/* RTL-aware checked thumb position */ 130:dir(ltr) .toggle:checked::before { 131 translate: 20px; 132} 133 134:dir(rtl) .toggle:checked::before { 135 translate: -20px; 136} 137 138@media (prefers-reduced-motion: reduce) { 139 .toggle, 140 .toggle::before { 141 transition: none; 142 } 143} 144 145/* Support forced colors */ 146@media (forced-colors: active) { 147 label > span { 148 background: Canvas; 149 color: Highlight; 150 forced-color-adjust: none; 151 } 152 153 label:has(.toggle:checked) > span { 154 background: Highlight; 155 color: Canvas; 156 } 157 158 .toggle::before { 159 forced-color-adjust: none; 160 background-color: Highlight; 161 } 162 163 .toggle, 164 .toggle:hover { 165 background: Canvas; 166 border-color: CanvasText; 167 } 168 169 .toggle:checked, 170 .toggle:checked:hover { 171 background: Highlight; 172 border-color: CanvasText; 173 } 174 175 .toggle:checked::before { 176 background: Canvas; 177 } 178} 179</style>