[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: replace links and buttons for compare and code page (#1243)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

authored by

Marcus Blättermann
autofix-ci[bot]
coderabbitai[bot]
and committed by
GitHub
85b52265 893a3d3c

+132 -173
+1 -1
app/components/AppHeader.vue
··· 259 259 class="border-none" 260 260 variant="button-secondary" 261 261 :to="link.to" 262 - :keyshortcut="link.keyshortcut" 262 + :aria-keyshortcuts="link.keyshortcut" 263 263 > 264 264 {{ link.label }} 265 265 </LinkBase>
+10 -15
app/components/Button/Base.vue
··· 1 1 <script setup lang="ts"> 2 2 const props = withDefaults( 3 3 defineProps<{ 4 - 'disabled'?: boolean 5 - 'type'?: 'button' | 'submit' 6 - 'variant'?: 'primary' | 'secondary' 7 - 'size'?: 'small' | 'medium' 8 - 'keyshortcut'?: string 4 + disabled?: boolean 5 + type?: 'button' | 'submit' 6 + variant?: 'primary' | 'secondary' 7 + size?: 'small' | 'medium' 8 + ariaKeyshortcuts?: string 9 9 10 - /** 11 - * Do not use this directly. Use keyshortcut instead; it generates the correct HTML and displays the shortcut in the UI. 12 - */ 13 - 'aria-keyshortcuts'?: never 14 - 15 - 'classicon'?: string 10 + classicon?: string 16 11 }>(), 17 12 { 18 13 type: 'button', ··· 36 31 :class="{ 37 32 'text-sm px-4 py-2': size === 'medium', 38 33 'text-xs px-2 py-0.5': size === 'small', 39 - 'bg-transparent text-fg hover:enabled:(bg-fg/10) focus-visible:enabled:(bg-fg/10) aria-pressed:(bg-fg text-bg border-fg hover:enabled:(bg-fg text-bg/50))': 34 + 'bg-transparent text-fg hover:enabled:(bg-fg/10) focus-visible:enabled:(bg-fg/10) aria-pressed:(bg-fg/10 border-fg/20 hover:enabled:(bg-fg/20 text-fg/50))': 40 35 variant === 'secondary', 41 36 'text-bg bg-fg hover:enabled:(bg-fg/50) focus-visible:enabled:(bg-fg/50) aria-pressed:(bg-fg text-bg border-fg hover:enabled:(text-bg/50))': 42 37 variant === 'primary', ··· 51 46 */ 52 47 disabled ? true : undefined 53 48 " 54 - :aria-keyshortcuts="keyshortcut" 49 + :aria-keyshortcuts="ariaKeyshortcuts" 55 50 > 56 51 <span 57 52 v-if="classicon" ··· 60 55 /> 61 56 <slot /> 62 57 <kbd 63 - v-if="keyshortcut" 58 + v-if="ariaKeyshortcuts" 64 59 class="ms-2 inline-flex items-center justify-center w-4 h-4 text-xs text-fg bg-bg-muted border border-border rounded no-underline" 65 60 aria-hidden="true" 66 61 > 67 - {{ keyshortcut }} 62 + {{ ariaKeyshortcuts }} 68 63 </kbd> 69 64 </button> 70 65 </template>
+23 -20
app/components/Code/DirectoryListing.vue
··· 76 76 class="border-b border-border hover:bg-bg-subtle transition-colors" 77 77 > 78 78 <td colspan="2"> 79 - <NuxtLink 79 + <LinkBase 80 80 :to="getCodeRoute(parentPath || undefined)" 81 - class="flex items-center gap-2 py-2 px-4 font-mono text-sm text-fg-muted hover:text-fg transition-colors" 81 + class="py-2 px-4 font-mono text-sm w-full" 82 + no-underline 83 + classicon="i-carbon:folder text-yellow-600" 82 84 > 83 - <span class="i-carbon:folder w-4 h-4 text-yellow-600" /> 84 - <span>..</span> 85 - </NuxtLink> 85 + <span class="w-full flex justify-self-stretch items-center gap-2"> .. </span> 86 + </LinkBase> 86 87 </td> 87 88 </tr> 88 89 ··· 93 94 class="border-b border-border hover:bg-bg-subtle transition-colors" 94 95 > 95 96 <td colspan="2"> 96 - <NuxtLink 97 + <LinkBase 97 98 :to="getCodeRoute(node.path)" 98 - class="flex items-center gap-2 py-2 px-4 font-mono text-sm hover:text-fg transition-colors" 99 - :class="node.type === 'directory' ? 'text-fg' : 'text-fg-muted'" 99 + class="py-2 px-4 font-mono text-sm w-full" 100 + no-underline 101 + :classicon=" 102 + node.type === 'directory' 103 + ? 'i-carbon:folder text-yellow-600' 104 + : getFileIcon(node.name) 105 + " 100 106 > 101 - <span 102 - v-if="node.type === 'directory'" 103 - class="i-carbon:folder w-4 h-4 text-yellow-600" 104 - /> 105 - <span v-else class="w-4 h-4" :class="getFileIcon(node.name)" /> 106 - <span class="flex-1">{{ node.name }}</span> 107 - <span 108 - v-if="node.type === 'file' && node.size" 109 - class="text-end font-mono text-xs text-fg-subtle" 110 - > 111 - {{ bytesFormatter.format(node.size) }} 107 + <span class="w-full flex justify-self-stretch items-center gap-2"> 108 + <span class="flex-1">{{ node.name }}</span> 109 + <span 110 + v-if="node.type === 'file' && node.size" 111 + class="text-end text-xs text-fg-subtle" 112 + > 113 + {{ bytesFormatter.format(node.size) }} 114 + </span> 112 115 </span> 113 - </NuxtLink> 116 + </LinkBase> 114 117 </td> 115 118 </tr> 116 119 </tbody>
+11 -14
app/components/Code/FileTree.vue
··· 49 49 <li v-for="node in tree" :key="node.path"> 50 50 <!-- Directory --> 51 51 <template v-if="node.type === 'directory'"> 52 - <button 53 - type="button" 54 - class="w-full flex items-center gap-1.5 py-1.5 px-3 text-start font-mono text-sm transition-colors hover:bg-bg-muted" 55 - :class="isNodeActive(node) ? 'text-fg' : 'text-fg-muted'" 52 + <ButtonBase 53 + class="w-full flex! justify-start! rounded-none! border-none!" 54 + :aria-pressed="isNodeActive(node)" 56 55 :style="{ paddingLeft: `${depth * 12 + 12}px` }" 57 56 @click="toggleDir(node.path)" 57 + :classicon="isExpanded(node.path) ? 'i-carbon:chevron-down' : 'i-carbon:chevron-right'" 58 58 > 59 - <span 60 - class="w-4 h-4 shrink-0 transition-transform" 61 - :class="[isExpanded(node.path) ? 'i-carbon:chevron-down' : 'i-carbon:chevron-right']" 62 - /> 63 59 <span 64 60 class="w-4 h-4 shrink-0" 65 61 :class=" ··· 69 65 " 70 66 /> 71 67 <span class="truncate">{{ node.name }}</span> 72 - </button> 68 + </ButtonBase> 73 69 <CodeFileTree 74 70 v-if="isExpanded(node.path) && node.children" 75 71 :tree="node.children" ··· 82 78 83 79 <!-- File --> 84 80 <template v-else> 85 - <NuxtLink 81 + <LinkBase 82 + variant="button-secondary" 86 83 :to="getFileRoute(node.path)" 87 - class="flex items-center gap-1.5 py-1.5 px-3 font-mono text-sm transition-colors hover:bg-bg-muted" 88 - :class="currentPath === node.path ? 'bg-bg-muted text-fg' : 'text-fg-muted'" 84 + :aria-current="currentPath === node.path" 85 + class="w-full flex! justify-start! rounded-none! border-none!" 89 86 :style="{ paddingLeft: `${depth * 12 + 32}px` }" 87 + :classicon="getFileIcon(node.name)" 90 88 > 91 - <span class="w-4 h-4 shrink-0" :class="getFileIcon(node.name)" /> 92 89 <span class="truncate">{{ node.name }}</span> 93 - </NuxtLink> 90 + </LinkBase> 94 91 </template> 95 92 </li> 96 93 </ul>
+8 -12
app/components/Code/MobileTreeDrawer.vue
··· 27 27 28 28 <template> 29 29 <!-- Toggle button (mobile only) --> 30 - <button 31 - type="button" 32 - class="md:hidden fixed bottom-4 inset-ie-4 z-40 w-12 h-12 bg-bg-elevated border border-border rounded-full shadow-lg flex items-center justify-center text-fg-muted hover:text-fg transition-colors" 30 + <ButtonBase 31 + variant="primary" 32 + class="md:hidden fixed bottom-4 inset-ie-4 z-45" 33 33 :aria-label="$t('code.toggle_tree')" 34 34 @click="isOpen = !isOpen" 35 - > 36 - <span class="w-5 h-5" :class="isOpen ? 'i-carbon:close' : 'i-carbon:folder'" /> 37 - </button> 35 + :classicon="isOpen ? 'i-carbon:close' : 'i-carbon:folder'" 36 + /> 38 37 39 38 <!-- Backdrop --> 40 39 <Transition ··· 66 65 > 67 66 <span class="font-mono text-sm text-fg-muted">{{ $t('code.files_label') }}</span> 68 67 <span aria-hidden="true" class="flex-shrink-1 flex-grow-1" /> 69 - <button 70 - type="button" 71 - class="text-fg-muted hover:text-fg transition-colors" 68 + <ButtonBase 72 69 :aria-label="$t('code.close_tree')" 73 70 @click="isOpen = false" 74 - > 75 - <span class="i-carbon:close w-5 h-5" /> 76 - </button> 71 + classicon="i-carbon-close" 72 + /> 77 73 </div> 78 74 <CodeFileTree 79 75 :tree="tree"
+1
app/components/Code/Viewer.vue
··· 67 67 :style="{ '--line-digits': lineDigits }" 68 68 aria-hidden="true" 69 69 > 70 + <!-- This needs to be a native <a> element, because `LinkBase` (or specifically `NuxtLink`) does not seem to work when trying to prevent default behavior (jumping to the anchor) --> 70 71 <a 71 72 v-for="lineNum in lineNumbers" 72 73 :id="`L${lineNum}`"
+6 -10
app/components/Compare/ComparisonGrid.vue
··· 40 40 <!-- Package columns --> 41 41 <div v-for="col in columns" :key="col.name" class="comparison-cell comparison-cell-header"> 42 42 <span class="inline-flex items-center gap-1.5 truncate"> 43 - <NuxtLink 43 + <LinkBase 44 44 :to="packageRoute(col.name, col.version)" 45 - class="link-subtle font-mono text-sm font-medium text-fg truncate" 45 + class="text-sm flex! truncate" 46 46 :title="col.version ? `${col.name}@${col.version}` : col.name" 47 47 > 48 48 {{ col.name }}<template v-if="col.version">@{{ col.version }}</template> 49 - </NuxtLink> 49 + </LinkBase> 50 50 <TooltipApp v-if="col.replacement" :text="getReplacementTooltip(col)" position="bottom"> 51 51 <span 52 52 class="i-carbon:idea w-3.5 h-3.5 text-amber-500 shrink-0 cursor-help" ··· 79 79 <p class="text-xs text-fg-muted"> 80 80 <i18n-t keypath="compare.no_dependency.tooltip_description" tag="span"> 81 81 <template #link> 82 - <a 83 - href="https://e18e.dev/docs/replacements/" 84 - target="_blank" 85 - rel="noopener noreferrer" 86 - class="text-accent hover:underline" 87 - >{{ $t('compare.no_dependency.e18e_community') }}</a 88 - > 82 + <LinkBase to="https://e18e.dev/docs/replacements/">{{ 83 + $t('compare.no_dependency.e18e_community') 84 + }}</LinkBase> 89 85 </template> 90 86 </i18n-t> 91 87 </p>
+20 -27
app/components/Compare/FacetSelector.vue
··· 32 32 <span class="text-3xs text-fg-subtle uppercase tracking-wider"> 33 33 {{ getCategoryLabel(category) }} 34 34 </span> 35 - <button 36 - type="button" 37 - class="text-3xs transition-colors focus-visible:outline-none focus-visible:underline focus-visible:underline-accent" 38 - :class=" 39 - isCategoryAllSelected(category) 40 - ? 'text-fg-muted' 41 - : 'text-fg-muted/60 hover:text-fg-muted' 42 - " 35 + <!-- TODO: These should be radios, since they are mutually exclusive, and currently this behavior is faked with buttons --> 36 + <ButtonBase 43 37 :aria-label=" 44 38 $t('compare.facets.select_category', { category: getCategoryLabel(category) }) 45 39 " 40 + :aria-pressed="isCategoryAllSelected(category)" 46 41 :disabled="isCategoryAllSelected(category)" 47 42 @click="selectCategory(category)" 43 + size="small" 48 44 > 49 45 {{ $t('compare.facets.all') }} 50 - </button> 46 + </ButtonBase> 51 47 <span class="text-2xs text-fg-muted/40">/</span> 52 - <button 53 - type="button" 54 - class="text-3xs transition-colors focus-visible:outline-none focus-visible:underline focus-visible:underline-accent" 55 - :class=" 56 - isCategoryNoneSelected(category) 57 - ? 'text-fg-muted' 58 - : 'text-fg-muted/60 hover:text-fg-muted' 59 - " 48 + <ButtonBase 60 49 :aria-label=" 61 50 $t('compare.facets.deselect_category', { category: getCategoryLabel(category) }) 62 51 " 52 + :aria-pressed="isCategoryNoneSelected(category)" 63 53 :disabled="isCategoryNoneSelected(category)" 64 54 @click="deselectCategory(category)" 55 + size="small" 65 56 > 66 57 {{ $t('compare.facets.none') }} 67 - </button> 58 + </ButtonBase> 68 59 </div> 69 60 70 61 <!-- Facet buttons --> 71 62 <div class="flex items-center gap-1.5 flex-wrap" role="group"> 72 - <button 63 + <!-- TODO: These should be checkboxes --> 64 + <ButtonBase 73 65 v-for="facet in facetsByCategory[category]" 74 66 :key="facet.id" 75 - type="button" 67 + size="small" 76 68 :title="facet.comingSoon ? $t('compare.facets.coming_soon') : facet.description" 77 69 :disabled="facet.comingSoon" 78 70 :aria-pressed="isFacetSelected(facet.id)" ··· 86 78 : 'text-fg-subtle bg-bg-subtle border-border-subtle hover:text-fg-muted hover:border-border' 87 79 " 88 80 @click="!facet.comingSoon && toggleFacet(facet.id)" 81 + :classicon=" 82 + facet.comingSoon 83 + ? undefined 84 + : isFacetSelected(facet.id) 85 + ? 'i-carbon:checkmark' 86 + : 'i-carbon:add' 87 + " 89 88 > 90 - <span 91 - v-if="!facet.comingSoon" 92 - class="w-3 h-3" 93 - :class="isFacetSelected(facet.id) ? 'i-carbon:checkmark' : 'i-carbon:add'" 94 - aria-hidden="true" 95 - /> 96 89 {{ facet.label }} 97 90 <span v-if="facet.comingSoon" class="text-4xs" 98 91 >({{ $t('compare.facets.coming_soon') }})</span 99 92 > 100 - </button> 93 + </ButtonBase> 101 94 </div> 102 95 </div> 103 96 </div>
+14 -26
app/components/Compare/PackageSelector.vue
··· 103 103 <div class="space-y-3"> 104 104 <!-- Selected packages --> 105 105 <div v-if="packages.length > 0" class="flex flex-wrap gap-2"> 106 - <div 107 - v-for="pkg in packages" 108 - :key="pkg" 109 - class="inline-flex items-center gap-2 px-3 py-1.5 bg-bg-subtle border border-border rounded-md" 110 - > 106 + <TagStatic v-for="pkg in packages" :key="pkg"> 111 107 <!-- No dependency display --> 112 108 <template v-if="pkg === NO_DEPENDENCY_ID"> 113 109 <span class="text-sm text-accent italic flex items-center gap-1.5"> ··· 115 111 {{ $t('compare.no_dependency.label') }} 116 112 </span> 117 113 </template> 118 - <NuxtLink 119 - v-else 120 - :to="packageRoute(pkg)" 121 - class="font-mono text-sm text-fg hover:text-accent transition-colors" 122 - > 114 + <LinkBase v-else :to="packageRoute(pkg)" class="text-sm"> 123 115 {{ pkg }} 124 - </NuxtLink> 125 - <button 126 - type="button" 127 - class="text-fg-subtle hover:text-fg transition-colors rounded" 116 + </LinkBase> 117 + <ButtonBase 118 + size="small" 128 119 :aria-label=" 129 120 $t('compare.selector.remove_package', { 130 121 package: pkg === NO_DEPENDENCY_ID ? $t('compare.no_dependency.label') : pkg, 131 122 }) 132 123 " 133 124 @click="removePackage(pkg)" 134 - > 135 - <span class="i-carbon:close flex items-center w-3.5 h-3.5" aria-hidden="true" /> 136 - </button> 137 - </div> 125 + classicon="i-carbon:close" 126 + /> 127 + </TagStatic> 138 128 </div> 139 129 140 130 <!-- Add package input --> ··· 182 172 class="absolute top-full inset-x-0 mt-1 bg-bg-elevated border border-border rounded-lg shadow-lg z-50 max-h-64 overflow-y-auto" 183 173 > 184 174 <!-- No dependency option (easter egg with James) --> 185 - <button 175 + <ButtonBase 186 176 v-if="showNoDependencyOption" 187 - type="button" 188 - class="w-full text-start px-4 py-2.5 hover:bg-bg-muted transition-colors focus-visible:outline-none focus-visible:bg-bg-muted border-b border-border/50" 177 + class="block w-full text-start" 189 178 :aria-label="$t('compare.no_dependency.add_column')" 190 179 @click="addPackage(NO_DEPENDENCY_ID)" 191 180 > ··· 196 185 <div class="text-xs text-fg-muted truncate mt-0.5"> 197 186 {{ $t('compare.no_dependency.typeahead_description') }} 198 187 </div> 199 - </button> 188 + </ButtonBase> 200 189 201 190 <div v-if="isSearching" class="px-4 py-3 text-sm text-fg-muted"> 202 191 {{ $t('compare.selector.searching') }} 203 192 </div> 204 - <button 193 + <ButtonBase 205 194 v-for="result in filteredResults" 206 195 :key="result.name" 207 - type="button" 208 - class="w-full text-start px-4 py-2.5 hover:bg-bg-muted transition-colors focus-visible:outline-none focus-visible:bg-bg-muted" 196 + class="block w-full text-start" 209 197 @click="addPackage(result.name)" 210 198 > 211 199 <div class="font-mono text-sm text-fg">{{ result.name }}</div> 212 200 <div v-if="result.description" class="text-xs text-fg-muted truncate mt-0.5"> 213 201 {{ result.description }} 214 202 </div> 215 - </button> 203 + </ButtonBase> 216 204 </div> 217 205 </Transition> 218 206 </div>
+5 -13
app/components/Compare/ReplacementSuggestion.vue
··· 63 63 </div> 64 64 65 65 <!-- No dependency action button --> 66 - <button 66 + <ButtonBase 67 67 v-if="variant === 'nodep' && showAction !== false" 68 - type="button" 69 - class="flex-shrink-0 px-2 py-1 text-xs font-medium bg-amber-500/20 hover:bg-amber-500/30 rounded transition-colors" 68 + size="small" 70 69 :aria-label="$t('compare.no_dependency.add_column')" 71 70 @click="emit('addNoDep')" 72 71 > 73 72 {{ $t('package.replacement.consider_no_dep') }} 74 - </button> 73 + </ButtonBase> 75 74 76 75 <!-- Info link --> 77 - <a 78 - v-else-if="docUrl" 79 - :href="docUrl" 80 - target="_blank" 81 - rel="noopener noreferrer" 82 - class="flex-shrink-0 px-2 py-1 text-xs font-medium bg-blue-500/20 hover:bg-blue-500/30 rounded transition-colors inline-flex items-center gap-1" 83 - > 76 + <LinkBase v-else-if="docUrl" :to="docUrl" variant="button-secondary" size="small"> 84 77 {{ $t('package.replacement.learn_more') }} 85 - <span class="i-carbon:launch w-3 h-3" /> 86 - </a> 78 + </LinkBase> 87 79 </div> 88 80 </template>
+22 -22
app/components/Link/Base.vue
··· 5 5 defineProps< 6 6 { 7 7 /** Disabled links will be displayed as plain text */ 8 - 'disabled'?: boolean 8 + disabled?: boolean 9 9 /** 10 10 * `type` should never be used, because this will always be a link. 11 11 * */ 12 - 'type'?: never 13 - 'variant'?: 'button-primary' | 'button-secondary' | 'link' 14 - 'size'?: 'small' | 'medium' 15 - 'iconSize'?: 'sm' | 'md' | 'lg' 16 - 17 - 'keyshortcut'?: string 12 + type?: never 13 + variant?: 'button-primary' | 'button-secondary' | 'link' 14 + size?: 'small' | 'medium' 15 + iconSize?: 'sm' | 'md' | 'lg' 18 16 19 - /** 20 - * Do not use this directly. Use keyshortcut instead; it generates the correct HTML and displays the shortcut in the UI. 21 - */ 22 - 'aria-keyshortcuts'?: never 17 + ariaKeyshortcuts?: string 23 18 24 19 /** 25 20 * Don't use this directly. This will automatically be set to `_blank` for external links passed via `to`. 26 21 */ 27 - 'target'?: never 22 + target?: never 28 23 29 24 /** 30 25 * Don't use this directly. This will automatically be set for external links passed via `to`. 31 26 */ 32 - 'rel'?: never 27 + rel?: never 33 28 34 - 'classicon'?: string 29 + classicon?: string 35 30 36 - 'to'?: NuxtLinkProps['to'] 31 + to?: NuxtLinkProps['to'] 37 32 38 33 /** always use `to` instead of `href` */ 39 - 'href'?: never 34 + href?: never 35 + 36 + /** should only be used for links where the context makes it very clear they are clickable. Don't just use this, because you don't like underlines. */ 37 + noUnderline?: boolean 40 38 } & NuxtLinkProps 41 39 >(), 42 40 { variant: 'link', size: 'medium' }, ··· 86 84 v-else 87 85 class="group/link inline-flex gap-x-1 items-center justify-center" 88 86 :class="{ 89 - 'underline-offset-[0.2rem] underline decoration-1 decoration-fg/30': !isLinkAnchor && isLink, 87 + 'underline-offset-[0.2rem] underline decoration-1 decoration-fg/30': 88 + !isLinkAnchor && isLink && !noUnderline, 90 89 'font-mono text-fg hover:(decoration-accent text-accent) focus-visible:(decoration-accent text-accent) transition-colors duration-200': 91 90 isLink, 92 91 'font-mono border border-border rounded-md transition-all duration-200': isButton, 93 92 'text-sm px-4 py-2': isButtonMedium, 94 93 'text-xs px-2 py-0.5': isButtonSmall, 95 - 'bg-transparent text-fg hover:(bg-fg/10) focus-visible:(bg-fg/10)': 94 + 'bg-transparent text-fg hover:(bg-fg/10 text-accent) focus-visible:(bg-fg/10 text-accent) aria-[current=true]:(bg-fg/10 text-accent border-fg/20 hover:enabled:(bg-fg/20 text-fg/50))': 96 95 variant === 'button-secondary', 97 - 'text-bg bg-fg hover:(bg-fg/50) focus-visible:(bg-fg/50)': variant === 'button-primary', 96 + 'text-bg bg-fg hover:(bg-fg/50 text-accent) focus-visible:(bg-fg/50) aria-current:(bg-fg text-bg border-fg hover:enabled:(text-bg/50))': 97 + variant === 'button-primary', 98 98 }" 99 99 :to="to" 100 - :aria-keyshortcuts="keyshortcut" 100 + :aria-keyshortcuts="ariaKeyshortcuts" 101 101 :target="isLinkExternal ? '_blank' : undefined" 102 102 > 103 103 <span v-if="classicon" class="me-1" :class="[iconSizeClass, classicon]" aria-hidden="true" /> ··· 114 114 aria-hidden="true" 115 115 /> 116 116 <kbd 117 - v-if="keyshortcut" 117 + v-if="ariaKeyshortcuts" 118 118 class="ms-2 inline-flex items-center justify-center w-4 h-4 text-xs text-fg bg-bg-muted border border-border rounded no-underline" 119 119 aria-hidden="true" 120 120 > 121 - {{ keyshortcut }} 121 + {{ ariaKeyshortcuts }} 122 122 </kbd> 123 123 </NuxtLink> 124 124 </template>
+8 -10
app/pages/compare.vue
··· 168 168 <h2 id="facets-heading" class="text-xs text-fg-subtle uppercase tracking-wider"> 169 169 {{ $t('compare.packages.section_facets') }} 170 170 </h2> 171 - <button 172 - type="button" 173 - class="text-3xs transition-colors focus-visible:outline-none focus-visible:underline focus-visible:underline-accent" 174 - :class="isAllSelected ? 'text-fg-muted' : 'text-fg-muted/60 hover:text-fg-muted'" 171 + <ButtonBase 172 + size="small" 173 + :aria-pressed="isAllSelected" 175 174 :disabled="isAllSelected" 176 175 :aria-label="$t('compare.facets.select_all')" 177 176 @click="selectAll" 178 177 > 179 178 {{ $t('compare.facets.all') }} 180 - </button> 179 + </ButtonBase> 181 180 <span class="text-3xs text-fg-muted/40" aria-hidden="true">/</span> 182 - <button 183 - type="button" 184 - class="text-3xs transition-colors focus-visible:outline-none focus-visible:underline focus-visible:underline-accent" 185 - :class="isNoneSelected ? 'text-fg-muted' : 'text-fg-muted/60 hover:text-fg-muted'" 181 + <ButtonBase 182 + size="small" 183 + :aria-pressed="isNoneSelected" 186 184 :disabled="isNoneSelected" 187 185 :aria-label="$t('compare.facets.deselect_all')" 188 186 @click="deselectAll" 189 187 > 190 188 {{ $t('compare.facets.none') }} 191 - </button> 189 + </ButtonBase> 192 190 </div> 193 191 <CompareFacetSelector /> 194 192 </section>
+3 -3
app/pages/package/[[org]]/[name].vue
··· 618 618 variant="button-secondary" 619 619 v-if="docsLink" 620 620 :to="docsLink" 621 - keyshortcut="d" 621 + aria-keyshortcuts="d" 622 622 classicon="i-carbon:document" 623 623 > 624 624 {{ $t('package.links.docs') }} ··· 626 626 <LinkBase 627 627 variant="button-secondary" 628 628 :to="{ name: 'code', params: { path: [pkg.name, 'v', resolvedVersion] } }" 629 - keyshortcut="." 629 + aria-keyshortcuts="." 630 630 classicon="i-carbon:code" 631 631 > 632 632 {{ $t('package.links.code') }} ··· 634 634 <LinkBase 635 635 variant="button-secondary" 636 636 :to="{ name: 'compare', query: { packages: pkg.name } }" 637 - keyshortcut="c" 637 + aria-keyshortcuts="c" 638 638 classicon="i-carbon:compare" 639 639 > 640 640 {{ $t('package.links.compare') }}