diff --git a/src/frontend/package.json b/src/frontend/package.json index 0e363f1f..19a168b2 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -56,7 +56,7 @@ "mermaid": "^11.12.1", "remark-directive": "^4.0.0", "sharp": "^0.34.5", - "starlight-contributor-list": "^0.3.1", + "starlight-contributor-list": "^0.3.2", "starlight-github-alerts": "^0.1.1", "starlight-image-zoom": "^0.13.2", "starlight-kbd": "^0.3.0", diff --git a/src/frontend/pnpm-lock.yaml b/src/frontend/pnpm-lock.yaml index 66384135..1bace087 100644 --- a/src/frontend/pnpm-lock.yaml +++ b/src/frontend/pnpm-lock.yaml @@ -78,8 +78,8 @@ importers: specifier: ^0.34.5 version: 0.34.5 starlight-contributor-list: - specifier: ^0.3.1 - version: 0.3.1(@astrojs/starlight@0.37.0(astro@5.16.4(@types/node@24.10.1)(jiti@1.21.7)(rollup@4.53.3)(typescript@5.9.3))) + specifier: ^0.3.2 + version: 0.3.2(@astrojs/starlight@0.37.0(astro@5.16.4(@types/node@24.10.1)(jiti@1.21.7)(rollup@4.53.3)(typescript@5.9.3))) starlight-github-alerts: specifier: ^0.1.1 version: 0.1.1(@astrojs/starlight@0.37.0(astro@5.16.4(@types/node@24.10.1)(jiti@1.21.7)(rollup@4.53.3)(typescript@5.9.3))) @@ -2928,8 +2928,8 @@ packages: space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} - starlight-contributor-list@0.3.1: - resolution: {integrity: sha512-8F3BcnqeCgvI/OcagJCBsp71/XU9/zDiuSmsgAkWrRTxql0H2bG9Z9VXvmwzB/569QVlAsOwK7StAxDxqG6Myw==} + starlight-contributor-list@0.3.2: + resolution: {integrity: sha512-8O01uabPxfrFHarmlAJrcM4Wy4Uy4z/Y7vpaO0Da0ihTizPVYhnU8wNtSg0H5CeyPMGjNNOnPFcLiz1c0Obn4A==} engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0} peerDependencies: '@astrojs/starlight': '>=0.30' @@ -6968,7 +6968,7 @@ snapshots: space-separated-tokens@2.0.2: {} - starlight-contributor-list@0.3.1(@astrojs/starlight@0.37.0(astro@5.16.4(@types/node@24.10.1)(jiti@1.21.7)(rollup@4.53.3)(typescript@5.9.3))): + starlight-contributor-list@0.3.2(@astrojs/starlight@0.37.0(astro@5.16.4(@types/node@24.10.1)(jiti@1.21.7)(rollup@4.53.3)(typescript@5.9.3))): dependencies: '@11ty/eleventy-fetch': 4.0.1 '@astrojs/starlight': 0.37.0(astro@5.16.4(@types/node@24.10.1)(jiti@1.21.7)(rollup@4.53.3)(typescript@5.9.3)) diff --git a/src/frontend/src/components/IconLinkCard.astro b/src/frontend/src/components/IconLinkCard.astro index 3d0776e5..9f0a6e35 100644 --- a/src/frontend/src/components/IconLinkCard.astro +++ b/src/frontend/src/components/IconLinkCard.astro @@ -82,6 +82,7 @@ const isImageIcon = !isStringIcon && icon && typeof icon === 'object'; position: absolute; inset: 0; } + .sl-link-card .title { display: flex; align-items: center; @@ -131,6 +132,16 @@ const isImageIcon = !isStringIcon && icon && typeof icon === 'object'; border-color: var(--sl-color-gray-2); } + .sl-link-card:focus-within { + outline: 0.15rem solid; + outline-offset: 0.15rem; + } + + .sl-link-card a:focus, + .sl-link-card a:focus-visible { + outline: none; + } + .sl-link-card:hover .icon { color: var(--sl-color-white); } diff --git a/src/frontend/src/components/IntegrationGrid.astro b/src/frontend/src/components/IntegrationGrid.astro index 89fe8038..949a359a 100644 --- a/src/frontend/src/components/IntegrationGrid.astro +++ b/src/frontend/src/components/IntegrationGrid.astro @@ -1,5 +1,7 @@ --- import { Image } from 'astro:assets'; +import PauseIcon from '@assets/icons/pause.svg'; +import PlayIcon from '@assets/icons/play.svg'; import adminerIcon from '@assets/icons/adminer-icon.png'; import activeMqIcon from '@assets/icons/activemq-icon.png'; @@ -274,7 +276,7 @@ const infiniteIconsRow2 = [...row2, ...row2]; const infiniteIconsRow3 = [...row3, ...row3]; --- -
+
@@ -355,8 +357,107 @@ const infiniteIconsRow3 = [...row3, ...row3]; }
+
+ +
+ + diff --git a/src/frontend/src/components/LoopingVideo.astro b/src/frontend/src/components/LoopingVideo.astro index 9796efc2..43b0d05d 100644 --- a/src/frontend/src/components/LoopingVideo.astro +++ b/src/frontend/src/components/LoopingVideo.astro @@ -29,6 +29,7 @@ const uid = globalThis.crypto?.randomUUID?.() ?? Math.random().toString(36).slic loop muted playsinline + tabindex="0" {controls} title={title} data-sources={sourcesJson} @@ -160,6 +161,29 @@ const uid = globalThis.crypto?.randomUUID?.() ?? Math.random().toString(36).slic video.addEventListener('click', togglePlayback); } + // Keyboard accessibility: toggle playback on Enter/Space when video is focused + video.addEventListener('keydown', (e) => { + if (e.key === ' ' || e.key === 'Enter') { + e.preventDefault(); + togglePlayback(); + } + }); + + // Show native controls when video receives keyboard focus (for a11y) + const hasExplicitControls = video.hasAttribute('controls'); + video.addEventListener('focus', (e) => { + // Only show controls if focus came from keyboard (not mouse click) + if (e.target === video && !video.matches(':hover')) { + video.setAttribute('controls', ''); + } + }); + video.addEventListener('blur', () => { + // Restore original controls state when focus leaves + if (!hasExplicitControls) { + video.removeAttribute('controls'); + } + }); + video.addEventListener('play', syncButton); video.addEventListener('pause', syncButton); syncButton(); @@ -254,6 +278,18 @@ const uid = globalThis.crypto?.randomUUID?.() ?? Math.random().toString(36).slic } } + /* Show controls when video or toggle button is keyboard focused */ + .looping-video-wrapper:focus-within .looping-video-toggle { + opacity: 1; + pointer-events: auto; + } + + /* Visual focus indicator on the video itself */ + video.looping-video:focus-visible { + outline: 2px solid var(--aspire-color-primary, #6d4aff); + outline-offset: 2px; + } + /* Mobile / touch: smaller, only when force-visible (after interaction) */ @media (hover: none) { .looping-video-toggle { diff --git a/src/frontend/src/components/starlight/Header.astro b/src/frontend/src/components/starlight/Header.astro index 6ed86d5d..3443450b 100644 --- a/src/frontend/src/components/starlight/Header.astro +++ b/src/frontend/src/components/starlight/Header.astro @@ -147,13 +147,19 @@ import { isHomepage } from "@utils/helpers"; gap: 1rem; align-items: center; } - + .social-icons::after { content: ""; height: 2rem; border-inline-end: 1px solid var(--sl-color-gray-5); } + @media (max-width: 1200px) { + :global(.social-icons) { + display: none !important; + } + } + @media (min-width: 50rem) { :global(:root[data-has-sidebar]) { --__sidebar-pad: calc(2 * var(--sl-nav-pad-x)); diff --git a/src/frontend/src/components/starlight/SocialIcons.astro b/src/frontend/src/components/starlight/SocialIcons.astro index 44535815..4fe64569 100644 --- a/src/frontend/src/components/starlight/SocialIcons.astro +++ b/src/frontend/src/components/starlight/SocialIcons.astro @@ -5,7 +5,7 @@ import InstallCliModal from '@components/InstallCliModal.astro'; import CookiesSvg from '@assets/icons/cookies.svg'; --- -
+
- RSS Feed + RSS Feed
@@ -46,35 +46,29 @@ import CookiesSvg from '@assets/icons/cookies.svg'; diff --git a/src/frontend/src/styles/site.css b/src/frontend/src/styles/site.css index 7586155e..71b0c125 100644 --- a/src/frontend/src/styles/site.css +++ b/src/frontend/src/styles/site.css @@ -454,6 +454,24 @@ figure.frame { min-height: 1rem; } +a:focus-visible, +button:focus-visible, +input:focus-visible, +select:focus-visible, +textarea:focus-visible { + outline-color: black !important; +} + +:root[data-theme='dark'] { + a:focus-visible, + button:focus-visible, + input:focus-visible, + select:focus-visible, + textarea:focus-visible { + outline-color: white !important; + } +} + @media (max-width: 72rem) { .expressive-code .copy button:not([data-disable-copy]) { width: 2rem; @@ -668,6 +686,12 @@ figure.frame { background: initial; } +site-search svg, +.social-icons svg, +.starlight-sidebar-topics-icon svg { + --sl-icon-size: 1.25rem !important; +} + .card-grid .card .icon { width: 2rem; height: 2rem;