Page MenuHomePhabricator

Devise a generic way for theme-agnostic stylesheets to adapt to the current theme
Closed, ResolvedPublic

Description

Goal

MediaWiki skins should be able to render MediaWiki own widgets and possibly also OOUI or other UI components in skin-specific styles.
Imagine a widget with WikimediaUI theme styles for Vector and MinervaNeue and Apex theme style for MonoBook.

Problem statement

I would like it if there was a way to provide OOUI-theme-specific styles in regular ResourceLoader modules shipped with MediaWiki.

My use case is the DateInputWidget. It is styled specifically for the default WikimediaUI theme, and while it looks neat there, it looks out of place elsewhere:

WikimediaUI themed default look in VectorApex-theme using skin Monobook
pasted_file (266×296 px, 17 KB)
pasted_file (242×273 px, 14 KB)

(That is actually not quite as awful as I was afraid, but still.)

Proposed solution

See also T112747#4093591, this is just the short summary of implemented path:

  • 1. Add a MediaWiki core solution that will offer sane defaults for all design-approved, naming convention following variables (and require them to be defined) – defined in core's 'resources/src/mediawiki.less/mediawiki.skin.defaults.less'
  • 2. Add skin-specific @import feature that offers to redefine values accordingly in all Wikimedia Foundation deployed skins – defined in skin's 'resources/mediawiki.less/mediawiki.skin.variables.less'
Instructions for skins
// In skin.json, add:
//    "SkinLessImportPaths": {
//        "skinname": "resources/mediawiki.less"
//    }
//
// Create a file called resources/mediawiki.less/mediawiki.skin.variables.less, which starts with:
//    @import 'mediawiki.skin.default.less';
// followed by any overrides for these variables, e.g.:
//    @width-breakpoint-desktop: 1234px;

In follow-ups to this task

  1. Bring mediawiki.skin.variables to all Wikimedia deployed skins
  2. Import WikimediaUI Base variables in Vector's 'mediawiki.skin.variables.less' file
  3. Import WikimediaUI Base variables in MinervaNeue's
  4. Use OOUI's Apex theme variables in Monobook's import

Related Objects

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes

Change 298637 had a related patch set uploaded (by Bartosz Dziewoński):
mw.widgets.DateInputWidget: Add Apex-theme-specific styles

https://gerrit.wikimedia.org/r/298637

Krinkle renamed this task from Devise a way to provide OOUI-theme-specific styles in regular ResourceLoader modules to Devise a generic way for theme-agnostic stylesheets to adapt to the current theme.Jul 19 2016, 7:05 PM

Proposal:

  • Define a set of standard variables (and maybe some functions/mixins) that will have default values that individual skins (or their OOjs UI themes) can override.
  • Provide a way to import that from any less module (e.g. make that part of the current skin/theme available as public import path).

For example:

Defaults in mediawiki-core:/resources/src/mediawiki.less/theme/defaults.less. Importable as @import theme/defaults.less. An empty file that just imports this would be at mediawiki-core:/resources/src/mediawiki.less/theme/theme.less.

By default, if a skin registers no OOUI theme and no custom theme file, @import theme.less will import that. Otherwise, it will resolve to the current skin's theme file.

Assuming we'll make OOUI's defaults are equal or a superset of what MediaWiki standardises, skins that register an OOUI theme (SkinOOUIThemes) won't need to do anything. Other skins can provide their theme file via a new config (e.g. SkinThemeDir: { skinname: path } or something).

That sounds nice, but I am not convinced that it will be sufficient to express the stylistic differences even between the two built-in themes (Apex and MediaWiki), much less any third-party ones (if anyone ever creates them). :/

@Krinkle I like the proposal, in one little note: I think it's overkill to have both, defaults.less and theme.less. theme.less seems sufficient to me carrying the variables.

@Krinkle I like the proposal, in one little note: I think it's overkill to have both, defaults.less and theme.less. theme.less

I suggested having both as otherwise it would greatly complicate versioning and future changes. If we start with 2 variables and then later "add" another (btw, what would "add" mean without a default), all skins would need to implement it, otherwise we can't safely reference it anywhere without risking fatal errors.

@Krinkle Ok, but that would refer to the mediawiki.less/default.less only, not to a theme, or? As it are Less variables, if a theme doesn't implement it, it would fallback to the default.less if it's not available in theme/theme.less?!

At M82 @Jdlrobson wrote:

@Volker_E What's the problem with having resources/wikimedia-base.less which is a copy and paste of the current distribution of your wikimedia-base repo (in absence of being able to use a package manager) - we do this for jquery and other files?

mediawiki.ui/variables.less can import from the new file to keep its contract but move us away from using that.

e.g. @mediaWikiVarible: @wikimedia-ui-variable

I will happily help migrate us away from mediawiki ui variables if that's what's needed but I worry about having all these places to look...

The problem is in my current understanding, that we shouldn't necessarily provide a WikimediaUI theme as default for MediaWiki from a software product point of view. Two related issues are problematic from my point of view:

  • The bundling of MW to Foundation use cases, where a default (empty) theme is a more-free out-of-the-box state.
  • A lot of problems that we're solving on the technical side are also resembled on the UI/presentational side and it's hard to come up with another default variant aside of WikimediaUI, given our scarce resources. Exemplified at the color palette M82, a useful production-ready accessible alternative palette is technically very hard to achieve.

Change 345440 had a related patch set uploaded (by VolkerE):
[mediawiki/core@master] Provide theme-agnostic style variables

https://gerrit.wikimedia.org/r/345440

What's left to do before this can be marked Resolved? Actual inheritance and use in legacy code like SpecialSearch.php and frameworks like MWUI?

Renewed proposal below, based on feedback from later comments and in-person with @Volker_E last week.

Goal

The end-result is that any Less stylesheet loaded by ResourceLoader can do @import 'mediawiki.theme.variables'; and that would provide theme variables associated with the current MediaWiki skin. The skin in turn may delegate to something else, like wikimedia-ui-base, or OOUI, or perhaps even derived from other libs' (eg. Bootstrap).

Take note here that ResourceLoader modules by design, already vary by skin, with existing features such as skinStyles, skinScripts, getLessVars($context), and getStyles($context) all varying by skin.

Implementation

Currently, ResourceLoader instantiates Less_Parser with a mostly empty ImportPaths array. (Albeit extendable via the deprecated wgResourceLoaderLESSImportPaths, T140807.)

My proposal is to make ResourceLoaderFileModule dynamically add one entry to this array based on the current skin.

The skin would declare (perhaps via skin.json) where its mediawiki.theme file(s) are.

At run-time, from the perspective of a random style module, import paths could end up as follows:

[
 "/resources/src/mediawiki.less/", # mediawiki.mixins, mediawiki.theme, mediawiki.theme.default
 "/skins/Vector/mediawiki.less/" # mediawiki.theme
]

MediaWiki core's mediawiki.theme.less file would be an empty placeholder proxying default, for cases where the skin does not register a theme file. The default file would be the place where we declare the "standard variable" names, a bit of documentation, with generic (unpinionetad) value as default (perhaps like a CSS reset, or with initial and inherit keywords).

core/.../mediawiki.less/mediawiki.theme.less
@import "mediawiki.theme.default"

Vector's mediawiki.theme.less file would shadow this file with its own, which could look like this:

Vector/mediawiki.less/mediawiki.theme.less
@import "mediawiki.theme.default"
@import "wikimedia-ui-base"

Other skins could potentially place direct variable assignments here instead.

Standard variables

The part I'm not yet sure of is which variable names we're going to define in the theme file. In other words, which variables should be standardised as shared across skins.

  • (master) wikimedia-ui-base.less defines 106 variables.
  • (master) oojs-ui/.../blank/common.less defines 7 variables.
    • (master) oojs-ui/.../apex/common.less defines 7 variables and 43 additional.
    • (master) oojs-ui/.../wikimediaui/common.less defines 7 variables and 111 additional.

I'm gonna leave that for during Code Review for now. I guess when we write this we should start with a single use case in mind that we can use to test it with (e.g. a particular place in core or an extension where we want to use a skin-dependent variable that we can also agree on can be set by multiple skins).

Change 434211 had a related patch set uploaded (by Krinkle; owner: Krinkle):
[mediawiki/core@master] [WIP] resourceloader: Add skin-based 'mediawiki.variables' import for LESS

https://gerrit.wikimedia.org/r/434211

Change 434212 had a related patch set uploaded (by Krinkle; owner: Krinkle):
[mediawiki/core@master] mediawiki.variables: Add @font-family-sans

https://gerrit.wikimedia.org/r/434212

Change 434214 had a related patch set uploaded (by Krinkle; owner: Krinkle):
[mediawiki/skins/Vector@master] Implement mediawiki.variables for Vector

https://gerrit.wikimedia.org/r/434214

Change 434215 had a related patch set uploaded (by Krinkle; owner: Krinkle):
[mediawiki/skins/MonoBook@master] Implement mediawiki.variables for MonoBook

https://gerrit.wikimedia.org/r/434215

Change 434213 had a related patch set uploaded (by Krinkle; owner: Krinkle):
[mediawiki/core@master] mediawiki.variables: Add @border-radius-base

https://gerrit.wikimedia.org/r/434213

Change 434212 abandoned by Krinkle:
mediawiki.variables: Add @font-family-sans

Reason:
Combined with Icf86c930a3b5524254

https://gerrit.wikimedia.org/r/434212

Change 434213 abandoned by Krinkle:
mediawiki.variables: Add @border-radius-base

Reason:
Combined with Icf86c930a3b5524254

https://gerrit.wikimedia.org/r/434213

Implementing SkinLessVariablesImportPaths would be valuable for Theme (https://www.mediawiki.org/wiki/Extension:Theme). For example, v4 of the Refreshed skin relies heavily on a custom set of LESS mixins. If Refreshed could give extensions easy access to those mixins through ResourceLoader, writing custom themes for Refreshed would be much easier.

Food for thought:
Theming that's done in LESS cannot be hot-swapped client-side.

  • Different color themes for skins are not practical to be swapped server-side. That would result in multiplied cache requirements and a full stylesheet reload when switching themes.
  • Only CSS that concerns branding, logo, website-specific style elements are practical to be placed into a server-side "theme". That would benefit mostly non-WMF operators of MediaWiki instances, though.

Change 579425 had a related patch set uploaded (by Jdlrobson; owner: Jdlrobson):
[mediawiki/skins/MinervaNeue@master] Use wikimedia.ui from core

https://gerrit.wikimedia.org/r/579425

Change 579857 had a related patch set uploaded (by Aron Manning; owner: Aron Manning):
[mediawiki/core@master] Provide theme-agnostic style variables

https://gerrit.wikimedia.org/r/579857

Change 579858 had a related patch set uploaded (by Aron Manning; owner: Aron Manning):
[mediawiki/core@master] Separate wikimedia-ui-base.less resource from OOUI into its own folder

https://gerrit.wikimedia.org/r/579858

Change 580558 had a related patch set uploaded (by Aron Manning; owner: Aron Manning):
[mediawiki/core@master] resources: Enable skins to override theme-agnostic style variables

https://gerrit.wikimedia.org/r/580558

Summary from @Krinkle on Gerrit:

The import directories will be injected by ResourceLoader.
Each skin and core will have its own "mediawiki.theme" directory, the name stays the same.
If the current skin provides "mediawiki.theme/variables" then that one is used. A skin would typically start with default.less to ensure all base variables are defined and then override as-needed, possibly using wikimedia-ui such as for Vector and Minerva.
If the skin doesn't (yet), then core's variable.less file is imported (which just includes defaults.less).
Then, anywhere in the system, in an extension or in core, without needing to know about skins, you import "mediawiki.theme/variables" and can then utilize the correct values automatically.

Importpath-based override of 'mediawiki.theme/variables' would result in a deep path for only a single file in skins, such as:
Vector/mediawiki.less/mediawiki.theme/variables.less this is necessary to avoid adding other files to the lookup path.

Another option would be if RL implicitly loaded the override from the skin, eg.:
Vector/mediawiki.theme/variables.less
This is very likely to be confusing to developers without the intricate knowledge of this RL behaviour:
it won't be understood why some variables (those overridden) have different values than defined in core.

One solution to this is to make the import explicit. That requires that the import path depends on the active skin. The active skin can be injected as a variable by RL as demonstrated in a POC (it is usual to import themes with this construct): Patch 580558.

Change 579857 had a related patch set uploaded (by Aron Manning; owner: Aron Manning):
[mediawiki/core@master] resources: Provide theme-agnostic style variables

https://gerrit.wikimedia.org/r/579857

Change 579857 abandoned by Aron Manning:
resources: Provide theme-agnostic style variables

Reason:
Discussion relevant to ticket

https://gerrit.wikimedia.org/r/579857

Change 579425 abandoned by Jdlrobson:
Use wikimedia.ui from core

https://gerrit.wikimedia.org/r/579425

Change 434211 merged by jenkins-bot:
[mediawiki/core@master] resourceloader: Add skin-based 'mediawiki.skin.variables.less' import

https://gerrit.wikimedia.org/r/434211

Change 434215 merged by jenkins-bot:
[mediawiki/skins/MonoBook@master] Implement mediawiki.skin.variables.less for MonoBook

https://gerrit.wikimedia.org/r/434215

Change 434214 merged by jenkins-bot:
[mediawiki/skins/Vector@master] Implement mediawiki.skin.variables.less for Vector

https://gerrit.wikimedia.org/r/434214

Change 345440 abandoned by Krinkle:
[mediawiki/core@master] Provide theme-agnostic style variables

Reason:
Superseded by <https://gerrit.wikimedia.org/r/c/mediawiki/core/ /434211>

https://gerrit.wikimedia.org/r/345440

Change 580558 abandoned by Krinkle:
[mediawiki/core@master] resourceloader: Inject @skin-folder-name for theme-agnostic style sheets

Reason:
Superseded by <https://gerrit.wikimedia.org/r/c/mediawiki/core/ /434211>

https://gerrit.wikimedia.org/r/580558

Volker_E assigned this task to Krinkle.
Volker_E removed a project: Patch-For-Review.
Volker_E updated the task description. (Show Details)

Resolving with MediaWiki v1.36 successfully.