-
-
Notifications
You must be signed in to change notification settings - Fork 424
refactor(a11y): use <dialog> tag for modal components
#522
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
14cfdfb
2515f33
bcee3c3
219e454
09fd230
fde38d0
6cad49e
0b542da
8986ea1
9504599
46b32bb
2204fd3
4d12eb1
a6ccf6a
906ec24
c7fbab0
f599c4b
8f45120
565c6da
62515f5
5e67d2d
d303dd1
4295395
8b84f93
8f56e14
4fcecdf
3bdff82
4066568
652a076
118ff4b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -233,3 +233,9 @@ input[type='search']::-webkit-search-results-decoration { | |
| animation-duration: 0.3s; | ||
| animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1); | ||
| } | ||
|
|
||
| /* Locking the scroll whenever any of the modals are open */ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This works reliably to scroll lock including Safari macOS and iOS: html:has(dialog:modal),
html:has(dialog:modal) body {
overflow: hidden;
height: 100%;
}
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm no difference on my end Screen.Recording.2026-01-31.at.11.29.23.PM.mov
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I seemed to have a cached version on my iPhone—seems to work fine on the preview.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, it seems to be inconsistent. Like the first time you open it, it’s fine, but then you do something else and open it again and suddenly the scroll isn’t locked. In any case, that seems like an edge case and I think we can ignore.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removing the explicit scrollbar width seemed to do it, wonder if there's a way to keep it and have no shift |
||
| html:has(dialog:modal) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Related to the effect of this: when the modal opens the scrollbar for the page disappears which causes a bit of a shift. It might be worth adding
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah right, good call
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very odd, it seems like Firefox is working exactly as expected, but I’m not seeing it work in Safari or Chrome.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh weird, I'm seeing it work in Firefox and Chrome but not Safari.. 🤔 |
||
| overflow: hidden; | ||
| scrollbar-gutter: stable; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| <script setup lang="ts"> | ||
| const handleInput = shallowRef('') | ||
|
|
||
| const { user, logout } = useAtproto() | ||
|
|
||
| async function handleBlueskySignIn() { | ||
| await navigateTo( | ||
| { | ||
| path: '/api/auth/atproto', | ||
| query: { handle: 'https://bsky.social' }, | ||
| }, | ||
| { external: true }, | ||
| ) | ||
| } | ||
|
|
||
| async function handleCreateAccount() { | ||
| await navigateTo( | ||
| { | ||
| path: '/api/auth/atproto', | ||
| query: { handle: 'https://npmx.social', create: 'true' }, | ||
| }, | ||
| { external: true }, | ||
| ) | ||
| } | ||
|
|
||
| async function handleLogin() { | ||
| if (handleInput.value) { | ||
| await navigateTo( | ||
| { | ||
| path: '/api/auth/atproto', | ||
| query: { handle: handleInput.value }, | ||
| }, | ||
| { external: true }, | ||
| ) | ||
| } | ||
| } | ||
| </script> | ||
|
|
||
| <template> | ||
| <!-- Modal --> | ||
| <Modal :modalTitle="$t('auth.modal.title')" class="max-w-lg" id="auth-modal"> | ||
| <div v-if="user?.handle" class="space-y-4"> | ||
| <div class="flex items-center gap-3 p-4 bg-bg-subtle border border-border rounded-lg"> | ||
| <span class="w-3 h-3 rounded-full bg-green-500" aria-hidden="true" /> | ||
| <div> | ||
| <p class="font-mono text-xs text-fg-muted"> | ||
| {{ $t('auth.modal.connected_as', { handle: user.handle }) }} | ||
| </p> | ||
| </div> | ||
| </div> | ||
| <button | ||
| 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" | ||
| @click="logout" | ||
| > | ||
| {{ $t('auth.modal.disconnect') }} | ||
| </button> | ||
| </div> | ||
|
|
||
| <!-- Disconnected state --> | ||
| <form v-else class="space-y-4" @submit.prevent="handleLogin"> | ||
| <p class="text-sm text-fg-muted">{{ $t('auth.modal.connect_prompt') }}</p> | ||
|
|
||
| <div class="space-y-3"> | ||
| <div> | ||
| <label | ||
| for="handle-input" | ||
| class="block text-xs text-fg-subtle uppercase tracking-wider mb-1.5" | ||
| > | ||
| {{ $t('auth.modal.handle_label') }} | ||
| </label> | ||
| <input | ||
| id="handle-input" | ||
| v-model="handleInput" | ||
| type="text" | ||
| name="handle" | ||
| :placeholder="$t('auth.modal.handle_placeholder')" | ||
| autocomplete="off" | ||
| spellcheck="false" | ||
| 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" | ||
| /> | ||
| </div> | ||
|
|
||
| <details class="text-sm"> | ||
| <summary | ||
| class="text-fg-subtle cursor-pointer hover:text-fg-muted transition-colors duration-200" | ||
| > | ||
| {{ $t('auth.modal.what_is_atmosphere') }} | ||
| </summary> | ||
| <div class="mt-3"> | ||
| <i18n-t keypath="auth.modal.atmosphere_explanation" tag="p"> | ||
| <template #npmx> | ||
| <span class="font-bold">npmx.dev</span> | ||
| </template> | ||
| <template #atproto> | ||
| <a href="https://atproto.com" target="_blank" class="text-blue-400 hover:underline"> | ||
| AT Protocol | ||
| </a> | ||
| </template> | ||
| <template #bluesky> | ||
| <a href="https://bsky.app" target="_blank" class="text-blue-400 hover:underline"> | ||
| Bluesky | ||
| </a> | ||
| </template> | ||
| <template #tangled> | ||
| <a href="https://tangled.org" target="_blank" class="text-blue-400 hover:underline"> | ||
| Tangled | ||
| </a> | ||
| </template> | ||
| </i18n-t> | ||
| </div> | ||
| </details> | ||
| </div> | ||
|
|
||
| <button | ||
| type="submit" | ||
| :disabled="!handleInput.trim()" | ||
| 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" | ||
| > | ||
| {{ $t('auth.modal.connect') }} | ||
| </button> | ||
| <button | ||
| type="button" | ||
| 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" | ||
| @click="handleCreateAccount" | ||
| > | ||
| {{ $t('auth.modal.create_account') }} | ||
| </button> | ||
| <hr /> | ||
| <button | ||
| type="button" | ||
| 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" | ||
| @click="handleBlueskySignIn" | ||
| > | ||
| {{ $t('auth.modal.connect_bluesky') }} | ||
| <svg fill="none" viewBox="0 0 64 57" width="20" style="width: 20px"> | ||
| <path | ||
| fill="#0F73FF" | ||
| d="M13.873 3.805C21.21 9.332 29.103 20.537 32 26.55v15.882c0-.338-.13.044-.41.867-1.512 4.456-7.418 21.847-20.923 7.944-7.111-7.32-3.819-14.64 9.125-16.85-7.405 1.264-15.73-.825-18.014-9.015C1.12 23.022 0 8.51 0 6.55 0-3.268 8.579-.182 13.873 3.805ZM50.127 3.805C42.79 9.332 34.897 20.537 32 26.55v15.882c0-.338.13.044.41.867 1.512 4.456 7.418 21.847 20.923 7.944 7.111-7.32 3.819-14.64-9.125-16.85 7.405 1.264 15.73-.825 18.014-9.015C62.88 23.022 64 8.51 64 6.55c0-9.818-8.578-6.732-13.873-2.745Z" | ||
| ></path> | ||
| </svg> | ||
| </button> | ||
| </form> | ||
| </Modal> | ||
| </template> |
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.