diff --git a/src/components/CodeExample.test.tsx b/src/components/CodeExample.test.tsx index 772acf3..3f3385e 100644 --- a/src/components/CodeExample.test.tsx +++ b/src/components/CodeExample.test.tsx @@ -271,4 +271,25 @@ describe('CodeExample', () => { }); }); }); + + describe('narrow viewport support', () => { + it('renders header with responsive class', () => { + render(); + const header = document.querySelector('.code-sample__header'); + expect(header).toBeTruthy(); + }); + + it('uses tabs container with BEM class for flex wrap', () => { + render(); + const tablist = screen.getByRole('tablist'); + expect(tablist.classList.contains('code-sample__tabs')).toBe(true); + }); + + it('has accessible copy button label', () => { + render(); + const copyBtn = screen.getByLabelText(/copy code/i); + expect(copyBtn).toBeTruthy(); + expect(copyBtn.classList.contains('code-sample__copy')).toBe(true); + }); + }); }); diff --git a/src/components/CodeExample.tsx b/src/components/CodeExample.tsx index fd1ef32..f747455 100644 --- a/src/components/CodeExample.tsx +++ b/src/components/CodeExample.tsx @@ -135,15 +135,7 @@ export default function CodeExample({
{/* Header Section: Contains Language Tabs and Copy Button */}
{/* Navigation Tabs List with Roving Tabindex */}
{ it("marks CodeExample header controls as no-print", () => { const codeExample = read("src/components/CodeExample.tsx"); - expect(codeExample).toMatch(/className="no-print"/); + expect(codeExample).toMatch(/className=".*no-print.*"/); }); it("does not import the removed print.css file", () => { diff --git a/src/styles/code.css b/src/styles/code.css index f9b7840..b6f7e0e 100644 --- a/src/styles/code.css +++ b/src/styles/code.css @@ -36,6 +36,7 @@ .code-sample__tabs { display: flex; + flex-wrap: wrap; gap: 4px; } @@ -98,6 +99,78 @@ overflow: hidden; } +/* Narrow viewport (≤480px): adjust layout for mobile */ +@media (max-width: 480px) { + .code-sample__header { + flex-direction: column; + align-items: stretch; + gap: 8px; + padding: 8px; + } + + .code-sample__tabs { + overflow-x: auto; + flex-wrap: nowrap; + -webkit-overflow-scrolling: touch; + scrollbar-width: none; + } + .code-sample__tabs::-webkit-scrollbar { + display: none; + } + + .code-sample__tab { + flex-shrink: 0; + min-height: 36px; + padding: 6px 10px; + font-size: 10px; + } + + .code-sample__copy { + align-self: flex-end; + min-height: 44px; + min-width: 80px; + padding: 8px 14px; + font-size: 12px; + } + + .code-sample__panel { + padding: 12px 8px; + } + + .code-sample__pre { + font-size: 12px; + } +} + +/* Extra-narrow viewport (≤375px): compact layout for small phones */ +@media (max-width: 375px) { + .code-sample__header { + padding: 6px; + gap: 6px; + } + + .code-sample__tab { + min-height: 36px; + padding: 5px 8px; + font-size: 9px; + } + + .code-sample__copy { + min-height: 44px; + min-width: 72px; + padding: 6px 10px; + font-size: 11px; + } + + .code-sample__panel { + padding: 10px 6px; + } + + .code-sample__pre { + font-size: 11px; + } +} + /* Reduced motion support */ @media (prefers-reduced-motion: reduce) { .code-sample__tab {