feat(ag-p03): header with nav dropdowns, theme toggle, mobile burger + drawer#856
Conversation
- src/components/Header.astro: full sticky nav, Browse/Resources dropdowns, mobile-actions cluster (theme → search → burger), right-side drawer - src/scripts/theme-toggle.js: JS-injected single icon (moon/sun), all .theme-toggle-btn buttons sync; storage key ag-theme - src/scripts/header.js: scroll-shrink sentinel, dropdown open/close, burger/drawer, branch toggle (ag-branch key), search dispatch, ⌘K - AwesomeGithubLayout.astro: switches from AwesomeGithubNav to Header Closes #855
📝 WalkthroughSummary by CodeRabbitRelease Notes
WalkthroughThis PR replaces the legacy catalogue-driven navigation with a new responsive Header component featuring a sticky desktop navbar with Browse/Resources dropdowns, mobile drawer, theme toggle, search trigger, and branch selector. The layout wiring is updated, and two new client-side scripts handle all interactive behaviours (dropdowns, drawer, search, theme, branch persistence). ChangesHeader Component Refactor
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
website/src/scripts/theme-toggle.jsParsing error: Unexpected token } Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
✅ Template check passed after update. Thanks for fixing the PR description. |
🔍 Reviewer Summary for PR #856CI Status: ✅ Recommendations
|
|
@coderabbitai review Generated by Claude Code |
There was a problem hiding this comment.
Code Review
This pull request introduces a new, modular Header component along with dedicated scripts for header interactions and theme toggling, replacing the previous navigation layout. The code review feedback highlights several key improvement opportunities: enhancing accessibility by dynamically updating aria-expanded states and trapping keyboard focus inside the mobile drawer; dispatching custom events for branch and theme changes to prevent regressions in other components; replacing the deprecated navigator.platform API; and refactoring duplicated initialization logic in the theme toggle script.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| document.querySelectorAll('.nav-dropdown-trigger').forEach(trigger => { | ||
| const parent = trigger.closest('.nav-dropdown-wrap'); | ||
| const dropdown = parent?.querySelector('.nav-dropdown'); | ||
| if (!parent || !dropdown) return; | ||
|
|
||
| trigger.addEventListener('click', e => { | ||
| e.stopPropagation(); | ||
| const isOpen = parent.classList.contains('open'); | ||
| document.querySelectorAll('.nav-dropdown-wrap.open').forEach(d => | ||
| d.classList.remove('open')); | ||
| if (!isOpen) parent.classList.add('open'); | ||
| }); | ||
|
|
||
| trigger.addEventListener('keydown', e => { | ||
| if (e.key === 'Escape') parent.classList.remove('open'); | ||
| }); | ||
| }); | ||
|
|
||
| document.addEventListener('click', () => { | ||
| document.querySelectorAll('.nav-dropdown-wrap.open').forEach(d => | ||
| d.classList.remove('open')); | ||
| }); |
There was a problem hiding this comment.
The dropdown triggers have aria-expanded="false" hardcoded in the HTML, but their expanded state is never updated dynamically in JavaScript when the dropdowns are opened or closed. This prevents screen readers from announcing the correct state of the menus.
Updating aria-expanded dynamically on click, escape key, and outside clicks ensures full accessibility compliance.
document.querySelectorAll('.nav-dropdown-trigger').forEach(trigger => {
const parent = trigger.closest('.nav-dropdown-wrap');
const dropdown = parent?.querySelector('.nav-dropdown');
if (!parent || !dropdown) return;
trigger.addEventListener('click', e => {
e.stopPropagation();
const isOpen = parent.classList.contains('open');
document.querySelectorAll('.nav-dropdown-wrap.open').forEach(d => {
d.classList.remove('open');
d.querySelector('.nav-dropdown-trigger')?.setAttribute('aria-expanded', 'false');
});
if (!isOpen) {
parent.classList.add('open');
trigger.setAttribute('aria-expanded', 'true');
}
});
trigger.addEventListener('keydown', e => {
if (e.key === 'Escape') {
parent.classList.remove('open');
trigger.setAttribute('aria-expanded', 'false');
trigger.focus();
}
});
});
document.addEventListener('click', () => {
document.querySelectorAll('.nav-dropdown-wrap.open').forEach(d => {
d.classList.remove('open');
d.querySelector('.nav-dropdown-trigger')?.setAttribute('aria-expanded', 'false');
});
});| function openDrawer() { | ||
| document.body.classList.add('drawer-open'); | ||
| drawer?.setAttribute('aria-hidden', 'false'); | ||
| drawer?.removeAttribute('inert'); | ||
| drawerClose?.focus(); | ||
| } | ||
| function closeDrawer() { | ||
| document.body.classList.remove('drawer-open'); | ||
| drawer?.setAttribute('aria-hidden', 'true'); | ||
| drawer?.setAttribute('inert', ''); | ||
| burger?.focus(); | ||
| } |
There was a problem hiding this comment.
When the mobile navigation drawer is open, keyboard focus is not trapped inside it. Users can still tab into background elements (like header links or main content), which violates accessibility standards for modal dialogs/drawers.
Using the native inert attribute on all other top-level body children when the drawer is open elegantly traps focus inside the drawer.
function openDrawer() {
document.body.classList.add('drawer-open');
drawer?.setAttribute('aria-hidden', 'false');
drawer?.removeAttribute('inert');
Array.from(document.body.children).forEach(child => {
if (child !== drawer && child !== drawerScrim) {
child.setAttribute('inert', '');
}
});
drawerClose?.focus();
}
function closeDrawer() {
document.body.classList.remove('drawer-open');
drawer?.setAttribute('aria-hidden', 'true');
drawer?.setAttribute('inert', '');
Array.from(document.body.children).forEach(child => {
if (child !== drawer && child !== drawerScrim) {
child.removeAttribute('inert');
}
});
burger?.focus();
}| btn.addEventListener('click', () => { | ||
| try { localStorage.setItem(BRANCH_KEY, b); } catch (e) {} | ||
| branchBtns.forEach(x => | ||
| x.setAttribute('aria-pressed', x.dataset.branch === b ? 'true' : 'false')); | ||
| }); |
There was a problem hiding this comment.
When the repository branch is toggled, the active branch is saved to localStorage, but no event is dispatched to notify other components on the page (such as install buttons or clone commands) to update their URLs. Dispatching a custom ag:branch-changed event allows other components to listen and update dynamically without requiring a full page reload.
btn.addEventListener('click', () => {
try { localStorage.setItem(BRANCH_KEY, b); } catch (e) {}
branchBtns.forEach(x =>
x.setAttribute('aria-pressed', x.dataset.branch === b ? 'true' : 'false'));
document.dispatchEvent(new CustomEvent('ag:branch-changed', { detail: { branch: b } }));
});There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ed2408c9c1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| @media (min-width: 1025px) { | ||
| #nav-drawer, | ||
| #drawer-scrim { display: none; } |
There was a problem hiding this comment.
Clear the drawer state when desktop layout takes over
When a user opens the mobile drawer and then rotates or resizes to a desktop viewport, this media query hides the drawer and scrim but nothing calls closeDrawer(). The drawer-open class added by header.js therefore remains on <body>, and the global body.drawer-open { overflow: hidden; } rule keeps the desktop page locked from scrolling until the user returns to mobile and closes the drawer.
Useful? React with 👍 / 👎.
| function openDrawer() { | ||
| document.body.classList.add('drawer-open'); | ||
| drawer?.setAttribute('aria-hidden', 'false'); | ||
| drawer?.removeAttribute('inert'); | ||
| drawerClose?.focus(); |
There was a problem hiding this comment.
Make the page inert while the mobile drawer is open
When the drawer is open on mobile, this only exposes and focuses the drawer; it does not make the underlying header, main content, or footer inert. Keyboard users can therefore tab past the drawer into controls behind the scrim, which breaks the modal drawer behaviour and the accessibility checklist for inert in this change.
Useful? React with 👍 / 👎.
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Get PR details and files changed
gh pr view 856 --repo lightspeedwp/.github --json files,additions,deletions,changedFiles
echo "=== FILES CHANGED ==="
gh pr diff 856 --repo lightspeedwp/.githubLength of output: 31165 🏁 Script executed: #!/bin/bash
# Check what event name the search palette listens for
rg -n "search-palette-open|ag:open-search" --type astro --type js -C3
# Check AwesomeGithubNav.astro for reference
fd "AwesomeGithubNav.astro" --exec cat {}Length of output: 26373
🔴 Critical — Accessibility Regressions1.
|
| # | Severity | File | Issue |
|---|---|---|---|
| 1 | 🔴 Critical | header.js |
aria-expanded never toggled on dropdown triggers |
| 2 | 🔴 Critical | header.js |
No inert on background elements when drawer opens |
| 3 | 🔴 Critical | Header.astro + header.js |
Burger missing aria-expanded / aria-controls |
| 4 | 🟠 Major | header.js + Header.astro |
Search event name change (search-palette-open → ag:open-search) — verify all consumers updated |
| 5 | 🟠 Major | header.js |
No matchMedia listener — scroll lock persists after resize |
| 6 | 🟠 Major | Header.astro |
aria-current="page" removed from nav links |
| 7 | 🟡 Minor | header.js |
navigator.platform deprecated |
| 8 | 🟡 Minor | header.js |
Dropdown focusout close behaviour not ported |
Items 1–3 are regressions from the old nav and block WCAG compliance. Happy to help draft diffs for any of these if useful! 🙌
There was a problem hiding this comment.
Pull request overview
Implements the Phase 03 Awesome GitHub site header, replacing the previous nav with a new Header.astro component and associated client-side behaviour scripts.
Changes:
- Added a new header component with desktop dropdown navigation, theme toggle buttons, and a mobile burger + drawer.
- Introduced client-side scripts for theme icon swapping and header interactions (dropdowns, drawer, scroll-shrink, branch toggle, search trigger wiring).
- Wired the new header into
AwesomeGithubLayout.astro, removing the legacy inline theme/search wiring.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 10 comments.
| File | Description |
|---|---|
website/src/components/Header.astro |
New header markup, global and scoped styles, plus script imports for header behaviour. |
website/src/scripts/theme-toggle.js |
Theme toggle behaviour with single-icon rendering across all toggle buttons. |
website/src/scripts/header.js |
Dropdown, drawer, scroll-shrink, branch toggle, and search trigger/keyboard shortcut wiring. |
website/src/layouts/AwesomeGithubLayout.astro |
Swaps legacy nav usage for the new Header component and removes inline handlers. |
| const isMac = navigator.platform.toUpperCase().includes('MAC'); | ||
| document.querySelectorAll('.search-kbd-hint').forEach(el => { | ||
| el.textContent = isMac ? '⌘K' : 'Ctrl K'; | ||
| }); |
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Ash Shaw <ashley@lightspeedwp.agency>
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@website/src/components/Header.astro`:
- Around line 266-267: The header's z-index (z-index: 100) is higher than the
drawer/scrim (90/91), leaving header controls clickable while the drawer is
open; fix by making the drawer/scrim stack above the header (e.g., increase the
scrim/drawer z-index to >100) or lower the header z-index below the scrim (e.g.,
set z-index: 50 on the header). Update the CSS rule containing "z-index: 100" in
Header.astro or the CSS rules that set the scrim/drawer z-index (the rules using
90/91) so the drawer's z-index is greater than the header, and ensure their
positioning/stacking contexts remain consistent.
In `@website/src/scripts/header.js`:
- Around line 87-98: The persisted branch key currently uses BRANCH_KEY =
'ag-branch' which mismatches the downstream reader expecting 'github_branch';
update BRANCH_KEY to 'github_branch' (and ensure any references to 'ag-branch'
in header.js are replaced) so the toggle (branchBtns logic that sets
aria-pressed and calls localStorage.setItem) and the page reader (github_branch)
use the same storage key.
- Around line 59-74: openDrawer/closeDrawer currently only toggle inert on the
drawer element, allowing background elements to remain tabbable and receive
focus; update these functions (openDrawer, closeDrawer) to set inert (and
aria-hidden where appropriate) on all page elements except the drawer and its
controls when opening, and remove inert from those elements when closing so
background content is fully excluded from focus and interaction; identify
targets by querying top-level children (e.g., document.body.children or a
container like main/header/footer) and skip the drawer, burger, and drawerClose
elements when toggling inert/aria-hidden, and ensure focus is moved into the
drawer on open and returned to the triggering control on close.
- Around line 80-84: The drawer can remain logically open after a viewport
crosses the desktop breakpoint because we only close it on Escape; add a
resize/viewport-change handler (e.g., use window.matchMedia and its change event
or window.addEventListener('resize')) that detects when the viewport becomes
desktop-sized and then calls the same cleanup used by closeDrawer (remove
document.body.classList.contains('drawer-open') state, remove the 'drawer-open'
class, clear scroll-lock and scrim, and restore any ARIA attributes). Locate the
existing document.addEventListener('keydown', ...) and reuse the same
closeDrawer cleanup logic to ensure all state (body class, ARIA, scroll
restoration) is cleared on breakpoint transition.
- Around line 41-43: The Escape key handler removes the visual "open" class but
doesn't update the ARIA state, causing assistive tech to still report the
dropdown as open; update the keydown listener on trigger so that after
parent.classList.remove('open') you also set the controlling element's
aria-expanded to "false" (e.g., call trigger.setAttribute('aria-expanded',
'false') or update the same attribute used elsewhere), ensuring the visible
state and ARIA state stay in sync.
In `@website/src/scripts/theme-toggle.js`:
- Around line 22-31: There is a stray closing brace after the updateAllIcons()
function causing a JS syntax error; open the block containing function
updateAllIcons (which uses getTheme, SVG_SUN and SVG_MOON) and remove the extra
`}` so the function and surrounding scope close only once, ensuring no unmatched
braces remain and the file ends with the correct closure.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro
Run ID: c2ec9ff2-8bae-46be-806b-b3fa649b14ae
📒 Files selected for processing (4)
website/src/components/Header.astrowebsite/src/layouts/AwesomeGithubLayout.astrowebsite/src/scripts/header.jswebsite/src/scripts/theme-toggle.js
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{php,js,jsx,ts,tsx,css,scss,html}
📄 CodeRabbit inference engine (AGENTS.md)
Follow WordPress Coding Standards (CSS, HTML, JavaScript, PHP) and inline-documentation standards at all times
Files:
website/src/scripts/header.jswebsite/src/scripts/theme-toggle.js
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{js,ts,jsx,tsx}: Follow ESLint/Prettier standards for JavaScript and TypeScript files
Avoid unnecessary JavaScript, defer/lazy-load where possible, and prefer native blocks
Files:
website/src/scripts/header.jswebsite/src/scripts/theme-toggle.js
**/*.{js,ts}
⚙️ CodeRabbit configuration file
**/*.{js,ts}: Review JavaScript/TypeScript:
- Ensure code is linted and follows project style guides.
- Check for dead code, unused variables, and clear function naming.
- Validate accessibility and performance optimisations.
- Ensure tests are isolated and do not depend on external state.
- Check for descriptive test names and clear test structure.
Files:
website/src/scripts/header.jswebsite/src/scripts/theme-toggle.js
🪛 ESLint
website/src/scripts/header.js
[error] 3-3: 'document' is not defined.
(no-undef)
[error] 6-6: 'document' is not defined.
(no-undef)
[error] 7-7: 'window' is not defined.
(no-undef)
[error] 8-8: 'document' is not defined.
(no-undef)
[error] 10-10: 'document' is not defined.
(no-undef)
[error] 11-11: 'IntersectionObserver' is not defined.
(no-undef)
[error] 19-19: 'document' is not defined.
(no-undef)
[error] 28-28: 'document' is not defined.
(no-undef)
[error] 46-46: 'document' is not defined.
(no-undef)
[error] 47-47: 'document' is not defined.
(no-undef)
[error] 54-54: 'document' is not defined.
(no-undef)
[error] 55-55: 'document' is not defined.
(no-undef)
[error] 56-56: 'document' is not defined.
(no-undef)
[error] 57-57: 'document' is not defined.
(no-undef)
[error] 60-60: 'document' is not defined.
(no-undef)
[error] 68-68: 'document' is not defined.
(no-undef)
[error] 80-80: 'document' is not defined.
(no-undef)
[error] 81-81: 'document' is not defined.
(no-undef)
[error] 88-88: 'document' is not defined.
(no-undef)
[error] 91-91: 'localStorage' is not defined.
(no-undef)
[error] 98-98: 'localStorage' is not defined.
(no-undef)
[error] 98-98: Empty block statement.
(no-empty)
[error] 105-105: 'document' is not defined.
(no-undef)
[error] 106-106: 'document' is not defined.
(no-undef)
[error] 106-106: 'CustomEvent' is not defined.
(no-undef)
[error] 108-108: 'document' is not defined.
(no-undef)
[error] 109-109: 'document' is not defined.
(no-undef)
[error] 109-109: 'CustomEvent' is not defined.
(no-undef)
[error] 113-113: 'document' is not defined.
(no-undef)
[error] 116-116: 'document' is not defined.
(no-undef)
[error] 116-116: 'CustomEvent' is not defined.
(no-undef)
[error] 121-121: 'navigator' is not defined.
(no-undef)
[error] 122-122: 'document' is not defined.
(no-undef)
🪛 GitHub Actions: Awesome GitHub Site / 1_Build website.txt
website/src/scripts/theme-toggle.js
[error] 30-30: Vite/Rollup build failed: Expression expected. Error location: src/scripts/theme-toggle.js:30:0.
🪛 GitHub Actions: Awesome GitHub Site / Build website
website/src/scripts/theme-toggle.js
[error] 30-30: Build failed in Vite/Rollup: Expression expected at src/scripts/theme-toggle.js:30:0.
🔇 Additional comments (1)
website/src/layouts/AwesomeGithubLayout.astro (1)
4-5: LGTM!Also applies to: 29-31
| z-index: 100; | ||
| height: var(--nav-h, 64px); |
There was a problem hiding this comment.
Drawer stack order is upside-down (header stays clickable above the modal).
At Line 266, the header sits at z-index: 100, while the scrim/drawer at Lines 551 and 570 are lower (90/91). Result: background header controls stay interactive while the drawer is open, which breaks modal isolation.
Suggested fix
- .nav {
+ .nav {
position: sticky;
top: 0;
- z-index: 100;
+ z-index: 80;
height: var(--nav-h, 64px);
...
}
`#drawer-scrim` {
position: fixed;
inset: 0;
- z-index: 90;
+ z-index: 110;
...
}
`#nav-drawer` {
position: fixed;
...
- z-index: 91;
+ z-index: 111;
...
}Also applies to: 551-552, 570-571
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/src/components/Header.astro` around lines 266 - 267, The header's
z-index (z-index: 100) is higher than the drawer/scrim (90/91), leaving header
controls clickable while the drawer is open; fix by making the drawer/scrim
stack above the header (e.g., increase the scrim/drawer z-index to >100) or
lower the header z-index below the scrim (e.g., set z-index: 50 on the header).
Update the CSS rule containing "z-index: 100" in Header.astro or the CSS rules
that set the scrim/drawer z-index (the rules using 90/91) so the drawer's
z-index is greater than the header, and ensure their positioning/stacking
contexts remain consistent.
| const BRANCH_KEY = 'ag-branch'; | ||
| const branchBtns = document.querySelectorAll('.branch-btn'); | ||
|
|
||
| const savedBranch = (() => { | ||
| try { return localStorage.getItem(BRANCH_KEY) || 'main'; } catch (e) { return 'main'; } | ||
| })(); | ||
|
|
||
| branchBtns.forEach(btn => { | ||
| const b = btn.dataset.branch; | ||
| btn.setAttribute('aria-pressed', b === savedBranch ? 'true' : 'false'); | ||
| btn.addEventListener('click', () => { | ||
| try { localStorage.setItem(BRANCH_KEY, b); } catch (e) {} |
There was a problem hiding this comment.
Branch persistence key breaks the existing cross-file contract.
At Line 87 you persist to ag-branch, but website/src/pages/c/[type]/[slug].astro (Lines 252-277 in provided context) reads github_branch. The header toggle and downstream page branch logic won’t stay in sync.
🧰 Tools
🪛 ESLint
[error] 88-88: 'document' is not defined.
(no-undef)
[error] 91-91: 'localStorage' is not defined.
(no-undef)
[error] 98-98: 'localStorage' is not defined.
(no-undef)
[error] 98-98: Empty block statement.
(no-empty)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/src/scripts/header.js` around lines 87 - 98, The persisted branch key
currently uses BRANCH_KEY = 'ag-branch' which mismatches the downstream reader
expecting 'github_branch'; update BRANCH_KEY to 'github_branch' (and ensure any
references to 'ag-branch' in header.js are replaced) so the toggle (branchBtns
logic that sets aria-pressed and calls localStorage.setItem) and the page reader
(github_branch) use the same storage key.
# Conflicts: # website/src/components/Header.astro # website/src/scripts/header.js # website/src/scripts/theme-toggle.js
Phase 03 — Header component
Linked issues
Closes #855
Changelog
Added
website/src/components/Header.astro— full sticky header with Browse/Resources mega-dropdowns, mobile-actions cluster (theme → search → burger order), right-side slide-in drawer with all spec-required sections (BROWSE, COOK & LEARN, RESOURCES, INSTALL SOURCE, EXTERNAL).website/src/scripts/theme-toggle.js— JS-injected single icon (moon in light mode, sun in dark mode); all.theme-toggle-btnbuttons sync simultaneously; usesag-themelocalStorage key.website/src/scripts/header.js— scroll-shrink via IntersectionObserver sentinel (64px → 52px after 60px scroll), dropdown open/close with keyboard support, burger/drawer toggle, branch toggle withag-branchkey, search palette event dispatch, ⌘K/Ctrl+K shortcut.Changed
website/src/layouts/AwesomeGithubLayout.astro— switched fromAwesomeGithubNavto the new spec-compliantHeadercomponent; removed inline theme-toggle delegation script (now handled bytheme-toggle.js).Fixed
display:nonetoggling (both icons could show simultaneously). Fixed to JS-inject a single icon per the v2 spec.github_branchlocalStorage key. Corrected toag-branchper spec.Risk Assessment
Risk Level: Low
Potential Impact: UI-only change to the site header and its client-side JS. No data, no API, no auth. Worst case is a header that renders incorrectly, which would be immediately visible.
Mitigation Steps:
is:globalstyle block scopes brand-icon swap rules correctly across component boundaries.AwesomeGithubNav.astropreserved (not deleted) for reference.How to Test
Prerequisites
npm ciinsidewebsite/Test Steps
npx astro build— expect 220 pages, no errors.ag-branch.Expected Results
Edge Cases to Verify
Checklist (Global DoD / PR)
<header role="banner">,<nav aria-label>,<aside aria-label>, skip link retainedaria-hidden,aria-expanded,aria-label,aria-pressed,inertlocalStorageaccess is try/caught; no secretsReferences
AG_PHASE_03.md,CLAUDE_CODE_HEADER_FOOTER_SPEC.md,CLAUDE_CODE_HEADER_V2_SPEC.mdAWESOME_GITHUB_THEME_TOKENS_SPEC.md §3.2AG_ORCHESTRATOR.md