Skip to content

Commit 259e6b6

Browse files
fix: improve accessibility and update font-display settings
- Add hidden label for filter search input - Change font-display from swap to optional for multiple font files - Add aria-labels to various IconButton components for better accessibility
1 parent d6223d0 commit 259e6b6

File tree

10 files changed

+44
-32
lines changed

10 files changed

+44
-32
lines changed

app/src/components/FilterBar.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,11 +460,14 @@ export function FilterBar({
460460
}}
461461
/>
462462
</Tooltip>
463+
<label htmlFor="filter-search" style={{ position: 'absolute', width: 1, height: 1, overflow: 'hidden', clip: 'rect(0,0,0,0)' }}>
464+
{selectedCategory ? `Search ${FILTER_LABELS[selectedCategory]}` : 'Search filters'}
465+
</label>
463466
<InputBase
464467
inputRef={inputRef}
465468
id="filter-search"
466469
name="filter-search"
467-
aria-label={selectedCategory ? `Search ${FILTER_LABELS[selectedCategory]}` : 'Search filters'}
470+
inputProps={{ 'aria-label': selectedCategory ? `Search ${FILTER_LABELS[selectedCategory]}` : 'Search filters' }}
468471
placeholder={selectedCategory ? FILTER_LABELS[selectedCategory] : ''}
469472
value={searchQuery}
470473
onChange={(e) => {

app/src/components/ImageCard.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ export const ImageCard = memo(function ImageCard({
189189
<IconButton
190190
onClick={handleCopyCode}
191191
disabled={copyState === 'loading'}
192+
aria-label="Copy code"
192193
size="small"
193194
sx={{
194195
position: 'absolute',

app/src/components/LibraryPills.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ export const LibraryPills = memo(function LibraryPills({
9494
{/* Left Arrow */}
9595
<IconButton
9696
onClick={handlePrev}
97+
aria-label="Previous library"
9798
size="small"
9899
sx={{
99100
color: '#9ca3af',
@@ -168,6 +169,7 @@ export const LibraryPills = memo(function LibraryPills({
168169
{/* Right Arrow */}
169170
<IconButton
170171
onClick={handleNext}
172+
aria-label="Next library"
171173
size="small"
172174
sx={{
173175
color: '#9ca3af',

app/src/components/SpecDetailView.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ export function SpecDetailView({
139139
<Tooltip title={codeCopied === currentImpl.library_id ? 'Copied!' : 'Copy Code'}>
140140
<IconButton
141141
onClick={() => onCopyCode(currentImpl)}
142+
aria-label="Copy code"
142143
sx={{
143144
bgcolor: 'rgba(255,255,255,0.9)',
144145
'&:hover': { bgcolor: '#fff' },
@@ -157,6 +158,7 @@ export function SpecDetailView({
157158
<Tooltip title="Download PNG">
158159
<IconButton
159160
onClick={() => onDownload(currentImpl)}
161+
aria-label="Download PNG"
160162
sx={{
161163
bgcolor: 'rgba(255,255,255,0.9)',
162164
'&:hover': { bgcolor: '#fff' },
@@ -172,6 +174,7 @@ export function SpecDetailView({
172174
<IconButton
173175
component={Link}
174176
to={`/interactive/${specId}/${selectedLibrary}`}
177+
aria-label="Open interactive"
175178
onClick={(e: React.MouseEvent) => {
176179
e.stopPropagation();
177180
onTrackEvent('open_interactive', { spec: specId, library: selectedLibrary });

app/src/components/SpecOverview.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ function ImplementationCard({
198198
<Tooltip title={codeCopied === impl.library_id ? 'Copied!' : 'Copy Code'}>
199199
<IconButton
200200
onClick={() => onCopyCode(impl)}
201+
aria-label="Copy code"
201202
sx={{
202203
bgcolor: 'rgba(255,255,255,0.9)',
203204
'&:hover': { bgcolor: '#fff' },
@@ -215,6 +216,7 @@ function ImplementationCard({
215216
<Tooltip title="Download PNG">
216217
<IconButton
217218
onClick={() => onDownload(impl)}
219+
aria-label="Download PNG"
218220
sx={{
219221
bgcolor: 'rgba(255,255,255,0.9)',
220222
'&:hover': { bgcolor: '#fff' },
@@ -229,6 +231,7 @@ function ImplementationCard({
229231
<IconButton
230232
component={Link}
231233
to={`/interactive/${specId}/${impl.library_id}`}
234+
aria-label="Open interactive"
232235
onClick={(e: React.MouseEvent) => {
233236
e.stopPropagation();
234237
onTrackEvent('open_interactive', { spec: specId, library: impl.library_id });

app/src/components/SpecTabs.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ export function SpecTabs({
288288
<Tooltip title={copied ? 'Copied!' : 'Copy code'}>
289289
<IconButton
290290
onClick={handleCopy}
291+
aria-label="Copy code"
291292
sx={{
292293
position: 'absolute',
293294
top: 8,

app/src/pages/InteractivePage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ export function InteractivePage() {
186186
}}
187187
>
188188
<Box sx={{ mb: 2 }}>{error || 'Interactive plot not available'}</Box>
189-
<IconButton onClick={handleClose} sx={{ color: '#3776AB' }}>
189+
<IconButton onClick={handleClose} aria-label="Close" sx={{ color: '#3776AB' }}>
190190
<CloseIcon />
191191
</IconButton>
192192
</Box>
@@ -225,7 +225,7 @@ export function InteractivePage() {
225225
]}
226226
rightAction={
227227
<Tooltip title="View Raw HTML">
228-
<IconButton onClick={handleOpenExternal} size="small">
228+
<IconButton onClick={handleOpenExternal} aria-label="View raw HTML" size="small">
229229
<OpenInNewIcon fontSize="small" />
230230
</IconButton>
231231
</Tooltip>

app/src/router.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import CircularProgress from '@mui/material/CircularProgress';
55
import { Layout, AppDataProvider } from './components/Layout';
66
import { ErrorBoundary } from './components/ErrorBoundary';
77
import { HomePage } from './pages/HomePage';
8-
import { SpecPage } from './pages/SpecPage';
98
import { NotFoundPage } from './pages/NotFoundPage';
109

1110
const LazyFallback = () => (
@@ -23,8 +22,8 @@ const router = createBrowserRouter([
2322
{ path: 'catalog', lazy: () => import('./pages/CatalogPage').then(m => ({ Component: m.CatalogPage, HydrateFallback: LazyFallback })) },
2423
{ path: 'legal', lazy: () => import('./pages/LegalPage').then(m => ({ Component: m.LegalPage, HydrateFallback: LazyFallback })) },
2524
{ path: 'mcp', lazy: () => import('./pages/McpPage').then(m => ({ Component: m.McpPage, HydrateFallback: LazyFallback })) },
26-
{ path: ':specId', element: <SpecPage /> },
27-
{ path: ':specId/:library', element: <SpecPage /> },
25+
{ path: ':specId', lazy: () => import('./pages/SpecPage').then(m => ({ Component: m.SpecPage, HydrateFallback: LazyFallback })) },
26+
{ path: ':specId/:library', lazy: () => import('./pages/SpecPage').then(m => ({ Component: m.SpecPage, HydrateFallback: LazyFallback })) },
2827
{ path: '*', element: <NotFoundPage /> },
2928
],
3029
},

app/src/styles/fonts.css

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
src: url('https://storage.googleapis.com/pyplots-static/fonts/0-MonoLisa-normal.woff2') format('woff2');
3232
font-weight: 100 900;
3333
font-style: normal;
34-
font-display: swap;
34+
font-display: optional;
3535
unicode-range: U+0020-007F;
3636
}
3737

@@ -40,7 +40,7 @@
4040
src: url('https://storage.googleapis.com/pyplots-static/fonts/1-MonoLisa-italic.woff2') format('woff2');
4141
font-weight: 100 900;
4242
font-style: italic;
43-
font-display: swap;
43+
font-display: optional;
4444
unicode-range: U+0020-007F;
4545
}
4646

@@ -50,7 +50,7 @@
5050
src: url('https://storage.googleapis.com/pyplots-static/fonts/2-MonoLisa-normal.woff2') format('woff2');
5151
font-weight: 100 900;
5252
font-style: normal;
53-
font-display: swap;
53+
font-display: optional;
5454
unicode-range: U+0080-00FF;
5555
}
5656

@@ -59,7 +59,7 @@
5959
src: url('https://storage.googleapis.com/pyplots-static/fonts/3-MonoLisa-italic.woff2') format('woff2');
6060
font-weight: 100 900;
6161
font-style: italic;
62-
font-display: swap;
62+
font-display: optional;
6363
unicode-range: U+0080-00FF;
6464
}
6565

@@ -69,7 +69,7 @@
6969
src: url('https://storage.googleapis.com/pyplots-static/fonts/4-MonoLisa-normal.woff2') format('woff2');
7070
font-weight: 100 900;
7171
font-style: normal;
72-
font-display: swap;
72+
font-display: optional;
7373
unicode-range: U+2000-206F;
7474
}
7575

@@ -78,7 +78,7 @@
7878
src: url('https://storage.googleapis.com/pyplots-static/fonts/5-MonoLisa-italic.woff2') format('woff2');
7979
font-weight: 100 900;
8080
font-style: italic;
81-
font-display: swap;
81+
font-display: optional;
8282
unicode-range: U+2000-206F;
8383
}
8484

@@ -88,7 +88,7 @@
8888
src: url('https://storage.googleapis.com/pyplots-static/fonts/6-MonoLisa-normal.woff2') format('woff2');
8989
font-weight: 100 900;
9090
font-style: normal;
91-
font-display: swap;
91+
font-display: optional;
9292
unicode-range: U+2300-23FF;
9393
}
9494

@@ -97,7 +97,7 @@
9797
src: url('https://storage.googleapis.com/pyplots-static/fonts/7-MonoLisa-italic.woff2') format('woff2');
9898
font-weight: 100 900;
9999
font-style: italic;
100-
font-display: swap;
100+
font-display: optional;
101101
unicode-range: U+2300-23FF;
102102
}
103103

@@ -107,7 +107,7 @@
107107
src: url('https://storage.googleapis.com/pyplots-static/fonts/8-MonoLisa-normal.woff2') format('woff2');
108108
font-weight: 100 900;
109109
font-style: normal;
110-
font-display: swap;
110+
font-display: optional;
111111
unicode-range: U+2190-21FF;
112112
}
113113

@@ -116,7 +116,7 @@
116116
src: url('https://storage.googleapis.com/pyplots-static/fonts/9-MonoLisa-italic.woff2') format('woff2');
117117
font-weight: 100 900;
118118
font-style: italic;
119-
font-display: swap;
119+
font-display: optional;
120120
unicode-range: U+2190-21FF;
121121
}
122122

@@ -126,7 +126,7 @@
126126
src: url('https://storage.googleapis.com/pyplots-static/fonts/10-MonoLisa-normal.woff2') format('woff2');
127127
font-weight: 100 900;
128128
font-style: normal;
129-
font-display: swap;
129+
font-display: optional;
130130
unicode-range: U+20A0-20CF;
131131
}
132132

@@ -135,7 +135,7 @@
135135
src: url('https://storage.googleapis.com/pyplots-static/fonts/11-MonoLisa-italic.woff2') format('woff2');
136136
font-weight: 100 900;
137137
font-style: italic;
138-
font-display: swap;
138+
font-display: optional;
139139
unicode-range: U+20A0-20CF;
140140
}
141141

@@ -145,7 +145,7 @@
145145
src: url('https://storage.googleapis.com/pyplots-static/fonts/12-MonoLisa-normal.woff2') format('woff2');
146146
font-weight: 100 900;
147147
font-style: normal;
148-
font-display: swap;
148+
font-display: optional;
149149
unicode-range: U+2200-22FF;
150150
}
151151

@@ -154,7 +154,7 @@
154154
src: url('https://storage.googleapis.com/pyplots-static/fonts/13-MonoLisa-italic.woff2') format('woff2');
155155
font-weight: 100 900;
156156
font-style: italic;
157-
font-display: swap;
157+
font-display: optional;
158158
unicode-range: U+2200-22FF;
159159
}
160160

@@ -164,7 +164,7 @@
164164
src: url('https://storage.googleapis.com/pyplots-static/fonts/14-MonoLisa-normal.woff2') format('woff2');
165165
font-weight: 100 900;
166166
font-style: normal;
167-
font-display: swap;
167+
font-display: optional;
168168
unicode-range: U+2580-259F;
169169
}
170170

@@ -173,7 +173,7 @@
173173
src: url('https://storage.googleapis.com/pyplots-static/fonts/15-MonoLisa-italic.woff2') format('woff2');
174174
font-weight: 100 900;
175175
font-style: italic;
176-
font-display: swap;
176+
font-display: optional;
177177
unicode-range: U+2580-259F;
178178
}
179179

@@ -183,7 +183,7 @@
183183
src: url('https://storage.googleapis.com/pyplots-static/fonts/16-MonoLisa-normal.woff2') format('woff2');
184184
font-weight: 100 900;
185185
font-style: normal;
186-
font-display: swap;
186+
font-display: optional;
187187
unicode-range: U+25A0-25FF;
188188
}
189189

@@ -192,7 +192,7 @@
192192
src: url('https://storage.googleapis.com/pyplots-static/fonts/17-MonoLisa-italic.woff2') format('woff2');
193193
font-weight: 100 900;
194194
font-style: italic;
195-
font-display: swap;
195+
font-display: optional;
196196
unicode-range: U+25A0-25FF;
197197
}
198198

@@ -202,7 +202,7 @@
202202
src: url('https://storage.googleapis.com/pyplots-static/fonts/18-MonoLisa-normal.woff2') format('woff2');
203203
font-weight: 100 900;
204204
font-style: normal;
205-
font-display: swap;
205+
font-display: optional;
206206
unicode-range: U+2500-257F;
207207
}
208208

@@ -211,7 +211,7 @@
211211
src: url('https://storage.googleapis.com/pyplots-static/fonts/19-MonoLisa-italic.woff2') format('woff2');
212212
font-weight: 100 900;
213213
font-style: italic;
214-
font-display: swap;
214+
font-display: optional;
215215
unicode-range: U+2500-257F;
216216
}
217217

@@ -221,7 +221,7 @@
221221
src: url('https://storage.googleapis.com/pyplots-static/fonts/20-MonoLisa-normal.woff2') format('woff2');
222222
font-weight: 100 900;
223223
font-style: normal;
224-
font-display: swap;
224+
font-display: optional;
225225
unicode-range: U+E000-F8FF;
226226
}
227227

@@ -230,6 +230,6 @@
230230
src: url('https://storage.googleapis.com/pyplots-static/fonts/21-MonoLisa-italic.woff2') format('woff2');
231231
font-weight: 100 900;
232232
font-style: italic;
233-
font-display: swap;
233+
font-display: optional;
234234
unicode-range: U+E000-F8FF;
235235
}

app/src/utils/responsiveImage.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ export function buildDetailSrcSet(url: string, format: 'webp' | 'png'): string {
5151
*/
5252
export function getResponsiveSizes(imageSize: ImageSize): string {
5353
if (imageSize === 'compact') {
54-
// xs/sm: 2 cols (50vw), md/lg: 4 cols (25vw), xl: 6 cols (17vw)
55-
return '(max-width: 899px) 50vw, (max-width: 1535px) 25vw, 17vw';
54+
// xs/sm: 2 cols (~45vw after gaps), md/lg: 4 cols (~23vw), xl: 6 cols (~15vw)
55+
return '(max-width: 899px) 45vw, (max-width: 1535px) 23vw, 15vw';
5656
}
57-
// xs/sm: 1 col (100vw), md/lg: 2 cols (50vw), xl: 3 cols (33vw)
58-
return '(max-width: 899px) 100vw, (max-width: 1535px) 50vw, 33vw';
57+
// xs/sm: 1 col (100vw), md/lg: 2 cols (~45vw after gaps), xl: 3 cols (~400px actual)
58+
return '(max-width: 899px) 100vw, (max-width: 1535px) 45vw, 400px';
5959
}
6060

6161
/**

0 commit comments

Comments
 (0)