Skip to content

Introduce a ThemeProvider for the shared component library #85

@SjaakSchilperoort

Description

@SjaakSchilperoort

User story

As a developer,
I want the components library to provide a ThemeProvider,
So that our apps can apply custom themes while sharing consistent default styling.

Context

The component library is used by two apps. Both apps have partially overlapping design systems. Currently, the components library has its own design system.

We want:

  • Shared defaults in the library
  • App-level overrides where needed
  • Strong TypeScript typing
  • No direct imports of static color/style constants inside components

This setup gives us one central place to control how an app looks. Each app can adjust its own styling, while the shared components stay consistent and don’t need to change. In the future, it will make it much easier to update the design, add things like dark mode, or support new styling needs, without rewriting existing components.

Functional requirements

Components library responsibilities

The components library:

  1. Defines a Theme type
  2. Defines a defaultTheme of type Theme
  3. Implements a ThemeProvider that:
  • Accepts a theme prop of type Partial<Theme>
  • Merges the provided theme with the internal defaultTheme.
  • Ensures the resulting theme is a complete Theme
  1. Creates a ThemeContext internally
  2. Exposes a types useTheme() hook that returns a fully merged Theme

App responsibilities

Each app:

  1. Defines an app-specific theme of type Partial<Theme>
  2. Only includes values that override defaults
  3. Wraps the root component tree in ThemeProvider
  4. Does not import default theme values directly

Component usage

Library components and app components and screens:

  • Must use const theme = useTheme()
  • Must not import static theme definitions
  • Must retrieve all styling values from the theme

Out of scope (for this story)

  • Runtime theme switching
  • Dark mode
  • Multiple theme variants
  • Dynamic theme updates

Definition of Done

  • Theme type defined and exported
  • defaultTheme implemented
  • ThemeProvider implemented
  • useTheme() implemented and typed
  • At least one existing component refactored to use useTheme()
  • One app successfully overrides at least one theme property
  • TypeScript validates incorrect overrides

Implementation phases

1. Introduce a Theme type

  • Move non-theme primitives (rounded, shadow, layout, etc.) out of theme
  • Centralize shared static styles in the component library
  • Ensured both apps conform to the Theme type
  • Still use static imports

2. Introduce a runtime Theme context

  • Create ThemeContext in the component library
  • Wrap apps with ThemeProvider

3. Migrate components to useTheme()

  • Migrate shared components, apps remain static.

4. Refactor text/textStyle to be theme-aware

5. Remove static theme imports everywhere

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions