Skip to content

Commit ac1171a

Browse files
jellydeckdanielroe
andauthored
feat: accessible rings, accent colors & visual changes (#904)
Co-authored-by: Daniel Roe <daniel@roe.dev>
1 parent 3b7c027 commit ac1171a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+356
-271
lines changed

app/assets/main.css

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,9 @@ a:hover {
196196
}
197197

198198
a:focus-visible {
199-
outline: 2px solid var(--border);
199+
outline: 2px solid var(--accent);
200200
outline-offset: 2px;
201-
border-radius: 2px;
201+
border-radius: 4px;
202202
}
203203

204204
/* Reset dd margin (browser default is margin-left: 40px) */
@@ -215,6 +215,13 @@ button {
215215
padding: 0;
216216
}
217217

218+
button:focus-visible,
219+
select:focus-visible {
220+
outline: 2px solid var(--accent);
221+
outline-offset: 2px;
222+
border-radius: 4px;
223+
}
224+
218225
/* Selection */
219226
::selection {
220227
background-color: var(--fg-muted);

app/components/AppFooter.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ const isHome = computed(() => route.name === 'index')
1515
</div>
1616
<!-- Desktop: Show all links. Mobile: Links are in MobileMenu -->
1717
<div class="hidden sm:flex items-center gap-6">
18-
<NuxtLink to="/about" class="link-subtle font-mono text-xs min-h-11 flex items-center">
18+
<NuxtLink to="/about" class="link-subtle font-mono text-xs flex items-center">
1919
{{ $t('footer.about') }}
2020
</NuxtLink>
2121
<a
2222
href="https://docs.npmx.dev"
2323
target="_blank"
2424
rel="noopener noreferrer"
25-
class="link-subtle font-mono text-xs min-h-11 flex items-center gap-1"
25+
class="link-subtle font-mono text-xs flex items-center gap-1"
2626
>
2727
{{ $t('footer.docs') }}
2828
<span class="i-carbon:launch rtl-flip w-3 h-3" aria-hidden="true" />
@@ -31,7 +31,7 @@ const isHome = computed(() => route.name === 'index')
3131
href="https://repo.npmx.dev"
3232
target="_blank"
3333
rel="noopener noreferrer"
34-
class="link-subtle font-mono text-xs min-h-11 flex items-center gap-1"
34+
class="link-subtle font-mono text-xs flex items-center gap-1"
3535
>
3636
{{ $t('footer.source') }}
3737
<span class="i-carbon:launch rtl-flip w-3 h-3" aria-hidden="true" />
@@ -40,7 +40,7 @@ const isHome = computed(() => route.name === 'index')
4040
href="https://social.npmx.dev"
4141
target="_blank"
4242
rel="noopener noreferrer"
43-
class="link-subtle font-mono text-xs min-h-11 flex items-center gap-1"
43+
class="link-subtle font-mono text-xs flex items-center gap-1"
4444
>
4545
{{ $t('footer.social') }}
4646
<span class="i-carbon:launch rtl-flip w-3 h-3" aria-hidden="true" />
@@ -49,7 +49,7 @@ const isHome = computed(() => route.name === 'index')
4949
href="https://chat.npmx.dev"
5050
target="_blank"
5151
rel="noopener noreferrer"
52-
class="link-subtle font-mono text-xs min-h-11 flex items-center gap-1"
52+
class="link-subtle font-mono text-xs flex items-center gap-1"
5353
>
5454
{{ $t('footer.chat') }}
5555
<span class="i-carbon:launch rtl-flip w-3 h-3" aria-hidden="true" />

app/components/AppHeader.vue

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -95,18 +95,11 @@ onKeyStroke(
9595
<button
9696
v-if="!isSearchExpanded && !isOnHomePage"
9797
type="button"
98-
class="sm:hidden flex-shrink-0 inline-flex items-center gap-2 font-mono text-lg font-medium text-fg hover:text-fg transition-colors duration-200 focus-ring rounded"
98+
class="sm:hidden flex-shrink-0 inline-flex items-center gap-2 font-mono text-lg font-medium text-fg hover:text-fg transition-colors duration-200 rounded"
9999
:aria-label="$t('nav.tap_to_search')"
100100
@click="expandMobileSearch"
101101
>
102-
<img
103-
aria-hidden="true"
104-
:alt="$t('alt_logo')"
105-
src="/logo.svg"
106-
width="96"
107-
height="96"
108-
class="w-8 h-8 rounded-lg"
109-
/>
102+
<AppLogo class="w-8 h-8 rounded-lg" />
110103
<span class="i-carbon:search w-4 h-4 text-fg-subtle" aria-hidden="true" />
111104
</button>
112105

@@ -116,16 +109,9 @@ onKeyStroke(
116109
to="/"
117110
:aria-label="$t('header.home')"
118111
dir="ltr"
119-
class="inline-flex items-center gap-2 header-logo font-mono text-lg font-medium text-fg hover:text-fg transition-colors duration-200 focus-ring rounded"
112+
class="inline-flex items-center gap-2 header-logo font-mono text-lg font-medium text-fg hover:text-fg transition-colors duration-200 rounded"
120113
>
121-
<img
122-
aria-hidden="true"
123-
:alt="$t('alt_logo')"
124-
src="/logo.svg"
125-
width="96"
126-
height="96"
127-
class="w-8 h-8 rounded-lg"
128-
/>
114+
<AppLogo class="w-8 h-8 rounded-lg" />
129115
<span>npmx</span>
130116
</NuxtLink>
131117
</div>
@@ -163,11 +149,11 @@ onKeyStroke(
163149
</div>
164150

165151
<!-- End: Desktop nav items + Mobile menu button -->
166-
<div class="flex-shrink-0 flex items-center gap-4 sm:gap-6">
152+
<div class="flex-shrink-0 flex items-center gap-0.5 sm:gap-2">
167153
<!-- Desktop: Compare link -->
168154
<NuxtLink
169155
to="/compare"
170-
class="hidden sm:inline-flex link-subtle font-mono text-sm items-center gap-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/50 rounded"
156+
class="hidden sm:inline-flex link-subtle font-mono text-sm items-center gap-2 px-2 py-1.5 hover:bg-bg-subtle focus-visible:outline-accent/70 rounded"
171157
aria-keyshortcuts="c"
172158
>
173159
{{ $t('nav.compare') }}
@@ -182,7 +168,7 @@ onKeyStroke(
182168
<!-- Desktop: Settings link -->
183169
<NuxtLink
184170
to="/settings"
185-
class="hidden sm:inline-flex link-subtle font-mono text-sm items-center gap-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/50 rounded"
171+
class="hidden sm:inline-flex link-subtle font-mono text-sm items-center gap-2 px-2 py-1.5 hover:bg-bg-subtle focus-visible:outline-accent/70 rounded"
186172
aria-keyshortcuts=","
187173
>
188174
{{ $t('nav.settings') }}
@@ -202,7 +188,7 @@ onKeyStroke(
202188
<!-- Mobile: Menu button (always visible, toggles menu) -->
203189
<button
204190
type="button"
205-
class="sm:hidden flex items-center p-2 -m-2 text-fg-subtle hover:text-fg transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/50 rounded"
191+
class="sm:hidden flex items-center p-2 -m-2 text-fg-subtle hover:text-fg transition-colors duration-200 focus-visible:outline-accent/70 rounded"
206192
:aria-label="showMobileMenu ? $t('common.close') : $t('nav.open_menu')"
207193
:aria-expanded="showMobileMenu"
208194
@click="showMobileMenu = !showMobileMenu"

app/components/AppLogo.vue

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<script setup lang="ts">
2+
defineProps<{
3+
class?: string
4+
}>()
5+
</script>
6+
7+
<template>
8+
<svg
9+
aria-hidden="true"
10+
xmlns="http://www.w3.org/2000/svg"
11+
viewBox="0 0 512 512"
12+
width="96"
13+
height="96"
14+
:class="class"
15+
>
16+
<title>{{ $t('alt_logo') }}</title>
17+
<rect fill="var(--bg)" width="512" height="512" rx="64" />
18+
<rect fill="var(--fg)" x="110" y="310" width="60" height="60" />
19+
<text
20+
fill="var(--accent)"
21+
x="320"
22+
y="370"
23+
font-family="'Geist Mono',ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace"
24+
font-size="420"
25+
font-weight="500"
26+
text-anchor="middle"
27+
>
28+
<tspan>/</tspan>
29+
</text>
30+
</svg>
31+
</template>

app/components/CollapsibleSection.vue

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ useHead({
7676

7777
<template>
7878
<section class="scroll-mt-20" :data-anchor-id="id">
79-
<div class="flex items-center justify-between mb-3">
79+
<div class="flex items-center justify-between mb-3 px-1">
8080
<component
8181
:is="headingLevel"
8282
:id="headingId"
@@ -85,7 +85,7 @@ useHead({
8585
<button
8686
:id="buttonId"
8787
type="button"
88-
class="w-4 h-4 flex items-center justify-center text-fg-subtle hover:text-fg-muted transition-colors duration-200 shrink-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50 rounded"
88+
class="w-4 h-4 flex items-center justify-center text-fg-subtle hover:text-fg-muted transition-colors duration-200 shrink-0 focus-visible:outline-accent/70 rounded"
8989
:aria-expanded="isOpen"
9090
:aria-controls="contentId"
9191
:aria-label="ariaLabel"
@@ -118,14 +118,17 @@ useHead({
118118
</component>
119119

120120
<!-- Actions slot for buttons or other elements -->
121-
<slot name="actions" />
121+
<div class="pe-1">
122+
<slot name="actions" />
123+
</div>
122124
</div>
123125

124126
<div
125127
:id="contentId"
126128
class="grid ms-6 transition-[grid-template-rows] duration-200 ease-in-out collapsible-content overflow-hidden"
129+
:inert="!isOpen"
127130
>
128-
<div class="min-h-0 min-w-0">
131+
<div class="min-h-0 min-w-0 p-1">
129132
<slot />
130133
</div>
131134
</div>

app/components/Compare/FacetSelector.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ function isCategoryNoneSelected(category: string): boolean {
3434
</span>
3535
<button
3636
type="button"
37-
class="text-[10px] transition-colors focus-visible:outline-none focus-visible:underline"
37+
class="text-[10px] transition-colors focus-visible:outline-none focus-visible:underline focus-visible:underline-accent"
3838
:class="
3939
isCategoryAllSelected(category)
4040
? 'text-fg-muted'
@@ -51,7 +51,7 @@ function isCategoryNoneSelected(category: string): boolean {
5151
<span class="text-[10px] text-fg-muted/40">/</span>
5252
<button
5353
type="button"
54-
class="text-[10px] transition-colors focus-visible:outline-none focus-visible:underline"
54+
class="text-[10px] transition-colors focus-visible:outline-none focus-visible:underline focus-visible:underline-accent"
5555
:class="
5656
isCategoryNoneSelected(category)
5757
? 'text-fg-muted'
@@ -77,7 +77,7 @@ function isCategoryNoneSelected(category: string): boolean {
7777
:disabled="facet.comingSoon"
7878
:aria-pressed="isFacetSelected(facet.id)"
7979
:aria-label="facet.label"
80-
class="inline-flex items-center gap-1 px-1.5 py-0.5 font-mono text-xs rounded border transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50"
80+
class="inline-flex items-center gap-1 px-1.5 py-0.5 font-mono text-xs rounded border transition-colors duration-200 focus-visible:outline-accent/70"
8181
:class="
8282
facet.comingSoon
8383
? 'text-fg-subtle/50 bg-bg-subtle border-border-subtle cursor-not-allowed'

app/components/Compare/PackageSelector.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ function handleBlur() {
7171
</NuxtLink>
7272
<button
7373
type="button"
74-
class="text-fg-subtle hover:text-fg transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/50 rounded"
74+
class="text-fg-subtle hover:text-fg transition-colors focus-visible:outline-accent/70 rounded"
7575
:aria-label="$t('compare.selector.remove_package', { package: pkg })"
7676
@click="removePackage(pkg)"
7777
>
@@ -82,12 +82,12 @@ function handleBlur() {
8282

8383
<!-- Add package input -->
8484
<div v-if="packages.length < maxPackages" class="relative">
85-
<div class="relative">
85+
<div class="relative group">
8686
<label for="package-search" class="sr-only">
8787
{{ $t('compare.selector.search_label') }}
8888
</label>
8989
<span
90-
class="absolute inset-is-3 top-1/2 -translate-y-1/2 text-fg-subtle flex"
90+
class="absolute inset-y-0 start-3 flex items-center text-fg-subtle pointer-events-none group-focus-within:text-accent"
9191
aria-hidden="true"
9292
>
9393
<span class="i-carbon:search w-4 h-4" />
@@ -101,7 +101,7 @@ function handleBlur() {
101101
? $t('compare.selector.search_first')
102102
: $t('compare.selector.search_add')
103103
"
104-
class="w-full bg-bg-subtle border border-border rounded-lg ps-10 pe-4 py-2.5 font-mono text-sm text-fg placeholder:text-fg-subtle transition-colors duration-200 focus:border-accent focus-visible:outline-none"
104+
class="w-full bg-bg-subtle border border-border rounded-lg ps-10 pe-4 py-2.5 font-mono text-sm text-fg placeholder:text-fg-subtle motion-reduce:transition-none duration-200 focus:border-accent focus-visible:(outline-2 outline-accent/70)"
105105
aria-autocomplete="list"
106106
@focus="isInputFocused = true"
107107
@blur="handleBlur"

app/components/Header/AccountMenu.client.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ function openAuthModal() {
5959
<div ref="accountMenuRef" class="relative flex min-w-24 justify-end">
6060
<button
6161
type="button"
62-
class="relative flex items-center gap-2 px-2 py-1.5 rounded-md transition-colors duration-200 hover:bg-bg-subtle focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50"
62+
class="relative flex items-center gap-2 px-2 py-1.5 rounded-md transition-colors duration-200 hover:bg-bg-subtle hover:text-accent focus-visible:outline-accent/70"
6363
:aria-expanded="isOpen"
6464
aria-haspopup="true"
6565
@click="isOpen = !isOpen"

app/components/Header/AuthModal.client.vue

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ async function handleLogin() {
3434
</div>
3535
</div>
3636
<button
37-
class="w-full px-4 py-2 font-mono text-sm text-fg-muted bg-bg-subtle border border-border rounded-md transition-colors duration-200 hover:text-fg hover:border-border-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50"
37+
class="w-full px-4 py-2 font-mono text-sm text-fg-muted bg-bg-subtle border border-border rounded-md transition-colors duration-200 hover:text-fg hover:border-border-hover focus-visible:outline-accent/70"
3838
@click="logout"
3939
>
4040
{{ $t('auth.modal.disconnect') }}
@@ -61,13 +61,13 @@ async function handleLogin() {
6161
:placeholder="$t('auth.modal.handle_placeholder')"
6262
autocomplete="off"
6363
spellcheck="false"
64-
class="w-full px-3 py-2 font-mono text-sm bg-bg-subtle border border-border rounded-md text-fg placeholder:text-fg-subtle transition-colors duration-200 focus:border-border-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50"
64+
class="w-full px-3 py-2 font-mono text-sm bg-bg-subtle border border-border rounded-md text-fg placeholder:text-fg-subtle transition-colors duration-200 focus:border-accent focus-visible:(outline-2 outline-accent/70)"
6565
/>
6666
</div>
6767

6868
<details class="text-sm">
6969
<summary
70-
class="text-fg-subtle cursor-pointer hover:text-fg-muted transition-colors duration-200"
70+
class="text-fg-subtle cursor-pointer hover:text-fg-muted transition-colors duration-200 focus-visible:(outline-2 outline-accent/70)"
7171
>
7272
{{ $t('auth.modal.what_is_atmosphere') }}
7373
</summary>
@@ -99,21 +99,21 @@ async function handleLogin() {
9999
<button
100100
type="submit"
101101
:disabled="!handleInput.trim()"
102-
class="w-full px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md transition-all duration-200 hover:bg-fg/90 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50 focus-visible:ring-offset-2 focus-visible:ring-offset-bg"
102+
class="w-full px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md transition-all duration-200 hover:bg-fg/90 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-accent/70 focus-visible:ring-offset-2 focus-visible:ring-offset-bg"
103103
>
104104
{{ $t('auth.modal.connect') }}
105105
</button>
106106
<button
107107
type="button"
108-
class="w-full px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md transition-all duration-200 hover:bg-fg/90 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50 focus-visible:ring-offset-2 focus-visible:ring-offset-bg"
108+
class="w-full px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md transition-all duration-200 hover:bg-fg/90 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-accent/70 focus-visible:ring-offset-2 focus-visible:ring-offset-bg"
109109
@click="handleCreateAccount"
110110
>
111111
{{ $t('auth.modal.create_account') }}
112112
</button>
113-
<hr />
113+
<hr class="color-border" />
114114
<button
115115
type="button"
116-
class="w-full px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md transition-all duration-200 hover:bg-fg/90 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50 focus-visible:ring-offset-2 focus-visible:ring-offset-bg flex items-center justify-center gap-2"
116+
class="w-full px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md transition-all duration-200 hover:bg-fg/90 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-accent/70 focus-visible:ring-offset-2 focus-visible:ring-offset-bg flex items-center justify-center gap-2"
117117
@click="handleBlueskySignIn"
118118
>
119119
{{ $t('auth.modal.connect_bluesky') }}

0 commit comments

Comments
 (0)