Skip to content

[3.0] Theme split (wave 5, part 3) — let the colour mode reach the post editor - #9498

Open
albertlast wants to merge 4 commits into
SimpleMachines:release-3.0from
albertlast:3.0/theme-editor-tokens
Open

[3.0] Theme split (wave 5, part 3) — let the colour mode reach the post editor#9498
albertlast wants to merge 4 commits into
SimpleMachines:release-3.0from
albertlast:3.0/theme-editor-tokens

Conversation

@albertlast

@albertlast albertlast commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Description

With dark mode on, the post editor stayed a light grey island in the middle of a dark page — its stylesheet had never been tokenised, so nothing could reach it. This gives jquery.sceditor.css tokens for all twenty-four of its colours and a dark value for each. It now has no literal colour left.

One of them is not a colour

Every toolbar icon is cut from a single raster sprite, images/icons/editor_sprite.png, so none of them can be recoloured the way an icon font or an SVG could — and in dark mode the near-black line art all but disappeared.

A filter is the only lever a colour mode has over a raster, so the sprite gets one: --editor-icon-filter, none here and an inversion in dark mode. The sprite is mixed — most icons are line art, but a few carry their own colour, the YouTube mark among them — so the inversion is paired with a hue rotation. The greys have no hue to rotate and simply invert; the coloured ones come back roughly where they started.

Keeping it as a token is what lets dark.css stay what it claims to be: a file that overrides tokens and restates no rules.

Only the chrome is in scope

The surface you actually type on is an iframe with its own document, and Editor.php:846 hands it jquery.sceditor.default.css as its single stylesheet. No token is in scope inside that document, so tokenising that file would leave every var() unresolved and break the light theme too. Feeding the iframe the tokens is a change to how the editor is given its stylesheets, and belongs on its own.

Worth knowing how much that leaves: the rich surface is only shown to members who have turned it on — rich_active needs the wysiwyg_default option, which is off by default — so what everybody sees first is the source view, an ordinary textarea on the page itself, which already follows the mode correctly.

Verification

Light mode is unchanged. Computed color, background-color, background-image, all four border colours, box-shadow, outline-color, text-shadow, filter and fill for every element over six pages, on this branch and on its parent, captured back to back so forum state could not drift:

records: 2183
LIGHT-MODE DIFFERENCES: 0

(Done twice — once for the first twenty tokens, once for the four a property-name regex had missed.)

Stacked on #9497 (wave 5, part 2, dark mode), which is itself stacked on #9496 (part 1). Without part 2 there is no dark mode for these tokens to have a second value in.

Part 3 of wave 5 of the #7933 split.

Issues References (Fixes|Related|Closes)

Related #7933

Wave 4 tokenised index.css area by area and left a remainder: 55 declarations
that no area owned, scattered across the file. This takes those, so that every
colour the default theme draws now resolves through variables.css.

Most are one-offs - the forum title link, the current page number, the status
words, the COPPA contact block, the error file viewer, the warning level bars.
Three are not: the sheen gradients on raised controls, on their hover state and
on the overlay surfaces are each shared by a long selector list spanning menus,
quick buttons, popups and post options, so they are named for what they are
rather than for any one component that uses them.

Every token is seeded with the literal it takes over from, so this is not meant
to change what the forum looks like, and does not. Verified by recording the
computed color, background, background-image, border colours, box-shadow,
outline and text-shadow of every element on twelve pages - the board index, a
topic, the poster, the profile, the stats, help, search, the calendar, personal
messages, the admin centre, its permission grid and its theme list - before and
after: 4254 elements, zero differences.

The one literal left is the diagonal stripe the progress bar draws over its
fill, which is a translucent white texture rather than a colour.

Signed-off-by: Mathias Alberts <mathiaspapealbert@hotmail.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
The colour mode plumbing has been in 3.0 since Alpha: Theme.php resolves the
mode, Themes.template.php and ThemeOptions.php offer it to the admin and the
member, index.template.php writes it into data-mode, and dark.css has sat in the
theme as a placeholder. None of it has ever run. Turning the flag on was not
enough, because the feature is broken in four places rather than one.

loadMode() had no callers. It is the method that resolves the mode and loads
dark.css, and nothing anywhere invoked it, so data-mode was never emitted and
the stylesheet was never asked for. It is now called beside loadVariant(), which
is its sibling and is read by the same line of the template.

The 'system' mode lost the very thing that makes it 'system'. That mode works by
loading dark.css with a (prefers-color-scheme: dark) media attribute, but
attributes are only printed for files served on their own - loadCSSFile()
defaults to minimizing, and a file folded into the bundle loses them. The
browser was never asked, so 'system' would have meant 'always dark'. That mode
now opts out of the bundle; 'light' and 'dark' carry no attribute and still
share one cached file.

Saving the chosen mode to a member's profile was fatal. Db::insert() wants a
list of rows and was handed a single flat one, which is a critical error rather
than a warning outside backward compatibility mode, so the first time a logged
in member chose a mode the page died. loadVariant() has the identical defect
three lines further down; it is left alone here because this branch neither
enables nor exercises variants, and shipping an unverified fix is worse than
recording a known one.

dark.css itself is written against release-3.0's own tokens rather than ported.
The snapshot on SimpleMachines#7933 could not be used: of its 197 overrides only 84 name a
token that exists here, while 213 colour-bearing tokens here have no value in
it. It overrides 243 tokens and restates no rules, all written against twelve
values declared at the top of the file, so the way to review it is to agree
those and then check each component reached for the right one.

The ramps are deliberately untouched, so a variant still re-tints the forum by
moving --primary-color-hue and dark mode moves with it.

Verified on a running forum. Light mode is unchanged: the computed colours of
4254 elements over twelve pages are identical with the file present and absent.
All three modes emit the right markup and the right stylesheets, including the
media attribute on 'system' alone. Eighteen pages were swept in both modes for
text that lands on a background too close to it; dark mode has nineteen elements
below the AA ratio against light mode's hundred and thirty-six, and both dark
causes sit outside the theme - the bundled coloris colour picker, which carries
no tokens at all, and the Administrator group's online_color, which is data. No
errors were logged.

Signed-off-by: Mathias Alberts <mathiaspapealbert@hotmail.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
The editor's own stylesheet was never tokenised, so with dark mode on, the
toolbar stayed a light grey island in the middle of a dark page. This gives its
twenty colours tokens and a dark value each.

One of them is not a colour. Every toolbar icon is cut from a single raster
sprite, editor_sprite.png, so none of them can be recoloured the way an icon
font or an SVG could, and in dark mode the near-black line art all but
disappeared. A filter is the only lever a colour mode has over a raster, so the
sprite gets one: `none` here, and an inversion in dark mode. The sprite is
mixed - most icons are line art but a few carry their own colour, the YouTube
mark among them - so the inversion is paired with a hue rotation, which puts the
coloured ones back roughly where they started while the greys, having no hue to
rotate, stay inverted.

Only the chrome is in scope. The surface you type on is an iframe with its own
document, and Editor.php hands it jquery.sceditor.default.css as its single
stylesheet. No token is in scope inside that document, so tokenising that file
would leave every var() unresolved and break the light theme as well; feeding
the iframe the tokens is a change to how the editor is given its stylesheets and
belongs on its own. Worth knowing that the surface is only shown to members who
have turned the rich editor on - rich_active needs the wysiwyg_default option,
which is off by default - so what everybody sees first is the source view, an
ordinary textarea on the page itself, which already follows the mode.

Light mode is unchanged: the computed colours of every element over twelve
pages, on this branch and its parent, are identical.

Signed-off-by: Mathias Alberts <mathiaspapealbert@hotmail.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
The first pass matched `border`, `border-*-color` and the usual paint
properties, which left four behind: the grip's `border-top`, the toolbar
group's `border-bottom`, and the `fill` on the SVG icon variant and its
disabled state. All four are light-theme values, so in dark mode the toolbar
group kept a pale hairline under it.

jquery.sceditor.css now has no literal colour left.

Light mode is unchanged, checked the same way as the first pass and with `fill`
added to the properties recorded.

Signed-off-by: Mathias Alberts <mathiaspapealbert@hotmail.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
@albertlast albertlast mentioned this pull request Aug 11, 2026
@jdarwood007 jdarwood007 added this to the 3.0 Alpha 5 milestone Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants