Themes/Modes: plugin declaration proposal

Created on 21 January 2023, almost 2 years ago
Updated 22 July 2023, over 1 year ago

Problem/Motivation

"Theming": some design systems have CSS switching like light/dark theme, accessibility modes, or different tones and branding. Most of the time, the theme can be defined with a class in the HTML or BODY element (ex: Tailwind) and the theme is applied to the current element and its children.

However, it can be more complicated:

Proposed resolution

Use this issue to propose a YAML structure for plugin declarations taking into account this complexity.

πŸ“Œ Task
Status

Fixed

Version

1.0

Component

Miscellaneous

Created by

πŸ‡«πŸ‡·France pdureau Paris

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @pdureau
  • πŸ‡«πŸ‡·France pdureau Paris
  • πŸ‡«πŸ‡·France G4MBINI BΓ¨gles
  • πŸ‡«πŸ‡·France duaelfr Montpellier, France

    Maybe I'm missing something but why do you care about how each Design System manages its variants?
    The core need is to have more than one preset of CSS vars and to be able to switch from one to another.

    • If this switch has to be done by admins in appearance it's only a matter of configuration.
      In this case, it would be really nice to be able to select a preset then override some values for the current project.
    • If you want to have some kind of switcher in the UI for end users, you can do this the way you want as long as it works in the end.
      In this case it might be interesting to restrict the list of available presets.

    My 2 cts

  • πŸ‡«πŸ‡·France pdureau Paris

    Hello Duaelfr

    Maybe I'm missing something but why do you care about how each Design System manages its variants?

    "Themes" (or "Modes") are often a "first class" artifacts in design system, they have a name, a documentation, a purpose, and a lifecycle. So, it will convenient to manipulate them as "first class" obejcts too.

    The core need is to have more than one preset of CSS vars and to be able to switch from one to another.

    Not every design systems design its themes as combinations of CSS vars. Some design systems have themes but no CSS variables. Some design have both, but they are not related.

  • πŸ‡«πŸ‡·France pdureau Paris

    Theme definition is UI SKins will be needed for https://www.drupal.org/project/ui_suite_bootstrap/issues/3351580#comment... πŸ“Œ Bootstrap 5.3 update Fixed

  • πŸ‡«πŸ‡·France pdureau Paris

    We need the usual metadata:

    • id, string : Machine name, unique and persistent
    • label, string : Human-friendly, preferably short, name
    • description, string : Human-friendly, more lengthy, explanation
    • status, string : Its stage in a lifecycle: Incomplete, Draft, Published, Obsolete... No processing is made on this value.

    And properties specific to theme processing:

    Attachment value (string, free text)

    The keyword which will be attached (as a class name or a data attribute value). If empty, it is the plugin ID, with Html:::getClass() applied.

    Attachment method (string)

    2 values:

    • If empty, the value will be merged into an HTML class attributes
    • If value, this will be the HTML attribute name (it will often be a data-* attribute, but not always)

    Examples:

    • HTML data attribute : DSFR, Bootsrap4
    • HTML class: Mozilla Protocol

    Attachment target (string, enum)

    3 values:

    • Empty: the theme (class or data attribute) is scopable, so it can be processed in 2 different ways:
      • If selected from Drupal theme settings page, it will be added (as a class or a data attribute) to the HTML body element.
      • It will also be possible to add it to any element of the page, like the styles from UI Styles.
    • "html": the theme (class or data attribute) will be added to the HTML root element
    • 'body" the theme (class or data attribute) will be added to the HTML body element

    Examples:

    • Empty (so "scopable"): Bootstrap 5, Mozilla Protocol
    • "html": DSFR

    Asset library

    A single assets library definition, which will be loaded if the theme is called in a render request.

    Look at SDC for the library attachment from YAML declaration:

    Examples: Europa

  • πŸ‡«πŸ‡·France pdureau Paris

    Example for Bootstrap 5.3:

    id: dark
    label: Dark
    description: ...
    # No value because same as plugin ID
    method: "data-bs-theme"
    # No target because scopable
    
    id: light
    label: Light
    description: ...
    # No value because same as plugin ID
    method: "data-bs-theme"
    # No target because scopable
    

    Example for Mozilla Protocol:

    id: dark
    label: Dark
    description: ...
    value: "mzp-t-dark"
    # No method because class name
    # No target because scopable
    

    Example for Ant Design:

    id: dark
    label: "Dark"
    library:
      css:
       "dist/antd.dark.min.css": {}
    id: compact
    label: "Compact"
    library:
      css:
       "dist/antd.compact.min.css": {}
  • Assigned to Grimreaper
  • πŸ‡«πŸ‡·France pdureau Paris
  • πŸ‡«πŸ‡·France pdureau Paris

    Vocabulary:

  • Issue was unassigned.
  • πŸ‡«πŸ‡·France Grimreaper France πŸ‡«πŸ‡·

    - New plugin type
    - new plugin definition class
    - Alter theme setting form to add theme selector
    - Implements hook_preprocess_html to add either in html_attributes or attributes the class or attribute
    - Implements tests

    - For scopable themes, how to be able to select the theme anywhere?

  • Assigned to seda12
  • Status changed to Needs work over 1 year ago
  • πŸ‡«πŸ‡·France Grimreaper France πŸ‡«πŸ‡·

    Update about libraries.

    Example for Ant Design:

    id: dark
    label: "Dark"
    library: "namespace/my_library"
    
    id: compact
    label: "Compact"
    library: "namespace/my_other_library"
    

    We do not care how the libraries are declared. We simply add it when the mode is selected.

  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    52 pass
  • @seda12 opened merge request.
  • Issue was unassigned.
  • Status changed to Needs review over 1 year ago
  • πŸ‡«πŸ‡·France Grimreaper France πŸ‡«πŸ‡·

    No "Theme mode" => "theme"

  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    55 pass
  • Assigned to Grimreaper
  • πŸ‡«πŸ‡·France Grimreaper France πŸ‡«πŸ‡·
  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    52 pass, 2 fail
  • Issue was unassigned.
  • Status changed to Needs work over 1 year ago
  • πŸ‡«πŸ‡·France Grimreaper France πŸ‡«πŸ‡·
  • Assigned to seda12
  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    51 pass, 2 fail
  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    52 pass, 2 fail
  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    60 pass
  • Issue was unassigned.
  • Status changed to Needs review over 1 year ago
  • Assigned to Grimreaper
  • πŸ‡«πŸ‡·France Grimreaper France πŸ‡«πŸ‡·
  • πŸ‡«πŸ‡·France pdureau Paris

    Thanks for your work.

    Tested on DSFR:

    system:
      label: "System"
      method: data-fr-scheme
      
    light:
      label: "Light"
      method: data-fr-scheme
      
    dark:
      label: "Dark"
      method: data-fr-scheme

    It was working well at the end but I got one fatal error:

    TypeError: array_keys(): Argument #1 ($array) must be of type array, null given in array_keys() (line 75 of  Drupal\ui_skins\HookHandler\PreprocessHtml                              
    Warning: Undefined property: Drupal\Core\Extension\Extension::$base_themes in Drupal\ui_skins\HookHandler\PreprocessHtml->preprocess()                                                                                          
    

    Not related to my tests, but there may be other attachment methods to implement:

    • If empty, the value will be merged into an HTML class attributes > Already implemented
    • If value, this will be the HTML attribute name (it will often be a data-* attribute, but not always) > Already implemented
    • Use case not met yet, but we may need to be able to add theme as a meta element. Example: <meta name="theme" content="system">

    Can we have a look on this?

  • πŸ‡«πŸ‡·France pdureau Paris

    Also, on /admin/appearance/settings/{theme} page, the Themes select list must not be mandatory. The default value must be empty (no theme), and it is possible to select this default empty value.

  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    58 pass
  • πŸ‡«πŸ‡·France Grimreaper France πŸ‡«πŸ‡·
  • Issue was unassigned.
  • Status changed to Fixed over 1 year ago
  • πŸ‡«πŸ‡·France Grimreaper France πŸ‡«πŸ‡·
  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024