Skip to content

feat: Refresh docs theme styling and icon set#425

Merged
elibosley merged 7 commits intomainfrom
codex/docs-theme-refresh
Mar 21, 2026
Merged

feat: Refresh docs theme styling and icon set#425
elibosley merged 7 commits intomainfrom
codex/docs-theme-refresh

Conversation

@elibosley
Copy link
Member

@elibosley elibosley commented Mar 21, 2026

Summary

  • replace several default Docusaurus theme icons with Tabler-based overrides and update the iframe back arrow
  • refine dark theme, footer, and DocSearch styling to better match the Unraid docs look and update the dark theme-color metadata
  • render footer copyright years dynamically across localized footers and ignore the local .gstack/ directory

Testing

  • pnpm run test:run
  • pnpm run lint
    • passes, but Docusaurus reports pre-existing broken links to warn/ in translated pages and one pre-existing broken anchor under SMART reports

Summary by CodeRabbit

  • New Features

    • Many new UI icons with a unified icon wrapper; dynamic footer shows the current year; new floating feedback widget; responsive embed accepts optional class overrides.
  • Style

    • Dark-mode meta/color tweak and refined menu/dropdown caret and search/external-link visuals; several theme CSS improvements for visual consistency.
  • Chores

    • Added Tabler Icons React package; updated ignore rules.
  • Documentation

    • Added validation guidance file.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 21, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds Tabler icon support and a ThemeIcon wrapper with many icon components; large CSS theming and DocSearch/icon-mask updates; dynamic footer year placeholder plus runtime footer component; a floating FeedbackWidget (iframe modal) and ResponsiveEmbed class overrides; minor config and SVG tweaks; .gstack/ ignored.

Changes

Cohort / File(s) Summary
Repo config & metadata
/.gitignore, docusaurus.config.ts, package.json
Ignore .gstack/ added, dark-mode theme-color metadata updated, and @tabler/icons-react@^3.40.0 dependency added.
Localized footer strings
i18n/de/docusaurus-theme-classic/footer.json, i18n/en/docusaurus-theme-classic/footer.json, i18n/es/docusaurus-theme-classic/footer.json, i18n/fr/docusaurus-theme-classic/footer.json, i18n/zh/docusaurus-theme-classic/footer.json
Replaced hard-coded end year with {currentYear} placeholder in localized footer HTML strings.
Footer runtime component
src/theme/Footer/Copyright/index.tsx
New component computes currentYear, replaces {currentYear} and 2005-<year> patterns, and injects resolved HTML via dangerouslySetInnerHTML.
CSS & theming
src/css/custom.css
Large additions: Tabler SVG URL variables, menu caret wiring, dark-theme selector changed to html[data-theme="dark"], DocSearch dark variables, CSS-mask-based icons for search/close/external links, feedback widget styles, and assorted formatting/casing tweaks.
Icon infrastructure
src/theme/Icon/shared.tsx
New ThemeIconProps type and ThemeIcon wrapper standardizing icon rendering, sizing, ARIA handling, and label forwarding.
Icon components
src/theme/Icon/...
src/theme/Icon/{Arrow,Close,Copy,DarkMode,Edit,ExternalLink,Home,Language,LightMode,Menu,Success,SystemColorMode,WordWrap}/index.tsx
Added ~13 icon wrapper components using Tabler glyphs and ThemeIcon; many provide default sizes and forward props.
Admonition icons
src/theme/Admonition/Icon/{Danger,Info,Note,Tip,Warning}.tsx
Added five admonition-specific icon components mapping admonitions to Tabler icons and forwarding ThemeIconProps.
Feedback & embed UI
src/theme/Layout/FeedbackWidget.tsx, src/components/ResponsiveEmbed/index.tsx, src/theme/Layout/Provider/index.tsx
New FeedbackWidget (floating button + modal iframe) with focus trapping, Escape handler, and body-scroll locking; ResponsiveEmbed accepts optional embedClassName/frameClassName/iframeClassName; Layout/Provider renders FeedbackWidget.
Layout SVG tweak
src/theme/Layout/IframeNavigation.tsx
Replaced the "Back to start" SVG path with a three-line stroked arrow path (presentational change).
Docs & guidance
AGENTS.md
New guidance file advising against full-build validation for routine checks and recommending targeted verification.
Hooks
src/hooks/useIframe.ts
useIframe now returns `boolean

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Widget as FeedbackWidget
    participant Embed as ResponsiveEmbed (iframe)
    participant Survey as External Survey

    User->>Widget: Click feedback button
    Widget->>Widget: setOpen(true) → render backdrop + dialog
    Widget->>Embed: render iframe src=".../survey"
    Embed->>Survey: Load survey URL
    User->>Embed: Interact with survey
    User->>Widget: Click close or press Escape
    Widget->>Widget: setOpen(false), restore focus & body overflow, remove listeners
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I nibbled through icons and stitched the night,
Years now flow in footers, neat and right,
A little button opens a curious frame,
DocSearch masks sparkle, and menus gain a name,
Hooray — the docs hum softly all the same.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: refreshing theme styling and replacing icons with Tabler-based versions, matching the substantial CSS and icon component additions throughout the changeset.
Description check ✅ Passed The PR description is substantially complete with a clear summary of changes and testing performed. However, it does not follow the template's checklist format for documentation and asset management.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/docs-theme-refresh

Comment @coderabbitai help to get the list of available commands and usage tips.

@elibosley elibosley changed the title Refresh docs theme styling and icon set feat: Refresh docs theme styling and icon set Mar 21, 2026
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 21, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
unraid-docs a0c8dc3 Commit Preview URL

Branch Preview URL
Mar 21 2026, 05:13 PM

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/css/custom.css (1)

385-387: ⚠️ Potential issue | 🟡 Minor

Invalid CSS: open is not a CSS property.

The open attribute on <details> elements is an HTML attribute, not a CSS property. This rule will have no effect. To auto-expand targeted details elements, you would need JavaScript.

🗑️ Suggested removal
-/* Auto-expand details when targeted */
-details:target {
-  open: true;
-}

If auto-expansion is needed, consider using the :target selector with JavaScript or a Docusaurus plugin/component that handles this behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/css/custom.css` around lines 385 - 387, The CSS rule using the selector
details:target with the property open is invalid because "open" is an HTML
attribute, not a CSS property; remove the rule (the selector details:target {
open: true; }) from the stylesheet, and if you need auto-expansion of targeted
<details> elements implement a small script that detects the :target element (or
location.hash) and sets the element.open = true programmatically (or use a
Docusaurus plugin/component) — update any references to the details:target
selector in the repo accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/css/custom.css`:
- Around line 167-181: The CSS uses the keyword with incorrect casing in the
rule for .DocSearch-Button-Container::before, .DocSearch-MagnifierLabel::before,
and .DocSearch-Close::before; update the background-color property from
"currentColor" to the lowercase "currentcolor" to satisfy Stylelint's CSS
keyword convention and re-run linting to confirm the warning is resolved.
- Around line 358-369: The rule for the external-link pseudo-element selector
a[href^="http"]:not([href*="docs.unraid.net"]):not([href*="releases.unraid.net"]):not([href*="localhost"]):not([href*="127.0.0.1"])::after
uses background-color: currentColor; which triggers the Stylelint casing
rule—change the value to lowercase (background-color: currentcolor;) so the
token matches the linter expectation; update the same occurrence in that
selector and run lint to confirm the fix.

In `@src/theme/Layout/IframeNavigation.tsx`:
- Around line 106-108: The SVG arrow in IframeNavigation.tsx is an open path and
needs stroke styling to render; update the <path> inside the SVG used by the
IframeNavigation component to include stroke attributes (e.g.,
stroke="currentColor", stroke-width="2", stroke-linecap="round",
stroke-linejoin="round") or add equivalent CSS targeting that path so the arrow
becomes visible while preserving currentColor for theming.

---

Outside diff comments:
In `@src/css/custom.css`:
- Around line 385-387: The CSS rule using the selector details:target with the
property open is invalid because "open" is an HTML attribute, not a CSS
property; remove the rule (the selector details:target { open: true; }) from the
stylesheet, and if you need auto-expansion of targeted <details> elements
implement a small script that detects the :target element (or location.hash) and
sets the element.open = true programmatically (or use a Docusaurus
plugin/component) — update any references to the details:target selector in the
repo accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: cdf448d9-9435-4ab5-b389-5867214bad05

📥 Commits

Reviewing files that changed from the base of the PR and between 5623f69 and 1a60e35.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (30)
  • .gitignore
  • docusaurus.config.ts
  • i18n/de/docusaurus-theme-classic/footer.json
  • i18n/en/docusaurus-theme-classic/footer.json
  • i18n/es/docusaurus-theme-classic/footer.json
  • i18n/fr/docusaurus-theme-classic/footer.json
  • i18n/zh/docusaurus-theme-classic/footer.json
  • package.json
  • src/css/custom.css
  • src/theme/Admonition/Icon/Danger.tsx
  • src/theme/Admonition/Icon/Info.tsx
  • src/theme/Admonition/Icon/Note.tsx
  • src/theme/Admonition/Icon/Tip.tsx
  • src/theme/Admonition/Icon/Warning.tsx
  • src/theme/Footer/Copyright/index.tsx
  • src/theme/Icon/Arrow/index.tsx
  • src/theme/Icon/Close/index.tsx
  • src/theme/Icon/Copy/index.tsx
  • src/theme/Icon/DarkMode/index.tsx
  • src/theme/Icon/Edit/index.tsx
  • src/theme/Icon/ExternalLink/index.tsx
  • src/theme/Icon/Home/index.tsx
  • src/theme/Icon/Language/index.tsx
  • src/theme/Icon/LightMode/index.tsx
  • src/theme/Icon/Menu/index.tsx
  • src/theme/Icon/Success/index.tsx
  • src/theme/Icon/SystemColorMode/index.tsx
  • src/theme/Icon/WordWrap/index.tsx
  • src/theme/Icon/shared.tsx
  • src/theme/Layout/IframeNavigation.tsx

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/css/custom.css (2)

48-80: The html[data-theme='dark']:root selector is unconventional but valid.

Since :root is equivalent to html in HTML documents, this selector is functionally the same as html[data-theme='dark']. If the intent is to increase specificity or explicitly scope variables at the root level, consider adding a brief comment explaining the choice for future maintainers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/css/custom.css` around lines 48 - 80, The selector
"html[data-theme='dark']:root" is redundant because :root equals html; either
simplify the CSS variable block to use "html[data-theme='dark']" or keep the
current selector but add a short inline comment above
"html[data-theme='dark']:root" explaining the deliberate use (e.g., to increase
specificity or explicitly scope root variables) so future maintainers understand
the intent.

359-360: Consider adopting complex :not() notation for broader Stylelint compliance.

Stylelint's selector-not-notation rule prefers complex notation with comma-separated selectors:

.theme-doc-markdown a[href^="http"]:not([href*="docs.unraid.net"], [href*="releases.unraid.net"], [href*="localhost"], [href*="127.0.0.1"])::after

This syntax has solid browser support (Chrome 88+, Firefox 84+, Safari 9+) but does not work in Internet Explorer. If IE support is required, you may need to disable this Stylelint rule or continue using the chained :not() approach.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/css/custom.css` around lines 359 - 360, The combined external-link
selectors (.theme-doc-markdown a[href^="http"]::after and .theme-blog-markdown
a[href^="http"]::after) currently use multiple chained :not() pseudo-classes;
update them to use a single complex :not() with comma-separated attribute
selectors (e.g., :not([href*="docs.unraid.net"], [href*="releases.unraid.net"],
[href*="localhost"], [href*="127.0.0.1"])) to satisfy Stylelint's
selector-not-notation rule, or if Internet Explorer support is required, keep
the chained :not() and instead disable or override that Stylelint rule for this
file. Ensure you update both the .theme-doc-markdown and .theme-blog-markdown
selectors mentioned in the diff.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/css/custom.css`:
- Around line 48-80: The selector "html[data-theme='dark']:root" is redundant
because :root equals html; either simplify the CSS variable block to use
"html[data-theme='dark']" or keep the current selector but add a short inline
comment above "html[data-theme='dark']:root" explaining the deliberate use
(e.g., to increase specificity or explicitly scope root variables) so future
maintainers understand the intent.
- Around line 359-360: The combined external-link selectors (.theme-doc-markdown
a[href^="http"]::after and .theme-blog-markdown a[href^="http"]::after)
currently use multiple chained :not() pseudo-classes; update them to use a
single complex :not() with comma-separated attribute selectors (e.g.,
:not([href*="docs.unraid.net"], [href*="releases.unraid.net"],
[href*="localhost"], [href*="127.0.0.1"])) to satisfy Stylelint's
selector-not-notation rule, or if Internet Explorer support is required, keep
the chained :not() and instead disable or override that Stylelint rule for this
file. Ensure you update both the .theme-doc-markdown and .theme-blog-markdown
selectors mentioned in the diff.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fbaff1a8-f77a-4551-9118-a5f8707288f5

📥 Commits

Reviewing files that changed from the base of the PR and between 1a60e35 and 00bc364.

📒 Files selected for processing (1)
  • src/css/custom.css

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
src/css/custom.css (2)

167-175: ⚠️ Potential issue | 🟡 Minor

Fix currentColor keyword casing in two places.

background-color: currentColor; at Line 174 and Line 368 still violates the configured Stylelint keyword-case rule.

🔧 Proposed fix
 .DocSearch-Button-Container::before,
 .DocSearch-MagnifierLabel::before,
 .DocSearch-Close::before {
@@
-  background-color: currentColor;
+  background-color: currentcolor;
@@
 .theme-doc-markdown a[href^="http"]:not([href*="docs.unraid.net"]):not([href*="releases.unraid.net"]):not([href*="localhost"]):not([href*="127.0.0.1"])::after,
 .theme-blog-markdown a[href^="http"]:not([href*="docs.unraid.net"]):not([href*="releases.unraid.net"]):not([href*="localhost"]):not([href*="127.0.0.1"])::after {
@@
-  background-color: currentColor;
+  background-color: currentcolor;
#!/bin/bash
# Verify no remaining keyword-case violations for currentColor in this file
rg -n 'currentColor' src/css/custom.css

Also applies to: 366-369

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/css/custom.css` around lines 167 - 175, The CSS uses the mixed-case
keyword "currentColor" which violates the Stylelint keyword-case rule; update
occurrences in the selectors (e.g. .DocSearch-Button-Container::before,
.DocSearch-MagnifierLabel::before, .DocSearch-Close::before and the other block
around lines noted) by replacing "currentColor" with the lowercase
"currentcolor" (search for the string "currentColor" in src/css/custom.css and
replace both instances), then run the provided ripgrep check to verify no
remaining occurrences.

359-360: ⚠️ Potential issue | 🟡 Minor

Refactor chained :not() selectors to list notation for Stylelint compliance.

The chained :not(...) sequence on Line 359-Line 360 and Line 373-Line 374 triggers selector-not-notation; merge into one :not(selector-list) form.

🔧 Proposed fix
-.theme-doc-markdown a[href^="http"]:not([href*="docs.unraid.net"]):not([href*="releases.unraid.net"]):not([href*="localhost"]):not([href*="127.0.0.1"])::after,
-.theme-blog-markdown a[href^="http"]:not([href*="docs.unraid.net"]):not([href*="releases.unraid.net"]):not([href*="localhost"]):not([href*="127.0.0.1"])::after {
+.theme-doc-markdown a[href^="http"]:not([href*="docs.unraid.net"], [href*="releases.unraid.net"], [href*="localhost"], [href*="127.0.0.1"])::after,
+.theme-blog-markdown a[href^="http"]:not([href*="docs.unraid.net"], [href*="releases.unraid.net"], [href*="localhost"], [href*="127.0.0.1"])::after {
@@
-.theme-doc-markdown a[href^="http"]:not([href*="docs.unraid.net"]):not([href*="releases.unraid.net"]):not([href*="localhost"]):not([href*="127.0.0.1"]):hover::after,
-.theme-blog-markdown a[href^="http"]:not([href*="docs.unraid.net"]):not([href*="releases.unraid.net"]):not([href*="localhost"]):not([href*="127.0.0.1"]):hover::after {
+.theme-doc-markdown a[href^="http"]:not([href*="docs.unraid.net"], [href*="releases.unraid.net"], [href*="localhost"], [href*="127.0.0.1"]):hover::after,
+.theme-blog-markdown a[href^="http"]:not([href*="docs.unraid.net"], [href*="releases.unraid.net"], [href*="localhost"], [href*="127.0.0.1"]):hover::after {
#!/bin/bash
# Inspect external-link selectors for chained :not(...) usage
rg -n 'theme-(doc|blog)-markdown a\[href\^="http"\].*:not\([^)]*\):not\(' src/css/custom.css

Also applies to: 373-374

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/css/custom.css` around lines 359 - 360, Replace the chained :not(...)
pseudo-classes on the external-link selectors (the rules starting with
.theme-doc-markdown a[href^="http"] and .theme-blog-markdown a[href^="http"])
with a single :not(...) using a comma-separated selector list; update both
occurrences (the rule blocks that currently include multiple
:not([href*="docs.unraid.net"]):not([href*="releases.unraid.net"]):not([href*="localhost"]):not([href*="127.0.0.1"]))
to use one :not([href*="docs.unraid.net"], [href*="releases.unraid.net"],
[href*="localhost"], [href*="127.0.0.1"]) so the selectors comply with
Stylelint's selector-not-notation rule.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/css/custom.css`:
- Around line 167-175: The CSS uses the mixed-case keyword "currentColor" which
violates the Stylelint keyword-case rule; update occurrences in the selectors
(e.g. .DocSearch-Button-Container::before, .DocSearch-MagnifierLabel::before,
.DocSearch-Close::before and the other block around lines noted) by replacing
"currentColor" with the lowercase "currentcolor" (search for the string
"currentColor" in src/css/custom.css and replace both instances), then run the
provided ripgrep check to verify no remaining occurrences.
- Around line 359-360: Replace the chained :not(...) pseudo-classes on the
external-link selectors (the rules starting with .theme-doc-markdown
a[href^="http"] and .theme-blog-markdown a[href^="http"]) with a single
:not(...) using a comma-separated selector list; update both occurrences (the
rule blocks that currently include multiple
:not([href*="docs.unraid.net"]):not([href*="releases.unraid.net"]):not([href*="localhost"]):not([href*="127.0.0.1"]))
to use one :not([href*="docs.unraid.net"], [href*="releases.unraid.net"],
[href*="localhost"], [href*="127.0.0.1"]) so the selectors comply with
Stylelint's selector-not-notation rule.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b083314d-84b2-41ad-8677-a535620c1aca

📥 Commits

Reviewing files that changed from the base of the PR and between 00bc364 and f663d1c.

⛔ Files ignored due to path filters (4)
  • static/img/icons/tabler-chevron-up.svg is excluded by !**/*.svg
  • static/img/icons/tabler-external-link.svg is excluded by !**/*.svg
  • static/img/icons/tabler-search.svg is excluded by !**/*.svg
  • static/img/icons/tabler-x.svg is excluded by !**/*.svg
📒 Files selected for processing (1)
  • src/css/custom.css

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/css/custom.css (1)

15-24: Quote font names to follow CSS best practices.

The unquoted font identifiers (Roboto, Helvetica, Arial, BlinkMacSystemFont) should be quoted to improve consistency and ensure proper handling in edge cases.

🧹 Minimal fix
   --unraid-brand-font-family:
-    "nudista-web", -apple-system, system-ui, "Segoe UI", Roboto, Helvetica,
-    Arial, sans-serif;
+    "nudista-web", -apple-system, system-ui, "Segoe UI", "Roboto",
+    "Helvetica", "Arial", sans-serif;
@@
   --ifm-font-family-base:
     "Atkinson Hyperlegible Next Variable", system-ui, -apple-system,
-    BlinkMacSystemFont, "Segoe UI", sans-serif;
+    "BlinkMacSystemFont", "Segoe UI", sans-serif;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/css/custom.css` around lines 15 - 24, The CSS custom properties
--unraid-brand-font-family and --ifm-font-family-base contain unquoted font
identifiers; update these variables to quote the font family names mentioned
(e.g., "Roboto", "Helvetica", "Arial", "BlinkMacSystemFont") so all font tokens
are consistently quoted, preserving the existing comma-separated order and
fallback list in each property.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/theme/Layout/FeedbackWidget.tsx`:
- Around line 10-11: The first-paint flash happens because useIframe()
initializes to false then flips, so change useIframe to initialize its state as
undefined (or null) and set a boolean only inside the effect; then update
FeedbackWidget to gate rendering on the iframe check being settled by only
showing the widget when isInIframeState === false (i.e., explicitly false),
keeping the useState(false) for isOpen but ensuring the component returns
null/no markup while isInIframeState is undefined; reference useIframe() and the
isInIframeState variable in FeedbackWidget and the effect/state in
src/hooks/useIframe.ts to implement the change.
- Around line 47-48: The hard-coded English strings in the FeedbackWidget
component need to be routed through Docusaurus i18n helpers; import and use the
Translate component or translate() helper from '@docusaurus/Translate' in
FeedbackWidget and replace literal strings used in attributes and JSX (e.g.,
aria-label="Open feedback panel", title="Share feedback", the panel heading(s)
and button/placeholder texts around lines noted) with translated equivalents so
they render through the site i18n pipeline; update each literal (aria-label,
title, headings, button text, placeholders referenced in FeedbackWidget) to use
Translate or translate({message: ...}) so localization works.
- Around line 13-36: The FeedbackWidget useEffect currently only hides body
scroll and listens for Escape; add focus management and opener trapping: when
opening (isOpen true) save document.activeElement (the opener button), set the
opener button to aria-hidden="true" and tabIndex={-1}, move focus into the modal
by focusing the first focusable element inside the dialog, and install keyboard
handlers to trap Tab/Shift+Tab cycling within the modal; on close restore the
opener button attributes, return focus to the saved element, and remove the
added handlers and revert document.body.style.overflow. Update the effect's
cleanup and the component's opener button props (the element that calls
setIsOpen) to support aria-hidden/tabIndex changes and ensure the modal DOM node
is referenced (e.g., via a ref used in the effect) so you can find first/last
focusable elements for the trap.

---

Nitpick comments:
In `@src/css/custom.css`:
- Around line 15-24: The CSS custom properties --unraid-brand-font-family and
--ifm-font-family-base contain unquoted font identifiers; update these variables
to quote the font family names mentioned (e.g., "Roboto", "Helvetica", "Arial",
"BlinkMacSystemFont") so all font tokens are consistently quoted, preserving the
existing comma-separated order and fallback list in each property.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 650f4a3b-6dc1-465a-b7cb-282281ed5b3f

📥 Commits

Reviewing files that changed from the base of the PR and between f663d1c and 4552272.

📒 Files selected for processing (6)
  • AGENTS.md
  • src/components/ResponsiveEmbed/index.tsx
  • src/css/custom.css
  • src/theme/Layout/FeedbackWidget.tsx
  • src/theme/Layout/IframeNavigation.tsx
  • src/theme/Layout/Provider/index.tsx
✅ Files skipped from review due to trivial changes (2)
  • AGENTS.md
  • src/theme/Layout/IframeNavigation.tsx

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/theme/Layout/FeedbackWidget.tsx`:
- Around line 9-16: The focusable selector constant FOCUSABLE_SELECTOR (and the
other identical selector occurrences used for the modal focus trap) currently
omits iframe elements; update the selector(s) to include iframe (e.g., 'iframe'
or 'iframe[src]') so the embedded survey iframe is part of the focusable set and
keyboard navigation can reach it; modify the FOCUSABLE_SELECTOR definition and
any duplicate selectors referenced around the modal/focus-trap logic (the same
selectors at the other occurrences noted) to include the iframe selector.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 6d6f3f08-b2f1-499f-903e-06de294c6742

📥 Commits

Reviewing files that changed from the base of the PR and between 4552272 and 5f8e0c5.

📒 Files selected for processing (3)
  • src/css/custom.css
  • src/hooks/useIframe.ts
  • src/theme/Layout/FeedbackWidget.tsx
✅ Files skipped from review due to trivial changes (1)
  • src/css/custom.css

@elibosley elibosley merged commit 152a882 into main Mar 21, 2026
3 checks passed
@elibosley elibosley deleted the codex/docs-theme-refresh branch March 21, 2026 17:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant