-
Notifications
You must be signed in to change notification settings - Fork 0
Refine docs dark theme contrast #42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,13 @@ const config = { | |
| turbopack: { | ||
| root: __dirname, | ||
| }, | ||
| async rewrites() { | ||
| // Agent-friendly: `curl https://docs/<slug>.md` returns raw markdown. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: Rewrite destination path separator — slash vs. dot mismatch The catch-all rewrite rule uses The actual risk is at the boundary: the |
||
| return [ | ||
| { source: '/index.md', destination: '/llms.mdx/docs/content.md' }, | ||
| { source: '/:path*.md', destination: '/llms.mdx/docs/:path*/content.md' }, | ||
| ]; | ||
| }, | ||
| }; | ||
|
|
||
| export default withMDX(config); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,38 +2,82 @@ | |
| @import 'fumadocs-ui/css/neutral.css'; | ||
| @import 'fumadocs-ui/css/preset.css'; | ||
|
|
||
| /* Mogplex brand colors — monochrome theme, aligned with mogplex.com */ | ||
| /* Mogplex docs theme: quiet dark technical reference surface. */ | ||
| :root { | ||
| --font-sans: var(--font-geist-sans); | ||
| --font-mono: var(--font-geist-mono); | ||
|
|
||
| /* Light mode tokens — warm cream surface, neutral ink */ | ||
| --color-fd-background: #f6f5f1; | ||
| --color-fd-foreground: #171717; | ||
| --color-fd-card: #ffffff; | ||
| --color-fd-muted: #efede7; | ||
| --color-fd-muted-foreground: #78716c; | ||
| --color-fd-primary: #171717; | ||
| --color-fd-primary-foreground: #fafaf9; | ||
| --color-fd-accent: #ebe7dd; | ||
| --color-fd-accent-foreground: #171717; | ||
| --color-fd-border: #ddd7ca; | ||
| --color-fd-ring: #171717; | ||
| --bg-canvas: hsl(0 0% 2%); | ||
| --bg-surface: hsl(0 0% 2%); | ||
| --bg-sidebar: hsl(0 0% 8%); | ||
| --bg-elevated: #16161a; | ||
| --bg-hover: rgba(255, 255, 255, 0.04); | ||
| --bg-overlay: rgba(0, 0, 0, 0.62); | ||
|
|
||
| --border-subtle: rgba(255, 255, 255, 0.05); | ||
| --border-default: rgba(255, 255, 255, 0.08); | ||
| --border-strong: rgba(255, 255, 255, 0.12); | ||
|
|
||
| --text-primary: rgba(255, 255, 255, 0.92); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Warning: --text-tertiary fails WCAG AA contrast (TOC, prose bullets)
Affected surfaces:
For a docs site, TOC navigation and list counters are core reading aids; failing AA here is a real accessibility regression. Suggestion: Raise |
||
| --text-body: rgba(255, 255, 255, 0.74); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Warning: Several text tokens fail WCAG AA contrast on their respective backgrounds The new token values produce contrast ratios below 4.5:1 (AA for normal text) in some combinations:
Sidebar navigation links ( |
||
| --text-secondary: rgba(255, 255, 255, 0.62); | ||
| --text-tertiary: rgba(255, 255, 255, 0.5); | ||
| --text-logo: rgba(255, 255, 255, 0.96); | ||
|
|
||
| --accent: #af71d2; | ||
| --accent-soft: rgba(175, 113, 210, 0.12); | ||
| --accent-underline: rgba(175, 113, 210, 0.4); | ||
| } | ||
|
|
||
| .light { | ||
| --bg-canvas: #f6f5f1; | ||
| --bg-surface: #ffffff; | ||
| --bg-sidebar: #efede7; | ||
| --bg-elevated: #faf9f5; | ||
| --bg-hover: rgba(23, 23, 23, 0.05); | ||
| --bg-overlay: rgba(23, 23, 23, 0.4); | ||
|
|
||
| --border-subtle: rgba(23, 23, 23, 0.08); | ||
| --border-default: rgba(23, 23, 23, 0.12); | ||
| --border-strong: rgba(23, 23, 23, 0.18); | ||
|
|
||
| --text-primary: rgba(23, 23, 23, 0.92); | ||
| --text-body: rgba(23, 23, 23, 0.78); | ||
| --text-secondary: rgba(23, 23, 23, 0.7); | ||
| --text-tertiary: rgba(23, 23, 23, 0.64); | ||
| --text-logo: rgba(23, 23, 23, 0.96); | ||
|
|
||
| --accent: #7d3fa2; | ||
| --accent-soft: rgba(125, 63, 162, 0.11); | ||
| --accent-underline: rgba(125, 63, 162, 0.42); | ||
| } | ||
|
|
||
| :root, | ||
| .light, | ||
| .dark { | ||
|
Comment on lines
+55
to
57
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The theme variables are now assigned identically for Useful? React with 👍 / 👎.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dismissing — the theme switcher is disabled in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: In The real problem is ordering: because More concretely: the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dismissing — same reason as the sibling Codex thread. Theme switcher is disabled ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: :root defaults dark tokens —
The cascade for Separately: the |
||
| /* Dark mode tokens — pure black surface, white ink */ | ||
| --color-fd-background: #0a0a0a; | ||
| --color-fd-foreground: #ededed; | ||
| --color-fd-card: #111111; | ||
| --color-fd-muted: #1a1a1a; | ||
| --color-fd-muted-foreground: #a1a1a1; | ||
| --color-fd-primary: #ffffff; | ||
| --color-fd-primary-foreground: #0a0a0a; | ||
| --color-fd-accent: #1e1e1e; | ||
| --color-fd-accent-foreground: #ededed; | ||
| --color-fd-border: #262626; | ||
| --color-fd-ring: #ffffff; | ||
| --color-fd-background: var(--bg-surface); | ||
| --color-fd-foreground: var(--text-body); | ||
| --color-fd-card: var(--bg-elevated); | ||
| --color-fd-card-foreground: var(--text-body); | ||
| --color-fd-muted: var(--bg-elevated); | ||
| --color-fd-muted-foreground: var(--text-secondary); | ||
| --color-fd-popover: var(--bg-elevated); | ||
| --color-fd-popover-foreground: var(--text-body); | ||
| --color-fd-primary: var(--accent); | ||
| --color-fd-primary-foreground: var(--text-primary); | ||
| --color-fd-secondary: var(--bg-elevated); | ||
| --color-fd-secondary-foreground: var(--text-body); | ||
| --color-fd-accent: var(--accent-soft); | ||
| --color-fd-accent-foreground: var(--text-primary); | ||
| --color-fd-border: var(--border-default); | ||
| --color-fd-ring: var(--border-strong); | ||
| --color-fd-overlay: var(--bg-overlay); | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: Inline Line ~73: |
||
|
|
||
| html, | ||
| body { | ||
| background: var(--bg-canvas); | ||
| color: var(--text-body); | ||
| } | ||
|
|
||
| html { | ||
|
|
@@ -45,6 +89,197 @@ html > body[data-scroll-locked] { | |
| --removed-body-scroll-bar-size: 0px !important; | ||
| } | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Warning: Hard-coded Roughly 200 lines of the new CSS target internal fumadocs DOM IDs ( |
||
| #nd-docs-layout { | ||
| position: relative; | ||
| z-index: 1; | ||
| background-color: var(--bg-canvas); | ||
| color: var(--text-body); | ||
| } | ||
|
|
||
| #nd-page { | ||
| min-height: 100dvh; | ||
| background: var(--bg-surface); | ||
| border-inline: 1px solid var(--border-subtle); | ||
| color: var(--text-body); | ||
| } | ||
|
|
||
| #nd-page h1, | ||
| #nd-page h2, | ||
| #nd-page h3, | ||
| #nd-page h4, | ||
| #nd-page h5, | ||
| #nd-page h6 { | ||
| color: var(--text-primary); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: #nd-page > p selector is likely dead CSS
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Warning: Fumadocs internal ID selectors ( The entire theming strategy relies on overriding styles via Fumadocs exposes a CSS variable override mechanism (the |
||
| } | ||
|
|
||
| #nd-page > .border-b { | ||
| border-color: var(--border-subtle); | ||
| } | ||
|
|
||
| #nd-sidebar, | ||
| #nd-sidebar-mobile { | ||
| background: var(--bg-sidebar) !important; | ||
| border-color: var(--border-default) !important; | ||
| color: var(--text-secondary); | ||
| } | ||
|
|
||
| #nd-sidebar a, | ||
| #nd-sidebar button, | ||
| #nd-sidebar p, | ||
| #nd-sidebar-mobile a, | ||
| #nd-sidebar-mobile button, | ||
| #nd-sidebar-mobile p { | ||
| color: var(--text-secondary); | ||
| } | ||
|
|
||
| #nd-sidebar a:not([data-active='true']):hover, | ||
| #nd-sidebar button:hover, | ||
| #nd-sidebar-mobile a:not([data-active='true']):hover, | ||
| #nd-sidebar-mobile button:hover { | ||
| background: var(--bg-hover); | ||
| color: var(--text-body); | ||
| } | ||
|
|
||
| #nd-sidebar a[data-active='true'], | ||
| #nd-sidebar-mobile a[data-active='true'] { | ||
| position: relative; | ||
| background: var(--accent-soft) !important; | ||
| color: var(--text-primary) !important; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: Active sidebar indicator ::after relies on undeclared position:relative The #nd-sidebar a[data-active='true']::after {
position: absolute;
inset-block: 0.625rem;
inset-inline-start: 0;
...
}For this to render correctly, the Suggestion: Add |
||
| } | ||
|
|
||
| #nd-sidebar a[data-active='true']::before, | ||
| #nd-sidebar-mobile a[data-active='true']::before { | ||
| display: none !important; | ||
| } | ||
|
|
||
| #nd-sidebar a[data-active='true']::after, | ||
| #nd-sidebar-mobile a[data-active='true']::after { | ||
| content: ''; | ||
| position: absolute; | ||
| inset-block: 0.625rem; | ||
| inset-inline-start: 0; | ||
| width: 2px; | ||
| border-radius: 999px; | ||
| background: var(--accent); | ||
| } | ||
|
|
||
| #nd-toc { | ||
| color: var(--text-tertiary); | ||
| } | ||
|
|
||
| #nd-toc #toc-title, | ||
| #nd-toc a { | ||
| color: var(--text-tertiary) !important; | ||
| } | ||
|
|
||
| #nd-toc a:hover { | ||
| color: var(--text-secondary) !important; | ||
| } | ||
|
|
||
| #nd-toc a[data-active='true'] { | ||
| color: var(--text-primary) !important; | ||
| } | ||
|
|
||
| #nd-toc [class*='border-fd-foreground'] { | ||
| border-color: var(--border-subtle) !important; | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: Prose link color is Links in prose are styled |
||
|
|
||
| #nd-page .prose { | ||
| --tw-prose-body: var(--text-body); | ||
| --tw-prose-headings: var(--text-primary); | ||
| --tw-prose-lead: var(--text-body); | ||
| --tw-prose-links: var(--text-body); | ||
| --tw-prose-bold: var(--text-primary); | ||
| --tw-prose-counters: var(--text-secondary); | ||
| --tw-prose-bullets: var(--text-secondary); | ||
| --tw-prose-hr: var(--border-subtle); | ||
| --tw-prose-quotes: var(--text-body); | ||
| --tw-prose-quote-borders: var(--border-default); | ||
| --tw-prose-captions: var(--text-secondary); | ||
| --tw-prose-code: var(--text-primary); | ||
| --tw-prose-th-borders: var(--border-subtle); | ||
| --tw-prose-td-borders: var(--border-subtle); | ||
| --tw-prose-kbd: var(--text-primary); | ||
| } | ||
|
|
||
| #nd-page .prose :where(h1, h2, h3, h4, h5, h6, strong):not( | ||
| :where([class~='not-prose'], [class~='not-prose'] *) | ||
| ) { | ||
| color: var(--text-primary); | ||
| } | ||
|
|
||
| #nd-page .prose :where(p, li):not( | ||
| :where([class~='not-prose'], [class~='not-prose'] *) | ||
| ) { | ||
| color: var(--text-body); | ||
| } | ||
|
|
||
| #nd-page .prose :where(a:not([data-card])):not( | ||
| :where([class~='not-prose'], [class~='not-prose'] *) | ||
| ) { | ||
| color: var(--text-body); | ||
| text-decoration-color: var(--accent-underline); | ||
| text-decoration-thickness: 1px; | ||
| opacity: 1; | ||
| } | ||
|
|
||
| #nd-page .prose :where(a:not([data-card]):hover):not( | ||
| :where([class~='not-prose'], [class~='not-prose'] *) | ||
| ) { | ||
| color: var(--accent); | ||
| opacity: 1; | ||
| } | ||
|
|
||
| #nd-page .prose :where(table):not( | ||
| :where([class~='not-prose'], [class~='not-prose'] *) | ||
| ) { | ||
| background: var(--bg-elevated); | ||
| border-color: var(--border-subtle); | ||
| } | ||
|
|
||
| #nd-page .prose :where(th):not( | ||
| :where([class~='not-prose'], [class~='not-prose'] *) | ||
| ) { | ||
| background: var(--bg-elevated); | ||
| border-color: var(--border-subtle); | ||
| color: var(--text-secondary); | ||
| } | ||
|
|
||
| #nd-page .prose :where(td):not( | ||
| :where([class~='not-prose'], [class~='not-prose'] *) | ||
| ) { | ||
| border-color: var(--border-subtle); | ||
| color: var(--text-secondary); | ||
| } | ||
|
|
||
| #nd-page .prose :where(code):not( | ||
| :where(pre code, [class~='not-prose'], [class~='not-prose'] *) | ||
| ) { | ||
| border: 1px solid var(--border-subtle); | ||
| border-radius: 0.25rem; | ||
| background: var(--bg-elevated); | ||
| padding: 0.125em 0.35em; | ||
| color: var(--text-primary); | ||
| } | ||
|
|
||
| #nd-page figure.shiki, | ||
| #nd-page [data-card='true'], | ||
| #nd-page table, | ||
| #nd-page [role='alert'] { | ||
| background-color: var(--bg-elevated); | ||
| border-color: var(--border-default); | ||
| } | ||
|
|
||
| #nd-page [data-card='true'] { | ||
| border-radius: 0.5rem; | ||
| } | ||
|
|
||
| #nd-docs-layout .shadow-sm, | ||
| #nd-docs-layout .shadow-md, | ||
| #nd-docs-layout .shadow-lg { | ||
| box-shadow: none !important; | ||
| } | ||
|
|
||
| @media (min-width: 768px) { | ||
| #nd-docs-layout { | ||
| --fd-sidebar-width: 270px; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Warning:
.mdrewrite conflicts with Next.js static asset handlingNext.js serves files in the
public/directory as static assets before rewrites are evaluated. If any.mdfile is ever placed inpublic/(e.g. aCHANGELOG.mdorREADME.mdfor agent crawling), it would bypass the rewrite silently. This is low risk currently but worth a short comment on the rewrite to document the assumption that no.mdfiles live inpublic/.