Hone logo
Hone
Problems

Dynamic Theming in Angular

Creating dynamic theming allows users to personalize the look and feel of an application without requiring code changes. This challenge focuses on building a simple Angular application with a theming system that allows switching between predefined themes (e.g., light, dark, blue) at runtime. This is a common requirement in modern web applications, enhancing user experience and accessibility.

Problem Description

You are tasked with building a basic Angular application that supports dynamic theming. The application should have a component that displays some content (e.g., a heading and a paragraph) and a theme selector (e.g., a dropdown or radio buttons). When the user selects a different theme, the application's appearance should update accordingly.

What needs to be achieved:

  • Implement a theming system using CSS variables (custom properties).
  • Create a theme selector component that allows users to choose from a predefined set of themes.
  • Update the application's CSS variables based on the selected theme.
  • Persist the selected theme in local storage so that it's remembered across sessions.

Key Requirements:

  • Themes: Define at least three themes: 'light', 'dark', and 'blue'. Each theme should modify at least three CSS variables (e.g., --background-color, --text-color, --primary-color).
  • Theme Selector: The theme selector should be a reusable component.
  • CSS Variables: Use CSS variables for theming. Avoid inline styles.
  • Local Storage: Store the selected theme in local storage.
  • Initial Theme: Load the theme from local storage on application startup. If no theme is found in local storage, default to the 'light' theme.

Expected Behavior:

  1. On application load, the application should apply the theme stored in local storage (or the 'light' theme if no theme is stored).
  2. The theme selector should display the available themes.
  3. When the user selects a theme from the selector, the application's appearance should immediately update to reflect the new theme.
  4. The selected theme should be saved to local storage.
  5. On subsequent application loads, the previously selected theme should be applied.

Edge Cases to Consider:

  • What happens if local storage is unavailable (e.g., due to browser settings)? The application should still function, defaulting to the 'light' theme.
  • How to handle potential errors when accessing local storage? (While not strictly required for this challenge, consider how you might gracefully handle errors).

Examples

Example 1:

Input: Initial state: Local storage is empty.
Output: The application loads with the 'light' theme applied. The theme selector displays 'light', 'dark', and 'blue'.
Explanation: The application defaults to the 'light' theme because no theme is found in local storage.

Example 2:

Input: User selects 'dark' theme from the theme selector.
Output: The application's background color changes to a dark shade, the text color changes to a light shade, and the primary color changes to a contrasting color, all defined in the 'dark' theme. The selected theme is saved to local storage.
Explanation: The application updates its CSS variables to match the 'dark' theme and stores the selection in local storage.

Example 3:

Input: User navigates away from the application and then returns. Local storage contains the 'blue' theme.
Output: The application loads with the 'blue' theme applied. The theme selector displays 'light', 'dark', and 'blue', with 'blue' potentially highlighted as the selected theme.
Explanation: The application retrieves the 'blue' theme from local storage and applies it.

Constraints

  • Angular Version: Use Angular 14 or later.
  • CSS Variables: The solution must use CSS variables for theming.
  • Local Storage: The solution must use local storage to persist the theme.
  • Performance: The theme switching should be reasonably performant. Avoid unnecessary DOM manipulations. The application should load quickly.
  • Component Structure: The solution should be structured with at least two components: a main application component and a theme selector component.

Notes

  • Consider using a service to manage the theme and handle local storage interactions. This promotes separation of concerns and testability.
  • Think about how to structure your CSS to make it easy to define and manage themes.
  • You don't need to create a complex UI for the theme selector; a simple dropdown or radio buttons is sufficient.
  • Focus on the core theming logic and the interaction between the theme selector and the application's appearance. Styling beyond the core theme variables is not required.
  • Error handling for local storage is not a primary requirement, but consider how you might handle it gracefully.
Loading editor...
typescript