Skip to content

refactor: move the site theme and chrome into a local extension - #2222

Merged
cderv merged 29 commits into
quarto-dev:mainfrom
mcanouil:refactor/quartoorg-extension
Oct 15, 2026
Merged

cderv merged 29 commits into
quarto-dev:mainfrom
mcanouil:refactor/quartoorg-extension

Conversation

@mcanouil

@mcanouil mcanouil commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

This moves the site's theme, scripts, Lua filters and chrome into a local extension, _extensions/quartoorg/, used through a quartoorg project type.
Pages no longer set a format; they inherit quartoorg-html from the project.
Brand images move to assets/images/, and the old /quarto.png URL redirects, since the brand docs used it in an example.
The page chooser shortcode and the accessibility fixes from main are part of the extension too, with their CSS now in the theme's SCSS.

The site should look the same as before once deployed. (Locally it does, except notebook preview, see issue below)
The one intended change is in dark mode, where borders now use $gray-400.
That's 3.70:1 against the page instead of 1.08:1, so they're actually visible, and the chooser and tool tiles no longer need their own #6c757d override.
An axe scan of the whole site finds the same issues as on main.

A new check, _tools/check-site-format.ts, stops a format: html from quietly dropping the site theme again.
It runs in CI and in the pre-commit hook, and it'll only block pull requests from forks once the check-site-format job is a required check.


This is to centralise/harmonise all themes together and tidy up a bit the repository.
This will help integrate #2140 with more chrome consistency, while also helping maintaining/updating it.


Caveat

Notebook preview pages lose everything in the site format except the theme, so the Posit badge, the code copy buttons and the site's grid widths are missing there (quarto-dev/quarto-cli#14954).

Notebook preview page for penguins.ipynb on main (top) and on this branch (bottom). On main, the navbar shows the supported by Posit badge and each code cell has a copy button. On this branch, both are missing and the content column is narrower and shifted right.

@cwickham

cwickham commented Oct 2, 2026

Copy link
Copy Markdown
Member

The accessibility contrast fixes that touch the theme are all in main now, including the new light-mode $primary (#2241), so you're clear to go ahead with this refactor.

I did a refactor of the tool choosers in #2258, so your rebase needs to include them:

  • The new chooser code is all in new files: _extensions/page-chooser/. You can keep it as a separate extension or move it into quartoorg. Its CSS is plain CSS with Bootstrap custom properties, so it can also become an SCSS partial if you rename the file.
  • filters/tools-tabset.lua changes only in the injected script. Git follows your rename.
  • styles.css conflicts with your rebase in any case. _tools-tabset.scss was copied before Move "Choose your tool" out of the tools-tabset tablist #2233 merged, so it does not have these rules from main:

Two things that can help with your goal of fewer places to add CSS:

  1. After Make the tool choosers consistent #2258, docs/get-started/tutorial.css and docs/manuscripts/tutorial.css hold only .step and .tool rules. The .tool block is the same in both files, so you can move it into quartoorg/scss/partials/.

  2. In the dark theme, --bs-border-color is rgba(36, 36, 38, 0.5), which is 1.08:1 against the page background, so borders are almost invisible. Make the tool choosers consistent #2258 overrides it for the chooser tiles with #6c757d. If the dark theme sets $border-color (for example $gray-400, 3.70:1), you can remove that override. This changes every dark-mode border on the site, so it needs a visual check.

@mcanouil
mcanouil force-pushed the refactor/quartoorg-extension branch 2 times, most recently from 1b2b923 to d8af130 Compare October 6, 2026 14:11
@mcanouil
mcanouil marked this pull request as ready for review October 6, 2026 14:25
@mcanouil

mcanouil commented Oct 6, 2026

Copy link
Copy Markdown
Collaborator Author

@cderv @cwickham the branch is rebased on main and includes all your changes, including the dark $border-color fix (the only visual change from main, borders in dark mode).
A full-site axe scan finds the same issues as on main.

One caveat: notebook preview pages only keep the theme (quarto-dev/quarto-cli#14954), so they lose the Posit badge, copy buttons and grid widths (screenshot in the PR description).
I think it's fine to merge since it's tracked upstream, but happy to hear otherwise.

@cwickham

cwickham commented Oct 6, 2026

Copy link
Copy Markdown
Member

/deploy-preview

@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

📝 Preview Deployment

🔍 Full site preview: https://deploy-preview-2222.quarto.org

🔄 Modified Documents

@cwickham

cwickham commented Oct 7, 2026

Copy link
Copy Markdown
Member

#2276 changes the announcement banner colours, this PR will need the same changes in the extension:

  1. In _extensions/quartoorg/scss/partials/_dark-rules.scss, change the #quarto-announcement background from #ff0039 to #447099. The main banner then has the same colour in light and dark mode.
  2. Rename _extensions/quartoorg/scss/prerelease.scss to prerelease-banner.scss. Use the #e60033 background from Reserve the red announcement banner for prerelease and fix its contrast #2276 (4.76:1 with white text). Cosmo's $danger gives only 3.95:1.
  3. In _quarto-prerelease-docs.yml, add the banner file to the dark theme too.
--- a/_extensions/quartoorg/scss/partials/_dark-rules.scss
+++ b/_extensions/quartoorg/scss/partials/_dark-rules.scss
@@ #quarto-announcement {
   padding: 1em;
   font-size: 1em;
   font-weight: bold;
   color: $white;
-  background-color: #ff0039; 
+  background-color: #447099; 
 }
--- a/_extensions/quartoorg/scss/prerelease.scss
+++ b/_extensions/quartoorg/scss/prerelease-banner.scss
@@
 /*-- scss:rules --*/
 
+// Red marks the prerelease site, in light and dark mode.
+// #e60033 gives white text 4.76:1 (WCAG 1.4.3 needs 4.5:1).
+// Cosmo's $danger (#ff0039) gives only 3.95:1.
 #quarto-announcement {
   font-size: 1em;
   font-weight: bold;
   color: $white;
-  background-color: $danger; 
+  background-color: #e60033;
 }
--- a/_quarto-prerelease-docs.yml
+++ b/_quarto-prerelease-docs.yml
@@ format:
   quartoorg-html:
     theme:
-      light: [_extensions/quartoorg/scss/prerelease.scss]
+      light: [_extensions/quartoorg/scss/prerelease-banner.scss]
+      dark: [_extensions/quartoorg/scss/prerelease-banner.scss]

The behaviour should be:

Profile Light Dark
default #447099 #447099
prerelease-docs #e60033 (overrides #447099) #e60033 (overrides #447099)

Pages with code-tools show their own front matter to readers. Setting their options at the top level lets them inherit the site format, so copied source still renders outside quarto.org.
git ls-files still lists a page deleted from the working tree, which made the check crash. A front matter parse error now names the file.
The pre-commit hook now checks the staged files only, as check-freeze.sh does; CI still checks the whole tree. The prerelease profile no longer repeats the toc setting the extension already provides.
Pages and _metadata.yml files no longer name quartoorg-html. They drop the format key and set their options at the top level, so they inherit the format from the project. Only html-multi-format.qmd, which lists several formats, still names it.
The staged check now reads the staged content, the project config files are checked too, and the pre-commit hook skips the check with a warning when quarto is not installed.
The check now works from any subdirectory and names a notebook it cannot parse. Its tests also run the script in a scratch repository, covering the staged and full modes.
A file the check cannot parse now exits with code 2 and a plain message, the two scripts are listed in _tools/README.md, and the CI job comment matches its trigger.
Notebook preview pages render with the built-in html format, so they missed respect-user-color-scheme. Setting it at the project level reaches them too.
Page styles written as raw HTML in the body now sit in include-in-header, so they land in the page head. The extension listing pages share theirs through listings/_metadata.yml.
js/lottie.min.js moves to assets/js/ with a redirect from its old URL, and ejs/links.ejs moves to assets/ejs/.
Only /quarto.png was published as a URL for readers to use. The other moved assets are loaded by quarto.org's own pages, which use the new paths.
The contrast and layout fixes that landed on main in theme.scss,
theme-dark.scss and styles.css now live in the extension SCSS.
The ui-icon and category chip rules were the same in both themes, so
they sit once in the shared content partial.
The page-chooser shortcode from main now ships with quartoorg, and its
stylesheet is an SCSS partial in the theme bundle. The tool tile rules
that both tutorial.css files repeated now sit in one partial too.
shift-headings.lua joins the extension filters in the same order as
before, and axe-page-links.lua moves next to the only page that uses it.
Three pages were re-executed so their freeze hashes match the sources
again. The plot images are main's, since a fresh run only changes their
anti-aliasing.
The dark theme's border colour was 1.08:1 against the page, so borders
were barely there. $gray-400 gives 3.70:1, which meets the 3:1 that
WCAG 1.4.11 asks for, and the chooser and tool tiles no longer need
their own #6c757d override. This changes every border in dark mode.
The three re-executed freezes now hold main's output with only the new
front matter. Re-running gave the Leaflet widgets new random IDs, and
the axe baseline matches those markers by ID, so they showed up as new
findings.
The main site's banner is now the brand blue in dark mode too, as on
main. The prerelease banner moves to prerelease-banner.scss with
#e60033, which gives white text 4.76:1, and the prerelease profile
applies it to the dark theme as well.
@mcanouil
mcanouil force-pushed the refactor/quartoorg-extension branch from d8af130 to a23a51d Compare October 7, 2026 21:21
@mcanouil

mcanouil commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator Author

Updated.

@cwickham

Copy link
Copy Markdown
Member

/deploy-preview

@github-actions

Copy link
Copy Markdown
Contributor

📝 Preview Deployment

🔍 Full site preview: https://deploy-preview-2222.quarto.org

🔄 Modified Documents

@mcanouil

Copy link
Copy Markdown
Collaborator Author

@cderv if you merge this, don't move it out of the repo yet.
As having the extension here will help checking accessibility/layout on the whole website more easily when working on integrating the gallery.

@cderv cderv assigned cderv and unassigned mcanouil Oct 15, 2026
@cderv
cderv self-requested a review October 15, 2026 12:53

@cderv cderv left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for this work.

Before merging, I will add redirects for the moved public files. Only /quarto.png is redirected. These return 200 on quarto.org today and 404 on the preview:

  • /favicon.png, which other sites hotlink in their footers and READMEs.
  • /quarto-dark-bg.jpeg, the old og:image. The quarto-cli smoke test tests/docs/smoke-all/2023/09/19/issue-6907.qmd downloads it, so quarto-cli CI could start failing after merge.
  • /images/hero_right.png, the social-card image of four docs index pages.

I will also fix _tools/check-site-format.test.ts for Windows. It builds the script path with new URL(...).pathname, which gives /C:/Users/... on Windows, so the 3 tests running the script through quarto run fail there (CI is fine as it runs on Linux). Using fromFileUrl() from stdlib/path, like _tools/snapshot-typst.ts does, fixes it.

Thanks again !

cderv added 2 commits October 15, 2026 15:22
Moving the root brand images into assets/images/ left only /quarto.png
redirected. The other old URLs are still loaded from outside the site
and now 404 on the deploy preview:

- /favicon.png is hotlinked by other sites.
- /quarto-dark-bg.jpeg was the og:image, and the quarto-cli smoke test
  tests/docs/smoke-all/2023/09/19/issue-6907.qmd downloads it.
- /images/hero_right.png was the og:image of several docs index pages,
  and the hero images, Posit logos and lottie assets lived next to it.

The images/ files are redirected one by one rather than with a
/images/* splat: the home page still serves its screenshots from the
root images/ directory, and a forced (301!) splat would shadow them.
URL.pathname on a file URL gives "/C:/Users/..." on Windows, which is
not a valid path, so `quarto run` failed with os error 123 and the three
tests that run the script as a subprocess failed. fromFileUrl() converts
the URL into a native path on every platform, as
_tools/snapshot-typst.ts already does.
@cderv

cderv commented Oct 15, 2026

Copy link
Copy Markdown
Member

/deploy-preview

@github-actions

Copy link
Copy Markdown
Contributor

📝 Preview Deployment

🔍 Full site preview: https://deploy-preview-2222.quarto.org

🔄 Modified Documents

@cderv
cderv merged commit ac878df into quarto-dev:main Oct 15, 2026
4 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Backport failed for prerelease, because it was unable to cherry-pick the commit(s).

Please cherry-pick the changes locally and resolve any conflicts.

git fetch origin prerelease
git worktree add -d .worktree/sync-2222-to-prerelease origin/prerelease
cd .worktree/sync-2222-to-prerelease
git switch --create sync-2222-to-prerelease
git cherry-pick -x ac878dfc989718894e9f8a003080d803bf4b34a4

cderv pushed a commit that referenced this pull request Oct 15, 2026
Move the site theme, scripts, Lua filters and page chrome into a local
extension at _extensions/quartoorg/, used through a quartoorg project
type. Pages inherit quartoorg-html from the project instead of naming
it, so the theme is set in one place and a page cannot drop it
silently. This centralises the themes and makes the site easier to
maintain, and it lets #2140 pick up the same chrome.

- Move the page chooser shortcode and the accessibility fixes from
  main into the extension, with their CSS in the theme SCSS.
- Move brand images to assets/images/ and redirect the old root URLs
  that other sites and docs still load: /quarto.png, /favicon.png, the
  og:image files, and the hero and Posit logo images. Files the home
  page still serves from images/ stay where they are.
- Add _tools/check-site-format.ts to CI and the pre-commit hook. It
  fails when a format: html page drops the site theme.
- Dark mode borders use $gray-400, which is 3.70:1 against the page
  instead of 1.08:1. The main banner is brand blue in dark mode too,
  and the prerelease banner moves to #e60033 (white text 4.76:1).

Notebook preview pages still render with the built-in html format, so
they lose the Posit badge, code copy buttons and site grid widths.

See quarto-dev/quarto-cli#14954

(cherry picked from commit ac878df)
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.

3 participants