-
Notifications
You must be signed in to change notification settings - Fork 0
Description
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:
- Defines a
Themetype - Defines a
defaultThemeof typeTheme - Implements a
ThemeProviderthat:- Accepts a
themeprop of typePartial<Theme> - Merges the provided theme with the internal
defaultTheme. - Ensures the resulting theme is a complete
Theme
- Accepts a
- Creates a
ThemeContextinternally - Exposes a types
useTheme()hook that returns a fully mergedTheme
App responsibilities
Each app:
- Defines an app-specific theme of type
Partial<Theme> - Only includes values that override defaults
- Wraps the root component tree in
ThemeProvider - 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
Themetype defined and exporteddefaultThemeimplementedThemeProviderimplementeduseTheme()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
Themetype - Still use static imports
Done in:
- Add a Theme type #86
- https://github.com/observation/obsidentify/pull/1187
- https://github.com/observation/app/pull/1186
2. Introduce a runtime Theme context
- Create
ThemeContextin the component library - Wrap apps with
ThemeProvider - Migrate shared components, apps remain static.
User story:
3. Refactor text/textStyle to be theme-aware
Introduce theme‑driven typography by moving text styles into the shared theme. This enables apps to override or extend text styles, and ensures shared components automatically use the correct text styles for each app. The component library will be updated to support dynamic text styles. The apps will follow later, after switching to semantic color names.
User story:
4. Use semantic color names
- Move color definitions to a palette definition
- For theme colors, use semantic names for colors, that resolve to a palette entry
- This way, you can use ThemeProvider to switch themes from one set ("Light") to the other ("Dark")
5. Switch the apps from static theme to dynamic theme
6. Move ad hoc colors (e.g. in species info) to theme
- Species info: rarity, status