Hone logo
Hone
Problems

Angular Theme Service Implementation

This challenge asks you to build a reusable Angular service that manages and applies application themes. A theme service allows you to easily switch between different visual styles (e.g., light, dark, high-contrast) without modifying component templates directly, promoting maintainability and a consistent user experience. This is a common requirement in modern web applications.

Problem Description

You need to create an ThemeService in Angular that allows components to:

  1. Set a theme: The service should accept a theme name (string) as input and store it.
  2. Get the current theme: The service should provide a method to retrieve the currently active theme name.
  3. Subscribe to theme changes: Components should be able to subscribe to an observable that emits the current theme whenever it changes.
  4. Apply theme styles: The service should dynamically apply CSS variables based on the selected theme. You will be provided with a set of CSS variables for each theme.

Key Requirements:

  • The service should be injectable into Angular components.
  • The theme changes should be observable and reactive.
  • The service should handle invalid theme names gracefully (e.g., by defaulting to a standard theme).
  • The service should not directly manipulate the DOM. Instead, it should set CSS variables that components can then use.

Expected Behavior:

  • When a component calls setTheme('dark'), the service should store 'dark' as the current theme and emit an event.
  • When another component calls getTheme(), it should return 'dark'.
  • Any component subscribed to the theme changes observable should receive an update when the theme changes.
  • If an invalid theme name is provided (e.g., 'purple'), the service should log an error and default to a predefined theme (e.g., 'light').

Edge Cases to Consider:

  • What happens if the service is called multiple times with the same theme?
  • What happens if the service is called with a theme that is not defined?
  • How should the service handle initialization (e.g., loading a theme from local storage)? (This is not required for the core functionality, but a good consideration for a production-ready service).

Examples

Example 1:

Input: setTheme('dark') followed by setTheme('light')
Output: The application's CSS variables are updated to reflect the 'dark' theme, then the 'light' theme.
Explanation: The service stores the theme and emits an event, triggering components to update their styles based on the new CSS variables.

Example 2:

Input: setTheme('invalidTheme')
Output: The service logs an error message and sets the theme to 'light' (the default).
Explanation: The service handles the invalid theme gracefully by defaulting to a known theme.

Example 3:

Input: A component subscribes to the theme changes observable and calls setTheme('dark').
Output: The component receives an emitted value of 'dark' from the observable.
Explanation: The observable pattern ensures that components are notified of theme changes in real-time.

Constraints

  • Theme Definitions: You will be provided with the following theme definitions as constants within the service:

    const themes = {
      light: {
        '--background-color': '#ffffff',
        '--text-color': '#000000',
        '--primary-color': '#007bff',
      },
      dark: {
        '--background-color': '#222222',
        '--text-color': '#ffffff',
        '--primary-color': '#00aaff',
      },
    };
    
  • CSS Variable Application: The service should apply the theme by setting CSS variables on the document.documentElement (the <html> element).

  • Performance: The service should be efficient and avoid unnecessary DOM manipulations. Setting CSS variables is generally performant.

  • Error Handling: Invalid theme names should be logged to the console.

Notes

  • Consider using RxJS observables for reactive theme changes.
  • Think about how to make the service extensible to support more themes in the future.
  • You don't need to create a full Angular application for this challenge. Focus solely on the ThemeService implementation.
  • The goal is to create a clean, reusable, and well-documented service.
  • Assume that the CSS variables defined in the themes object are already used in your application's CSS.
Loading editor...
typescript