Skip to content

feat(theme): add dark mode#649

Draft
ervcz wants to merge 8 commits into
mainfrom
ervin/feat/dark-mode
Draft

feat(theme): add dark mode#649
ervcz wants to merge 8 commits into
mainfrom
ervin/feat/dark-mode

Conversation

@ervcz

@ervcz ervcz commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

adds a dark/light toggle that remembers your choice, plus dark styles for most of the site.

  • theme switcher js + partial, wired into head/baseof
  • dark scss palette + dark syntax highlighting
  • dark styles for navbar, footer, search, blog, docs, product, careers, releases and 404
  • a11y: focus/selected colors, contrast, mobile toggle focus
  • dropped an unused static/js/common.js and fixed a dropdown null check

[Title: describe the change in one sentence]

[ describe the change in 1 - 3 paragraphs ]

How to use

[ describe what reviewers need to do in order to validate this PR ]

Testing done

[Describe the testing you have done before submitting this PR. Please include both the commands you issued as well as the output you got.]

  • Changelog entries added in the respective changelog/ directory (user-facing change, bug fix, security fix, update)
  • Inspected CI output for image differences: /boot and /usr size, packages, list files for any missing binaries, kernel modules, config files, kernel modules, etc.

Copilot AI review requested due to automatic review settings July 21, 2026 13:27
@ervcz
ervcz force-pushed the ervin/feat/dark-mode branch from eb79028 to 0d07496 Compare July 21, 2026 13:28
@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://lemon-wave-085522403-649.westeurope.1.azurestaticapps.net

1 similar comment
@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://lemon-wave-085522403-649.westeurope.1.azurestaticapps.net

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a site-wide dark/light/auto theme toggle (persisted via localStorage) and updates templates + styles to support Bootstrap color modes across most pages, including dark-mode syntax highlighting.

Changes:

  • Adds theme-mode plumbing (inline head script + switcher bundle + navbar dropdown) and wires it into key layouts.
  • Introduces a dark palette via Bootstrap dark-variable overrides and replaces many hard-coded light colors with CSS variables.
  • Adds a dark Chroma syntax theme and updates blog/docs/release/404 styling for dark mode.

Reviewed changes

Copilot reviewed 42 out of 42 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
themes/flatcar/layouts/taxonomy/tag.html Adds theme-mode + hero layout
themes/flatcar/layouts/section/releases.html Removes white box-shadow hacks
themes/flatcar/layouts/section/blog.html Refactors blog list template + theme-mode
themes/flatcar/layouts/partials/theme-mode.html New partial: head/body theme-mode emits
themes/flatcar/layouts/partials/navbar.html Adds theme selector dropdown
themes/flatcar/layouts/partials/hero.html Adjusts hero description fallback logic
themes/flatcar/layouts/partials/head.html Removes html/head/body wrappers; adds view-transition CSS
themes/flatcar/layouts/partials/footer.html Switches to fingerprinted common.js asset
themes/flatcar/layouts/partials/article.html Blog article layout updates for new hero usage
themes/flatcar/layouts/partials/announcement_banner.html Moves banner bg to CSS variable + class
themes/flatcar/layouts/docs/docsportal_home.html Adds theme-mode + html/head/body structure
themes/flatcar/layouts/docs/baseof.html Adds theme-mode + docs body class
themes/flatcar/layouts/careers/single.html Adds theme-mode + html/head/body structure
themes/flatcar/layouts/blog/single.html Adds hero + authors header above article
themes/flatcar/layouts/blog/baseof.html New blog base template with theme-mode
themes/flatcar/layouts/404.html Refactors markup + theme-mode includes
themes/flatcar/layouts/_default/baseof.html Adds theme-mode + home-page forced light attributes
themes/flatcar/assets/scss/sections/section-related-post.scss Converts colors to Bootstrap CSS vars
themes/flatcar/assets/scss/sections/section-product.scss Dark-mode variable-based styling, releases accent
themes/flatcar/assets/scss/sections/section-docs.scss Docs theming + layout alignment tweaks
themes/flatcar/assets/scss/sections/section-contact-us.scss Converts colors to Bootstrap CSS vars
themes/flatcar/assets/scss/search.scss Makes search UI color-mode compatible
themes/flatcar/assets/scss/partials/navbar.scss Adds theme-switcher styles + dropdown selector change
themes/flatcar/assets/scss/partials/hero.scss Dark-mode hero border + z-index adjustments
themes/flatcar/assets/scss/partials/header.scss Dark-mode scrolled header background
themes/flatcar/assets/scss/partials/grid-statements.scss Converts card/surface colors to CSS vars
themes/flatcar/assets/scss/partials/footer.scss Dark-mode footer/link colors
themes/flatcar/assets/scss/pages/blog-page.scss Blog hero overlap + dark-friendly surfaces
themes/flatcar/assets/scss/pages/article.scss Link/selection/related area dark-friendly updates
themes/flatcar/assets/scss/main.scss Imports dark syntax stylesheet
themes/flatcar/assets/scss/layouts.scss Dark-friendly muted text + 404 styling remains
themes/flatcar/assets/scss/buttons.scss Makes .btn-black invert in dark mode
themes/flatcar/assets/scss/_syntax.scss Updates comments to reflect new dark syntax
themes/flatcar/assets/scss/_syntax-dark.scss.parked Removes parked dark syntax file
themes/flatcar/assets/scss/_syntax-dark.scss Adds scoped dark Chroma theme
themes/flatcar/assets/scss/_styles.scss Adds Flatcar CSS custom properties + dark pagination vars
themes/flatcar/assets/scss/_custom.scss Adds Bootstrap dark-mode Sass variable overrides
themes/flatcar/assets/js/theme-switcher.js New JS: persisted theme switching + a11y focus handling
themes/flatcar/assets/js/common.js Updates mobile dropdown handling + code copy fix
static/js/common.js Removes unused static common.js
content/blog/_index.md Adds blog section front matter for hero config
config.yaml Updates syntax theme docs + changes Docs menu URL
Comments suppressed due to low confidence (1)

themes/flatcar/assets/scss/partials/navbar.scss:111

  • The desktop hover/focus dropdown rule now relies on the :has() selector (.nav-item.dropdown:not(:has(.theme-switcher__toggle))). In browsers that don't support :has(), this entire rule will be ignored, potentially breaking hover-to-open behavior for all dropdowns. Prefer excluding the theme switcher via an explicit class on the
  • (e.g. theme-switcher) and use .nav-item.dropdown:not(.theme-switcher) instead.
.nav-item.dropdown:not(:has(.theme-switcher__toggle))  {
  &:hover,&.focus {
    @include media-breakpoint-up(md) {
      > .dropdown-menu {
        display: block;
      }
    }
  }
}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread themes/flatcar/layouts/_default/baseof.html
Comment thread themes/flatcar/layouts/docs/baseof.html
Comment thread themes/flatcar/layouts/blog/baseof.html
Comment thread themes/flatcar/layouts/section/blog.html
Comment thread themes/flatcar/layouts/taxonomy/tag.html
Comment thread themes/flatcar/layouts/careers/single.html
Comment thread themes/flatcar/layouts/docs/docsportal_home.html
Comment on lines +3 to +6
<head>
{{- partial "head.html" . -}} {{ partial "theme-mode.html" (dict "part"
"head" "page" .) }}
</head>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed by centralizing the theme-init call in head.html before all stylesheet links. On themeable pages, data-bs-theme is now set before CSS loads; the home page remains explicitly forced to light mode.

Comment thread themes/flatcar/layouts/404.html
Comment thread config.yaml
Comment on lines 100 to 102
- name: Docs
url: /docs
url: /docs/latest
identifier: docs
Copilot AI review requested due to automatic review settings July 21, 2026 13:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (3)

themes/flatcar/layouts/partials/head.html:9

  • The dark/light FOUC-prevention script is currently emitted by callers after this partial, but this partial already outputs multiple tags (Google Fonts, Bootstrap, main.scss). That means the inline theme script runs too late to prevent a flash of the wrong theme.

A robust fix is to emit the theme-mode "head" part from inside head.html before any stylesheet links (and then remove the per-template theme-mode "head" calls to avoid duplication).
config.yaml:103

  • This PR is scoped to adding dark mode/theme toggling, but it also changes the main menu Docs URL from /docs to /docs/latest. That’s a user-facing navigation change unrelated to theming and should either be justified in the PR description or reverted to keep scope focused.
      identifier: releases
      weight: -400
    - name: Docs
      url: /docs/latest
      identifier: docs
      weight: -200

themes/flatcar/layouts/404.html:12

  • The 404 template no longer renders the /images/404.svg illustration that was previously shown. The PR description mentions adding dark styles for the 404 page, but not removing the illustration; if this removal is intentional, it should be called out explicitly since it changes the 404 page content/layout.
    <main class="main notfound row">
      <div class="mx-auto my-auto content">
        <h1>Whoops! Something's missing!</h1>
        <h2>Not to worry, head back <a href="/">home</a>!</h2>
      </div>

Comment thread themes/flatcar/layouts/partials/head.html Outdated
Comment on lines +11 to +19
var ICONS = { auto: "auto-icon", light: "sun-icon", dark: "moon-icon" };

function stored() {
try {
return localStorage.getItem(KEY) || AUTO;
} catch (e) {
return AUTO;
}
}
Copilot AI review requested due to automatic review settings July 22, 2026 12:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (2)

themes/flatcar/layouts/partials/head.html:112

  • The reduced-motion media query is invalid without a value, so the View Transition animations won’t be disabled for users who prefer reduced motion. Use the standard syntax prefers-reduced-motion: reduce.
    themes/flatcar/layouts/404.html:11
  • The 404 page removed the previous illustration (404.svg). This is a visible content change not mentioned in the PR description; if it’s intentional, it should be called out in the PR, otherwise consider restoring the image (possibly with a dark-mode friendly asset).
    <main class="main notfound row">
      <div class="mx-auto my-auto content">
        <h1>Whoops! Something's missing!</h1>
        <h2>Not to worry, head back <a href="/">home</a>!</h2>
      </div>

Comment thread themes/flatcar/layouts/partials/navbar.html Outdated
}

.nav-item.dropdown {
.nav-item.dropdown:not(:has(.theme-switcher__toggle)) {
@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://lemon-wave-085522403-649.westeurope.1.azurestaticapps.net

ervcz added 3 commits July 22, 2026 17:33
adds a dark/light toggle that remembers your choice, plus dark styles
for most of the site.

- theme switcher js + partial, wired into head/baseof
- dark scss palette + dark syntax highlighting
- dark styles for navbar, footer, search, blog, docs, product, careers,
  releases and 404
- a11y: focus/selected colors, contrast, mobile toggle focus
- dropped an unused static/js/common.js and fixed a dropdown null check

Signed-off-by: Ervin Rácz <ervin.racz@protonmail.com>
- move the theme script into head.html before the stylesheets so the right
  theme paints first, and drop the duplicate call from each layout head
- set $link-color so body links aren't black in light mode, and remove the
  global a:hover override so the per-theme hover colors apply
- use the theme link color for the docs toc and code-copy hover, which were
  low-contrast on the dark code background
- add accessible light syntax-token variants that clear wcag aa
- give navbar controls a visible focus ring in both themes
- keep product cta text readable on hover
- honor prefers-reduced-motion
- drop an unused variable

Signed-off-by: Ervin Rácz <ervin.racz@protonmail.com>
- releases: use --flatcar-accent for badge/hover/version colours so they
  meet contrast on the dark cards
- search: dark-mode highlight now uses near-solid brand yellow with dark
  text instead of low-contrast translucent yellow
- theme init: ignore invalid stored modes and keep following the system
  theme on pages without a switcher (e.g. 404)
- reduced-motion: also cap animation iterations
- switcher: options are radio buttons (role=menuitemradio, aria-checked),
  the toggle announces the active theme, and selection is delegated so
  extra switcher instances stay in sync
- restore the "Posts Tagged #<tag>" heading on tag pages

Signed-off-by: Ervin Rácz <ervin.racz@protonmail.com>
Copilot AI review requested due to automatic review settings July 22, 2026 14:33
@ervcz
ervcz force-pushed the ervin/feat/dark-mode branch from e0e001c to 6493df3 Compare July 22, 2026 14:33
@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://lemon-wave-085522403-649.westeurope.1.azurestaticapps.net

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

themes/flatcar/layouts/partials/head.html:116

  • The media query @media (prefers-reduced-motion) is not a valid prefers-reduced-motion query in CSS; it should specify a value (e.g. reduce). As written, the rule will be ignored so view-transition animations won’t be disabled for reduced-motion users.

Comment on lines +111 to +114
var menu = (toggle.closest(".dropdown") || document).querySelector(
".theme-switcher__menu",
);
if (!menu) return;
Comment thread themes/flatcar/assets/js/common.js
@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://lemon-wave-085522403-649.westeurope.1.azurestaticapps.net

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

themes/flatcar/layouts/partials/head.html:116

  • The prefers-reduced-motion media query is invalid as written (@media (prefers-reduced-motion)); it won’t match and the View Transition animations won’t be disabled for users who request reduced motion. Use the correct feature syntax prefers-reduced-motion: reduce.
    themes/flatcar/assets/js/theme-switcher.js:113
  • There is an unnecessary trailing comma in the querySelector() call argument list. Trailing commas in function calls can break parsing in older JS engines and aren’t needed here.
      var menu = (toggle.closest(".dropdown") || document).querySelector(
        ".theme-switcher__menu",
      );

Found during the dark-mode review; not part of the theme feature itself:

- .navbar-toggler had `outline: none !important`, leaving the mobile menu
  button with no keyboard focus indicator; add a :focus-visible ring
- pagination active/hover was white on cyan (3.09:1); use navy text (5.75:1)
- docs body links (.td-content a) were cyan on white (3.09:1); use the
  theme link colour (5.85:1 light / 5.75:1 dark), consistent with site links

Signed-off-by: Ervin Rácz <ervin.racz@protonmail.com>
Copilot AI review requested due to automatic review settings July 22, 2026 15:22
@ervcz
ervcz force-pushed the ervin/feat/dark-mode branch from 4babd51 to 7e6b7a7 Compare July 22, 2026 15:22
@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://lemon-wave-085522403-649.westeurope.1.azurestaticapps.net

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (2)

themes/flatcar/layouts/partials/head.html:112

  • The media query uses an invalid prefers-reduced-motion syntax. prefers-reduced-motion requires a value (e.g. reduce), otherwise the rule won’t match and view-transition animations won’t be disabled for users who request reduced motion.
    config.yaml:102
  • The main menu Docs link was changed from /docs to /docs/latest, which is unrelated to the dark-mode work described in the PR description. If this navigation change is intentional, it should be called out explicitly in the PR description (or moved to a separate PR) to avoid surprising reviewers/users.
      identifier: releases
      weight: -400
    - name: Docs
      url: /docs/latest
      identifier: docs

Comment on lines +90 to +94
window
.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", function () {
if (stored() === AUTO) updateUI(AUTO);
});
- Replace `addEventListener` with fallback to `addListener` for older browsers
- Add `e.preventDefault()` to prevent default link behavior
- Fix `prefers-reduced-motion` media query syntax
- Update CSS selector for theme-switcher dropdown
- Remove unused image max-width style

Signed-off-by: Ervin Rácz <ervin.racz@protonmail.com>
Copilot AI review requested due to automatic review settings July 23, 2026 09:10
@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://lemon-wave-085522403-649.westeurope.1.azurestaticapps.net

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated 2 comments.

Comment on lines +16 to +20
{{ if and (eq .Kind "term") (eq .Data.Singular "tag") }}
{{ $title = printf "Posts Tagged #%s" $title }}
{{ end }}
{{ $description := index $hero "description" }}
{{ if eq $description nil }}
Comment on lines +81 to +84
if (t && window.bootstrap) {
var d = bootstrap.Dropdown.getInstance(t);
if (d) d.hide();
}
- Revert docs URL from /docs/latest to /docs

Signed-off-by: Ervin Rácz <ervin.racz@protonmail.com>
Copilot AI review requested due to automatic review settings July 23, 2026 11:22
@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://lemon-wave-085522403-649.westeurope.1.azurestaticapps.net

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated 2 comments.


{{ if eq .part "head" }}
{{ if not .page.IsHome }}
<script>(function(){var m="auto";try{var s=localStorage.getItem("theme-mode");if(s==="light"||s==="dark")m=s}catch(e){}var t=m==="auto"?window.matchMedia("(prefers-color-scheme:dark)").matches?"dark":"light":m;document.documentElement.setAttribute("data-bs-theme",t)})()</script>
Comment on lines +73 to +75
<div class="dropdown-menu dropdown-menu-end theme-switcher__menu" role="menu" aria-label="Theme">
{{- range $themes }}
<button type="button" class="dropdown-item theme-switcher__option" role="menuitemradio" aria-checked="false" data-theme-mode="{{ .mode }}">
- Guard hero configuration with `with` block to prevent nil pointer errors
- Simplify theme dropdown hide logic using `getOrCreateInstance`
- Preserve existing inheritance behavior for hero section parameters

Signed-off-by: Ervin Rácz <ervin.racz@protonmail.com>
Copilot AI review requested due to automatic review settings July 23, 2026 11:36
@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://lemon-wave-085522403-649.westeurope.1.azurestaticapps.net

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

themes/flatcar/layouts/docs/docsportal_home.html:86

  • After closing the header .container.main-container near the top of the section, the </div> immediately before </section> becomes an extra unmatched closing tag. Remove it to keep the <div> nesting balanced.

Comment on lines +25 to +27
{{ $homeParams := .Params }}
<div class="container">
<div class="row">
- Replace `aria-checked` with `aria-pressed` for theme toggle buttons
- Add `role="button"` to theme switcher toggle link
- Remove redundant `role="menu"` and `role="menuitemradio` attributes
- Improve semantic HTML for dropdown menu structure

Signed-off-by: Ervin Rácz <ervin.racz@protonmail.com>
Copilot AI review requested due to automatic review settings July 23, 2026 12:18
@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://lemon-wave-085522403-649.westeurope.1.azurestaticapps.net

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated no new comments.

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.

2 participants