Skip to content

Review brief: components, patterns and JavaScript

Author: Shibin Das (d34dman)Last updated

In review

Reviewers: open, join #3627978 on drupal.org

Try it yourself

Everything in this brief runs on the demo site: Drupal 11.5.0-beta1 with the module, its adapters, the Media Library pilot and demo content. You need DDEV 1.25 or newer:

git clone https://github.com/d34dman/design_system_api_demo.git
cd design_system_api_demo
ddev start && ddev install-demo   # prints a one-time login link

Why this reaches your area

The contract has two halves. Tokens are built (v0). Patterns come next (v1, starting with Dialog): an abstract spec of a component's anatomy, states, keyboard behaviour and accessibility contract. In v1, Dialog is realized in admin themes only; realizations that any theme or module can provide come in v2. There, Single-Directory Components are the obvious realization for Twig, and light-DOM custom elements for JavaScript islands. Component tokens in SDC (#3624211) are how a component would declare its tokens. We'd like to shape patterns with you before writing the first spec.

Questions for you

  1. Component tokens in component.yml (#3624211). Our component tokens use DTCG fields: $type, $description, and $value as a reference to a semantic token, which is the suggested mapping an author can override. Could SDC component tokens use the same fields, so a component declares its tokens the same way whether it's an SDC or a module? → Q15
  2. An "implements" relation. We'd like an SDC to declare that it realizes a pattern (for example implements: design_system_api:dialog), so a theme can swap the realization and a conformance test knows what to check. Would that belong in SDC metadata in core, or should contrib keep it in its own file? → §7, Q13
  3. The pattern spec format. We plan to combine Open UI anatomy names, SDC-shaped props, slots and variants, and for behaviour an APG reference and its keyboard table (the concept defers statecharts). Is SDC's schema the right home for the props, slots and variants, so a spec can be checked against a component? → Q11
  4. Custom elements as a second realization. For JavaScript islands we lean toward light-DOM custom elements (no Shadow DOM), so server-rendered markup stays styleable and works before JavaScript loads. Does that fit how core's JavaScript is heading? → Q11, §10
  5. Bridging legacy theming. Media Library isn't SDC. The pilot adds stable ds-* classes in preprocess and form-alter hooks, because core's templates only carry js-* hooks. Is there a better bridge until modules ship components? → Q3

What we built

  • Nothing SDC-specific yet; v0 proves the token half.
  • Component tokens without SDC: the Media Library pilot declares media-card.*, media-panel.* and media-tabs.* in design_system_api_media_library.tokens.yml, each with a reference to a semantic token as its suggested mapping. Its colors come only from var(--ds-*); some sizes, border widths, line heights, the disabled opacity and transition durations are still literal values. It hooks onto its own ds-* classes, core's state classes and jQuery UI's .ui-dialog* classes.
  • A JavaScript-friendly output: every token is a CSS custom property on :root, so any framework can read it from the page's CSS. That is all "any framework" means today: component tokens are emitted as resolved values, not as var() references to semantic tokens; the stylesheet is attached only to pages Drupal renders; and there is no JSON form or JavaScript API yet. A dark or high-contrast area can be marked with data-ds-mode="dark" or data-ds-contrast="more" on any element, or both, on one element or nested.
  • Rules as data (design_system_api.rules.yml): stable IDs, a level (must/should/may; all five v0 rules are must), and how each rule is checked (stylelint for two, the proof gallery for one, a FunctionalJavascript test for one, manual review for one). The file's shape (summary, check, IDs without a prefix) doesn't yet match the sample in concept §8 (statement, enforced_by, drupal-ds: IDs), so how pattern specs will reference rules is still open.

See it

Media Library on Olivero with the pilot on

Olivero, pilot on: the Media Library's colors come only from contract tokens. The markup is core's, with ds-* classes added by the pilot.

Known issues

Found in our own check of the code. Items marked Fixed name the commit that fixed them. We track the open ones ourselves; if one matters for your review, say so in this brief's issue.

  • Component token names have no provider namespace. If two modules declare the same name, the first one wins without a warning.
  • Component tokens are flattened to plain values on the server, so overriding a semantic variable in a subtree doesn't change the component tokens that point at it.
  • Partly fixed (191fe37): a {reference} in a core-typed token (dimension, number, fontWeight) used to break token discovery for the whole site; it is now dropped and reported (drush ds:tokens). Still, nothing validates a module's tokens.yml: a component token that references a missing token, or that core rejects, is only left out of the CSS and logged as a warning.
  • Partly fixed (bb2a125): a combined context mode=dark contrast=more now covers dark + more contrast on one element, nested either way, or split between OS and page; since 77237c5 a [data-ds-mode="light"] region on an OS-dark page with OS more contrast keeps the contrast values. Remaining: adapter themes keep their own values for the tokens they map, in every context.
  • jQuery UI moves dialogs to <body>, so a dialog opened from a [data-ds-mode="dark"] region loses the mode.
  • Fixed (a424851): the pilot CSS styles its own classes, not js-* ones.
  • Fixed (14a82bd, bbadea9, ed82558): CI runs the drupal-ds/* rules over all module CSS and fails on a violation; drupal-ds/custom-properties refuses a var() that is neither a contract token nor declared in the same file.
  • A group's $description isn't passed down to its tokens, so most pilot tokens have no description.

Read only these sections

What we heard

Nothing yet.


Edit note (2026-10-03): Corrected the v1 realization scope (admin themes only; SDC and custom elements are v2), replaced the statechart in Q3 with the APG reference and keyboard table, narrowed "only var(--ds-*)" to colors, stated what "any framework" covers today, and described the rules file as it is (all must, not yet the §8 shape); added Known issues. All found in a pre-review check of the code.

Edit note (2026-10-03, later): Updated after the fixes in bb2a125 (combined dark + more-contrast context), 191fe37 (references in core-typed tokens dropped and reported) and b8ffdc0 (new a11y/reduced-motion rule; a11y/focus-visible now checked by a FunctionalJavascript test). Open known issues are now tracked by the maintainers instead of as separate issues.

Edit note (2026-10-18): Updated Known issues for 77237c5 (light region keeps more contrast), a424851 (no js-* classes in the pilot CSS) and 14a82bd/bbadea9/ed82558 (the drupal-ds rules gate CI); the demo site now runs Drupal 11.5.0-beta1 (the module supports ^11.5 || ^12).