✨ feat: adding preset, dark mode service improvements, prevent SSR flickering#384
✨ feat: adding preset, dark mode service improvements, prevent SSR flickering#384Luizgomess merged 8 commits intomasterfrom
Conversation
|
Note
|
| Cohort / File(s) | Change Summary |
|---|---|
Dark Mode Service libs/zard/src/lib/shared/services/dark-mode.ts |
Rewrote lifecycle to constructor/effect + init(); added MediaMatcher & DestroyRef; replaced previous API with a currentTheme ReadonlySignal; updated updateThemeMode signature; hardened localStorage and system-listener handling. |
Dark Mode Tests libs/zard/src/lib/shared/services/dark-mode.spec.ts |
Added comprehensive unit tests: init, system-preference listening, SSR handling, toggle flows, and listener lifecycle with mocked matchMedia/localStorage. |
App Init Wiring apps/web/src/app/app.config.ts |
Added provideAppInitializer(() => inject(ZardDarkMode).init()) to run dark-mode init during app startup. |
Call Site Updates apps/web/src/app/domain/pages/dark-mode/*, apps/web/src/app/core/layouts/documentation/documentation.layout.ts, apps/web/src/app/domain/components/block-preview/block-preview.component.ts |
Updated consumers to use currentTheme() signal access instead of removed getters/properties (theme/getCurrentTheme); removed obsolete properties and adjusted template/local bindings. |
Theme Presets & Sidebar apps/web/src/app/domain/pages/themes/data/theme-presets.ts, apps/web/src/app/domain/pages/themes/components/theme-sidebar/theme-sidebar.component.html |
Added nordIceTheme and Nord Ice entry in THEME_PRESETS; adjusted sidebar HTML to wrap each color item with a py-3 per-item container (spacing change). |
Fonts & Global Styles / Index apps/web/src/styles.css, apps/web/src/index.html |
Switched to Geist variable fonts imports, added --font-geist-mono, updated font variable mappings, adjusted container max-width utility, removed Google Fonts preconnects, and simplified early theme class toggling. |
Prerender & Build Config apps/web/prerender-routes.txt, apps/web/project.json |
Added /themes to prerender routes; set optimization.styles.inlineCritical = false in production config. |
Minor Formatting apps/web/src/app/shared/services/markdown.service.ts |
Reflowed Tailwind class arrays to multi-line for readability only. |
Sequence Diagram(s)
sequenceDiagram
actor Browser
participant App as Angular App
participant Init as AppInitializer
participant Zard as ZardDarkMode
participant Media as MediaMatcher
participant DOM as Document
Note right of App: App bootstrap
App->>Init: run app initializers
Init->>Zard: init()
Note right of Zard: constructor/effect may run earlier (signals)
Zard->>Zard: read stored theme (localStorage, guarded)
alt stored theme present
Zard->>DOM: apply stored theme (html class / data-theme)
else
Zard->>Media: query prefers-color-scheme
Media-->>Zard: current preference
Zard->>DOM: apply SYSTEM-derived theme (html class / data-theme)
end
alt SYSTEM mode active
Browser->>Media: system preference changes
Media->>Zard: change event
Zard->>Zard: updateThemeMode(isDark, SYSTEM)
Zard->>DOM: update classes / data-theme
end
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
- Task/#336 foutc #337 — related API changes to the dark-mode service and updated callers.
- ✨ feat(theme-generator): customize zard/ui theme #380 — overlapping edits to theme presets and theme-sidebar/template.
- ✨ feat(CLI): improving CLI to support index.html update and adding appearance service to support theme switching #369 — related dark-mode refactor and initialization wiring.
Suggested reviewers
- srizzon
- Luizgomess
- ribeiromatheuss
"Effects hum, MediaMatcher sings,
Nord Ice brings its frosty rings,
Geist variables take the stage,
Signals, init, and tests engage—
Light and dark in tidy wings."
Pre-merge checks and finishing touches
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | You can run @coderabbitai generate docstrings to improve docstring coverage. |
✅ Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title check | ✅ Passed | The title accurately summarizes the three main changes: adding a theme preset, improving the dark mode service, and fixing SSR flickering issues. |
| Description check | ✅ Passed | The description is comprehensive and well-structured, covering all major changes with clear sections, detailed explanations, and completed checklist items matching the template. |
✨ Finishing touches
- 📝 Generate docstrings
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Post copyable unit tests in a comment
- Commit unit tests in branch
themes-update
📜 Recent review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
apps/web/public/r/dark-mode.jsonis excluded by!apps/web/public/**and included byapps/**
📒 Files selected for processing (3)
apps/web/src/app/app.config.tslibs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
🧰 Additional context used
📓 Path-based instructions (3)
libs/zard/**/*.{css,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Use CSS custom properties for design tokens and theming in the component library
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
**/*.spec.ts
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use Jest with @happy-dom/jest-environment and Angular TestBed utilities for testing
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use path aliases @zard/* to map to libs/zard/src/lib/* in imports
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.tsapps/web/src/app/app.config.ts
🧠 Learnings (36)
📓 Common learnings
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Implement TailwindCSS v4 with PostCSS for styling and use class merging with tailwind-merge to resolve conflicts
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Use Angular TestBed and ComponentFixture utilities for testing components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tsapps/web/src/app/app.config.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Place tests co-located with components using the .spec.ts naming convention
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Co-locate test files with components using `.spec.ts` suffix next to component files
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.tsapps/web/src/app/app.config.ts
📚 Learning: 2025-12-13T11:50:56.310Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 372
File: libs/zard/src/lib/shared/components/card/card.component.spec.ts:86-88
Timestamp: 2025-12-13T11:50:56.310Z
Learning: Do not flag or suggest removing `standalone: true` from test components (*.spec.ts files) or demo components (demo/*.ts files) in libs/zard/src/lib/shared/components/**/*.ts, as it is not a significant concern and the explicit flag is acceptable in these contexts.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-26T11:20:45.264Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/select/select.component.spec.ts:79-88
Timestamp: 2025-11-26T11:20:45.264Z
Learning: In ZardUI select component tests (libs/zard/src/lib/components/select/select.component.spec.ts), use fakeAsync() with flush() instead of setTimeout because the component uses setTimeout(..., 0) for focus management, which requires advancing macrotasks in tests.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to **/*.spec.ts : Use Jest with happy-dom/jest-environment and Angular TestBed utilities for testing
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use OnPush change detection strategy in Angular components: `changeDetection: ChangeDetectionStrategy.OnPush`
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.tsapps/web/src/app/app.config.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/demo/**/*.ts : Create demo components in the `demo/` folder with a main export, default example, and variant examples
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-10T21:46:33.213Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 318
File: libs/zard/src/lib/components/select/demo/default.ts:21-21
Timestamp: 2025-11-10T21:46:33.213Z
Learning: In demo files under libs/zard/src/lib/components/**/demo/*.ts, intentionally showing different patterns (e.g., primitive values vs signals) across different demos is valuable for demonstrating the flexibility of Angular features like two-way binding.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use Signal-based inputs with the `input()` function instead of Input decorators in Angular components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use ChangeDetectionStrategy.OnPush for performance optimization in components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-30T19:07:11.572Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 352
File: apps/web/src/app/domain/components/sidebar/scroll-on-active.directive.ts:23-27
Timestamp: 2025-11-30T19:07:11.572Z
Learning: In apps/web/src/app/domain/components/sidebar/scroll-on-active.directive.ts, the guard checking if scrollIntoView exists before calling it is necessary due to mobile browser compatibility issues. Physical testing on mobile devices shows scrollIntoView may not be present or functional. This defensive pattern should be kept despite scrollIntoView being part of the standard DOM API.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Use Jest with `happy-dom/jest-environment` for testing Angular components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-15T11:43:06.831Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 373
File: libs/zard/src/lib/shared/components/select/select.component.ts:33-33
Timestamp: 2025-12-15T11:43:06.831Z
Learning: In files under libs/zard/src/lib/**/*.{ts,tsx,js}, prefer the @/ path alias for imports that map to libs/zard/src/lib/* directories. For example, write import { mergeClasses } from '@/shared/utils/merge-classes' instead of using the 'zard/' alias. This improves path readability and aligns with the project's alias configuration.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use `mergeClasses()` utility with `clsx` and `tailwind-merge` to resolve class conflicts in component styling
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Implement TailwindCSS v4 with PostCSS for styling and use class merging with tailwind-merge to resolve conflicts
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-30T13:27:41.206Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/popover/popover.component.ts:28-29
Timestamp: 2025-11-30T13:27:41.206Z
Learning: In libs/zard/src/lib/components/core/**/*.ts files (core utilities, plugins, and providers), use relative imports for intra-core dependencies because the ZardUI CLI performs path transformations during component installation. The CLI expects specific relative path patterns and transforms them to the target project structure. For all other component imports and application code, use zard/* path aliases.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.tsapps/web/src/app/app.config.ts
📚 Learning: 2025-11-14T22:52:09.135Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 326
File: libs/zard/src/lib/components/input/float.label.component.ts:71-0
Timestamp: 2025-11-14T22:52:09.135Z
Learning: In libs/zard/src/lib/components/*/*.component.ts files, move HostListener and HostBinding to the Component decorator's host property instead of using decorators on class members (e.g., host: { '(input)': 'onInput()' }).
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use mergeClasses utility from zard/shared/utils for combining CVA variants with custom classes
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use computed properties in Angular components for reactive class calculations: `protected readonly classes = computed(() => ...)`
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-29T15:31:22.377Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 339
File: libs/zard/src/lib/components/carousel/carousel.component.ts:92-92
Timestamp: 2025-11-29T15:31:22.377Z
Learning: In libs/zard/src/lib/components/**/*.component.ts files using TailwindCSS, avoid suggesting individual class bindings like `[class.fill-primary]="condition"` because they can cause TailwindCSS issues. Prefer string concatenation or `[class]` binding with conditional expressions instead.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T21:17:39.497Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 383
File: libs/zard/src/lib/shared/components/carousel/carousel.component.ts:114-115
Timestamp: 2025-12-21T21:17:39.497Z
Learning: In Angular components using signal inputs (input()) with types from external libraries like Embla Carousel, explicit type annotations (e.g., `readonly zOptions: InputSignal<EmblaOptionsType> = input<EmblaOptionsType>(...)`) may be necessary to prevent TypeScript IDE errors about inferred types referencing non-portable node_modules paths. This is not redundant when the annotation prevents the "cannot be named without a reference to node_modules" error.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Applies to libs/blocks/src/lib/**/*.component.html : Use TailwindCSS utility classes for styling, following responsive design patterns with prefixes for breakpoints (sm:, lg:) and ensure accessibility with semantic HTML and ARIA guidelines
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.variants.ts : Use CVA (Class Variance Authority) for type-safe styling variants in components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/src/styles.css : Set up `src/styles.css` with Tailwind CSS configuration and design tokens using CSS `theme` and `plugin` directives
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.variants.ts : Use CVA (Class Variance Authority) for typed variants in component styling
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Components should be built with TailwindCSS v4 using the new inline configuration approach (no `tailwind.config.js` needed, configuration via `.postcssrc.json`, design tokens defined in CSS with `theme`)
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Use TailwindCSS v4 with PostCSS for styling the component library
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-26T10:13:44.258Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/layout/sidebar.component.ts:22-22
Timestamp: 2025-11-26T10:13:44.258Z
Learning: The ZardUI CLI will automatically add `provideZard()` to the app configuration and install the core component before the next CLI release, addressing the breaking change requirement for the event manager plugins.
Applied to files:
apps/web/src/app/app.config.ts
📚 Learning: 2025-11-30T08:50:23.436Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/core/providezard.ts:0-0
Timestamp: 2025-11-30T08:50:23.436Z
Learning: In libs/zard/src/lib/components/core/providezard.ts, the import paths `../core/event-manager-plugins/...` are intentionally structured this way because the ZardUI CLI transforms them to 'shared/components/core/event-manager-plugins/...' format. Other relative path combinations don't work with the current CLI implementation. This path pattern should not be simplified until the CLI transformation logic is updated.
Applied to files:
apps/web/src/app/app.config.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Create components as standalone components with `standalone: true` in Angular
Applied to files:
apps/web/src/app/app.config.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/components.ts : Export all components in `libs/zard/src/lib/components/components.ts` for public API
Applied to files:
apps/web/src/app/app.config.ts
🔇 Additional comments (13)
apps/web/src/app/app.config.ts (2)
2-13: LGTM! Clean imports following path alias conventions.The imports are well-organized and correctly use the
@zard/*path alias for the dark mode service import.
31-31: App initializer pattern correctly implements early theme setup.The
provideAppInitializerapproach ensures the dark mode service initializes before first render, preventing SSR flicker. The synchronousinit()call is appropriate here and won't block app startup.libs/zard/src/lib/shared/services/dark-mode.spec.ts (4)
1-65: Excellent test setup with comprehensive mocking and cleanup.The test suite properly:
- Mocks browser APIs (matchMedia, localStorage) for isolation
- Configures TestBed with the service under test
- Calls
TestBed.tick()after initialization to flush effects- Clears mocks and localStorage between tests to prevent state leakage
This follows Jest and Angular TestBed best practices.
67-120: Thorough coverage of system theme detection and listener lifecycle.The tests properly verify:
- Media query initialization and matcher configuration
- Event listener registration when theme is set to SYSTEM
- Listener cleanup when switching away from SYSTEM
- Dynamic system preference changes updating the theme
- Fresh service initialization with system dark mode preference
The use of
TestBed.tick()after state changes ensures effects execute before assertions.
122-158: Excellent SSR safety coverage.The tests verify:
- Proper listener setup when initializing with SYSTEM theme default
- Graceful degradation in SSR environments (no browser API access)
- All theme toggle operations work safely without throwing in SSR context
The SSR test correctly simulates server environment by providing a non-browser
PLATFORM_IDand confirms the service doesn't access browser-only APIs.
160-212: Comprehensive toggleTheme test coverage.The test suite verifies:
- Implicit toggling between light and dark modes
- Toggling from system-detected theme (both dark and light) to explicit modes
- Explicit theme setting via the
targetModeparameter- Proper listener cleanup when switching away from SYSTEM mode
- Correct theme resolution when SYSTEM mode depends on media query state
All tests properly use
TestBed.tick()to flush effects before assertions.libs/zard/src/lib/shared/services/dark-mode.ts (7)
1-24: Excellent use of modern Angular APIs and dependency injection patterns.The service correctly:
- Uses
inject()function for dependency injection (modern Angular pattern)- Replaces
OnDestroywithDestroyReffor lifecycle management- Uses signals for reactive state management
- Integrates
MediaMatcherfrom Angular CDK for media query handling- Employs proper browser/server detection with
isPlatformBrowser
26-37: Constructor correctly implements reactive theme management with effect-based lifecycle.The implementation:
- Guards browser-only code with
isBrowsercheck for SSR safety- Uses
MediaMatcher.matchMedia()for system theme detection- Registers cleanup via
DestroyRef.onDestroy()(modern Angular pattern)- Employs
effect()to reactively apply theme changes when signal updatesThis centralizes theme application logic and eliminates the need for manual
OnDestroyimplementation.
39-51: Computed signal correctly resolves system theme to actual mode.The
themeModecomputed signal:
- Resolves
SYSTEMtoDARKorLIGHTbased on media query state- Returns explicit modes unchanged
- Provides a clean API for consumers who need the resolved theme
The
init()method:
- Guards against multiple initializations with the
initializedflag- Only runs in browser context for SSR safety
- Bootstraps theme state during app initialization
53-73: Public API correctly exposes theme control and readonly access.The
toggleTheme()method:
- Guards against SSR with browser check
- Supports both explicit mode setting and implicit toggling
- Implicit toggle switches between resolved DARK/LIGHT modes
The
currentThemegetter:
- Returns
ReadonlySignalto prevent external mutation- Provides clear JSDoc with usage example
- Enables reactive template bindings via signal
75-92: Initialization correctly restores stored theme and sets up system listeners.The
querygetter:
- Throws descriptive error if accessed in SSR context
- Guards against missing
_queryinstanceThe
initializeTheme()method:
- Loads stored theme preference via
getStoredTheme()- Sets up system change listeners when using SYSTEM mode or no stored preference
- Uses
initializedflag to prevent duplicate initialization
94-127: Robust error handling around localStorage operations.Both methods properly:
- Guard browser-only operations
- Wrap localStorage access in try-catch blocks
- Log errors with
console.warn()without crashing the app- Validate stored values against the expected enum values
- Gracefully handle
QuotaExceededErrorandSecurityError(private browsing)The
applyTheme()method correctly manages listener lifecycle:
- Adds system change listener when theme is SYSTEM
- Removes listener when switching to explicit LIGHT/DARK
129-153: DOM manipulation and listener management correctly implemented.The helper methods:
updateThemeMode():
- Updates both the
darkclass anddata-themeattribute- Accepts resolved dark mode state and theme mode for flexible updates
isDarkModeActive():
- Correctly determines dark mode: explicit DARK or SYSTEM with query match
- Guards browser-only logic
handleSystemChanges():
- Wraps listener operations in try-catch for defensive programming
- Handles both adding and removing listeners based on parameter
- Logs errors without crashing
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
apps/web/src/app/domain/pages/themes/components/theme-sidebar/theme-sidebar.component.htmlapps/web/src/app/domain/pages/themes/data/theme-presets.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use path aliases @zard/* to map to libs/zard/src/lib/* in imports
Files:
apps/web/src/app/domain/pages/themes/data/theme-presets.ts
🧠 Learnings (4)
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
Applied to files:
apps/web/src/app/domain/pages/themes/components/theme-sidebar/theme-sidebar.component.html
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Applies to libs/blocks/src/lib/**/*.component.html : Use TailwindCSS utility classes for styling, following responsive design patterns with prefixes for breakpoints (sm:, lg:) and ensure accessibility with semantic HTML and ARIA guidelines
Applied to files:
apps/web/src/app/domain/pages/themes/components/theme-sidebar/theme-sidebar.component.html
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Implement TailwindCSS v4 with PostCSS for styling and use class merging with tailwind-merge to resolve conflicts
Applied to files:
apps/web/src/app/domain/pages/themes/components/theme-sidebar/theme-sidebar.component.html
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/src/styles.css : Set up `src/styles.css` with Tailwind CSS configuration and design tokens using CSS `theme` and `plugin` directives
Applied to files:
apps/web/src/app/domain/pages/themes/components/theme-sidebar/theme-sidebar.component.html
🧬 Code graph analysis (1)
apps/web/src/app/domain/pages/themes/data/theme-presets.ts (1)
apps/web/src/app/domain/pages/themes/models/theme.model.ts (1)
ThemeDefinition(35-40)
🔇 Additional comments (2)
apps/web/src/app/domain/pages/themes/data/theme-presets.ts (2)
694-694: Destructive color deviation from other themes noted.This dark mode destructive color (
oklch(0.606 0.121 15)) differs from the standardoklch(0.704 0.191 22.216)used in other themes (Neutral, Slate, Zinc, etc.). If this is intentional for Violet's palette harmony, looks good. Just flagging for awareness in case cross-theme consistency was desired.
796-796: LGTM!The Nord Ice preset entry follows the established pattern. Preview colors align with the icy blue Nord aesthetic.
apps/web/src/app/domain/pages/themes/components/theme-sidebar/theme-sidebar.component.html
Show resolved
Hide resolved
c8b5ab6 to
a9a7e63
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/web/src/app/domain/pages/themes/data/theme-presets.ts (1)
661-661: Verify destructive color consistency in violet theme.The violet theme applies a custom dark destructive color (
'oklch(0.606 0.121 15)'at line 694) while keeping the light destructive color as the standard ('oklch(0.577 0.245 27.325)'at line 661). All other themes use consistent destructive colors across both modes. This creates a visual inconsistency between the violet theme's light and dark variants.Confirm whether this custom dark color for violet theme is intentional, or if the light destructive should also be updated to maintain visual parity.
♻️ Duplicate comments (2)
apps/web/src/app/domain/pages/themes/data/theme-presets.ts (1)
765-765: Decimal precision inconsistency in destructive color.Line 765 uses 4-decimal precision (
'oklch(0.6061 0.1206 15.34)') while the rest of the file consistently uses 3 decimals for oklch values. For consistency with the codebase standard, consider adjusting to 3-decimal precision:'oklch(0.606 0.121 15.34)'.🔎 Proposed fix for consistency
- destructive: 'oklch(0.6061 0.1206 15.34)', + destructive: 'oklch(0.606 0.121 15.34)',apps/web/src/app/domain/pages/themes/components/theme-sidebar/theme-sidebar.component.html (1)
76-84: Per-item wrapper creates cumulative padding between color pickers.The restructuring moved
py-3from a parent container to individual per-item wrappers. This creates cumulative spacing: each color picker now has 12px top + 12px bottom padding, resulting in 24px of space between adjacent items (versus the 16px thatspace-y-4would have provided on a parent).If this increased spacing is intentional as part of the "visual fix" mentioned in the PR objectives, this looks good. However, if the intent was to maintain similar spacing, consider using
space-y-3on a parent wrapper or adjusting topy-1.5per-item to achieve ~12-16px total spacing.💡 Alternative: If less spacing is desired
Option 1 - Use parent wrapper with space-y utility:
+ <div class="space-y-3"> @for (colorKey of group.colors; track colorKey) { - <div class="py-3"> <app-color-picker-field [colorKey]="colorKey" [value]="currentColors()[colorKey]" (valueChange)="onColorChange(colorKey, $event)" /> - </div> } + </div>Option 2 - Reduce per-item padding:
@for (colorKey of group.colors; track colorKey) { - <div class="py-3"> + <div class="py-1.5"> <app-color-picker-field [colorKey]="colorKey" [value]="currentColors()[colorKey]" (valueChange)="onColorChange(colorKey, $event)" /> </div> }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
apps/web/src/app/domain/pages/themes/components/theme-sidebar/theme-sidebar.component.htmlapps/web/src/app/domain/pages/themes/data/theme-presets.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use path aliases @zard/* to map to libs/zard/src/lib/* in imports
Files:
apps/web/src/app/domain/pages/themes/data/theme-presets.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Follow PR checklist including: passing tests, code pattern compliance, updated documentation, working demos, no lint/typecheck warnings, linked issues, conventional commit in title
📚 Learning: 2025-11-29T15:31:22.377Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 339
File: libs/zard/src/lib/components/carousel/carousel.component.ts:92-92
Timestamp: 2025-11-29T15:31:22.377Z
Learning: In libs/zard/src/lib/components/**/*.component.ts files using TailwindCSS, avoid suggesting individual class bindings like `[class.fill-primary]="condition"` because they can cause TailwindCSS issues. Prefer string concatenation or `[class]` binding with conditional expressions instead.
Applied to files:
apps/web/src/app/domain/pages/themes/components/theme-sidebar/theme-sidebar.component.html
🔇 Additional comments (1)
apps/web/src/app/domain/pages/themes/data/theme-presets.ts (1)
796-796: Nord Ice preset addition looks good!The new preset entry follows the established pattern correctly and includes appropriate preview colors that align with the Nord Ice theme palette.
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
.gitignoreis excluded by none and included by none
📒 Files selected for processing (2)
libs/zard/src/lib/shared/services/dark-mode.test.tslibs/zard/src/lib/shared/services/dark-mode.ts
🧰 Additional context used
📓 Path-based instructions (2)
libs/zard/**/*.{css,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Use CSS custom properties for design tokens and theming in the component library
Files:
libs/zard/src/lib/shared/services/dark-mode.tslibs/zard/src/lib/shared/services/dark-mode.test.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use path aliases @zard/* to map to libs/zard/src/lib/* in imports
Files:
libs/zard/src/lib/shared/services/dark-mode.tslibs/zard/src/lib/shared/services/dark-mode.test.ts
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
📚 Learning: 2025-11-30T13:27:41.206Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/popover/popover.component.ts:28-29
Timestamp: 2025-11-30T13:27:41.206Z
Learning: In libs/zard/src/lib/components/core/**/*.ts files (core utilities, plugins, and providers), use relative imports for intra-core dependencies because the ZardUI CLI performs path transformations during component installation. The CLI expects specific relative path patterns and transforms them to the target project structure. For all other component imports and application code, use zard/* path aliases.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.tslibs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/components.ts : Add barrel exports for all new components in libs/zard/src/lib/components/components.ts
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-30T08:50:23.436Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/core/providezard.ts:0-0
Timestamp: 2025-11-30T08:50:23.436Z
Learning: In libs/zard/src/lib/components/core/providezard.ts, the import paths `../core/event-manager-plugins/...` are intentionally structured this way because the ZardUI CLI transforms them to 'shared/components/core/event-manager-plugins/...' format. Other relative path combinations don't work with the current CLI implementation. This path pattern should not be simplified until the CLI transformation logic is updated.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.tslibs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-15T11:43:06.831Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 373
File: libs/zard/src/lib/shared/components/select/select.component.ts:33-33
Timestamp: 2025-12-15T11:43:06.831Z
Learning: In files under libs/zard/src/lib/**/*.{ts,tsx,js}, prefer the @/ path alias for imports that map to libs/zard/src/lib/* directories. For example, write import { mergeClasses } from '@/shared/utils/merge-classes' instead of using the 'zard/' alias. This improves path readability and aligns with the project's alias configuration.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.tslibs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Place tests co-located with components using the .spec.ts naming convention
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Use Angular TestBed and ComponentFixture utilities for testing components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Co-locate test files with components using `.spec.ts` suffix next to component files
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-26T11:20:45.264Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/select/select.component.spec.ts:79-88
Timestamp: 2025-11-26T11:20:45.264Z
Learning: In ZardUI select component tests (libs/zard/src/lib/components/select/select.component.spec.ts), use fakeAsync() with flush() instead of setTimeout because the component uses setTimeout(..., 0) for focus management, which requires advancing macrotasks in tests.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-13T11:50:56.310Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 372
File: libs/zard/src/lib/shared/components/card/card.component.spec.ts:86-88
Timestamp: 2025-12-13T11:50:56.310Z
Learning: Do not flag or suggest removing `standalone: true` from test components (*.spec.ts files) or demo components (demo/*.ts files) in libs/zard/src/lib/shared/components/**/*.ts, as it is not a significant concern and the explicit flag is acceptable in these contexts.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/demo/**/*.ts : Create demo components in the `demo/` folder with a main export, default example, and variant examples
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to **/*.spec.ts : Use Jest with happy-dom/jest-environment and Angular TestBed utilities for testing
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-10T21:46:33.213Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 318
File: libs/zard/src/lib/components/select/demo/default.ts:21-21
Timestamp: 2025-11-10T21:46:33.213Z
Learning: In demo files under libs/zard/src/lib/components/**/demo/*.ts, intentionally showing different patterns (e.g., primitive values vs signals) across different demos is valuable for demonstrating the flexibility of Angular features like two-way binding.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Use Jest with `happy-dom/jest-environment` for testing Angular components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
🔇 Additional comments (5)
libs/zard/src/lib/shared/services/dark-mode.ts (2)
23-28: LGTM! Constructor initialization follows Angular best practices.The constructor properly initializes dark mode in browser context using
isPlatformBrowserguard andinject()function. This ensures SSR compatibility and follows modern Angular patterns with functional injection.
125-133: Excellent refactor: centralized state with signals.Refactoring
isDarkMode()to read fromthemeSignal()instead of directly accessing localStorage centralizes state management and aligns with Angular's signal-based reactivity patterns. The logic correctly evaluates dark mode as either explicit DARK preference or SYSTEM mode with dark system preference.libs/zard/src/lib/shared/services/dark-mode.test.ts (3)
1-60: LGTM! Test setup follows Angular testing best practices.The test setup properly mocks browser APIs (
matchMedia,localStorage) and usesTestBedfor Angular service testing. The mock implementations are clean and thebeforeEach/afterEachhooks ensure proper test isolation.
62-119: Comprehensive initialization test coverage.The test cases thoroughly validate constructor-driven initialization, system preference detection, and listener management. Accessing private properties like
darkModeService['darkModeQuery']on line 64 is acceptable for unit test verification.Minor observation: Line 101 creates a new service instance while the one from
beforeEachstill exists. Consider explicitly resetting TestBed before creating the new instance to avoid potential state conflicts, though this is not critical.
121-168: Excellent toggle behavior coverage.The
toggleThemetest suite comprehensively validates all toggle scenarios: bidirectional light/dark toggling, system mode transitions, and explicit mode setting. The verification of listener cleanup (lines 141, 152, 166) ensures proper resource management during mode transitions.
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
.gitignoreis excluded by none and included by none
📒 Files selected for processing (2)
libs/zard/src/lib/shared/services/dark-mode.test.tslibs/zard/src/lib/shared/services/dark-mode.ts
🧰 Additional context used
📓 Path-based instructions (2)
libs/zard/**/*.{css,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Use CSS custom properties for design tokens and theming in the component library
Files:
libs/zard/src/lib/shared/services/dark-mode.tslibs/zard/src/lib/shared/services/dark-mode.test.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use path aliases @zard/* to map to libs/zard/src/lib/* in imports
Files:
libs/zard/src/lib/shared/services/dark-mode.tslibs/zard/src/lib/shared/services/dark-mode.test.ts
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Keep commit messages in present tense, single line format with scope and description (e.g., '✨ feat(popover): add popover component')
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
📚 Learning: 2025-11-30T13:27:41.206Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/popover/popover.component.ts:28-29
Timestamp: 2025-11-30T13:27:41.206Z
Learning: In libs/zard/src/lib/components/core/**/*.ts files (core utilities, plugins, and providers), use relative imports for intra-core dependencies because the ZardUI CLI performs path transformations during component installation. The CLI expects specific relative path patterns and transforms them to the target project structure. For all other component imports and application code, use zard/* path aliases.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/components.ts : Add barrel exports for all new components in libs/zard/src/lib/components/components.ts
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.tslibs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-30T08:50:23.436Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/core/providezard.ts:0-0
Timestamp: 2025-11-30T08:50:23.436Z
Learning: In libs/zard/src/lib/components/core/providezard.ts, the import paths `../core/event-manager-plugins/...` are intentionally structured this way because the ZardUI CLI transforms them to 'shared/components/core/event-manager-plugins/...' format. Other relative path combinations don't work with the current CLI implementation. This path pattern should not be simplified until the CLI transformation logic is updated.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-29T15:31:22.377Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 339
File: libs/zard/src/lib/components/carousel/carousel.component.ts:92-92
Timestamp: 2025-11-29T15:31:22.377Z
Learning: In libs/zard/src/lib/components/**/*.component.ts files using TailwindCSS, avoid suggesting individual class bindings like `[class.fill-primary]="condition"` because they can cause TailwindCSS issues. Prefer string concatenation or `[class]` binding with conditional expressions instead.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.tslibs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-15T11:43:06.831Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 373
File: libs/zard/src/lib/shared/components/select/select.component.ts:33-33
Timestamp: 2025-12-15T11:43:06.831Z
Learning: In files under libs/zard/src/lib/**/*.{ts,tsx,js}, prefer the @/ path alias for imports that map to libs/zard/src/lib/* directories. For example, write import { mergeClasses } from '@/shared/utils/merge-classes' instead of using the 'zard/' alias. This improves path readability and aligns with the project's alias configuration.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.tslibs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Place tests co-located with components using the .spec.ts naming convention
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Use Angular TestBed and ComponentFixture utilities for testing components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Co-locate test files with components using `.spec.ts` suffix next to component files
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-26T11:20:45.264Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/select/select.component.spec.ts:79-88
Timestamp: 2025-11-26T11:20:45.264Z
Learning: In ZardUI select component tests (libs/zard/src/lib/components/select/select.component.spec.ts), use fakeAsync() with flush() instead of setTimeout because the component uses setTimeout(..., 0) for focus management, which requires advancing macrotasks in tests.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-13T11:50:56.310Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 372
File: libs/zard/src/lib/shared/components/card/card.component.spec.ts:86-88
Timestamp: 2025-12-13T11:50:56.310Z
Learning: Do not flag or suggest removing `standalone: true` from test components (*.spec.ts files) or demo components (demo/*.ts files) in libs/zard/src/lib/shared/components/**/*.ts, as it is not a significant concern and the explicit flag is acceptable in these contexts.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to **/*.spec.ts : Use Jest with happy-dom/jest-environment and Angular TestBed utilities for testing
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-10T21:46:33.213Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 318
File: libs/zard/src/lib/components/select/demo/default.ts:21-21
Timestamp: 2025-11-10T21:46:33.213Z
Learning: In demo files under libs/zard/src/lib/components/**/demo/*.ts, intentionally showing different patterns (e.g., primitive values vs signals) across different demos is valuable for demonstrating the flexibility of Angular features like two-way binding.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Use Jest with `happy-dom/jest-environment` for testing Angular components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
🔇 Additional comments (5)
libs/zard/src/lib/shared/services/dark-mode.ts (3)
23-28: Clean constructor initialization with proper SSR guard.Using
this.isBrowserto gate browser-specific initialization is the right approach for Angular Universal compatibility. The eager initialization ofdarkModeQueryandinitializeTheme()ensures consistent theme state from service creation.
88-102: Initialization logic is clean and handles all theme states correctly.The flow properly distinguishes between stored explicit themes (LIGHT/DARK) and SYSTEM mode, only registering the system listener when appropriate. The previous redundant nested condition has been addressed.
128-131: Good refactor: reading from signal rather than localStorage.Using
this.themeSignal()as the source of truth is consistent with Angular's reactive patterns and avoids redundant localStorage reads. The signal is already kept in sync with persistence inapplyTheme()andinitializeTheme().libs/zard/src/lib/shared/services/dark-mode.test.ts (2)
121-168: Solid coverage of toggleTheme behavior.These tests thoroughly exercise the toggle functionality across all theme modes, including proper verification that system listeners are added/removed when transitioning to/from SYSTEM mode. The assertions on both
themeMode()and listener management are well-structured.
83-96: Good defensive test structure with fallback fail().Using
find()to locate the registered callback and callingfail()if not found ensures the test doesn't silently pass when listener registration fails. This pattern makes test failures more diagnosable.
5e6b3ab to
c8825e0
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
libs/zard/src/lib/shared/services/dark-mode.test.ts (2)
58-60: Past review comment remains valid: Clear localStorage between tests.The localStorage mock isn't cleared in
afterEach, which could cause state leakage between tests if any test modifies it.🔎 Proposed fix
afterEach(() => { jest.clearAllMocks(); + window.localStorage.clear(); });Based on learnings, this aligns with Jest best practices for test isolation.
98-104: Past review comment remains valid: Test doesn't verify initialization.Since
ZardDarkModeis a root-level singleton,TestBed.inject(ZardDarkMode)on line 101 returns the instance already created inbeforeEach(line 55) whenmatcheswasfalse. Settingmatches = trueon line 99 after construction doesn't test initialization—it only tests the computed signal's reactivity.🔎 Proposed fix to properly test initialization
it('initializes with system dark theme when no stored theme exists', () => { + TestBed.resetTestingModule(); mockMediaQueryList.matches = true; + mockMediaQueryList.addEventListener.mockClear(); + + TestBed.configureTestingModule({ + providers: [ZardDarkMode], + }); const newService = TestBed.inject(ZardDarkMode); expect(newService.themeMode()).toBe(EDarkModes.DARK); + expect(mockMediaQueryList.addEventListener).toHaveBeenCalled(); });The test on lines 106-119 demonstrates the correct pattern for verifying initialization behavior.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
.gitignoreis excluded by none and included by none
📒 Files selected for processing (3)
apps/web/src/index.htmllibs/zard/src/lib/shared/services/dark-mode.test.tslibs/zard/src/lib/shared/services/dark-mode.ts
🧰 Additional context used
📓 Path-based instructions (2)
libs/zard/**/*.{css,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Use CSS custom properties for design tokens and theming in the component library
Files:
libs/zard/src/lib/shared/services/dark-mode.tslibs/zard/src/lib/shared/services/dark-mode.test.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use path aliases @zard/* to map to libs/zard/src/lib/* in imports
Files:
libs/zard/src/lib/shared/services/dark-mode.tslibs/zard/src/lib/shared/services/dark-mode.test.ts
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
📚 Learning: 2025-11-30T13:27:41.206Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/popover/popover.component.ts:28-29
Timestamp: 2025-11-30T13:27:41.206Z
Learning: In libs/zard/src/lib/components/core/**/*.ts files (core utilities, plugins, and providers), use relative imports for intra-core dependencies because the ZardUI CLI performs path transformations during component installation. The CLI expects specific relative path patterns and transforms them to the target project structure. For all other component imports and application code, use zard/* path aliases.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.tslibs/zard/src/lib/shared/services/dark-mode.test.tsapps/web/src/index.html
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-30T08:50:23.436Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/core/providezard.ts:0-0
Timestamp: 2025-11-30T08:50:23.436Z
Learning: In libs/zard/src/lib/components/core/providezard.ts, the import paths `../core/event-manager-plugins/...` are intentionally structured this way because the ZardUI CLI transforms them to 'shared/components/core/event-manager-plugins/...' format. Other relative path combinations don't work with the current CLI implementation. This path pattern should not be simplified until the CLI transformation logic is updated.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-29T15:31:22.377Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 339
File: libs/zard/src/lib/components/carousel/carousel.component.ts:92-92
Timestamp: 2025-11-29T15:31:22.377Z
Learning: In libs/zard/src/lib/components/**/*.component.ts files using TailwindCSS, avoid suggesting individual class bindings like `[class.fill-primary]="condition"` because they can cause TailwindCSS issues. Prefer string concatenation or `[class]` binding with conditional expressions instead.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.tslibs/zard/src/lib/shared/services/dark-mode.test.tsapps/web/src/index.html
📚 Learning: 2025-12-15T11:43:06.831Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 373
File: libs/zard/src/lib/shared/components/select/select.component.ts:33-33
Timestamp: 2025-12-15T11:43:06.831Z
Learning: In files under libs/zard/src/lib/**/*.{ts,tsx,js}, prefer the @/ path alias for imports that map to libs/zard/src/lib/* directories. For example, write import { mergeClasses } from '@/shared/utils/merge-classes' instead of using the 'zard/' alias. This improves path readability and aligns with the project's alias configuration.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.tslibs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Place tests co-located with components using the .spec.ts naming convention
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Use Angular TestBed and ComponentFixture utilities for testing components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Co-locate test files with components using `.spec.ts` suffix next to component files
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-26T11:20:45.264Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/select/select.component.spec.ts:79-88
Timestamp: 2025-11-26T11:20:45.264Z
Learning: In ZardUI select component tests (libs/zard/src/lib/components/select/select.component.spec.ts), use fakeAsync() with flush() instead of setTimeout because the component uses setTimeout(..., 0) for focus management, which requires advancing macrotasks in tests.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-13T11:50:56.310Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 372
File: libs/zard/src/lib/shared/components/card/card.component.spec.ts:86-88
Timestamp: 2025-12-13T11:50:56.310Z
Learning: Do not flag or suggest removing `standalone: true` from test components (*.spec.ts files) or demo components (demo/*.ts files) in libs/zard/src/lib/shared/components/**/*.ts, as it is not a significant concern and the explicit flag is acceptable in these contexts.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/demo/**/*.ts : Create demo components in the `demo/` folder with a main export, default example, and variant examples
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-10T21:46:33.213Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 318
File: libs/zard/src/lib/components/select/demo/default.ts:21-21
Timestamp: 2025-11-10T21:46:33.213Z
Learning: In demo files under libs/zard/src/lib/components/**/demo/*.ts, intentionally showing different patterns (e.g., primitive values vs signals) across different demos is valuable for demonstrating the flexibility of Angular features like two-way binding.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to **/*.spec.ts : Use Jest with happy-dom/jest-environment and Angular TestBed utilities for testing
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Use Jest with `happy-dom/jest-environment` for testing Angular components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
🔇 Additional comments (5)
libs/zard/src/lib/shared/services/dark-mode.ts (3)
23-28: LGTM! Clean constructor initialization.The constructor properly initializes dark mode query and theme state in the browser context. Good use of platform checking and the Angular
inject()function.
88-102: LGTM! Initialization logic is correct.The theme initialization properly handles all cases (no stored theme, SYSTEM mode, and explicit LIGHT/DARK). The redundant nested condition from the previous review has been successfully addressed.
123-131: LGTM! Proper signal usage.Line 129 correctly derives the stored theme from
themeSignal()rather than directly accessing localStorage, which is the idiomatic approach for Angular signals. This ensures consistency with the signal-based state management.libs/zard/src/lib/shared/services/dark-mode.test.ts (2)
62-96: LGTM! Well-structured initialization tests.These tests properly verify:
- Dark mode query initialization on service creation
- System listener registration/removal when switching modes
- Theme updates when system preference changes
The callback extraction pattern on line 86 is a clean way to test event handling.
121-168: LGTM! Comprehensive toggleTheme coverage.The test suite thoroughly covers all toggle scenarios:
- Parameterless toggle alternating between modes
- Toggle from SYSTEM mode (both light and dark system preferences)
- Explicit theme mode setting
- Proper listener cleanup when switching away from SYSTEM mode
Excellent test coverage for this critical functionality.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
libs/zard/src/lib/shared/services/dark-mode.test.ts (1)
100-106: Test still doesn't verify initialization behavior.This test was previously flagged as not properly testing initialization because
TestBed.inject(ZardDarkMode)returns the singleton created inbeforeEach(withmatches: false). Settingmatches = trueon line 101 after construction doesn't test initialization—it tests signal reactivity.Despite being marked "✅ Addressed in commit 5e6b3ab" in past comments, the issue persists in this code.
🔎 Proposed fix to properly test initialization
Follow the pattern from the test on lines 108-121:
it('initializes with system dark theme when no stored theme exists', () => { + TestBed.resetTestingModule(); mockMediaQueryList.matches = true; + mockMediaQueryList.addEventListener.mockClear(); + + TestBed.configureTestingModule({ + providers: [ZardDarkMode], + }); const newService = TestBed.inject(ZardDarkMode); expect(newService.themeMode()).toBe(EDarkModes.DARK); });This ensures the service is constructed after setting
matches = true, properly verifying initialization behavior.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
.gitignoreis excluded by none and included by none
📒 Files selected for processing (3)
apps/web/src/index.htmllibs/zard/src/lib/shared/services/dark-mode.test.tslibs/zard/src/lib/shared/services/dark-mode.ts
🧰 Additional context used
📓 Path-based instructions (2)
libs/zard/**/*.{css,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Use CSS custom properties for design tokens and theming in the component library
Files:
libs/zard/src/lib/shared/services/dark-mode.test.tslibs/zard/src/lib/shared/services/dark-mode.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use path aliases @zard/* to map to libs/zard/src/lib/* in imports
Files:
libs/zard/src/lib/shared/services/dark-mode.test.tslibs/zard/src/lib/shared/services/dark-mode.ts
🧠 Learnings (14)
📓 Common learnings
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
Applied to files:
apps/web/src/index.htmllibs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
Applied to files:
apps/web/src/index.htmllibs/zard/src/lib/shared/services/dark-mode.test.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Place tests co-located with components using the .spec.ts naming convention
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Co-locate test files with components using `.spec.ts` suffix next to component files
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Use Angular TestBed and ComponentFixture utilities for testing components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-26T11:20:45.264Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/select/select.component.spec.ts:79-88
Timestamp: 2025-11-26T11:20:45.264Z
Learning: In ZardUI select component tests (libs/zard/src/lib/components/select/select.component.spec.ts), use fakeAsync() with flush() instead of setTimeout because the component uses setTimeout(..., 0) for focus management, which requires advancing macrotasks in tests.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-13T11:50:56.310Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 372
File: libs/zard/src/lib/shared/components/card/card.component.spec.ts:86-88
Timestamp: 2025-12-13T11:50:56.310Z
Learning: Do not flag or suggest removing `standalone: true` from test components (*.spec.ts files) or demo components (demo/*.ts files) in libs/zard/src/lib/shared/components/**/*.ts, as it is not a significant concern and the explicit flag is acceptable in these contexts.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/demo/**/*.ts : Create demo components in the `demo/` folder with a main export, default example, and variant examples
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to **/*.spec.ts : Use Jest with happy-dom/jest-environment and Angular TestBed utilities for testing
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-10T21:46:33.213Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 318
File: libs/zard/src/lib/components/select/demo/default.ts:21-21
Timestamp: 2025-11-10T21:46:33.213Z
Learning: In demo files under libs/zard/src/lib/components/**/demo/*.ts, intentionally showing different patterns (e.g., primitive values vs signals) across different demos is valuable for demonstrating the flexibility of Angular features like two-way binding.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-15T11:43:06.831Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 373
File: libs/zard/src/lib/shared/components/select/select.component.ts:33-33
Timestamp: 2025-12-15T11:43:06.831Z
Learning: In files under libs/zard/src/lib/**/*.{ts,tsx,js}, prefer the @/ path alias for imports that map to libs/zard/src/lib/* directories. For example, write import { mergeClasses } from '@/shared/utils/merge-classes' instead of using the 'zard/' alias. This improves path readability and aligns with the project's alias configuration.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-30T13:27:41.206Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/popover/popover.component.ts:28-29
Timestamp: 2025-11-30T13:27:41.206Z
Learning: In libs/zard/src/lib/components/core/**/*.ts files (core utilities, plugins, and providers), use relative imports for intra-core dependencies because the ZardUI CLI performs path transformations during component installation. The CLI expects specific relative path patterns and transforms them to the target project structure. For all other component imports and application code, use zard/* path aliases.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-29T15:31:22.377Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 339
File: libs/zard/src/lib/components/carousel/carousel.component.ts:92-92
Timestamp: 2025-11-29T15:31:22.377Z
Learning: In libs/zard/src/lib/components/**/*.component.ts files using TailwindCSS, avoid suggesting individual class bindings like `[class.fill-primary]="condition"` because they can cause TailwindCSS issues. Prefer string concatenation or `[class]` binding with conditional expressions instead.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
🔇 Additional comments (7)
apps/web/src/index.html (1)
70-75: Verify asymmetric localStorage persistence is intentional.When no stored preference exists and system prefers dark mode, line 71 persists
'system'to localStorage. However, when system prefers light mode (lines 73-75), no value is persisted. This asymmetry means:
- First visit in dark mode → localStorage.darkMode = 'system'
- First visit in light mode → localStorage.darkMode remains unset
If the user's system preference changes after their first visit, the behavior will differ depending on whether their initial visit was in dark or light mode. Is this intentional?
💡 Consider symmetric initialization
If consistent behavior is desired:
} else if (systemDarkMode && hasDocument) { localStorage.setItem('darkMode', 'system'); document.documentElement.classList.add('dark'); } else if (hasDocument) { + localStorage.setItem('darkMode', 'system'); document.documentElement.classList.remove('dark'); }This ensures both paths persist
'system'when no preference is stored, making the service initialization indark-mode.tsbehave consistently regardless of initial system preference.libs/zard/src/lib/shared/services/dark-mode.ts (3)
23-28: LGTM: Clean constructor initialization.The constructor properly initializes the dark mode query and theme state in the browser environment. Guards with
isBrowsercheck and delegates toinitializeThemefor setup logic, keeping concerns separated.
88-102: LGTM: Solid initialization logic.The
initializeThememethod correctly:
- Loads persisted preference and sets the signal
- Defaults to system preference when no explicit choice is stored
- Manages system-change listeners appropriately (enabled for SYSTEM mode, disabled otherwise)
The previously flagged redundant nested condition has been removed.
129-129: LGTM: Signal as source of truth.Using
themeSignal()instead of reading localStorage directly is more efficient and aligns with Angular's signal-based reactivity. The signal is kept in sync with localStorage viaapplyTheme, making this a clean refactor.libs/zard/src/lib/shared/services/dark-mode.test.ts (3)
1-62: LGTM: Comprehensive test setup.The test setup correctly:
- Mocks
matchMediawith controllablematchesstate and listener tracking- Mocks
localStoragewith a proper in-memory implementation- Clears localStorage in
afterEachto prevent state leakage between tests (addressing previous feedback)Clean and thorough test infrastructure.
64-98: LGTM: Thorough system-change detection tests.These tests comprehensively verify:
- Dark mode query initialization in the constructor
- Listener lifecycle (add when entering SYSTEM mode, remove when leaving)
- System preference change callback updates the theme correctly
Clear test structure with good coverage of the system-aware behavior.
108-170: LGTM: Excellent test coverage of public API.Lines 108-121 correctly reset TestBed to create a fresh service instance, properly testing constructor initialization behavior.
The
toggleThemetest suite (lines 123-170) comprehensively covers:
- Toggling without arguments (light ↔ dark)
- Toggling from system-based modes
- Setting specific target modes
- Listener lifecycle during mode transitions
Well-organized tests with clear expectations.
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (2)
apps/web/src/index.html (1)
126-126: Remove unusedhasBodyvariable.The
hasBodyvariable is declared but never used. After the refactor to usedocument.documentElement, this check is no longer needed.🔎 Proposed fix
- let hasBody = !!document && !!document.body; let hasDocument = !!document && !!document.documentElement;libs/zard/src/lib/shared/services/dark-mode.test.ts (1)
100-106: Test doesn't verify initialization—it tests computed signal reactivity.The service is
providedIn: 'root', soTestBed.inject(ZardDarkMode)at line 103 returns the singleton created inbeforeEachwithmatches: falsealready initialized. Settingmatches = trueon line 101 after the singleton exists only changes the mock's state. WhenthemeMode()is called, the computed signal reads the liveisDarkMode()value (which checks the currentmatches), making the test pass but testing reactivity, not initialization.To properly test initialization with system dark mode enabled, reset TestBed like the test at lines 108-121:
it('initializes with system dark theme when no stored theme exists', () => { + TestBed.resetTestingModule(); mockMediaQueryList.matches = true; + mockMediaQueryList.addEventListener.mockClear(); + + TestBed.configureTestingModule({ + providers: [ZardDarkMode], + }); const newService = TestBed.inject(ZardDarkMode); expect(newService.themeMode()).toBe(EDarkModes.DARK); });
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
.gitignoreis excluded by none and included by none
📒 Files selected for processing (4)
apps/web/src/index.htmlapps/web/src/styles.csslibs/zard/src/lib/shared/services/dark-mode.test.tslibs/zard/src/lib/shared/services/dark-mode.ts
🧰 Additional context used
📓 Path-based instructions (2)
libs/zard/**/*.{css,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Use CSS custom properties for design tokens and theming in the component library
Files:
libs/zard/src/lib/shared/services/dark-mode.test.tslibs/zard/src/lib/shared/services/dark-mode.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use path aliases @zard/* to map to libs/zard/src/lib/* in imports
Files:
libs/zard/src/lib/shared/services/dark-mode.test.tslibs/zard/src/lib/shared/services/dark-mode.ts
🧠 Learnings (15)
📓 Common learnings
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Place tests co-located with components using the .spec.ts naming convention
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Co-locate test files with components using `.spec.ts` suffix next to component files
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Use Angular TestBed and ComponentFixture utilities for testing components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.tsapps/web/src/index.html
📚 Learning: 2025-12-13T11:50:56.310Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 372
File: libs/zard/src/lib/shared/components/card/card.component.spec.ts:86-88
Timestamp: 2025-12-13T11:50:56.310Z
Learning: Do not flag or suggest removing `standalone: true` from test components (*.spec.ts files) or demo components (demo/*.ts files) in libs/zard/src/lib/shared/components/**/*.ts, as it is not a significant concern and the explicit flag is acceptable in these contexts.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-26T11:20:45.264Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/select/select.component.spec.ts:79-88
Timestamp: 2025-11-26T11:20:45.264Z
Learning: In ZardUI select component tests (libs/zard/src/lib/components/select/select.component.spec.ts), use fakeAsync() with flush() instead of setTimeout because the component uses setTimeout(..., 0) for focus management, which requires advancing macrotasks in tests.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/demo/**/*.ts : Create demo components in the `demo/` folder with a main export, default example, and variant examples
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/components.ts : Add barrel exports for all new components in libs/zard/src/lib/components/components.ts
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to **/*.spec.ts : Use Jest with happy-dom/jest-environment and Angular TestBed utilities for testing
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-10T21:46:33.213Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 318
File: libs/zard/src/lib/components/select/demo/default.ts:21-21
Timestamp: 2025-11-10T21:46:33.213Z
Learning: In demo files under libs/zard/src/lib/components/**/demo/*.ts, intentionally showing different patterns (e.g., primitive values vs signals) across different demos is valuable for demonstrating the flexibility of Angular features like two-way binding.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.ts
📚 Learning: 2025-12-15T11:43:06.831Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 373
File: libs/zard/src/lib/shared/components/select/select.component.ts:33-33
Timestamp: 2025-12-15T11:43:06.831Z
Learning: In files under libs/zard/src/lib/**/*.{ts,tsx,js}, prefer the @/ path alias for imports that map to libs/zard/src/lib/* directories. For example, write import { mergeClasses } from '@/shared/utils/merge-classes' instead of using the 'zard/' alias. This improves path readability and aligns with the project's alias configuration.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.test.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/src/styles.css : Set up `src/styles.css` with Tailwind CSS configuration and design tokens using CSS `theme` and `plugin` directives
Applied to files:
apps/web/src/index.html
📚 Learning: 2025-11-29T15:31:22.377Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 339
File: libs/zard/src/lib/components/carousel/carousel.component.ts:92-92
Timestamp: 2025-11-29T15:31:22.377Z
Learning: In libs/zard/src/lib/components/**/*.component.ts files using TailwindCSS, avoid suggesting individual class bindings like `[class.fill-primary]="condition"` because they can cause TailwindCSS issues. Prefer string concatenation or `[class]` binding with conditional expressions instead.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
🔇 Additional comments (6)
libs/zard/src/lib/shared/services/dark-mode.ts (3)
23-28: LGTM: Constructor follows Angular best practices.The constructor properly gates browser-only initialization using
isPlatformBrowser()and leverages theinject()function. The initialization flow is explicit and clear.
88-102: LGTM: Initialization logic is clear and correct.The
initializeThememethod properly handles three scenarios:
- No stored theme → defaults to system preference with listener
- Stored SYSTEM mode → applies system preference with listener
- Stored explicit mode → applies stored preference without listener
The flow is straightforward and the system listener management is correctly placed.
123-131: LGTM: Improved efficiency by reading from signal instead of localStorage.Refactoring
isDarkModeto read fromthemeSignal(line 129) instead of directly accessinglocalStorageimproves performance and maintains the signal as the single source of truth. This follows reactive patterns and reduces I/O overhead.libs/zard/src/lib/shared/services/dark-mode.test.ts (3)
14-62: LGTM: Comprehensive test setup with proper mocking and cleanup.The test setup properly mocks
window.matchMediaandlocalStoragewith complete implementations. TheafterEachhook on line 61 clears localStorage between tests, preventing state leakage.
85-98: LGTM: Proper verification of system preference change handling.The test correctly retrieves the registered callback (line 88), simulates a system preference change (line 92), and validates the theme update (line 94). The
fail()guard (line 96) properly handles unexpected callback absence.
123-170: LGTM: Comprehensive toggleTheme test coverage.The test suite thoroughly covers:
- Simple toggle between LIGHT and DARK modes
- Transitions from SYSTEM mode to explicit modes with listener cleanup
- Setting specific theme modes with proper listener management
- System preference integration (lines 136, 147, 164)
All critical paths are validated.
408a462 to
415baf5
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (1)
apps/web/src/index.html (1)
123-123: Remove unusedhasBodyvariable.The
hasBodyvariable is declared but never used. The code correctly useshasDocumentanddocument.documentElementthroughout. Clean up the dead code.🔎 Proposed fix
- let hasBody = !!document && !!document.body; let hasDocument = !!document && !!document.documentElement;
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
apps/web/src/index.htmlapps/web/src/server.tsapps/web/src/styles.css
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use path aliases @zard/* to map to libs/zard/src/lib/* in imports
Files:
apps/web/src/server.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Keep commit messages in present tense, single line format with scope and description (e.g., '✨ feat(popover): add popover component')
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Applies to libs/blocks/src/lib/**/*.component.html : Use TailwindCSS utility classes for styling, following responsive design patterns with prefixes for breakpoints (sm:, lg:) and ensure accessibility with semantic HTML and ARIA guidelines
Applied to files:
apps/web/src/index.html
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
Applied to files:
apps/web/src/index.html
🪛 GitHub Check: CodeQL
apps/web/src/server.ts
[failure] 227-227: Incomplete URL substring sanitization
'fonts.googleapis.com' can be anywhere in the URL, and arbitrary hosts may come before or after it.
🔇 Additional comments (2)
apps/web/src/server.ts (1)
232-237: LGTM: Caching strategy aligns with font optimization goals.The 1-year immutable cache for fonts (line 232) and 5-minute revalidation for HTML (line 236) appropriately balance performance and update propagation. This complements the font preloading strategy in index.html.
apps/web/src/index.html (1)
126-135: LGTM: Dark mode initialization correctly handles localStorage preferences.The dark mode logic properly handles
'dark','light', and system preference fallback, aligning with the dark-mode service changes in libs/zard/src/lib/shared/services/dark-mode.ts.
e59d413 to
5536138
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
libs/zard/src/lib/shared/services/dark-mode.ts (1)
114-121: Consider consolidating dark mode class naming.Line 118 adds
dark-themeclass alongside the existingdarkclass on line 117. While not incorrect, maintaining two classes for the same state could cause confusion. Verify that both classes are required for compatibility or different styling contexts.#!/bin/bash # Verify usage of both 'dark' and 'dark-theme' classes across the codebase rg -n "\.dark-theme\b|class.*dark-theme" --type=css --type=html --type=ts -C2
♻️ Duplicate comments (1)
libs/zard/src/lib/shared/services/dark-mode.spec.ts (1)
104-118: AddTestBed.tick()afterinit()for consistent effect flushing.Line 115 calls
newService.init()but doesn't flush effects before the assertion on line 117. While this test may currently pass, addingTestBed.tick()afterinit()ensures effects run consistently across all tests.🔎 Proposed fix for consistency
const newService = TestBed.inject(ZardDarkMode); newService.init(); + TestBed.tick(); expect(newService.themeMode()).toBe(EDarkModes.DARK);
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (4)
apps/web/public/r/dark-mode.jsonis excluded by!apps/web/public/**and included byapps/**package-lock.jsonis excluded by!**/package-lock.jsonand included by nonepackage.jsonis excluded by none and included by nonepackages/cli/src/commands/add/dark-mode-setup.tsis excluded by!packages/**and included by none
📒 Files selected for processing (6)
apps/web/project.jsonapps/web/src/app/shared/services/markdown.service.tsapps/web/src/index.htmlapps/web/src/styles.csslibs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use path aliases @zard/* to map to libs/zard/src/lib/* in imports
Files:
apps/web/src/app/shared/services/markdown.service.tslibs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
libs/zard/**/*.{css,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Use CSS custom properties for design tokens and theming in the component library
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
**/*.spec.ts
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use Jest with @happy-dom/jest-environment and Angular TestBed utilities for testing
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
🧠 Learnings (28)
📓 Common learnings
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Implement TailwindCSS v4 with PostCSS for styling and use class merging with tailwind-merge to resolve conflicts
Applied to files:
apps/web/src/app/shared/services/markdown.service.tsapps/web/src/styles.csslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use `mergeClasses()` utility with `clsx` and `tailwind-merge` to resolve class conflicts in component styling
Applied to files:
apps/web/src/app/shared/services/markdown.service.ts
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Applies to libs/blocks/src/lib/**/*.component.html : Use TailwindCSS utility classes for styling, following responsive design patterns with prefixes for breakpoints (sm:, lg:) and ensure accessibility with semantic HTML and ARIA guidelines
Applied to files:
apps/web/src/app/shared/services/markdown.service.tsapps/web/src/index.htmlapps/web/src/styles.css
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Components should be built with TailwindCSS v4 using the new inline configuration approach (no `tailwind.config.js` needed, configuration via `.postcssrc.json`, design tokens defined in CSS with `theme`)
Applied to files:
apps/web/src/app/shared/services/markdown.service.tsapps/web/src/styles.css
📚 Learning: 2025-11-29T15:31:22.377Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 339
File: libs/zard/src/lib/components/carousel/carousel.component.ts:92-92
Timestamp: 2025-11-29T15:31:22.377Z
Learning: In libs/zard/src/lib/components/**/*.component.ts files using TailwindCSS, avoid suggesting individual class bindings like `[class.fill-primary]="condition"` because they can cause TailwindCSS issues. Prefer string concatenation or `[class]` binding with conditional expressions instead.
Applied to files:
apps/web/src/app/shared/services/markdown.service.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
Applied to files:
apps/web/src/index.htmlapps/web/src/styles.csslibs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-26T10:13:44.258Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/layout/sidebar.component.ts:22-22
Timestamp: 2025-11-26T10:13:44.258Z
Learning: The ZardUI CLI will automatically add `provideZard()` to the app configuration and install the core component before the next CLI release, addressing the breaking change requirement for the event manager plugins.
Applied to files:
apps/web/src/index.html
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/src/styles.css : Set up `src/styles.css` with Tailwind CSS configuration and design tokens using CSS `theme` and `plugin` directives
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Use TailwindCSS v4 with PostCSS for styling the component library
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Use Angular TestBed and ComponentFixture utilities for testing components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Place tests co-located with components using the .spec.ts naming convention
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Co-locate test files with components using `.spec.ts` suffix next to component files
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-26T11:20:45.264Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/select/select.component.spec.ts:79-88
Timestamp: 2025-11-26T11:20:45.264Z
Learning: In ZardUI select component tests (libs/zard/src/lib/components/select/select.component.spec.ts), use fakeAsync() with flush() instead of setTimeout because the component uses setTimeout(..., 0) for focus management, which requires advancing macrotasks in tests.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-13T11:50:56.310Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 372
File: libs/zard/src/lib/shared/components/card/card.component.spec.ts:86-88
Timestamp: 2025-12-13T11:50:56.310Z
Learning: Do not flag or suggest removing `standalone: true` from test components (*.spec.ts files) or demo components (demo/*.ts files) in libs/zard/src/lib/shared/components/**/*.ts, as it is not a significant concern and the explicit flag is acceptable in these contexts.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to **/*.spec.ts : Use Jest with happy-dom/jest-environment and Angular TestBed utilities for testing
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use OnPush change detection strategy in Angular components: `changeDetection: ChangeDetectionStrategy.OnPush`
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/demo/**/*.ts : Create demo components in the `demo/` folder with a main export, default example, and variant examples
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-10T21:46:33.213Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 318
File: libs/zard/src/lib/components/select/demo/default.ts:21-21
Timestamp: 2025-11-10T21:46:33.213Z
Learning: In demo files under libs/zard/src/lib/components/**/demo/*.ts, intentionally showing different patterns (e.g., primitive values vs signals) across different demos is valuable for demonstrating the flexibility of Angular features like two-way binding.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use Signal-based inputs with the `input()` function instead of Input decorators in Angular components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use ChangeDetectionStrategy.OnPush for performance optimization in components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-15T11:43:06.831Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 373
File: libs/zard/src/lib/shared/components/select/select.component.ts:33-33
Timestamp: 2025-12-15T11:43:06.831Z
Learning: In files under libs/zard/src/lib/**/*.{ts,tsx,js}, prefer the @/ path alias for imports that map to libs/zard/src/lib/* directories. For example, write import { mergeClasses } from '@/shared/utils/merge-classes' instead of using the 'zard/' alias. This improves path readability and aligns with the project's alias configuration.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-14T22:52:09.135Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 326
File: libs/zard/src/lib/components/input/float.label.component.ts:71-0
Timestamp: 2025-11-14T22:52:09.135Z
Learning: In libs/zard/src/lib/components/*/*.component.ts files, move HostListener and HostBinding to the Component decorator's host property instead of using decorators on class members (e.g., host: { '(input)': 'onInput()' }).
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use computed properties in Angular components for reactive class calculations: `protected readonly classes = computed(() => ...)`
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-30T13:27:41.206Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/popover/popover.component.ts:28-29
Timestamp: 2025-11-30T13:27:41.206Z
Learning: In libs/zard/src/lib/components/core/**/*.ts files (core utilities, plugins, and providers), use relative imports for intra-core dependencies because the ZardUI CLI performs path transformations during component installation. The CLI expects specific relative path patterns and transforms them to the target project structure. For all other component imports and application code, use zard/* path aliases.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T21:17:39.497Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 383
File: libs/zard/src/lib/shared/components/carousel/carousel.component.ts:114-115
Timestamp: 2025-12-21T21:17:39.497Z
Learning: In Angular components using signal inputs (input()) with types from external libraries like Embla Carousel, explicit type annotations (e.g., `readonly zOptions: InputSignal<EmblaOptionsType> = input<EmblaOptionsType>(...)`) may be necessary to prevent TypeScript IDE errors about inferred types referencing non-portable node_modules paths. This is not redundant when the annotation prevents the "cannot be named without a reference to node_modules" error.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
🔇 Additional comments (20)
apps/web/src/app/shared/services/markdown.service.ts (1)
52-59: Formatting improvements for readability — LGTM!The multi-line reformatting of the h2 and inline code class arrays improves maintainability and readability without altering behavior. All Tailwind utility classes remain valid and unchanged in value/order.
Also applies to: 95-104
apps/web/src/index.html (1)
5-6: LGTM! Clean consolidation of critical head elements.Moving
<base href="/" />and<title>to the top of the<head>follows best practices—base href is required for Angular routing and should be declared early, and title placement here improves SEO parsing. The title content correctly matches your OpenGraph metadata at line 27.apps/web/src/styles.css (2)
2-3: LGTM! Font loading strategy improved.Using
@fontsource-variablenpm packages eliminates the fragility of hard-coded Google Fonts URLs (version paths, filename mismatches) flagged in previous reviews. This approach provides version-controlled, self-hosted variable fonts that are more reliable and maintainable.
14-15: LGTM! Font variables align with imports.CSS custom properties correctly reference the imported
@fontsource-variablefont families with appropriate fallbacks. Aligns with the coding guideline to use CSS custom properties for design tokens and theming.libs/zard/src/lib/shared/services/dark-mode.spec.ts (6)
14-58: LGTM! Test setup follows best practices.Mock structure is comprehensive, covering
matchMediaandlocalStorage. CallingTestBed.tick()afterinit()ensures effects are flushed before tests run—correct pattern per Jest and Angular TestBed utilities guidelines.
60-64: LGTM! Cleanup prevents test state leakage.Clearing both Jest mocks and the localStorage mock ensures tests remain isolated and don't affect each other.
66-69: LGTM! Initialization verification is correct.Test confirms
matchMediaquery setup and default theme behavior.
71-88: LGTM! Listener lifecycle tests are comprehensive.Tests verify that system change listeners are correctly attached when theme is set to
SYSTEMand detached when changing away fromSYSTEM. Proper use ofTestBed.tick()ensures effects execute before assertions.
90-102: LGTM! System preference change simulation is correct.Test properly extracts the registered callback, verifies its existence, and simulates a system preference change to validate reactivity. Addresses previous concern about using
fail()(not available in Jest) by usingexpect().toBeDefined()instead.
120-189: LGTM! Theme toggle tests are comprehensive and correct.Test suite thoroughly covers toggle behavior across different scenarios (light↔dark, system→explicit mode). Proper use of
TestBed.tick()throughout ensures effects execute before assertions, addressing all previous review concerns.libs/zard/src/lib/shared/services/dark-mode.ts (9)
1-15: LGTM! Modern Angular patterns applied correctly.Service uses
inject()for DI,DestroyReffor lifecycle management (replacingOnDestroy), andMediaMatcherfrom Angular CDK for browser API abstraction. Aligns with Angular best practices: signals,inject(), and strict typing.
16-23: LGTM! Dependency injection and state management properly implemented.Consistent use of
inject()for all dependencies. Signal-based state withEDarkModes.SYSTEMdefault is appropriate. MediaMatcher query initialized eagerly for immediate availability.
25-31: LGTM! Computed signal correctly derives resolved theme.The
computed()signal properly resolvesSYSTEMmode toDARK/LIGHTbased on system preference while returning explicit modes directly. Follows Angular signal best practices.
33-37: LGTM! Lifecycle cleanup properly implemented withDestroyRef.Constructor correctly guards browser-specific cleanup with
isBrowsercheck and usesDestroyRef.onDestroy()to remove system change listeners. Modern Angular pattern replacingOnDestroy.
39-43: LGTM! Initialization separated from construction for SSR safety.Public
init()method allows deferred browser-context initialization, invoked via app initializer (perprovidezard.tschanges). Correctly guards withisBrowsercheck.
58-65: LGTM! Readonly signal exposure with clear documentation.Getter returns
asReadonly()signal, preventing external mutation while maintaining reactivity. JSDoc clearly explains usage and return type. Addresses previous review feedback about signal exposure pattern.
67-79: LGTM! Theme initialization logic is correct and clean.Method properly loads stored theme, applies initial mode, and conditionally attaches system change listeners only when needed (SYSTEM mode). Addresses previous review comment about redundant nested conditions.
81-96: LGTM! Theme application correctly manages state and listeners.Method stores theme, updates signal, derives active mode via
isDarkModeActive(), and properly manages system change listeners based on mode (attached forSYSTEM, removed otherwise).
123-137: LGTM! System integration properly uses MediaMatcher.
isDarkModeActive()centralizes active mode detection, checking both explicitDARKandSYSTEMwith query match.handleSystemChanges()properly manages MediaMatcher listener lifecycle with consistent callback reference.apps/web/project.json (1)
42-46: This optimization is appropriate for the project architecture.The
inlineCritical: falsesetting is correct for this SSR + prerendered application. Since styles are rendered server-side and pages are pregenerated, inlining critical CSS in the<head>would be redundant. TailwindCSS v4 uses different optimization strategies that don't rely on critical CSS extraction, so the assumption about FCP/LCP degradation doesn't apply here.Likely an incorrect or invalid review comment.
762c7d1 to
4d9440b
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/web/src/index.html (2)
75-75: Log errors for debuggability.The empty catch block silently swallows all errors. While preventing crashes is good, this makes debugging theme initialization issues difficult (e.g., localStorage access failures, matchMedia errors).
🔎 Proposed fix
- } catch (_) {} + } catch (e) { + console.error('[Theme Init]', e); + }
61-77: Fix data-theme attribute inconsistency between inline script and service initialization.The inline script (line 75) sets
data-themeto the raw localStorage value ('dark','light', or'system'), preserving user intent. However,ZardDarkMode.updateThemeMode()(line 118) setsdata-themeto only the resolved theme ('dark'or'light'), dropping the'system'value entirely.This causes a behavioral mismatch when no theme is explicitly set:
- Script:
data-theme="system"- Service after
init():data-theme="dark"or"light"(resolved value)If CSS or logic depends on detecting
data-theme="system"to distinguish user preference from system default, the service initialization will break this. UpdateupdateThemeMode()to preserve the raw theme value indata-themewhile thecolorSchemestyle anddarkclass remain resolved-only.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (4)
apps/web/public/r/dark-mode.jsonis excluded by!apps/web/public/**and included byapps/**package-lock.jsonis excluded by!**/package-lock.jsonand included by nonepackage.jsonis excluded by none and included by nonepackages/cli/src/commands/add/dark-mode-setup.tsis excluded by!packages/**and included by none
📒 Files selected for processing (4)
apps/web/project.jsonapps/web/src/index.htmlapps/web/src/styles.csslibs/zard/src/lib/shared/services/dark-mode.spec.ts
🧰 Additional context used
📓 Path-based instructions (3)
libs/zard/**/*.{css,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Use CSS custom properties for design tokens and theming in the component library
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
**/*.spec.ts
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use Jest with @happy-dom/jest-environment and Angular TestBed utilities for testing
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use path aliases @zard/* to map to libs/zard/src/lib/* in imports
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
🧠 Learnings (23)
📓 Common learnings
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Place tests co-located with components using the .spec.ts naming convention
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Use Angular TestBed and ComponentFixture utilities for testing components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Co-locate test files with components using `.spec.ts` suffix next to component files
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-13T11:50:56.310Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 372
File: libs/zard/src/lib/shared/components/card/card.component.spec.ts:86-88
Timestamp: 2025-12-13T11:50:56.310Z
Learning: Do not flag or suggest removing `standalone: true` from test components (*.spec.ts files) or demo components (demo/*.ts files) in libs/zard/src/lib/shared/components/**/*.ts, as it is not a significant concern and the explicit flag is acceptable in these contexts.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-26T11:20:45.264Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/select/select.component.spec.ts:79-88
Timestamp: 2025-11-26T11:20:45.264Z
Learning: In ZardUI select component tests (libs/zard/src/lib/components/select/select.component.spec.ts), use fakeAsync() with flush() instead of setTimeout because the component uses setTimeout(..., 0) for focus management, which requires advancing macrotasks in tests.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to **/*.spec.ts : Use Jest with happy-dom/jest-environment and Angular TestBed utilities for testing
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/demo/**/*.ts : Create demo components in the `demo/` folder with a main export, default example, and variant examples
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use OnPush change detection strategy in Angular components: `changeDetection: ChangeDetectionStrategy.OnPush`
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/components.ts : Add barrel exports for all new components in libs/zard/src/lib/components/components.ts
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-10T21:46:33.213Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 318
File: libs/zard/src/lib/components/select/demo/default.ts:21-21
Timestamp: 2025-11-10T21:46:33.213Z
Learning: In demo files under libs/zard/src/lib/components/**/demo/*.ts, intentionally showing different patterns (e.g., primitive values vs signals) across different demos is valuable for demonstrating the flexibility of Angular features like two-way binding.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use Signal-based inputs with the `input()` function instead of Input decorators in Angular components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use ChangeDetectionStrategy.OnPush for performance optimization in components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-15T11:43:06.831Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 373
File: libs/zard/src/lib/shared/components/select/select.component.ts:33-33
Timestamp: 2025-12-15T11:43:06.831Z
Learning: In files under libs/zard/src/lib/**/*.{ts,tsx,js}, prefer the @/ path alias for imports that map to libs/zard/src/lib/* directories. For example, write import { mergeClasses } from '@/shared/utils/merge-classes' instead of using the 'zard/' alias. This improves path readability and aligns with the project's alias configuration.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Applies to libs/blocks/src/lib/**/*.component.html : Use TailwindCSS utility classes for styling, following responsive design patterns with prefixes for breakpoints (sm:, lg:) and ensure accessibility with semantic HTML and ARIA guidelines
Applied to files:
apps/web/src/index.htmlapps/web/src/styles.css
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
Applied to files:
apps/web/src/index.htmlapps/web/src/styles.css
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/src/styles.css : Set up `src/styles.css` with Tailwind CSS configuration and design tokens using CSS `theme` and `plugin` directives
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Implement TailwindCSS v4 with PostCSS for styling and use class merging with tailwind-merge to resolve conflicts
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Use TailwindCSS v4 with PostCSS for styling the component library
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Components should be built with TailwindCSS v4 using the new inline configuration approach (no `tailwind.config.js` needed, configuration via `.postcssrc.json`, design tokens defined in CSS with `theme`)
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Applies to libs/blocks/src/lib/**/*.component.html : Block components should implement responsive design that works across all viewport sizes: Desktop (100% width), Tablet (768px), and Mobile (375px)
Applied to files:
apps/web/src/styles.css
🔇 Additional comments (9)
apps/web/project.json (1)
42-46: LGTM! Valid SSR optimization to prevent flickering.Disabling critical CSS inlining prevents style duplication during SSR hydration, which can cause flash-of-unstyled-content issues. This is a well-established pattern for Angular Universal applications.
apps/web/src/styles.css (3)
2-3: Excellent! Using Fontsource npm packages instead of CDN.This modern approach provides better performance (no external requests), version control, and offline support. The previous concerns about hard-coded Google Fonts URLs have been properly addressed.
14-15: Font variables correctly configured.The CSS custom properties for Geist Variable and Geist Mono Variable align with the Fontsource imports and follow the project's theming pattern using CSS custom properties.
213-213: Container width update aligns with design system changes.The shift from an explicit 1400px constraint to the
max-w-350token maintains consistency with the project's design token system while keeping the effective maximum width.libs/zard/src/lib/shared/services/dark-mode.spec.ts (4)
1-64: Excellent test setup with comprehensive mocking.The test configuration properly mocks browser APIs (matchMedia, localStorage) and uses TestBed with proper initialization and cleanup. All previously identified issues have been addressed:
- ✅
localStorage.clear()prevents state leakage (line 63)- ✅
TestBed.tick()flushes effects afterinit()(line 57)- ✅ Clean mock setup and teardown
66-102: Core functionality thoroughly tested with proper effect flushing.These tests verify initialization, listener management, and system preference detection. Critical improvements from previous reviews are properly implemented:
TestBed.tick()consistently called after operations that trigger effects (lines 73, 80, 84, 92)- Callback existence checked before usage (line 96)
- System theme detection correctly validates behavior
104-136: Re-initialization scenarios handled correctly.Both tests properly reset TestBed before creating new service instances, ensuring clean state for initialization testing. The pattern of
resetTestingModule()→ configure → inject →init()→tick()correctly validates bootstrap behavior.
138-190: Comprehensive toggle behavior coverage.The toggle tests verify all state transitions (LIGHT ↔ DARK ↔ SYSTEM) with proper effect flushing and listener management assertions. Each scenario includes
TestBed.tick()after theme changes, ensuring effects execute before assertions.apps/web/src/index.html (1)
5-6: LGTM! Structural improvement for SEO and URL resolution.Moving
<base>and<title>to the top of<head>follows best practices—<base>ensures relative URLs resolve correctly throughout the document, and an early<title>improves perceived load time and SEO.
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (4)
apps/web/public/r/dark-mode.jsonis excluded by!apps/web/public/**and included byapps/**package-lock.jsonis excluded by!**/package-lock.jsonand included by nonepackage.jsonis excluded by none and included by nonepackages/cli/src/commands/add/dark-mode-setup.tsis excluded by!packages/**and included by none
📒 Files selected for processing (5)
apps/web/project.jsonapps/web/src/index.htmlapps/web/src/styles.csslibs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
🧰 Additional context used
📓 Path-based instructions (3)
libs/zard/**/*.{css,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Use CSS custom properties for design tokens and theming in the component library
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
**/*.spec.ts
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use Jest with @happy-dom/jest-environment and Angular TestBed utilities for testing
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use path aliases @zard/* to map to libs/zard/src/lib/* in imports
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
🧠 Learnings (28)
📓 Common learnings
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/src/styles.css : Set up `src/styles.css` with Tailwind CSS configuration and design tokens using CSS `theme` and `plugin` directives
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
Applied to files:
apps/web/src/styles.cssapps/web/src/index.htmllibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/src/styles.css : Set up `src/styles.css` with Tailwind CSS configuration and design tokens using CSS `theme` and `plugin` directives
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Implement TailwindCSS v4 with PostCSS for styling and use class merging with tailwind-merge to resolve conflicts
Applied to files:
apps/web/src/styles.csslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Use TailwindCSS v4 with PostCSS for styling the component library
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Applies to libs/blocks/src/lib/**/*.component.html : Use TailwindCSS utility classes for styling, following responsive design patterns with prefixes for breakpoints (sm:, lg:) and ensure accessibility with semantic HTML and ARIA guidelines
Applied to files:
apps/web/src/styles.cssapps/web/src/index.html
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Components should be built with TailwindCSS v4 using the new inline configuration approach (no `tailwind.config.js` needed, configuration via `.postcssrc.json`, design tokens defined in CSS with `theme`)
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Applies to libs/blocks/src/lib/**/*.component.html : Block components should implement responsive design that works across all viewport sizes: Desktop (100% width), Tablet (768px), and Mobile (375px)
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Place tests co-located with components using the .spec.ts naming convention
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Use Angular TestBed and ComponentFixture utilities for testing components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Co-locate test files with components using `.spec.ts` suffix next to component files
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-13T11:50:56.310Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 372
File: libs/zard/src/lib/shared/components/card/card.component.spec.ts:86-88
Timestamp: 2025-12-13T11:50:56.310Z
Learning: Do not flag or suggest removing `standalone: true` from test components (*.spec.ts files) or demo components (demo/*.ts files) in libs/zard/src/lib/shared/components/**/*.ts, as it is not a significant concern and the explicit flag is acceptable in these contexts.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-26T11:20:45.264Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/select/select.component.spec.ts:79-88
Timestamp: 2025-11-26T11:20:45.264Z
Learning: In ZardUI select component tests (libs/zard/src/lib/components/select/select.component.spec.ts), use fakeAsync() with flush() instead of setTimeout because the component uses setTimeout(..., 0) for focus management, which requires advancing macrotasks in tests.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to **/*.spec.ts : Use Jest with happy-dom/jest-environment and Angular TestBed utilities for testing
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/demo/**/*.ts : Create demo components in the `demo/` folder with a main export, default example, and variant examples
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use OnPush change detection strategy in Angular components: `changeDetection: ChangeDetectionStrategy.OnPush`
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/components.ts : Add barrel exports for all new components in libs/zard/src/lib/components/components.ts
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-10T21:46:33.213Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 318
File: libs/zard/src/lib/components/select/demo/default.ts:21-21
Timestamp: 2025-11-10T21:46:33.213Z
Learning: In demo files under libs/zard/src/lib/components/**/demo/*.ts, intentionally showing different patterns (e.g., primitive values vs signals) across different demos is valuable for demonstrating the flexibility of Angular features like two-way binding.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use Signal-based inputs with the `input()` function instead of Input decorators in Angular components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use ChangeDetectionStrategy.OnPush for performance optimization in components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-15T11:43:06.831Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 373
File: libs/zard/src/lib/shared/components/select/select.component.ts:33-33
Timestamp: 2025-12-15T11:43:06.831Z
Learning: In files under libs/zard/src/lib/**/*.{ts,tsx,js}, prefer the @/ path alias for imports that map to libs/zard/src/lib/* directories. For example, write import { mergeClasses } from '@/shared/utils/merge-classes' instead of using the 'zard/' alias. This improves path readability and aligns with the project's alias configuration.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-14T22:52:09.135Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 326
File: libs/zard/src/lib/components/input/float.label.component.ts:71-0
Timestamp: 2025-11-14T22:52:09.135Z
Learning: In libs/zard/src/lib/components/*/*.component.ts files, move HostListener and HostBinding to the Component decorator's host property instead of using decorators on class members (e.g., host: { '(input)': 'onInput()' }).
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use computed properties in Angular components for reactive class calculations: `protected readonly classes = computed(() => ...)`
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-30T13:27:41.206Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/popover/popover.component.ts:28-29
Timestamp: 2025-11-30T13:27:41.206Z
Learning: In libs/zard/src/lib/components/core/**/*.ts files (core utilities, plugins, and providers), use relative imports for intra-core dependencies because the ZardUI CLI performs path transformations during component installation. The CLI expects specific relative path patterns and transforms them to the target project structure. For all other component imports and application code, use zard/* path aliases.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-29T15:31:22.377Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 339
File: libs/zard/src/lib/components/carousel/carousel.component.ts:92-92
Timestamp: 2025-11-29T15:31:22.377Z
Learning: In libs/zard/src/lib/components/**/*.component.ts files using TailwindCSS, avoid suggesting individual class bindings like `[class.fill-primary]="condition"` because they can cause TailwindCSS issues. Prefer string concatenation or `[class]` binding with conditional expressions instead.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T21:17:39.497Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 383
File: libs/zard/src/lib/shared/components/carousel/carousel.component.ts:114-115
Timestamp: 2025-12-21T21:17:39.497Z
Learning: In Angular components using signal inputs (input()) with types from external libraries like Embla Carousel, explicit type annotations (e.g., `readonly zOptions: InputSignal<EmblaOptionsType> = input<EmblaOptionsType>(...)`) may be necessary to prevent TypeScript IDE errors about inferred types referencing non-portable node_modules paths. This is not redundant when the annotation prevents the "cannot be named without a reference to node_modules" error.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
🔇 Additional comments (12)
apps/web/project.json (1)
42-46: LGTM—disabling inlineCritical prevents SSR theme flickering.The optimization setting correctly disables critical CSS inlining in production builds, which prevents flash-of-unstyled-content during SSR hydration when the dark mode theme is applied client-side. This aligns with the PR's SSR improvements.
apps/web/src/styles.css (2)
2-3: Excellent—using @fontsource packages resolves all previous font loading issues.Switching from hardcoded Google Fonts URLs to npm-managed @fontsource-variable packages provides:
- Proper version control and reproducible builds
- No broken gstatic URLs or version mismatches
- Offline font availability during development
- Consistent font loading behavior
This addresses all previous review concerns about font URL fragility.
14-15: Font variable updates are consistent with the @fontsource imports.The CSS custom properties correctly reference the variable font families imported via @fontsource-variable, maintaining proper fallback stacks (sans-serif, monospace).
apps/web/src/index.html (2)
5-6: Standard meta tags added—LGTM.The
<base href="/">and<title>tags are correctly placed in the<head>for SEO and routing.
61-77: Theme initialization script correctly prevents SSR flickering.The inline script executes before Angular hydration to apply the theme synchronously:
- Reads
localStorage.theme(system/dark/light)- Checks system preference via
matchMedia- Applies 'dark' class and
data-themeattribute- Sets
colorSchemestyle for native UIThis prevents flash-of-incorrect-theme during SSR hydration. The logic correctly handles all three theme modes.
libs/zard/src/lib/shared/services/dark-mode.ts (5)
1-18: Excellent—modernized service using Angular best practices.The refactor adopts:
- DestroyRef for cleanup instead of OnDestroy lifecycle hook
- MediaMatcher from @angular/cdk/layout for robust system preference detection
- inject() function for dependency injection
- Signals (signal, computed, effect) for reactive state management
This aligns with Angular's modern API surface and improves maintainability.
33-43: Effect-based theme synchronization is clean and reactive.The constructor establishes a reactive pipeline:
- Effect (lines 35-39) runs whenever
themeSignalchanges, applying theme to DOM- Cleanup (line 41) properly removes system change listeners on destroy
This may trigger twice during initialization (default SYSTEM value → stored value from localStorage), but DOM operations are cheap and the declarative approach improves clarity.
45-49: Initialization separated from construction for SSR compatibility.The
init()method (lines 45-49) is invoked viaAPP_INITIALIZERper the provider changes, allowing the service to:
- Skip localStorage access during SSR (where it's unavailable)
- Read stored theme once DOM is available (line 74)
- Set up system listeners only when needed (lines 79-81)
This pattern prevents SSR errors and ensures correct theme application on hydration.
Also applies to: 73-82
64-71: Readonly signal exposure prevents external mutation—correct pattern.The getter returns
asReadonly(), ensuring components can read but not modify the theme signal. The JSDoc clearly documents usage:
- Template:
service.currentTheme()for reactive bindings- Code:
service.currentTheme()returns "light", "dark", or "system"For resolved theme (LIGHT/DARK only), consumers should use
themeMode()instead.
84-97: System change listener management is correct and efficient.The service correctly manages MediaQueryList listeners:
- Lines 92-96: Adds listener when switching to SYSTEM mode, removes when switching to explicit (LIGHT/DARK)
- Line 21: Arrow function preserves context for event handler
- Lines 126-132: Conditional listener attachment based on mode
This prevents memory leaks and unnecessary listener overhead when using explicit themes.
Also applies to: 126-132
libs/zard/src/lib/shared/services/dark-mode.spec.ts (2)
14-64: Test setup is comprehensive with proper mocking and cleanup.The
beforeEachcorrectly:
- Mocks
window.matchMediawith a Jest-compatibleMediaQueryListinterface- Mocks
localStoragewith getter/setter/clear operations- Initializes the service via
init()and flushes effects withTestBed.tick()(correct replacement for deprecatedflushEffects())The
afterEach(lines 60-64) prevents state leakage by clearing both Jest mocks and the localStorage mock.
66-190: Comprehensive test coverage with correct effect flushing.The test suite covers all critical paths:
- Initialization with stored/default themes
- System preference detection and change handling
- Listener lifecycle (attach/detach based on mode)
- Theme toggling (explicit and implicit)
- SSR compatibility (init() called separately from constructor)
All tests correctly use
TestBed.tick()to flush effects before assertions (lines 57, 73, 80, 84, 116, 132, 154, 158, 167, 171, 186), addressing the async nature of Angular effects.The tests follow the AAA (Arrange-Act-Assert) pattern and properly isolate concerns.
282106f to
e882fe9
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (5)
apps/web/public/r/dark-mode.jsonis excluded by!apps/web/public/**and included byapps/**package-lock.jsonis excluded by!**/package-lock.jsonand included by nonepackage.jsonis excluded by none and included by nonepackages/cli/src/commands/add/dark-mode-setup.tsis excluded by!packages/**and included by nonepackages/cli/src/commands/init/theme-loader.tsis excluded by!packages/**and included by none
📒 Files selected for processing (5)
apps/web/project.jsonapps/web/src/index.htmlapps/web/src/styles.csslibs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
🧰 Additional context used
📓 Path-based instructions (3)
libs/zard/**/*.{css,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Use CSS custom properties for design tokens and theming in the component library
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
**/*.spec.ts
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use Jest with @happy-dom/jest-environment and Angular TestBed utilities for testing
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use path aliases @zard/* to map to libs/zard/src/lib/* in imports
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
🧠 Learnings (34)
📓 Common learnings
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Implement TailwindCSS v4 with PostCSS for styling and use class merging with tailwind-merge to resolve conflicts
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/src/styles.css : Set up `src/styles.css` with Tailwind CSS configuration and design tokens using CSS `theme` and `plugin` directives
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
Applied to files:
apps/web/src/styles.cssapps/web/src/index.htmllibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Applies to libs/blocks/src/lib/**/*.component.html : Use TailwindCSS utility classes for styling, following responsive design patterns with prefixes for breakpoints (sm:, lg:) and ensure accessibility with semantic HTML and ARIA guidelines
Applied to files:
apps/web/src/styles.cssapps/web/src/index.html
📚 Learning: 2025-12-25T11:10:09.078Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 384
File: apps/web/src/styles.css:213-213
Timestamp: 2025-12-25T11:10:09.078Z
Learning: In Tailwind CSS v4, max-width utilities support dynamic numeric values derived from the spacing scale (using the --spacing variable, default 0.25rem = 4px). Prefer using numeric classes like max-w-350 when the value aligns with the spacing scale, since 350 × 0.25rem = 87.5rem = 1400px. Avoid arbitrary values expressed with brackets (e.g., max-w-[1400px]) when a scale-based value is available and accurate. Apply this guidance to CSS files in the web app (e.g., apps/web/src/styles.css) and across the codebase where Tailwind is used.
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-11-29T15:31:22.377Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 339
File: libs/zard/src/lib/components/carousel/carousel.component.ts:92-92
Timestamp: 2025-11-29T15:31:22.377Z
Learning: In libs/zard/src/lib/components/**/*.component.ts files using TailwindCSS, avoid suggesting individual class bindings like `[class.fill-primary]="condition"` because they can cause TailwindCSS issues. Prefer string concatenation or `[class]` binding with conditional expressions instead.
Applied to files:
apps/web/src/styles.csslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Implement TailwindCSS v4 with PostCSS for styling and use class merging with tailwind-merge to resolve conflicts
Applied to files:
apps/web/src/styles.csslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Components should be built with TailwindCSS v4 using the new inline configuration approach (no `tailwind.config.js` needed, configuration via `.postcssrc.json`, design tokens defined in CSS with `theme`)
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-11-07T08:49:00.973Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 311
File: libs/zard/src/lib/components/carousel/carousel.variants.ts:28-56
Timestamp: 2025-11-07T08:49:00.973Z
Learning: In Tailwind CSS v4, fractional spacing values like `pt-4.5` (1.125rem) and `-left-12.5` (3.125rem) are valid canonical classes supported by default, unlike Tailwind v3 which had a more restricted spacing scale. These should be used instead of arbitrary bracket notation like `pt-[1.125rem]`.
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use `mergeClasses()` utility with `clsx` and `tailwind-merge` to resolve class conflicts in component styling
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Use TailwindCSS v4 with PostCSS for styling the component library
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.variants.ts : Use CVA (Class Variance Authority) for type-safe styling variants in components
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.variants.ts : Use CVA (Class Variance Authority) for typed variants in component styling
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Applies to libs/blocks/src/lib/**/*.component.html : Block components should implement responsive design that works across all viewport sizes: Desktop (100% width), Tablet (768px), and Mobile (375px)
Applied to files:
apps/web/src/styles.css
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Use Angular TestBed and ComponentFixture utilities for testing components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Place tests co-located with components using the .spec.ts naming convention
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Co-locate test files with components using `.spec.ts` suffix next to component files
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-13T11:50:56.310Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 372
File: libs/zard/src/lib/shared/components/card/card.component.spec.ts:86-88
Timestamp: 2025-12-13T11:50:56.310Z
Learning: Do not flag or suggest removing `standalone: true` from test components (*.spec.ts files) or demo components (demo/*.ts files) in libs/zard/src/lib/shared/components/**/*.ts, as it is not a significant concern and the explicit flag is acceptable in these contexts.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to **/*.spec.ts : Use Jest with happy-dom/jest-environment and Angular TestBed utilities for testing
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-26T11:20:45.264Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/select/select.component.spec.ts:79-88
Timestamp: 2025-11-26T11:20:45.264Z
Learning: In ZardUI select component tests (libs/zard/src/lib/components/select/select.component.spec.ts), use fakeAsync() with flush() instead of setTimeout because the component uses setTimeout(..., 0) for focus management, which requires advancing macrotasks in tests.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/demo/**/*.ts : Create demo components in the `demo/` folder with a main export, default example, and variant examples
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/components.ts : Add barrel exports for all new components in libs/zard/src/lib/components/components.ts
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use OnPush change detection strategy in Angular components: `changeDetection: ChangeDetectionStrategy.OnPush`
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-10T21:46:33.213Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 318
File: libs/zard/src/lib/components/select/demo/default.ts:21-21
Timestamp: 2025-11-10T21:46:33.213Z
Learning: In demo files under libs/zard/src/lib/components/**/demo/*.ts, intentionally showing different patterns (e.g., primitive values vs signals) across different demos is valuable for demonstrating the flexibility of Angular features like two-way binding.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use Signal-based inputs with the `input()` function instead of Input decorators in Angular components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use ChangeDetectionStrategy.OnPush for performance optimization in components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-15T11:43:06.831Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 373
File: libs/zard/src/lib/shared/components/select/select.component.ts:33-33
Timestamp: 2025-12-15T11:43:06.831Z
Learning: In files under libs/zard/src/lib/**/*.{ts,tsx,js}, prefer the @/ path alias for imports that map to libs/zard/src/lib/* directories. For example, write import { mergeClasses } from '@/shared/utils/merge-classes' instead of using the 'zard/' alias. This improves path readability and aligns with the project's alias configuration.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-14T22:52:09.135Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 326
File: libs/zard/src/lib/components/input/float.label.component.ts:71-0
Timestamp: 2025-11-14T22:52:09.135Z
Learning: In libs/zard/src/lib/components/*/*.component.ts files, move HostListener and HostBinding to the Component decorator's host property instead of using decorators on class members (e.g., host: { '(input)': 'onInput()' }).
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-30T13:27:41.206Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/popover/popover.component.ts:28-29
Timestamp: 2025-11-30T13:27:41.206Z
Learning: In libs/zard/src/lib/components/core/**/*.ts files (core utilities, plugins, and providers), use relative imports for intra-core dependencies because the ZardUI CLI performs path transformations during component installation. The CLI expects specific relative path patterns and transforms them to the target project structure. For all other component imports and application code, use zard/* path aliases.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-30T08:50:23.436Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/core/providezard.ts:0-0
Timestamp: 2025-11-30T08:50:23.436Z
Learning: In libs/zard/src/lib/components/core/providezard.ts, the import paths `../core/event-manager-plugins/...` are intentionally structured this way because the ZardUI CLI transforms them to 'shared/components/core/event-manager-plugins/...' format. Other relative path combinations don't work with the current CLI implementation. This path pattern should not be simplified until the CLI transformation logic is updated.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use computed properties in Angular components for reactive class calculations: `protected readonly classes = computed(() => ...)`
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T21:17:39.497Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 383
File: libs/zard/src/lib/shared/components/carousel/carousel.component.ts:114-115
Timestamp: 2025-12-21T21:17:39.497Z
Learning: In Angular components using signal inputs (input()) with types from external libraries like Embla Carousel, explicit type annotations (e.g., `readonly zOptions: InputSignal<EmblaOptionsType> = input<EmblaOptionsType>(...)`) may be necessary to prevent TypeScript IDE errors about inferred types referencing non-portable node_modules paths. This is not redundant when the annotation prevents the "cannot be named without a reference to node_modules" error.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
🔇 Additional comments (17)
apps/web/src/index.html (2)
5-6: LGTM! Standard HTML document structure improvements.Adding explicit
<base>and<title>elements improves SEO and ensures consistent URL resolution. The title clearly communicates the product positioning.
61-76: Excellent SSR-safe theme initialization!The inline script correctly:
- Runs synchronously before body render to prevent flicker
- Safely handles missing localStorage with try-catch
- Detects system preference via matchMedia
- Applies the
scheme-light-darkclass for CSS color-scheme coordination- Sets both
darkclass anddata-themeattributeThis pairs well with the new
ZardDarkMode.init()flow for hydration.apps/web/src/styles.css (3)
2-3: Excellent font loading strategy upgrade!Switching from hardcoded CDN URLs to
@fontsource-variablepackages provides:
- Version control and reproducibility via package.json
- Improved offline development experience
- Variable font support with proper subsetting
- Eliminates the versioning issues flagged in previous reviews
Based on learnings, this aligns with using CSS custom properties for design tokens.
14-15: LGTM! Font token structure follows best practices.The two-tier variable approach (public
--font-geist-*→ theme--font-sans/mono) enables:
- Theme-level font family switching
- Consistent token reference in components
- Future extensibility for additional themes
Also applies to: 109-110
213-213: Correct Tailwind CSS v4 usage confirmed.The
max-w-350class leverages Tailwind v4's dynamic spacing scale (350 × 0.25rem = 87.5rem = 1400px), which is cleaner than the arbitrary value syntax. This is the preferred approach in v4.Based on learnings, Tailwind CSS v4 max-width utilities support dynamic numeric values derived from the spacing scale.
libs/zard/src/lib/shared/services/dark-mode.ts (6)
1-1: Excellent use of Angular CDK MediaMatcher!Using
@angular/cdk/layout'sMediaMatcheris the Angular-idiomatic way to handle media queries with proper testing support and SSR compatibility. This is superior to rawwindow.matchMedia.Also applies to: 18-18
3-3: Modern lifecycle management with DestroyRef!Replacing
OnDestroywithDestroyReffollows Angular's modern functional approach:
- ✅ Works with
inject()- ✅ Simpler cleanup via
onDestroy()callback- ✅ Better composability with functional patterns
The effect cleanup is properly registered in the constructor.
Also applies to: 15-15, 17-17, 41-42
33-43: Effect-based reactivity eliminates manual subscription management!The constructor's
effect()automatically synchronizes DOM state wheneverthemeSignalchanges, eliminating error-prone manual subscription/unsubscription. ThedestroyRef.onDestroy()cleanup ensures listeners are removed.This is Angular Signals best practice.
64-71: Readonly signal exposure prevents external mutation!Returning
asReadonly()enforces unidirectional data flow while maintaining reactivity. The JSDoc clearly explains usage for both imperative reads and template bindings.
111-115: Simplified theme application focuses on class and attribute.Removing
colorSchemeDOM manipulation addresses SSR flickering issues mentioned in the PR objectives. Thescheme-light-darkclass in index.html now handles this declaratively via CSS.
125-131: Clean listener lifecycle management.The default parameter
addListener = trueenables concise call sites (handleSystemChanges()for add,handleSystemChanges(false)for remove). The effect in the constructor ensures listeners are added/removed reactively when switching modes.libs/zard/src/lib/shared/services/dark-mode.spec.ts (6)
14-58: Comprehensive test setup with proper isolation!The
beforeEachcorrectly mocks:
- ✅
matchMediawith a mockMediaQueryListsupportingaddEventListener/removeEventListener- ✅
localStoragewith a functional in-memory implementation- ✅ TestBed configuration for clean service instantiation
- ✅
TestBed.tick()afterinit()to flush effectsThis ensures tests are isolated and deterministic.
As per coding guidelines, using Jest with Angular TestBed utilities for testing.
60-64: Proper test cleanup prevents state leakage!Calling
localStorage.clear()inafterEachensures subsequent tests start with a clean slate. This was correctly added based on previous review feedback.
71-88: Effect flushing with TestBed.tick() is correct!Since the service uses
effect()to manage listeners, these tests properly callTestBed.tick()aftertoggleTheme()to flush scheduled effects before asserting onaddEventListener/removeEventListenercalls.This replaces the deprecated
TestBed.flushEffects()per Angular 20+ guidance.
90-102: System preference callback test demonstrates proper verification!This test:
- Arrange: Sets theme to SYSTEM and flushes effects
- Act: Captures the registered callback and invokes it with
matches: true- Assert: Verifies
themeMode()reflects the dark preferenceThe callback extraction from
mock.callsis a solid approach to test internal listener behavior.
104-119: Re-initialization tests properly reset TestBed state!Both tests correctly use
TestBed.resetTestingModule()to create fresh service instances, ensuring initialization logic is actually tested rather than relying on the singleton frombeforeEach.This pattern properly verifies bootstrap-time behavior.
Also applies to: 121-136
138-190: Toggle scenarios comprehensively cover mode transitions!The test suite validates:
- ✅ Implicit toggle (no argument)
- ✅ Explicit mode setting (targetMode)
- ✅ System mode with both light and dark OS preferences
- ✅ Listener lifecycle during mode transitions
All tests follow AAA pattern and properly flush effects. Excellent coverage!
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
apps/web/src/app/app.config.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use path aliases @zard/* to map to libs/zard/src/lib/* in imports
Files:
apps/web/src/app/app.config.ts
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Implement TailwindCSS v4 with PostCSS for styling and use class merging with tailwind-merge to resolve conflicts
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
📚 Learning: 2025-11-26T10:13:44.258Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/layout/sidebar.component.ts:22-22
Timestamp: 2025-11-26T10:13:44.258Z
Learning: The ZardUI CLI will automatically add `provideZard()` to the app configuration and install the core component before the next CLI release, addressing the breaking change requirement for the event manager plugins.
Applied to files:
apps/web/src/app/app.config.ts
📚 Learning: 2025-11-30T13:27:41.206Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/popover/popover.component.ts:28-29
Timestamp: 2025-11-30T13:27:41.206Z
Learning: In libs/zard/src/lib/components/core/**/*.ts files (core utilities, plugins, and providers), use relative imports for intra-core dependencies because the ZardUI CLI performs path transformations during component installation. The CLI expects specific relative path patterns and transforms them to the target project structure. For all other component imports and application code, use zard/* path aliases.
Applied to files:
apps/web/src/app/app.config.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use OnPush change detection strategy in Angular components: `changeDetection: ChangeDetectionStrategy.OnPush`
Applied to files:
apps/web/src/app/app.config.ts
📚 Learning: 2025-11-30T08:50:23.436Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/core/providezard.ts:0-0
Timestamp: 2025-11-30T08:50:23.436Z
Learning: In libs/zard/src/lib/components/core/providezard.ts, the import paths `../core/event-manager-plugins/...` are intentionally structured this way because the ZardUI CLI transforms them to 'shared/components/core/event-manager-plugins/...' format. Other relative path combinations don't work with the current CLI implementation. This path pattern should not be simplified until the CLI transformation logic is updated.
Applied to files:
apps/web/src/app/app.config.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Use Angular TestBed and ComponentFixture utilities for testing components
Applied to files:
apps/web/src/app/app.config.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/components.ts : Export all components in `libs/zard/src/lib/components/components.ts` for public API
Applied to files:
apps/web/src/app/app.config.ts
🔇 Additional comments (2)
apps/web/src/app/app.config.ts (2)
2-8: LGTM! Modern Angular DI patterns.The addition of
injectandprovideAppInitializerfollows Angular's modern functional approach for dependency injection and bootstrap-time initialization.
13-13: LGTM! Path alias follows guidelines.The import uses the
@zard/services/*path alias pattern as specified in the coding guidelines.
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
apps/web/public/r/dark-mode.jsonis excluded by!apps/web/public/**and included byapps/**
📒 Files selected for processing (3)
apps/web/src/app/app.config.tslibs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
🧰 Additional context used
📓 Path-based instructions (3)
libs/zard/**/*.{css,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Use CSS custom properties for design tokens and theming in the component library
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
**/*.spec.ts
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use Jest with @happy-dom/jest-environment and Angular TestBed utilities for testing
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use path aliases @zard/* to map to libs/zard/src/lib/* in imports
Files:
libs/zard/src/lib/shared/services/dark-mode.spec.tsapps/web/src/app/app.config.tslibs/zard/src/lib/shared/services/dark-mode.ts
🧠 Learnings (29)
📓 Common learnings
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Implement TailwindCSS v4 with PostCSS for styling and use class merging with tailwind-merge to resolve conflicts
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Place tests co-located with components using the .spec.ts naming convention
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Use Angular TestBed and ComponentFixture utilities for testing components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tsapps/web/src/app/app.config.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.spec.ts : Co-locate test files with components using `.spec.ts` suffix next to component files
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-13T11:50:56.310Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 372
File: libs/zard/src/lib/shared/components/card/card.component.spec.ts:86-88
Timestamp: 2025-12-13T11:50:56.310Z
Learning: Do not flag or suggest removing `standalone: true` from test components (*.spec.ts files) or demo components (demo/*.ts files) in libs/zard/src/lib/shared/components/**/*.ts, as it is not a significant concern and the explicit flag is acceptable in these contexts.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-26T11:20:45.264Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/select/select.component.spec.ts:79-88
Timestamp: 2025-11-26T11:20:45.264Z
Learning: In ZardUI select component tests (libs/zard/src/lib/components/select/select.component.spec.ts), use fakeAsync() with flush() instead of setTimeout because the component uses setTimeout(..., 0) for focus management, which requires advancing macrotasks in tests.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to **/*.spec.ts : Use Jest with happy-dom/jest-environment and Angular TestBed utilities for testing
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:12:15.303Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: packages/cli/README.md:0-0
Timestamp: 2025-12-21T00:12:15.303Z
Learning: Applies to packages/cli/**/*.{ts,tsx,css} : Components should include built-in dark mode support
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/components.ts : Add barrel exports for all new components in libs/zard/src/lib/components/components.ts
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tsapps/web/src/app/app.config.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/demo/**/*.ts : Create demo components in the `demo/` folder with a main export, default example, and variant examples
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Create components as standalone components with `standalone: true` in Angular
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tsapps/web/src/app/app.config.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use OnPush change detection strategy in Angular components: `changeDetection: ChangeDetectionStrategy.OnPush`
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tsapps/web/src/app/app.config.ts
📚 Learning: 2025-11-10T21:46:33.213Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 318
File: libs/zard/src/lib/components/select/demo/default.ts:21-21
Timestamp: 2025-11-10T21:46:33.213Z
Learning: In demo files under libs/zard/src/lib/components/**/demo/*.ts, intentionally showing different patterns (e.g., primitive values vs signals) across different demos is valuable for demonstrating the flexibility of Angular features like two-way binding.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use Signal-based inputs with the `input()` function instead of Input decorators in Angular components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use ChangeDetectionStrategy.OnPush for performance optimization in components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-30T19:07:11.572Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 352
File: apps/web/src/app/domain/components/sidebar/scroll-on-active.directive.ts:23-27
Timestamp: 2025-11-30T19:07:11.572Z
Learning: In apps/web/src/app/domain/components/sidebar/scroll-on-active.directive.ts, the guard checking if scrollIntoView exists before calling it is necessary due to mobile browser compatibility issues. Physical testing on mobile devices shows scrollIntoView may not be present or functional. This defensive pattern should be kept despite scrollIntoView being part of the standard DOM API.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Use Jest with `happy-dom/jest-environment` for testing Angular components
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.ts
📚 Learning: 2025-12-21T00:12:01.332Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: libs/blocks/README.md:0-0
Timestamp: 2025-12-21T00:12:01.332Z
Learning: Blocks must use the DarkModeService for automatic theme detection and adaptation, ensuring that components and preview images respond to theme changes
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-15T11:43:06.831Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 373
File: libs/zard/src/lib/shared/components/select/select.component.ts:33-33
Timestamp: 2025-12-15T11:43:06.831Z
Learning: In files under libs/zard/src/lib/**/*.{ts,tsx,js}, prefer the @/ path alias for imports that map to libs/zard/src/lib/* directories. For example, write import { mergeClasses } from '@/shared/utils/merge-classes' instead of using the 'zard/' alias. This improves path readability and aligns with the project's alias configuration.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.spec.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-26T10:13:44.258Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/layout/sidebar.component.ts:22-22
Timestamp: 2025-11-26T10:13:44.258Z
Learning: The ZardUI CLI will automatically add `provideZard()` to the app configuration and install the core component before the next CLI release, addressing the breaking change requirement for the event manager plugins.
Applied to files:
apps/web/src/app/app.config.ts
📚 Learning: 2025-11-30T13:27:41.206Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/popover/popover.component.ts:28-29
Timestamp: 2025-11-30T13:27:41.206Z
Learning: In libs/zard/src/lib/components/core/**/*.ts files (core utilities, plugins, and providers), use relative imports for intra-core dependencies because the ZardUI CLI performs path transformations during component installation. The CLI expects specific relative path patterns and transforms them to the target project structure. For all other component imports and application code, use zard/* path aliases.
Applied to files:
apps/web/src/app/app.config.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-30T08:50:23.436Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 348
File: libs/zard/src/lib/components/core/providezard.ts:0-0
Timestamp: 2025-11-30T08:50:23.436Z
Learning: In libs/zard/src/lib/components/core/providezard.ts, the import paths `../core/event-manager-plugins/...` are intentionally structured this way because the ZardUI CLI transforms them to 'shared/components/core/event-manager-plugins/...' format. Other relative path combinations don't work with the current CLI implementation. This path pattern should not be simplified until the CLI transformation logic is updated.
Applied to files:
apps/web/src/app/app.config.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/components.ts : Export all components in `libs/zard/src/lib/components/components.ts` for public API
Applied to files:
apps/web/src/app/app.config.tslibs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/**/*.{css,ts} : Use CSS custom properties for design tokens and theming in the component library
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T00:11:39.443Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T00:11:39.443Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Implement TailwindCSS v4 with PostCSS for styling and use class merging with tailwind-merge to resolve conflicts
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-25T18:54:01.560Z
Learnt from: CR
Repo: zard-ui/zardui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T18:54:01.560Z
Learning: Applies to libs/zard/src/lib/components/**/*.component.ts : Use `mergeClasses()` utility with `clsx` and `tailwind-merge` to resolve class conflicts in component styling
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-14T22:52:09.135Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 326
File: libs/zard/src/lib/components/input/float.label.component.ts:71-0
Timestamp: 2025-11-14T22:52:09.135Z
Learning: In libs/zard/src/lib/components/*/*.component.ts files, move HostListener and HostBinding to the Component decorator's host property instead of using decorators on class members (e.g., host: { '(input)': 'onInput()' }).
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-11-29T15:31:22.377Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 339
File: libs/zard/src/lib/components/carousel/carousel.component.ts:92-92
Timestamp: 2025-11-29T15:31:22.377Z
Learning: In libs/zard/src/lib/components/**/*.component.ts files using TailwindCSS, avoid suggesting individual class bindings like `[class.fill-primary]="condition"` because they can cause TailwindCSS issues. Prefer string concatenation or `[class]` binding with conditional expressions instead.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
📚 Learning: 2025-12-21T21:17:39.497Z
Learnt from: mikij
Repo: zard-ui/zardui PR: 383
File: libs/zard/src/lib/shared/components/carousel/carousel.component.ts:114-115
Timestamp: 2025-12-21T21:17:39.497Z
Learning: In Angular components using signal inputs (input()) with types from external libraries like Embla Carousel, explicit type annotations (e.g., `readonly zOptions: InputSignal<EmblaOptionsType> = input<EmblaOptionsType>(...)`) may be necessary to prevent TypeScript IDE errors about inferred types referencing non-portable node_modules paths. This is not redundant when the annotation prevents the "cannot be named without a reference to node_modules" error.
Applied to files:
libs/zard/src/lib/shared/services/dark-mode.ts
🔇 Additional comments (20)
libs/zard/src/lib/shared/services/dark-mode.ts (10)
1-3: LGTM: Modern Angular imports with CDK integration.The imports follow Angular best practices: CDK MediaMatcher for media queries, inject() for DI, signals/computed/effect for reactivity, and DestroyRef for lifecycle management.
25-36: LGTM: Excellent use of modern Angular patterns.The constructor demonstrates best practices:
- inject() for dependency injection (no constructor parameters)
- DestroyRef for cleanup instead of OnDestroy lifecycle hook
- effect() for reactive theme synchronization
- Browser-only guard prevents SSR issues
38-43: LGTM: Defensive getter prevents SSR access violations.The query getter with explicit SSR guard and error message is good defensive programming, ensuring MediaQueryList is never accessed on the server.
45-51: LGTM: Clean computed signal for theme resolution.The themeMode computed signal correctly derives the resolved theme from currentTheme, handling the SYSTEM mode by checking system preferences.
53-57: LGTM: Well-documented initialization method.The init() method with JSDoc clarifying APP_INITIALIZER usage and browser-only guard is correct.
59-70: LGTM: Clean toggle implementation.The toggleTheme method correctly handles both explicit theme setting and toggling between light/dark modes with proper browser guards.
72-79: LGTM: Well-documented readonly signal exposure.The currentTheme getter with comprehensive JSDoc and asReadonly() prevents external mutation while maintaining reactivity.
81-90: LGTM: Clean initialization logic.The initializeTheme method correctly reads stored preferences and sets up system preference monitoring when needed, with no redundant checks.
92-125: LGTM: Robust error handling for storage operations.Both applyTheme and getStoredTheme include try-catch blocks around localStorage operations, gracefully handling QuotaExceededError and SecurityError scenarios with appropriate warnings.
133-151: LGTM: Robust system preference detection.Both isDarkModeActive and handleSystemChanges are well-implemented with proper error handling and clear logic for media query management.
libs/zard/src/lib/shared/services/dark-mode.spec.ts (7)
1-14: LGTM: Clean test setup with proper imports.The test file uses Angular testing utilities correctly with proper TypeScript typing for mocks.
15-65: LGTM: Comprehensive test setup with proper cleanup.The beforeEach and afterEach blocks demonstrate excellent testing practices:
- Thorough mocking of matchMedia and localStorage
- TestBed.tick() after init() ensures effects are flushed
- localStorage.clear() prevents state leakage between tests
All past review concerns have been addressed.
67-89: LGTM: System change listener tests properly flush effects.The tests correctly use TestBed.tick() after toggleTheme() calls to ensure effects run before assertions on addEventListener/removeEventListener.
91-120: LGTM: Callback verification and initialization tests are robust.The tests correctly:
- Use
expect(callback).toBeDefined()instead of Jest's non-existentfail()function- Reset TestBed to test initialization with different system preferences
- Flush effects with TestBed.tick() before assertions
All past review concerns have been addressed.
122-158: LGTM: Comprehensive SSR and initialization coverage.The tests include excellent coverage for:
- System appearance change detection from init()
- Graceful degradation in SSR environments (non-browser PLATFORM_ID)
The SSR test verifies no browser APIs are accessed and toggleTheme doesn't throw, ensuring server-side safety.
160-212: LGTM: Comprehensive toggleTheme test coverage.The toggleTheme tests thoroughly cover:
- Basic light/dark toggling
- System mode transitions with proper effect flushing (TestBed.tick())
- Explicit theme mode setting
- Listener lifecycle management verification
All past review concerns about missing TestBed.tick() calls have been addressed.
6-213: Excellent test coverage demonstrating Angular testing best practices.The test suite is comprehensive and well-structured, covering:
- System preference detection and listener lifecycle
- Theme initialization and toggling scenarios
- SSR environment graceful degradation
- LocalStorage persistence and error handling
All tests properly use TestBed.tick() to flush effects, ensuring synchronous verification of async behavior. The cleanup strategy prevents state leakage between tests.
apps/web/src/app/app.config.ts (3)
1-13: LGTM: Clean imports for app initialization pattern.The added imports (inject, provideAppInitializer) and ZardDarkMode service import follow Angular best practices and use the correct @zard/ path alias.
17-32: LGTM: Proper app initializer for early theme setup.The provideAppInitializer pattern ensures the dark mode service initializes during app bootstrap, preventing SSR flickering. The service's init() method includes appropriate error handling for localStorage operations (as verified in dark-mode.ts).
This pattern is synchronous (returns void), maintaining fast app startup while ensuring theme is applied before first render.
31-31: Well-architected bootstrap initialization pattern.The app initializer approach ensures dark mode preferences are loaded and applied during app bootstrap, preventing FOUC (flash of unstyled content) and SSR flickering. This aligns perfectly with the service's new init() method design.
What was done? 📝
Major Dark Mode Service Refactoring
The
ZardDarkModeservice has been significantly improved with modern Angular patterns:Key Changes:
OnDestroyin favor ofDestroyReffor better resource managementinit()method called viaprovideAppInitializerto ensure proper theme setup on app startgetCurrentTheme()method with acurrentThemegetter that returns a readonly signalMediaMatcherfrom CDK instead of manual media query managementTheme System Enhancements
New Theme Presets:
UI Improvements:
SSR Compatibility Fixes
Production Build Optimizations:
inlineCriticalCSS inlining to prevent SSR flickering issues/themesroute to prerender list for better SEOProvider Updates:
provideZard()to include dark mode initializationFont System Updates
Typography Enhancements:
Testing Infrastructure
Comprehensive Test Suite:
CLI and Build Improvements
Registry Updates:
Summary
This branch represents a comprehensive overhaul of the theming system with a focus on:
The changes maintain backward compatibility while significantly improving the robustness and performance of the dark mode functionality.
Screenshots or GIFs 📸
|-----Figma-----|
|-----Implementation-----|
Link to Issue 🔗
Type of change 🏗
Breaking change 🚨
Checklist 🧐
Summary by CodeRabbit
New Features
Improvements
Style
Tests
✏️ Tip: You can customize this high-level summary in your review settings.