Hone logo
Hone
Problems

Dynamic Theme Switching with CSS Custom Properties in Angular

This challenge focuses on leveraging CSS custom properties (also known as CSS variables) to implement a dynamic theme switcher in an Angular application. Using custom properties allows for efficient and maintainable theme changes without directly manipulating CSS classes, providing a clean separation of concerns. Successfully completing this challenge demonstrates understanding of Angular component interaction and the power of CSS custom properties for styling.

Problem Description

You are tasked with creating an Angular component that allows users to switch between a light and dark theme. The component should:

  1. Define a Theme Service: Create a service that manages the current theme (light or dark) and provides a method to toggle the theme.
  2. Define CSS Custom Properties: Define CSS custom properties within a global stylesheet (e.g., src/styles.css) to control the primary colors, background color, and text color of the application. Use --primary-color, --background-color, and --text-color as the custom property names.
  3. Implement the Theme Switcher Component: Create an Angular component with a button that, when clicked, calls the theme service to toggle the theme.
  4. Apply Custom Properties: In the global stylesheet, use the theme service's current theme value to dynamically set the values of the CSS custom properties. For example, if the theme is 'light', --primary-color should be set to #007bff, --background-color to #f8f9fa, and --text-color to #212529. If the theme is 'dark', --primary-color should be #61dafb, --background-color to #282c34, and --text-color to #f8f9fa.
  5. Apply Custom Properties to Elements: In a sample component (e.g., AppComponent), apply the CSS custom properties to various elements (e.g., body, h1, p) to demonstrate the theme change.

Expected Behavior:

  • Initially, the application should load with a default theme (e.g., light).
  • Clicking the theme switcher button should toggle between the light and dark themes.
  • The application's appearance (colors of elements) should update immediately upon theme change.
  • The theme should persist across page reloads (using localStorage in the Theme Service).

Edge Cases to Consider:

  • Handling initial theme loading from localStorage.
  • Ensuring the theme service is properly injected into the component.
  • Properly updating the CSS custom properties based on the current theme.

Examples

Example 1:

Input: Initial theme is 'light'.  User clicks the theme switcher button.
Output: Theme changes to 'dark'.  `body` background color changes from `#f8f9fa` to `#282c34`, text color changes from `#212529` to `#f8f9fa`, and the primary color changes accordingly.
Explanation: The theme service toggles the theme, updates the CSS custom properties in the global stylesheet, and the elements using those properties reflect the change.

Example 2:

Input: Initial theme is 'dark'.  User refreshes the page.
Output: Theme remains 'dark'.
Explanation: The Theme Service retrieves the theme from `localStorage` on initialization and applies the corresponding CSS custom properties.

Example 3: (Edge Case)

Input: `localStorage` is empty. User clicks the theme switcher button multiple times.
Output: Theme cycles between 'light' and 'dark' and persists the current theme in `localStorage` after each click.
Explanation: The Theme Service defaults to a light theme if no theme is found in `localStorage`, and then saves the selected theme.

Constraints

  • Angular Version: Angular 14 or higher.
  • CSS Custom Properties: Must use CSS custom properties for theme switching. Directly manipulating CSS classes is discouraged.
  • Persistence: The theme must be persisted across page reloads using localStorage.
  • Performance: The theme switching should be performant and not cause noticeable delays. Avoid unnecessary DOM manipulations.
  • Code Quality: The code should be well-structured, readable, and follow Angular best practices.

Notes

  • Consider using Angular's dependency injection to provide the theme service to the component.
  • The global stylesheet is the ideal place to define and update the CSS custom properties.
  • Think about how to handle the initial theme loading from localStorage gracefully.
  • You can use a simple button element for the theme switcher.
  • Focus on the core functionality of theme switching using CSS custom properties. Styling the application extensively is not required, but demonstrating the application of the custom properties is.
Loading editor...
typescript