Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multi-theme support to Polaris #10290

Merged
merged 12 commits into from
Sep 7, 2023
Merged

Add multi-theme support to Polaris #10290

merged 12 commits into from
Sep 7, 2023

Commits on Aug 31, 2023

  1. Add changeset entry

    aaronccasanova committed Aug 31, 2023
    Configuration menu
    Copy the full SHA
    ad6eafe View commit details
    Browse the repository at this point in the history
  2. Add multi-theme support to Polaris tokens (#10103)

    This PR introduces multi-theme support to `@shopify/polaris-tokens` by
    implementing a base/variant architecture. The base theme serves as the
    foundation for any number of variant themes. Variant themes have two
    primary constraints in that they can only extend the base theme and are
    the only themes exposed to consumers.
    
    One advantage of this pattern is that it simplifies system changes by
    flattening the relationship between themes. There is no need to consider
    deeply inherited themes, making updates more predictable.
    
    <details>
      <summary>Deeply inherited vs base/variant themes</summary>
    
    **❌ With deeply inherited themes**
    ```mermaid
    flowchart TD
        A[Base Theme]
        A --> B[Light Theme]
        B --> C[Light High Contrast Theme]
        A --> D[Dark Theme]
        D --> E[Dark High Contrast Theme]
        A --> F[Dim Theme]
        A --> G[etc...]
    ```
    
    **✅ With base/variant themes**
    ```mermaid
    flowchart TD
        A[Base Theme]
        A --> B[Light Theme]
        A --> C[Light High Contrast Theme]
        A --> D[Dark Theme]
        A --> E[Dark High Contrast Theme]
        A --> F[Dim Theme]
        A --> G[etc...]
    ```
     
    </details>
    
    
    ## Implementation Details
    
    This PR focuses on implementing backward compatible multi-theme support
    for Polaris tokens. It enables the addition of new variant themes while
    promoting incremental adoption and ensuring compatibility with existing
    implementations.
    
    ### Directory Structure
    
    The `src/themes` directory consists of the following components:
    
    - Internal base theme and public variant themes.
    - Default variant theme, which is essentially an alias of the base
    theme, aliased to the light theme.
    - Light uplift theme, which is the first variant theme that simply
    ported `valueExperimental` tokens from our token groups.
    `valueExperimental` properties were initially introduced as a short-term
    solution during the SE23 upgrades, allowing token overrides by replacing
    `value` with `valueExperimental` at build time.
    - Note: `valueExperimental` references in token groups were kept in this
    PR to prevent breaking changes and maintain backward compatibility.
    Although these properties should be allowed to remove, a couple usages
    were found across the organization.
    - TypeScript definitions describing the shape of themes, partial themes,
    theme names, etc.
    - Utilities for validating themes and consistently creating theme
    classes/selectors.
    
    ### Stylesheet Generation
    
    The `toStyleSheet` build step has been updated to generate a
    backward-compatible
    [styles.scss](https://unpkg.com/browse/@shopify/polaris-tokens@7.5.2/dist/css/styles.css)
    file. This file assigns the default variant theme custom properties
    (`light`) to the `:root` selector and the `light-uplift` variant theme
    custom properties to the `html.Polaris-Summer-Editions-2023` selector.
    
    It should be noted that while the stylesheet remains backward compatible
    in this PR, the plan is to propose removing the `:root` selector in the
    next major release. This change aims to flatten the specificity of all
    variant themes since the `:where()` selector cannot currently be
    leveraged. For example:
    
    - Current specificity breakdown: `:root` has a specificity of 10,
    `html.Polaris-Summer-Editions-2023` has a specificity of 11.
    - Next specificity breakdown: `html.p-theme-light` has a specificity of
    11, `html.Polaris-Summer-Editions-2023` has a specificity of 11, etc.
    
    ### Variant Theme Functionality
    
    Variant themes override a subset of the base theme tokens by assigning
    them to a `partials` object. This `partials` object is then deep merged
    with the base theme for JavaScript access. Additionally, the `partials`
    object is used in the `toStyleSheet` build step to generate custom
    properties and insert them into the variant theme selector.
    Consequently, variant theme selectors only contain the subset of
    overridden custom properties, ensuring a minimal stylesheet.
    
    It should be noted that if the strategy shifts from global themes to
    allowing nested themes, the approach would likely change to inserting
    all custom properties in each class. However, even in such cases, the
    performance impact of having a large collection of custom properties is
    expected to be minimal.
    
    **Example `styles.scss` updates**
    
    ```scss
    :root {
      /* Default variant theme custom properties (light) */
    }
    
    html.Polaris-Summer-Editions-2023 {
      /* Variant theme custom properties */
      /*
         Note: The above selector is special
         cased for backward compatibility. See
         below for updated theme selector structure.
      */
    }
    
    html.p-theme-light-high-contrast {
      /* Variant theme custom properties */
      /*
         Note: Variant theme selectors
         contain a subset of custom properties
         overriding the base theme
      */
    }
    
    html.p-theme-dark {/* ... */}
    html.p-theme-dark-high-contrast {/* ... */}
    html.p-theme-dim {/* ... */}
    ```
    aaronccasanova committed Aug 31, 2023
    Configuration menu
    Copy the full SHA
    fbc5de4 View commit details
    Browse the repository at this point in the history
  3. Add multi-theme build artifacts to Polaris tokens 2 (#10250)

    Rework of PR #10153:
    
    - The dedicated `@shopify/polaris-tokens/themes` entry point has been
    removed in favor of accessing the `themes` directly from
    `@shopify/polaris-tokens`, avoiding `package.json` `exports` and
    `typesVersions` changes.
    
    - Instead of using arguments for each asset builder function, the
    dependent modules are now accessed directly, reducing unnecessary
    TypeScript boilerplate.
    
    - References to `themes.light` have been replaced with a `themeDefault`
    alias throughout the library and build scripts. This change should
    improve clarity and consistency in communicating the behavior.
    
    - The build function `toTokenValues` has been renamed to `toValues` as
    it now operates on `themes` rather than `tokens`.
    
    - The root entry point has been updated to expose both `themes` and
    `themePartials`. The `themes` object contains complete theme objects for
    each theme, serving as a replacement for the previously proposed
    `/themes` entry point. Currently, it is designed for building low-level
    integrations, such as React Native themes. On the other hand, the
    `themePartials` object contains partial override objects for each theme.
    Originally used in the `toStyleSheet` build script to generate the
    smallest possible CSS rule of themed custom properties, it is now being
    exposed to enable the creation of client-side integrations with minimal
    impact on bundle size. Note that a separate PR will introduce a
    `createThemeVariant` hook that accepts partials and dynamically
    constructs the complete theme object at runtime.
    
    **Before:** 
    ```ts
    import {metadata} from '@shopify/polaris-tokens';
    
    metadata.color['color-bg'].valueExperimental
    ```
    ```ts
    import * as themes from '@shopify/polaris-tokens/themes';
    
    themes.polarisSummerEditions2023.color['color-bg']
    ```
    
    **After:**
    ```ts
    import {themes} from '@shopify/polaris-tokens';
    
    themes['Polaris-Summer-Editions-2023'].color['color-bg']
    ```
    
    ---------
    
    Co-authored-by: Laura Griffee <laura@mailzone.com>
    aaronccasanova and lgriffee committed Aug 31, 2023
    Configuration menu
    Copy the full SHA
    12c5fe3 View commit details
    Browse the repository at this point in the history
  4. Add useTheme hook for runtime Polaris tokens access (#10252)

    Rework of #10229.
    
    - To enhance clarity and avoid ambiguity, we have reintroduced the
    convention of prefixing all `theme` related objects and types with
    `meta`. While I was trying to steer us away from this convention,
    keeping it establishes consistency and makes it easier to differentiate
    between `theme` constructs with and without metadata.
    
    - Introduced a new `createThemeVariant` utility, which accepts a theme
    partial and constructs a complete `theme` object. This utility
    simplifies the process of creating theme variants and ensures that all
    required properties are included.
    
    - The AppProvider has been updated to incorporate a new
    `ThemeContext.Provider` and associated `useTheme` hook. This provider
    utilizes the `createThemeVariant` utility to expose the active theme to
    child components. This eliminates the need for several previously
    proposed exports and hooks, including `themeVars`, `useThemeName`,
    `useThemeVarDecl`, and `useCSSDecl`.
    
    **Before:**
    
    ```ts
    import {themeVars} from '@shopify/polaris';
    
    themeVars.color['color-bg'] // 'var(--p-color-bg)'
    ```
    ```ts
    import {useThemeVarDecl} from '@shopify/polaris';
    
    function App() {
      const colorBgDecl = useThemeVarDecl('--p-color-bg');
    
      colorBgDecl // { status: 'success', value: '#123', ... }
    }
    ```
    
    **After:**
    ```ts
    import {useTheme} from '@shopify/polaris';
    
    function App() {
      const theme = useTheme()
    
      theme.color['color-bg'] // '#123'
    }
    ```
    
    ---------
    
    Co-authored-by: Laura Griffee <laura@mailzone.com>
    aaronccasanova and lgriffee committed Aug 31, 2023
    Configuration menu
    Copy the full SHA
    5c58ccc View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    e44486c View commit details
    Browse the repository at this point in the history
  6. Configuration menu
    Copy the full SHA
    3870291 View commit details
    Browse the repository at this point in the history
  7. Update dependencies

    aaronccasanova committed Aug 31, 2023
    Configuration menu
    Copy the full SHA
    cc398fd View commit details
    Browse the repository at this point in the history

Commits on Sep 5, 2023

  1. Configuration menu
    Copy the full SHA
    dc3b830 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    e6359b9 View commit details
    Browse the repository at this point in the history
  3. Fix formatting

    aaronccasanova committed Sep 5, 2023
    Configuration menu
    Copy the full SHA
    e915800 View commit details
    Browse the repository at this point in the history
  4. Configuration menu
    Copy the full SHA
    f3a07f7 View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    c42b720 View commit details
    Browse the repository at this point in the history