[READ-ONLY] a fast, modern browser for the npm registry
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor: extract toggle into reusable component (#560)

authored by

Matteo Gabriele and committed by
GitHub
47215cd4 8081bb6a

+78 -121
+49
app/components/Toggle.client.vue
··· 1 + <script setup lang="ts"> 2 + defineProps<{ 3 + label?: string 4 + description?: string 5 + }>() 6 + 7 + const checked = defineModel<boolean>({ 8 + default: false, 9 + }) 10 + </script> 11 + 12 + <template> 13 + <button 14 + type="button" 15 + class="w-full flex items-center justify-between gap-4 group" 16 + role="switch" 17 + :aria-checked="checked" 18 + @click="checked = !checked" 19 + > 20 + <span v-if="label" class="text-sm text-fg font-medium text-start"> 21 + {{ label }} 22 + </span> 23 + <span 24 + class="relative inline-flex h-6 w-11 shrink-0 items-center rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out motion-reduce:transition-none shadow-sm cursor-pointer" 25 + :class="checked ? 'bg-accent' : 'bg-bg border border-border'" 26 + aria-hidden="true" 27 + > 28 + <span 29 + class="pointer-events-none inline-block h-5 w-5 rounded-full shadow-sm ring-0 transition-transform duration-200 ease-in-out motion-reduce:transition-none" 30 + :class="checked ? 'bg-bg' : 'bg-fg-muted'" 31 + /> 32 + </span> 33 + </button> 34 + <p v-if="description" class="text-sm text-fg-muted"> 35 + {{ description }} 36 + </p> 37 + </template> 38 + 39 + <style scoped> 40 + button[aria-checked='false'] > span:last-of-type > span { 41 + translate: 0; 42 + } 43 + button[aria-checked='true'] > span:last-of-type > span { 44 + translate: calc(100%); 45 + } 46 + html[dir='rtl'] button[aria-checked='true'] > span:last-of-type > span { 47 + translate: calc(-100%); 48 + } 49 + </style>
+18
app/components/Toggle.server.vue
··· 1 + <script setup lang="ts"> 2 + defineProps<{ 3 + label?: string 4 + description?: string 5 + }>() 6 + </script> 7 + 8 + <template> 9 + <div class="w-full flex items-center justify-between gap-4"> 10 + <span v-if="label" class="text-sm text-fg font-medium text-start"> 11 + {{ label }} 12 + </span> 13 + <span class="skeleton block h-6 w-11 shrink-0 rounded-full" /> 14 + </div> 15 + <p v-if="description" class="text-sm text-fg-muted"> 16 + {{ description }} 17 + </p> 18 + </template>
-14
app/components/ToggleSkeleton.vue
··· 1 - <script setup lang="ts"> 2 - defineProps<{ 3 - label: string 4 - }>() 5 - </script> 6 - 7 - <template> 8 - <div class="w-full flex items-center justify-between gap-4"> 9 - <span class="text-sm text-fg font-medium text-start"> 10 - {{ label }} 11 - </span> 12 - <span class="skeleton block h-6 w-11 shrink-0 rounded-full" /> 13 - </div> 14 - </template>
+11 -107
app/pages/settings.vue
··· 100 100 </h2> 101 101 <div class="bg-bg-subtle border border-border rounded-lg p-4 sm:p-6 space-y-4"> 102 102 <!-- Relative dates toggle --> 103 - <div class="space-y-2"> 104 - <ClientOnly> 105 - <button 106 - type="button" 107 - class="w-full flex items-center justify-between gap-4 group" 108 - role="switch" 109 - :aria-checked="settings.relativeDates" 110 - @click="settings.relativeDates = !settings.relativeDates" 111 - > 112 - <span class="text-sm text-fg font-medium text-start"> 113 - {{ $t('settings.relative_dates') }} 114 - </span> 115 - <span 116 - class="relative inline-flex h-6 w-11 shrink-0 items-center rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out motion-reduce:transition-none shadow-sm cursor-pointer" 117 - :class="settings.relativeDates ? 'bg-accent' : 'bg-bg border border-border'" 118 - aria-hidden="true" 119 - > 120 - <span 121 - class="pointer-events-none inline-block h-5 w-5 rounded-full shadow-sm ring-0 transition-transform duration-200 ease-in-out motion-reduce:transition-none" 122 - :class="settings.relativeDates ? 'bg-bg' : 'bg-fg-muted'" 123 - /> 124 - </span> 125 - </button> 126 - <template #fallback> 127 - <ToggleSkeleton :label="$t('settings.relative_dates')" /> 128 - </template> 129 - </ClientOnly> 130 - <p class="text-sm text-fg-muted"> 131 - {{ $t('settings.relative_dates_description') }} 132 - </p> 133 - </div> 103 + <Toggle :label="$t('settings.relative_dates')" v-model="settings.relativeDates" /> 134 104 135 105 <!-- Divider --> 136 106 <div class="border-t border-border" /> 137 107 138 108 <!-- Include @types in install toggle --> 139 109 <div class="space-y-2"> 140 - <ClientOnly> 141 - <button 142 - type="button" 143 - class="w-full flex items-center justify-between gap-4 group" 144 - role="switch" 145 - :aria-checked="settings.includeTypesInInstall" 146 - @click="settings.includeTypesInInstall = !settings.includeTypesInInstall" 147 - > 148 - <span class="text-sm text-fg font-medium text-start"> 149 - {{ $t('settings.include_types') }} 150 - </span> 151 - <span 152 - class="relative inline-flex h-6 w-11 shrink-0 items-center rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out motion-reduce:transition-none shadow-sm cursor-pointer" 153 - :class=" 154 - settings.includeTypesInInstall ? 'bg-accent' : 'bg-bg border border-border' 155 - " 156 - aria-hidden="true" 157 - > 158 - <span 159 - class="pointer-events-none inline-block h-5 w-5 rounded-full shadow-sm ring-0 transition-transform duration-200 ease-in-out motion-reduce:transition-none" 160 - :class="settings.includeTypesInInstall ? 'bg-bg' : 'bg-fg-muted'" 161 - /> 162 - </span> 163 - </button> 164 - <template #fallback> 165 - <ToggleSkeleton :label="$t('settings.include_types')" /> 166 - </template> 167 - </ClientOnly> 168 - <p class="text-sm text-fg-muted"> 169 - {{ $t('settings.include_types_description') }} 170 - </p> 110 + <Toggle 111 + :label="$t('settings.include_types')" 112 + :description="$t('settings.include_types_description')" 113 + v-model="settings.includeTypesInInstall" 114 + /> 171 115 </div> 172 116 173 117 <!-- Divider --> ··· 175 119 176 120 <!-- Hide platform-specific packages toggle --> 177 121 <div class="space-y-2"> 178 - <ClientOnly> 179 - <button 180 - type="button" 181 - class="w-full flex items-center justify-between gap-4 group" 182 - role="switch" 183 - :aria-checked="settings.hidePlatformPackages" 184 - @click="settings.hidePlatformPackages = !settings.hidePlatformPackages" 185 - > 186 - <span class="text-sm text-fg font-medium text-start"> 187 - {{ $t('settings.hide_platform_packages') }} 188 - </span> 189 - <span 190 - class="relative inline-flex h-6 w-11 shrink-0 items-center rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out motion-reduce:transition-none shadow-sm cursor-pointer" 191 - :class=" 192 - settings.hidePlatformPackages ? 'bg-accent' : 'bg-bg border border-border' 193 - " 194 - aria-hidden="true" 195 - > 196 - <span 197 - class="pointer-events-none inline-block h-5 w-5 rounded-full shadow-sm ring-0 transition-transform duration-200 ease-in-out motion-reduce:transition-none" 198 - :class="settings.hidePlatformPackages ? 'bg-bg' : 'bg-fg-muted'" 199 - /> 200 - </span> 201 - </button> 202 - <template #fallback> 203 - <p class="text-sm text-fg-muted"> 204 - {{ $t('settings.hide_platform_packages') }} 205 - </p> 206 - </template> 207 - </ClientOnly> 208 - <p class="text-sm text-fg-muted"> 209 - {{ $t('settings.hide_platform_packages_description') }} 210 - </p> 122 + <Toggle 123 + :label="$t('settings.hide_platform_packages')" 124 + :description="$t('settings.hide_platform_packages')" 125 + v-model="settings.hidePlatformPackages" 126 + /> 211 127 </div> 212 128 </div> 213 129 </section> ··· 271 187 </article> 272 188 </main> 273 189 </template> 274 - 275 - <style scoped> 276 - button[aria-checked='false'] > span:last-of-type > span { 277 - translate: 0; 278 - } 279 - button[aria-checked='true'] > span:last-of-type > span { 280 - translate: calc(100%); 281 - } 282 - html[dir='rtl'] button[aria-checked='true'] > span:last-of-type > span { 283 - translate: calc(-100%); 284 - } 285 - </style>