Skip to content

feat/light-mode #444

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open

feat/light-mode #444

wants to merge 14 commits into from

Conversation

marcin-hoa
Copy link
Contributor

@marcin-hoa marcin-hoa commented May 13, 2025

Readded light-mode branch in order to have the possibility to test it out.

Summary by CodeRabbit

  • New Features

    • Theme switcher (light/dark) added and persisted; theme toggle exposed in header and applied app-wide.
    • Article cards: optimized image loading, featured visuals, and image priority control.
  • Style

    • Updated color system, foreground tokens and light-mode variants across layouts, cards, footer, navigation, author cards, roadmap.
    • Transparent cards, centered/uppercase primary buttons, pill/text color tweaks, social icons theming, accessibility image attributes.
  • Bug Fixes

    • Removed duplicate import in latest-articles component.
  • Chores

    • Added tailwind theme variants and updated Tailwind config.

@marcin-hoa marcin-hoa requested a review from DDonochVA May 13, 2025 06:10
Copy link

coderabbitai bot commented May 13, 2025

Walkthrough

Adds data-attribute-based theming and a theme store with toggle; wires theme into header, shell, and several components; introduces light-mode Tailwind variants and tokens; adjusts many templates/styles to respect theme, gradients, image handling, and button variants. No major control-flow changes beyond theme propagation.

Changes

Cohort / File(s) Summary
Theming infrastructure
libs/shared/assets/src/lib/styles/main.scss, tailwind.preset.js, package.json, libs/shared/assets/src/lib/styles/cookies-consent.scss, libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts
Switch to :root[data-theme] scoping, add --primary-foreground/--grey tokens, move al-link base rule, add tailwind theme-variants dependency and config, change darkMode to selector, export Theme, default theme set to dark, add toggle and setThemeAttribute that writes data-theme.
Shell / Header / Navigation / Footer
libs/blog/shell/feature-shell-web/src/lib/root-shell.component.ts, libs/blog/layouts/ui-layouts/src/lib/header/header.component.ts, libs/blog/layouts/ui-layouts/src/lib/header/components/header-hamburger.component.ts, libs/blog/layouts/ui-navigation/src/lib/navigation/navigation.component.ts, libs/blog/layouts/ui-navigation/src/lib/navigation/navigation.component.html, libs/blog/layouts/ui-navigation/src/lib/language-picker/language-picker.component.ts, libs/blog/layouts/ui-layouts/src/lib/footer/footer.component.html, libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-logo.component.ts, libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-social-media-icons.component.ts, libs/blog/layouts/ui-layouts/src/lib/footer/footer.component.scss
Wire theme signal and themeToggle event from header to shell/store; add header theme input/output and icon; add whiteFont input to navigation; update hamburger and label colors; adjust footer layout, background color and remove currentYear usage; footer social icons use light variant.
Card & Author components
libs/blog/shared/ui-card/src/lib/card.component.ts, libs/blog/shared/ui-card/src/lib/card.stories.ts, libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts, libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.ts, libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html, libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.ts, libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.html
Add hideGradient input to GradientCardDirective and conditional host class; CardComponent host classes include bg-al-card; expose hideGradient and articleCard inputs on author components; About Us injects theme and passes hideGradient; some al-card usages set bg-transparent; add primary-foreground text classes.
Article cards & content
libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.{ts,html}, .../article-regular-card/article-regular-card.component.html, .../article-horizontal-card/article-horizontal-card.component.html, .../article-hero-card/article-hero-card-skeleton.component.ts, libs/blog/articles/ui-article-card/src/lib/ui-article-card/ui-article-card.component.html, libs/blog/articles/ui-article-content/src/lib/article-content/article-content.component.{ts,scss}
Convert compact card to standalone, add NgOptimizedImage and imagePriority input; render featured images as positioned with sizes and opacity; pass imagePriority in switch; adjust borders/backgrounds and dark selector in SCSS; remove empty imports array.
Latest articles feature
libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.{ts,html}
Remove duplicate CardComponent import from imports array and add size="medium" to category button.
Comments theme binding
libs/blog/articles/feature-comments/src/lib/giscus-comments/giscus-comments.component.{ts,html}
Inject AppThemeStore and bind <giscus-widget> theme attribute to store signal theme().
Typography & small UI tweaks
libs/blog/articles/ui-article-list-title/src/lib/ui-article-list-title/ui-article-list-title.component.html, libs/blog/newsletter/feature-newsletter/src/lib/feature-newsletter/newsletter.component.html, libs/blog/become-author/feature-become-author-page/src/lib/components/become-author-list-item/become-author-list-item.component.html, libs/blog/writing-rules/feature-writing-rules/src/lib/rules-row/rules-row.component.html, libs/blog/partners/ui-partners/src/lib/partners-list/partners-list.component.html
Apply text-al-primary-foreground and text-white classes to headings/labels and add light:border/rounded classes to partner links; minor attribute formatting changes.
Buttons
libs/blog/become-author/feature-become-author-page/src/lib/become-author-page/become-author-page.component.{ts,html}, libs/blog/shared/ui-button/src/lib/button/button.component.ts
Replace styled anchor buttons with al-button, import ButtonComponent, add size inputs; update base button classes to include justify-center; primary variant gains text-white and uppercase.
Social media icons
libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.{ts,html}
Add exported SocialMediaIconsVariant type and variant input; compute iconColorClass and bind per-item; footer uses variant="light".
Article details author mode
libs/blog/articles/feature-article/src/lib/article-details/article-details.component.html
Pass [articleCard]="true" to <al-author-card> in article details aside.
Roadmap UI
libs/blog/roadmap/feature-roadmap/src/lib/roadmap-dialog-manager.service.ts, libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog*.component.ts, libs/blog/roadmap/ui-roadmap-node/src/lib/components/..., libs/blog/roadmap/ui-roadmap/src/lib/components/connected-nodes/connected-nodes.component.html, libs/blog/roadmap/ui-roadmap/src/lib/components/vertical-connector-arrow/vertical-connector-arrow.component.{ts,scss}
Add light-mode variants and primary-foreground text in dialog and nodes; change dialog panelClass to array; use currentColor for SVG stroke; inline vertical connector styles in template and remove separate SCSS; add cluster input signal.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Header as HeaderComponent
  participant Shell as RootShellComponent
  participant Store as AppThemeStore
  participant Consumer as CCAppThemeConsumer
  participant DOM as document.documentElement
  participant UI as Themed Components

  User->>Header: Click "Toggle theme"
  Header-->>Shell: emit themeToggle
  Shell->>Store: toggleTheme()
  Store->>Consumer: setThemeAttribute(theme)
  Consumer->>DOM: set data-theme='dark'|'light'\nadd/remove cc--darkmode
  Store-->>Shell: state patched (theme)
  Note right of UI: Components read Store.theme() or inputs\n(e.g., Giscus, AuthorCard.hideGradient, Navigation.whiteFont)
  DOM-->>UI: CSS [data-theme] variants apply
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested reviewers

  • marcin-hoa
  • DDonochVA
  • mateuszbasinski

Poem

I twitch my nose and flip the switch,
Moon or sun in one small click. 🌙☀️
Gradients hush, the cards comply,
Colors dance beneath the sky.
Hoppity hop — the theme looks neat,
CSS carrots for us to eat. 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/light-mode

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@valueadd-robot
Copy link

PR is detected, will deploy to dev environment

@valueadd-robot
Copy link

Deployed to dev environment
Branch: feature/light-mode
BFF URL: https://dbdc7bbc-blog-bff-dev.contact-ef8.workers.dev
Deploy URL: https://a7b8ff11.angular-love-client.pages.dev
Alias URL: https://feature-light-mode.angular-love-client.pages.dev

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (2)
libs/blog/become-author/feature-become-author-page/src/lib/become-author-page/become-author-page.component.html (2)

34-34: Consider using theme-aware text color for improved theme compatibility

While white text works well on the pink background, if the button background color might change based on theme, consider using a theme-aware text color class.

If the button background remains pink in all themes, this change is fine. Otherwise, consider:

- <p class="text-sm font-bold text-white">
+ <p class="text-sm font-bold text-al-pink-foreground">

This assumes you have defined appropriate foreground colors for your themed backgrounds.


64-64: Consider using theme-aware text color for improved theme compatibility

Similar to the other button, if the background color remains pink in all themes, white text is appropriate. For full theme support, consider a variable-based approach.

If the button background remains pink in all themes, this change is fine. Otherwise, consider using a theme-aware text color that complements the button background.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3be6ade and 1e19dd3.

⛔ Files ignored due to path filters (2)
  • apps/blog/src/assets/icons/arrow-down.svg is excluded by !**/*.svg
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (30)
  • libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.html (2 hunks)
  • libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.ts (0 hunks)
  • libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.html (1 hunks)
  • libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.ts (2 hunks)
  • libs/blog/articles/ui-article-card/src/lib/components/article-hero-card/article-hero-card-skeleton.component.ts (1 hunks)
  • libs/blog/articles/ui-article-card/src/lib/components/article-horizontal-card/article-horizontal-card.component.html (1 hunks)
  • libs/blog/articles/ui-article-card/src/lib/components/article-regular-card/article-regular-card.component.html (3 hunks)
  • libs/blog/articles/ui-article-card/src/lib/ui-article-card/ui-article-card.component.html (1 hunks)
  • libs/blog/articles/ui-article-list-title/src/lib/ui-article-list-title/ui-article-list-title.component.html (1 hunks)
  • libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts (2 hunks)
  • libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html (1 hunks)
  • libs/blog/become-author/feature-become-author-page/src/lib/become-author-page/become-author-page.component.html (2 hunks)
  • libs/blog/become-author/feature-become-author-page/src/lib/components/become-author-list-item/become-author-list-item.component.html (1 hunks)
  • libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-logo.component.ts (2 hunks)
  • libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-social-media-icons.component.ts (1 hunks)
  • libs/blog/layouts/ui-layouts/src/lib/footer/footer.component.html (1 hunks)
  • libs/blog/layouts/ui-layouts/src/lib/footer/footer.component.scss (1 hunks)
  • libs/blog/layouts/ui-navigation/src/lib/navigation/navigation.component.html (3 hunks)
  • libs/blog/layouts/ui-navigation/src/lib/navigation/navigation.component.ts (1 hunks)
  • libs/blog/newsletter/feature-newsletter/src/lib/feature-newsletter/newsletter.component.html (1 hunks)
  • libs/blog/partners/ui-partners/src/lib/partners-list/partners-list.component.html (1 hunks)
  • libs/blog/shared/ui-card/src/lib/card.component.ts (2 hunks)
  • libs/blog/shared/ui-card/src/lib/card.stories.ts (1 hunks)
  • libs/blog/shared/ui-difficulty/src/lib/ui-difficulty.component.ts (3 hunks)
  • libs/blog/shared/ui-pill/src/lib/pill.directive.ts (1 hunks)
  • libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.html (1 hunks)
  • libs/blog/writing-rules/feature-writing-rules/src/lib/rules-row/rules-row.component.html (2 hunks)
  • libs/shared/assets/src/lib/styles/main.scss (1 hunks)
  • package.json (1 hunks)
  • tailwind.preset.js (2 hunks)
💤 Files with no reviewable changes (1)
  • libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.ts (1)
libs/blog/shared/types/src/lib/article-card.ts (1)
  • ArticleCard (1-13)
🔇 Additional comments (48)
package.json (1)

67-67: Verify plugin version compatibility
The plugin is added as a beta release; please confirm that 2.0.0-beta.0 of tailwindcss-theme-variants is compatible with Tailwind CSS ^3.3.6 and appropriate for production use.

libs/blog/shared/ui-card/src/lib/card.stories.ts (1)

61-61: Demonstration of transparent background variant
This story correctly showcases the transparent background use case by applying bg-transparent to the <al-card> element.

libs/blog/newsletter/feature-newsletter/src/lib/feature-newsletter/newsletter.component.html (1)

8-8: Consistent use of primary-foreground token
Applying text-al-primary-foreground ensures that the heading color adapts to theme variants and remains consistent across light/dark modes.

libs/blog/articles/ui-article-card/src/lib/components/article-hero-card/article-hero-card-skeleton.component.ts (1)

10-10: Consistent transparent background
Adding bg-transparent aligns the skeleton card with the new light-mode theming, ensuring the skeleton blends correctly across themes.

libs/blog/articles/ui-article-card/src/lib/components/article-horizontal-card/article-horizontal-card.component.html (1)

3-3: Verify removal of fixed height
Removing max-h-52 in favor of theme-based styling could affect the card's vertical sizing. Please verify that the card height remains consistent and does not overflow its container across breakpoints.

libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html (1)

45-45: Apply theme-aware text color
Adding text-al-foreground ensures the author name responds to light/dark mode variants and aligns with the new theming tokens. Looks good.

libs/blog/partners/ui-partners/src/lib/partners-list/partners-list.component.html (1)

6-6: Verify dark mode background color
With bg-white still applied, this element may not adapt its background in dark mode. Please confirm that bg-white is intended, or consider using a theme-variant class (e.g., dark:bg-al-card) so the background aligns with dark theme.

libs/blog/articles/ui-article-list-title/src/lib/ui-article-list-title/ui-article-list-title.component.html (1)

4-4: Standardize primary heading color
Adding text-al-primary-foreground ensures the title adheres to the new primary text color token and is consistent with other headings across the app.

libs/blog/articles/ui-article-card/src/lib/ui-article-card/ui-article-card.component.html (1)

15-18: LGTM! Improved consistency across card variants

Adding the imagePriority input to the compact card variant brings consistency with the other card types and enables image loading optimization.

libs/blog/writing-rules/feature-writing-rules/src/lib/rules-row/rules-row.component.html (2)

14-14: Good addition of explicit text color

Adding the text-white class ensures the step numbers maintain proper contrast with the pink background in both light and dark modes.


49-49: Proper contrast for button text

The addition of text-white ensures the button text has adequate contrast against the pink background regardless of theme, supporting accessibility.

libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.html (3)

2-2: Good use of semantic color token

Using text-al-primary-foreground for the title enables proper theme adaptation instead of a hard-coded color value.


6-6: Appropriate background setting for theme support

Setting the card to bg-transparent allows it to properly inherit background colors when switching between light and dark themes.


38-38: Consistent use of semantic color token

Using text-al-primary-foreground for the authors title maintains styling consistency with the main title and supports theme adaptation.

libs/blog/layouts/ui-navigation/src/lib/navigation/navigation.component.html (3)

9-9: Improved layout with centered navigation

Adding justify-center improves the horizontal navigation layout by properly centering the navigation items.


24-25: Good implementation of theme-aware text styling

Replacing static text color with conditional styling [ngClass]="whiteFont() ? 'text-white' : 'text-al-foreground'" enables proper text color adaptation based on context and theme.

Make sure the whiteFont() input property is properly implemented in the component TypeScript file and documented for consumers of this component.


37-38: Consistent styling for external links

The same conditional text styling is correctly applied to external links, maintaining styling consistency across all navigation items.

libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-logo.component.ts (1)

2-2: Good component simplification

Removing the unused input import and the currentYear property simplifies the component appropriately. This cleanup removes unnecessary functionality while maintaining the component's core purpose.

Ensure that any components using <al-footer-logo> no longer pass the currentYear input property, as it has been removed.

Also applies to: 23-23

libs/blog/become-author/feature-become-author-page/src/lib/components/become-author-list-item/become-author-list-item.component.html (3)

3-5: Consistent trailing comma in [ngClass] object literal
The trailing comma after the single entry is valid and aligns with our formatting conventions for multiline object literals.


11-11: Explicit text-white class applied for contrast
Adding text-white ensures the index label remains legible against the pink background.


15-15: Use of text-al-pink token for the tick icon
The text-al-pink token aligns with our design system’s color palette.

libs/blog/layouts/ui-layouts/src/lib/footer/footer.component.html (1)

5-6: Footer logo and navigation setup looks good
Explicitly centering the logo and passing whiteFont="true" to <al-navigation> ensures consistent styling.

libs/blog/layouts/ui-layouts/src/lib/footer/footer.component.scss (2)

15-17: Updated default grid-template-areas
The new two-row layout ('logo social' / 'nav nav') is clear and concise for smaller viewports.


19-23: Verify breakpoint rename from @screen xl to @screen lg
Dropping the MD breakpoint and shifting the XL layout to LG may alter mid-size layouts. Please confirm that the updated breakpoints align with the design mockups and QA in all viewport widths.

libs/shared/assets/src/lib/styles/main.scss (2)

11-17: New CSS variables for theming added
Introducing --primary-foreground and --grey completes the palette for both light and dark modes. This aligns with the Tailwind configuration’s new tokens.


19-29: Light-mode media query block implemented
The prefers-color-scheme: light override correctly defines lighter values for all variables, enabling automatic theme switching.

libs/blog/shared/ui-card/src/lib/card.component.ts (2)

71-73: GradientCardDirective classes updated for theme variants
Switching to 'bg-al-radial-gradient dark:bg-al-background' removes the border and adds a dark-mode fallback—this matches our updated theming strategy.


99-101: Ensure component and directive hostClasses merge correctly
Both CardComponent and a consumer of alGradientCard bind to the class attribute. Please verify in the rendered DOM that classes from both the component and the directive are applied and not overridden.

libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts (3)

11-11: Great conversion to standalone component!

This conversion to a standalone component aligns with modern Angular best practices and improves the component's modularity.


23-24: Properly implemented light/dark mode styling

The alGradientCard directive and conditional dark/light mode classes are correctly applied, ensuring consistent styling that adapts to the theme. The background styling appropriately uses different colors for each theme variant.


27-28: LGTM: Content styling with directive

Adding the alCardContent directive to the inner content maintains styling consistency with other card components in the application.

libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.html (3)

3-3: Improved positioning and container styling

The addition of relative, overflow-hidden, and bg-black classes properly prepares the container for the new image layering approach.


6-13: Great improvement using proper image elements

Replacing CSS background with an actual <img> element is a significant improvement that:

  • Enhances accessibility with proper alt text
  • Enables image optimization through NgOptimizedImage
  • Provides better loading control with the priority attribute
  • Makes explicit width/height handling possible

The absolute positioning with opacity control creates a nice background effect while maintaining content readability.


14-14: Proper text color handling

The explicit text color setting ensures good contrast over the background image in all scenarios.

libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.ts (2)

1-1: Well-implemented standalone component conversion

The component has been properly converted to standalone with all necessary imports. Including NgOptimizedImage enables better image loading performance and optimization.

Also applies to: 13-20


25-25: Good addition of image priority control

The new imagePriority input property allows control over image loading priority, which is important for performance optimization and core web vitals. This aligns with the template changes using this property.

libs/blog/articles/ui-article-card/src/lib/components/article-regular-card/article-regular-card.component.html (5)

3-3: Improved border styling for theme consistency

The border styling now properly handles light and dark mode variations, maintaining visual separation in light mode while using transparent borders in dark mode.


21-25: Enhanced avatar component with priority loading

Adding the [priority] binding to the avatar component improves loading performance for this important UI element.


26-28: Proper text color styling for author name

The explicit text color class ensures consistent styling across light and dark modes.


41-47: Improved heading styling with proper color and text properties

The heading now uses explicit color, font weight, and style classes, ensuring consistent appearance across theme modes.


48-50: Consistent paragraph styling with theme-aware colors

The paragraph styling now properly uses theme-specific colors with appropriate font styling.

tailwind.preset.js (4)

1-5: Excellent addition of theme variant support

Good job introducing the tailwindcss-theme-variants plugin which enables media query-based theme switching. This is a more modern approach than the class-based dark mode.


13-14: New color tokens look good

The addition of 'al-primary-foreground' and 'al-grey' tokens will help maintain consistent theming across light and dark modes.

Also applies to: 22-22


35-35: Box shadow color change looks intentional

Changing from --border to --grey for the al-full-border shadow matches the new theming approach. Just ensure this change doesn't unexpectedly affect existing components.


39-51: Well-structured theme configuration

The plugin configuration properly sets up light and dark themes using media queries. This approach allows the UI to automatically adapt to the user's system preferences.

libs/blog/shared/ui-difficulty/src/lib/ui-difficulty.component.ts (3)

28-30: Good adaptation for light/dark mode in left block

The conditional class application correctly handles both light and dark modes based on the isColorBackground() condition:

  • Using dark:bg-al-background bg-transparent for colored backgrounds
  • Using bg-al-grey for non-colored backgrounds

This approach maintains visual consistency across themes.


47-50: Well-implemented shadow handling for different themes

The shadow classes are properly updated for the dot container:

  • dark:shadow-al-full-background shadow-transparent for colored backgrounds
  • shadow-al-full-border for non-colored backgrounds

This ensures proper visual representation in both light and dark modes.


80-82: Consistent styling in right block

The right block styling matches the left block's implementation, maintaining design consistency throughout the component. The code cleanly handles both light and dark themes.

@@ -9,7 +9,7 @@ import { SocialMediaIconsComponent } from '@angular-love/blog/shared/ui-social-m
<div class="flex flex-col items-start">
<h3
id="social-media-title"
class="mb-4 hidden text-sm font-bold lg:block"
class="mb-4 hidden text-sm font-bold text-[#fff] lg:block"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use design token instead of hardcoded hex
To support dynamic theming and maintain consistency with other components, replace the literal hex color with the text-al-primary-foreground token:

- class="mb-4 hidden text-sm font-bold text-[#fff] lg:block"
+ class="mb-4 hidden text-sm font-bold text-al-primary-foreground lg:block"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class="mb-4 hidden text-sm font-bold text-[#fff] lg:block"
class="mb-4 hidden text-sm font-bold text-al-primary-foreground lg:block"

@@ -9,7 +9,7 @@ const pillVariants = cva(
{
variants: {
variant: <Record<AlPillVariant, string>>{
flat: 'bg-al-primary/90',
flat: 'bg-al-primary/90 text-white',
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use design token for pill text color
For theme variant compatibility, replace text-white with the text-al-primary-foreground token in the flat variant:

- flat: 'bg-al-primary/90 text-white',
+ flat: 'bg-al-primary/90 text-al-primary-foreground',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
flat: 'bg-al-primary/90 text-white',
flat: 'bg-al-primary/90 text-al-primary-foreground',

@@ -32,6 +32,7 @@ export type NavItem = {
})
export class NavigationComponent {
readonly layout = input<'vertical' | 'horizontal'>('horizontal');
readonly whiteFont = input<boolean>(false);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider a more flexible theming approach instead of a boolean flag

While adding a whiteFont input provides basic text color control, a more comprehensive theming approach would better support light mode implementation.

Consider using a theme enum or string input that supports multiple theme options:

- readonly whiteFont = input<boolean>(false);
+ readonly textTheme = input<'default' | 'light' | 'dark' | 'contrast'>('default');

Then in the template, you could apply different classes based on the selected theme:

[ngClass]="{
  'text-white': textTheme() === 'light',
  'text-al-foreground': textTheme() === 'default',
  'text-al-primary': textTheme() === 'dark',
  'text-al-contrast': textTheme() === 'contrast'
}"

This approach would be more maintainable as you add more theme variants beyond just light mode.

Comment on lines +13 to +15
<small class="block pb-4 text-center text-xs text-[#6a798b]">
Copyright &#169; {{ currentYear }}
</small>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Hardcoded text color for copyright; use token
The inline text-[#6a798b] will not adjust for light mode. Swap in the design token (e.g., text-al-grey).

-  <small class="block pb-4 text-center text-xs text-[#6a798b]">
+  <small class="block pb-4 text-center text-xs text-al-grey">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<small class="block pb-4 text-center text-xs text-[#6a798b]">
Copyright &#169; {{ currentYear }}
</small>
<small class="block pb-4 text-center text-xs text-al-grey">
Copyright &#169; {{ currentYear }}
</small>

@@ -1,17 +1,16 @@
<footer class="bg-al-card w-full">
<footer class="w-full bg-[#191a22]">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Hardcoded background color blocks theming
Using bg-[#191a22] ties the footer to one static color and prevents automatic switching in light mode. Replace this with a theme-aware token (e.g., bg-al-background).

-<footer class="w-full bg-[#191a22]">
+<footer class="w-full bg-al-background">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<footer class="w-full bg-[#191a22]">
<footer class="w-full bg-al-background">

@valueadd-robot
Copy link

PR is detected, will deploy to dev environment

@valueadd-robot
Copy link

Deployed to dev environment
Branch: feature/light-mode
BFF URL: https://99e4388b-blog-bff-dev.contact-ef8.workers.dev
Deploy URL: https://babb5bbc.angular-love-client.pages.dev
Alias URL: https://feature-light-mode.angular-love-client.pages.dev

@valueadd-robot
Copy link

PR is detected, will deploy to dev environment

@valueadd-robot
Copy link

Deployed to dev environment
Branch: feature/light-mode
BFF URL: https://f56c1566-blog-bff-dev.contact-ef8.workers.dev
Deploy URL: https://12eb1423.angular-love-client.pages.dev
Alias URL: https://feature-light-mode.angular-love-client.pages.dev

@valueadd-robot
Copy link

PR is detected, will deploy to dev environment

@valueadd-robot
Copy link

Deployed to dev environment
Branch: feature/light-mode
BFF URL: https://eb347c0b-blog-bff-dev.contact-ef8.workers.dev
Deploy URL: https://3a9a6fd1.angular-love-client.pages.dev
Alias URL: https://feature-light-mode.angular-love-client.pages.dev

@valueadd-robot
Copy link

PR is detected, will deploy to dev environment

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts (1)

42-42: Consider addressing the architectural TODO.

The TODO comment highlights a valid architectural concern about decoupling the store from CCAppThemeConsumer. Consider creating an interface to improve testability and modularity.

Would you like me to help design an interface to decouple the theme store from the consumer implementation?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4852439 and 31a555a.

⛔ Files ignored due to path filters (2)
  • apps/blog/src/assets/icons/moon.svg is excluded by !**/*.svg
  • apps/blog/src/assets/icons/sun.svg is excluded by !**/*.svg
📒 Files selected for processing (5)
  • libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts (3 hunks)
  • libs/blog/layouts/ui-layouts/src/lib/header/header.component.ts (3 hunks)
  • libs/blog/shared/ui-icon/src/lib/icon/icon.component.ts (1 hunks)
  • libs/blog/shell/feature-shell-web/src/lib/root-shell.component.ts (4 hunks)
  • libs/shared/assets/src/lib/styles/main.scss (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • libs/blog/shared/ui-icon/src/lib/icon/icon.component.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • libs/shared/assets/src/lib/styles/main.scss
🧰 Additional context used
🧬 Code Graph Analysis (1)
libs/blog/shell/feature-shell-web/src/lib/root-shell.component.ts (1)
libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts (1)
  • AppThemeStore (11-34)
🔇 Additional comments (11)
libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts (4)

3-3: Good addition of patchState import.

The import of patchState is necessary for properly updating the signal store state in the new methods.


5-5: Good export of Theme type for reusability.

Exporting the Theme type allows other components to import and use the same type definition, promoting type consistency across the application.


27-31: Excellent implementation of theme toggle functionality.

The toggleTheme method correctly:

  • Toggles between 'dark' and 'light' themes
  • Updates the DOM attribute via the consumer
  • Patches the store state with the new theme

The logic is clean and follows the signal store pattern properly.


45-47: Improvement: Using data attributes instead of CSS classes.

The change from setThemeClass to setThemeAttribute is a good architectural improvement. Using data-theme attributes instead of CSS classes provides better separation of concerns and is more semantic for theme management.

libs/blog/shell/feature-shell-web/src/lib/root-shell.component.ts (3)

79-81: Clean integration of theme store.

The injection of AppThemeStore and creation of a computed theme signal provides reactive theme state to the template. This follows Angular best practices for signal-based state management.


31-33: Proper template integration for theme management.

The template correctly:

  • Passes the reactive theme() signal to the header component
  • Handles the themeToggle event to trigger theme switching

This creates a clean data flow from store → shell → header.


104-106: Simple and effective theme toggle handler.

The onThemeToggle method correctly delegates to the store's toggleTheme method, maintaining separation of concerns between UI events and state management.

libs/blog/layouts/ui-layouts/src/lib/header/header.component.ts (4)

83-83: Well-typed theme input.

The theme input is properly typed as 'light' | 'dark' and marked as required, ensuring type safety and preventing undefined theme states.


87-87: Clean event-driven architecture.

The themeToggle output event follows Angular patterns for component communication, allowing the parent component to handle theme changes appropriately.


91-93: Intuitive icon selection logic.

The themeSwitchIcon computed property correctly shows:

  • Moon icon in light mode (to indicate switching to dark)
  • Sun icon in dark mode (to indicate switching to light)

This provides clear visual indication of the toggle action.


41-52: Excellent accessibility and styling for theme toggle.

The theme toggle button implementation includes:

  • Proper aria-label for screen readers
  • Clean styling with transparent background
  • Proper click event handling
  • Test ID for automated testing (once typo is fixed)
  • Semantic use of SVG icons

This provides a great user experience for theme switching.

aria-label="Toggle theme"
class="flex items-center bg-transparent p-1"
(click)="themeToggle.emit()"
date-testid="header-theme-switch"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix typo in data attribute.

There's a typo in the test ID attribute.

Apply this diff to fix the typo:

-            date-testid="header-theme-switch"
+            data-testid="header-theme-switch"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
date-testid="header-theme-switch"
data-testid="header-theme-switch"
🤖 Prompt for AI Agents
In libs/blog/layouts/ui-layouts/src/lib/header/header.component.ts at line 45,
there is a typo in the data attribute "date-testid". Change "date-testid" to the
correct attribute "data-testid" to fix the typo.

@valueadd-robot
Copy link

Deployed to dev environment
Branch: feature/light-mode
BFF URL: https://7d56e499-blog-bff-dev.contact-ef8.workers.dev
Deploy URL: https://226218aa.angular-love-client.pages.dev
Alias URL: https://feature-light-mode.angular-love-client.pages.dev

@valueadd-robot
Copy link

PR is detected, will deploy to dev environment

@valueadd-robot
Copy link

Deployed to dev environment
Branch: feature/light-mode
BFF URL: https://67638abc-blog-bff-dev.contact-ef8.workers.dev
Deploy URL: https://04c64b85.angular-love-client.pages.dev
Alias URL: https://feature-light-mode.angular-love-client.pages.dev

@valueadd-robot
Copy link

PR is detected, will deploy to dev environment

@valueadd-robot
Copy link

Deployed to dev environment
Branch: feature/light-mode
BFF URL: https://2e673f35-blog-bff-dev.contact-ef8.workers.dev
Deploy URL: https://5dbbc279.angular-love-client.pages.dev
Alias URL: https://feature-light-mode.angular-love-client.pages.dev

@valueadd-robot
Copy link

PR is detected, will deploy to dev environment

@valueadd-robot
Copy link

Deployed to dev environment
Branch: feature/light-mode
BFF URL: https://3d4ac9fe-blog-bff-dev.contact-ef8.workers.dev
Deploy URL: https://61cc06c5.angular-love-client.pages.dev
Alias URL: https://feature-light-mode.angular-love-client.pages.dev

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
tailwind.preset.js (1)

1-1: Remove unused import or utilize the imported themeVariants.

The themeVariants import from 'tailwindcss-theme-variants' is not being used in the plugins array. You're implementing a custom plugin instead.

Apply this diff to remove the unused import:

-const { themeVariants } = require('tailwindcss-theme-variants');

Alternatively, if you intend to use the library's implementation, replace the custom plugin with:

-const { themeVariants } = require('tailwindcss-theme-variants');
+const { themeVariants } = require('tailwindcss-theme-variants');

// In plugins array:
-    function ({ addVariant }) {
-      addVariant(
-        'light',
-        '&:where([data-theme="light"], [data-theme="light"] *)',
-      );
-      addVariant('dark', '&:where([data-theme="dark"], [data-theme="dark"] *)');
-    },
+    themeVariants({
+      themes: {
+        light: 'selector',
+        dark: 'selector'
+      }
+    }),
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c822c6 and 6b67725.

📒 Files selected for processing (13)
  • libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.html (2 hunks)
  • libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.ts (2 hunks)
  • libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.html (1 hunks)
  • libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts (2 hunks)
  • libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html (2 hunks)
  • libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.ts (1 hunks)
  • libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-social-media-icons.component.ts (1 hunks)
  • libs/blog/shared/ui-button/src/lib/button/button.component.ts (1 hunks)
  • libs/blog/shared/ui-card/src/lib/card.component.ts (2 hunks)
  • libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.html (1 hunks)
  • libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.ts (2 hunks)
  • libs/shared/assets/src/lib/styles/main.scss (2 hunks)
  • tailwind.preset.js (2 hunks)
✅ Files skipped from review due to trivial changes (2)
  • libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.html
  • libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • libs/blog/shared/ui-button/src/lib/button/button.component.ts
  • libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-social-media-icons.component.ts
  • libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.html
  • libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html
  • libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.html
  • libs/shared/assets/src/lib/styles/main.scss
  • libs/blog/shared/ui-card/src/lib/card.component.ts
  • libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.ts (1)
libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts (1)
  • AppThemeStore (11-38)
🔇 Additional comments (10)
libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.ts (3)

4-6: LGTM: Modern Angular signal imports

Good adoption of Angular's signal-based reactive programming with computed and input.


15-15: LGTM: Well-defined variant type

The type definition provides good type safety for the theming variants.


27-27: LGTM: Modern input signal usage

Using Angular's signal-based input with a sensible default value follows current best practices.

libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.ts (3)

19-19: LGTM! Clean integration with the theme system.

The import correctly adds the AppThemeStore following the established import pattern and module structure.


45-45: Excellent use of modern Angular patterns.

The injection uses the proper inject() function and correctly accesses the theme signal from the store. The readonly modifier appropriately prevents direct modification.


47-47: Well-implemented theme-aware computed property.

The computed property correctly implements the gradient hiding logic for light mode using Angular's reactive patterns. The naming is descriptive and the logic is straightforward and appropriate.

tailwind.preset.js (4)

5-5: LGTM: Appropriate darkMode configuration for attribute-based theming.

The change from ['class'] to 'selector' correctly aligns with the data-theme attribute approach used throughout the application.


10-11: LGTM: New color token follows established pattern.

The al-primary-foreground color token is properly defined using the CSS variable pattern with alpha value support.


19-19: LGTM: Grey color token addition supports theming system.

The al-grey color token follows the established pattern and will be used in the updated box shadow configuration.


32-32: LGTM: Box shadow color update aligns with new color tokens.

The change from --border to --grey CSS variable correctly utilizes the newly added al-grey color token.

@valueadd-robot
Copy link

PR is detected, will deploy to dev environment

@valueadd-robot
Copy link

Deployed to dev environment
Branch: feature/light-mode
BFF URL: https://9ee4689f-blog-bff-dev.contact-ef8.workers.dev
Deploy URL: https://b0976493.angular-love-client.pages.dev
Alias URL: https://feature-light-mode.angular-love-client.pages.dev

@valueadd-robot
Copy link

PR is detected, will deploy to dev environment

@valueadd-robot
Copy link

Deploy failed, please check the logs in jenkins for more details.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🔭 Outside diff range comments (3)
libs/blog/partners/ui-partners/src/lib/partners-list/partners-list.component.html (2)

5-10: Add rel="noopener noreferrer" for external link security

External links with target="_blank" should include rel="noopener noreferrer" to prevent reverse tabnabbing and improve performance.

Apply this diff:

-      target="_blank"
+      target="_blank" rel="noopener noreferrer"

12-17: Specify sizes for NgOptimizedImage with fill to improve image selection

With fill, providing sizes helps the browser pick the correct resource and reduces bandwidth. Based on the container’s max widths, 160px base and 200px from md breakpoint:

Apply this diff:

         <img
           class="object-scale-down p-1"
           [ngSrc]="partner.asset_URL"
           [alt]="partner.alt"
+          sizes="(min-width: 768px) 200px, 160px"
           fill
         />
libs/blog/layouts/ui-navigation/src/lib/navigation/navigation.component.html (1)

4-11: Fix duplicate class attributes on

    — earlier one gets overridden

    The UL currently has two class attributes (one static, one later static) plus [class] and [ngClass]. In HTML, duplicate class attributes are invalid; the later class wins, so justify-center is effectively lost. Consolidate to a single static class and a single [ngClass].

    Apply this diff:

    -  <ul
    -    class="flex flex-wrap justify-center"
    -    [ngClass]="{
    -      'flex-col justify-between': layout() === 'vertical',
    -    }"
    -    class="flex flex-wrap"
    -    [attr.aria-label]="t('nav.navLinks')"
    -    [class]="isVerticalLayout ? 'flex-col justify-between' : ''"
    -  >
    +  <ul
    +    class="flex flex-wrap justify-center"
    +    [ngClass]="{ 'flex-col justify-between': layout() === 'vertical' }"
    +    [attr.aria-label]="t('nav.navLinks')"
    +  >
🧹 Nitpick comments (8)
libs/blog/layouts/ui-layouts/src/lib/footer/footer.component.scss (2)

13-17: Ensure .al-container actually uses CSS Grid and has predictable tracks

If .al-container isn't already display: grid via Tailwind classes in the template, the grid-template-areas here will have no effect. Also, defining explicit columns will stabilize sizing on small screens.

Proposed inline improvement:

 .al-container {
-  grid-template-areas:
+  display: grid;
+  grid-template-columns: 1fr 1fr;
+  grid-template-areas:
     'logo social'
     'nav nav';
 }

If the template already sets grid with Tailwind (e.g., class="grid grid-cols-2 ..."), keep that and only consider the columns suggestion here for consistency.


19-23: Confirm breakpoint intent (xl → lg) and add columns to prevent overflow at large screens

Renaming the breakpoint to @screen lg changes when the 3-column layout kicks in; verify this aligns with design and Tailwind config. To avoid nav stretching or squeeze between logo/social, define track sizes explicitly.

Proposed inline improvement:

 @screen lg {
   .al-container {
-    grid-template-areas: 'logo nav social';
+    grid-template-columns: auto 1fr auto;
+    grid-template-areas: 'logo nav social';
   }
 }

Also double-check DOM order vs visual order at lg; ensure the DOM sequence (logo → nav → social) matches the visual intent to avoid screen-reader and tab-order confusion.

libs/blog/partners/ui-partners/src/lib/partners-list/partners-list.component.html (2)

6-6: Remove redundant light:rounded-lg (already have rounded-lg)

rounded-lg is applied unconditionally; the light:rounded-lg variant is redundant and adds noise.

Apply this diff:

-      class="light:border light:rounded-lg aspect-[2/1] w-full max-w-[160px] rounded-lg bg-white md:max-w-[200px] lg:transition-transform lg:hover:scale-105 lg:hover:cursor-pointer lg:motion-reduce:transition-none lg:motion-reduce:hover:scale-100"
+      class="light:border aspect-[2/1] w-full max-w-[160px] rounded-lg bg-white md:max-w-[200px] lg:transition-transform lg:hover:scale-105 lg:hover:cursor-pointer lg:motion-reduce:transition-none lg:motion-reduce:hover:scale-100"

5-10: Improve keyboard focus visibility on interactive card

The anchor is interactive but lacks focus-visible styles. Add focus-visible ring/outline to meet a11y expectations for keyboard users.

Example (adjust tokens/colors to your design system):

-      class="light:border aspect-[2/1] w-full max-w-[160px] rounded-lg bg-white md:max-w-[200px] lg:transition-transform lg:hover:scale-105 lg:hover:cursor-pointer lg:motion-reduce:transition-none lg:motion-reduce:hover:scale-100"
+      class="light:border aspect-[2/1] w-full max-w-[160px] rounded-lg bg-white md:max-w-[200px] lg:transition-transform lg:hover:scale-105 lg:hover:cursor-pointer lg:motion-reduce:transition-none lg:motion-reduce:hover:scale-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2"

Optionally append theme-specific ring colors (e.g., light:focus-visible:ring-gray-300 dark:focus-visible:ring-white/40) consistent with your tokens.

libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.html (1)

11-12: Add responsive sources (ngSrcset/sizes) to avoid overserving large images

The card currently serves a fixed 1215×750 image. On smaller viewports this wastes bandwidth and hurts LCP. If your image service supports multi-size URLs, wire them via NgOptimizedImage.

Example (adjust to your CDN and size breakpoints):

<img
  ...
  [ngSrc]="article().featuredImageUrl"
  [ngSrcset]="{
  }"
  sizes="(max-width: 480px) 405px, (max-width: 1024px) 810px, 1215px"
/>
libs/blog/shell/feature-shell-web/src/lib/root-shell.component.ts (1)

95-97: Optional: avoid a redundant computed wrapper

You can expose the store’s signal directly; wrapping it in computed adds an unnecessary layer.

Apply this diff if you prefer the simpler approach:

-  protected readonly theme = computed(() => this._appThemeStore.theme());
+  protected readonly theme = this._appThemeStore.theme;
libs/blog/shared/ui-difficulty/src/lib/ui-difficulty.component.ts (1)

28-30: Verify token availability and consider a light-mode fallback for visual containment

  • Ensure the new token bg-al-grey exists and is theming-consistent with the rest of the palette.
  • Using bg-transparent in light mode may make the left/right blocks visually “float” on certain backgrounds. Consider a subtle, token-based fallback (e.g., a low-contrast surface token) if this causes loss of containment.

Also applies to: 80-82

libs/blog/articles/ui-article-card/src/lib/components/article-regular-card/article-regular-card.component.html (1)

41-47: Consider removing redundant word-break style.

The inline style="word-break: break-word" duplicates functionality that could be handled by Tailwind's break-words class, which provides better consistency with the existing class-based approach.

-        <h3
-          class="*:text-al-primary-foreground text-2xl font-bold *:not-italic"
-          [id]="article().slug"
-          style="word-break: break-word"
-        >
+        <h3
+          class="*:text-al-primary-foreground text-2xl font-bold *:not-italic break-words"
+          [id]="article().slug"
+        >
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5408343 and e957263.

⛔ Files ignored due to path filters (4)
  • apps/blog/src/assets/icons/arrow-down.svg is excluded by !**/*.svg
  • apps/blog/src/assets/icons/moon.svg is excluded by !**/*.svg
  • apps/blog/src/assets/icons/sun.svg is excluded by !**/*.svg
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (48)
  • libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.html (2 hunks)
  • libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.ts (2 hunks)
  • libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts (3 hunks)
  • libs/blog/articles/feature-article/src/lib/article-details/article-details.component.html (1 hunks)
  • libs/blog/articles/feature-comments/src/lib/giscus-comments/giscus-comments.component.html (1 hunks)
  • libs/blog/articles/feature-comments/src/lib/giscus-comments/giscus-comments.component.ts (2 hunks)
  • libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.html (1 hunks)
  • libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.ts (0 hunks)
  • libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.html (1 hunks)
  • libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.ts (2 hunks)
  • libs/blog/articles/ui-article-card/src/lib/components/article-hero-card/article-hero-card-skeleton.component.ts (1 hunks)
  • libs/blog/articles/ui-article-card/src/lib/components/article-horizontal-card/article-horizontal-card.component.html (1 hunks)
  • libs/blog/articles/ui-article-card/src/lib/components/article-regular-card/article-regular-card.component.html (3 hunks)
  • libs/blog/articles/ui-article-card/src/lib/ui-article-card/ui-article-card.component.html (1 hunks)
  • libs/blog/articles/ui-article-content/src/lib/article-content/article-content.component.scss (2 hunks)
  • libs/blog/articles/ui-article-content/src/lib/article-content/article-content.component.ts (0 hunks)
  • libs/blog/articles/ui-article-list-title/src/lib/ui-article-list-title/ui-article-list-title.component.html (1 hunks)
  • libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts (2 hunks)
  • libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html (2 hunks)
  • libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.ts (1 hunks)
  • libs/blog/become-author/feature-become-author-page/src/lib/become-author-page/become-author-page.component.html (2 hunks)
  • libs/blog/become-author/feature-become-author-page/src/lib/become-author-page/become-author-page.component.ts (2 hunks)
  • libs/blog/become-author/feature-become-author-page/src/lib/components/become-author-list-item/become-author-list-item.component.html (1 hunks)
  • libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-logo.component.ts (2 hunks)
  • libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-social-media-icons.component.ts (1 hunks)
  • libs/blog/layouts/ui-layouts/src/lib/footer/footer.component.html (1 hunks)
  • libs/blog/layouts/ui-layouts/src/lib/footer/footer.component.scss (1 hunks)
  • libs/blog/layouts/ui-layouts/src/lib/header/components/header-hamburger.component.ts (1 hunks)
  • libs/blog/layouts/ui-layouts/src/lib/header/header.component.ts (3 hunks)
  • libs/blog/layouts/ui-navigation/src/lib/language-picker/language-picker.component.ts (1 hunks)
  • libs/blog/layouts/ui-navigation/src/lib/navigation/navigation.component.html (3 hunks)
  • libs/blog/layouts/ui-navigation/src/lib/navigation/navigation.component.ts (2 hunks)
  • libs/blog/newsletter/feature-newsletter/src/lib/feature-newsletter/newsletter.component.html (1 hunks)
  • libs/blog/partners/ui-partners/src/lib/partners-list/partners-list.component.html (1 hunks)
  • libs/blog/shared/ui-button/src/lib/button/button.component.ts (1 hunks)
  • libs/blog/shared/ui-card/src/lib/card.component.ts (2 hunks)
  • libs/blog/shared/ui-card/src/lib/card.stories.ts (1 hunks)
  • libs/blog/shared/ui-difficulty/src/lib/ui-difficulty.component.ts (3 hunks)
  • libs/blog/shared/ui-icon/src/lib/icon/icon.component.ts (1 hunks)
  • libs/blog/shared/ui-pill/src/lib/pill.directive.ts (1 hunks)
  • libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.html (1 hunks)
  • libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.ts (2 hunks)
  • libs/blog/shell/feature-shell-web/src/lib/root-shell.component.ts (4 hunks)
  • libs/blog/writing-rules/feature-writing-rules/src/lib/rules-row/rules-row.component.html (2 hunks)
  • libs/shared/assets/src/lib/styles/cookies-consent.scss (1 hunks)
  • libs/shared/assets/src/lib/styles/main.scss (3 hunks)
  • package.json (1 hunks)
  • tailwind.preset.js (3 hunks)
💤 Files with no reviewable changes (2)
  • libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.ts
  • libs/blog/articles/ui-article-content/src/lib/article-content/article-content.component.ts
✅ Files skipped from review due to trivial changes (2)
  • libs/blog/articles/ui-article-card/src/lib/components/article-hero-card/article-hero-card-skeleton.component.ts
  • libs/blog/articles/ui-article-list-title/src/lib/ui-article-list-title/ui-article-list-title.component.html
🚧 Files skipped from review as they are similar to previous changes (32)
  • package.json
  • libs/blog/become-author/feature-become-author-page/src/lib/become-author-page/become-author-page.component.ts
  • libs/blog/newsletter/feature-newsletter/src/lib/feature-newsletter/newsletter.component.html
  • libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.html
  • libs/blog/become-author/feature-become-author-page/src/lib/components/become-author-list-item/become-author-list-item.component.html
  • libs/blog/shared/ui-icon/src/lib/icon/icon.component.ts
  • libs/blog/layouts/ui-navigation/src/lib/navigation/navigation.component.ts
  • libs/shared/assets/src/lib/styles/cookies-consent.scss
  • libs/blog/articles/ui-article-card/src/lib/components/article-horizontal-card/article-horizontal-card.component.html
  • libs/blog/articles/feature-comments/src/lib/giscus-comments/giscus-comments.component.html
  • libs/blog/shared/ui-pill/src/lib/pill.directive.ts
  • libs/blog/articles/ui-article-content/src/lib/article-content/article-content.component.scss
  • libs/blog/become-author/feature-become-author-page/src/lib/become-author-page/become-author-page.component.html
  • libs/blog/shared/ui-card/src/lib/card.stories.ts
  • libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.ts
  • libs/blog/shared/ui-card/src/lib/card.component.ts
  • libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.html
  • libs/blog/shared/ui-button/src/lib/button/button.component.ts
  • libs/blog/layouts/ui-layouts/src/lib/header/components/header-hamburger.component.ts
  • libs/blog/layouts/ui-layouts/src/lib/footer/footer.component.html
  • libs/blog/layouts/ui-navigation/src/lib/language-picker/language-picker.component.ts
  • libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.ts
  • libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-social-media-icons.component.ts
  • libs/blog/articles/feature-comments/src/lib/giscus-comments/giscus-comments.component.ts
  • libs/blog/articles/ui-article-card/src/lib/ui-article-card/ui-article-card.component.html
  • libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.ts
  • libs/blog/layouts/ui-layouts/src/lib/header/header.component.ts
  • libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-logo.component.ts
  • libs/blog/writing-rules/feature-writing-rules/src/lib/rules-row/rules-row.component.html
  • libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts
  • tailwind.preset.js
  • libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.html
🧰 Additional context used
🧬 Code Graph Analysis (7)
libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.ts (5)
libs/blog/articles/ui-article-card/src/lib/components/article-regular-card/article-regular-card.component.ts (1)
  • ArticleRegularCardComponent (22-25)
libs/blog/articles/ui-article-card/src/lib/components/article-hero-card/article-hero-card.component.ts (1)
  • ArticleHeroCardComponent (28-30)
libs/blog/articles/ui-article-card/src/lib/ui-article-card/ui-article-card.component.ts (1)
  • UiArticleCardComponent (26-30)
libs/blog/authors/ui-author-card/src/lib/author-card/author-card-skeleton.component.ts (1)
  • AuthorCardSkeletonComponent (54-54)
libs/blog/shared/ui-card/src/lib/card-skeleton.component.ts (1)
  • CardSkeletonComponent (34-39)
libs/blog/articles/feature-article/src/lib/article-details/article-details.component.html (4)
libs/blog/articles/ui-article-card/src/lib/ui-article-card/ui-article-card.component.ts (1)
  • UiArticleCardComponent (26-30)
libs/blog/articles/ui-article-card/src/lib/components/article-hero-card/article-hero-card.component.ts (1)
  • ArticleHeroCardComponent (28-30)
libs/blog/articles/ui-article-card/src/lib/components/article-regular-card/article-regular-card.component.ts (1)
  • ArticleRegularCardComponent (22-25)
libs/blog/articles/feature-article/src/lib/article-details/article-details.component.ts (1)
  • ArticleDetailsComponent (62-69)
libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html (2)
libs/blog/articles/ui-article-card/src/lib/ui-article-card/ui-article-card.component.ts (1)
  • UiArticleCardComponent (26-30)
libs/blog/articles/ui-article-card/src/lib/components/article-regular-card/article-regular-card.component.ts (1)
  • ArticleRegularCardComponent (22-25)
libs/blog/shell/feature-shell-web/src/lib/root-shell.component.ts (2)
libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts (1)
  • AppThemeStore (11-38)
apps/blog/src/app/app.component.ts (2)
  • AppComponent (14-43)
  • constructor (17-29)
libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.html (2)
libs/blog/articles/ui-article-card/src/lib/components/article-regular-card/article-regular-card.component.ts (1)
  • ArticleRegularCardComponent (22-25)
libs/blog/articles/ui-article-card/src/lib/ui-article-card/ui-article-card.component.ts (1)
  • UiArticleCardComponent (26-30)
libs/blog/articles/ui-article-card/src/lib/components/article-regular-card/article-regular-card.component.html (2)
libs/blog/articles/ui-article-card/src/lib/ui-article-card/ui-article-card.component.ts (1)
  • UiArticleCardComponent (26-30)
libs/blog/articles/ui-article-card/src/lib/components/article-regular-card/article-regular-card.component.ts (1)
  • ArticleRegularCardComponent (22-25)
libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts (2)
libs/blog/articles/ui-article-card/src/lib/ui-article-card/ui-article-card.component.ts (1)
  • UiArticleCardComponent (26-30)
libs/blog/articles/ui-article-card/src/lib/components/article-regular-card/article-regular-card.component.ts (1)
  • ArticleRegularCardComponent (22-25)
🪛 Biome (2.1.2)
libs/blog/shell/feature-shell-web/src/lib/root-shell.component.ts

[error] 92-93: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found '==='.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 98-99: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found '>'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 99-99: numbers cannot be followed by identifiers directly after

an identifier cannot appear here

(parse)


[error] 99-99: expected a semicolon to end the class property, but found none

(parse)


[error] 99-99: expected a semicolon to end the class property, but found none

(parse)


[error] 99-99: expected a semicolon to end the class property, but found none

(parse)


[error] 99-99: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found '-'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 99-99: expected a semicolon to end the class property, but found none

(parse)


[error] 99-99: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found ')'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 99-99: Duplicate class member name "theme"

(lint/suspicious/noDuplicateClassMembers)

🔇 Additional comments (21)
libs/blog/partners/ui-partners/src/lib/partners-list/partners-list.component.html (1)

12-17: Verify alt text semantics for logos

If partner.asset_URL represents a logo, alt should be the partner name (not empty and not “logo”). If the image is purely decorative and the partner name is elsewhere in accessible text, alt should be an empty string.

libs/blog/shell/feature-shell-web/src/lib/root-shell.component.ts (2)

36-39: Header theming bindings look correct

Wiring [theme] and (themeToggle) to the header matches the new API and keeps the RootShell as a thin coordinator. Once the theme signal is defined (see conflict fix below), this should work as intended.


127-129: Theme toggle handler correctly delegates to the store

This keeps the component logic minimal and defers the side effects (DOM attribute + localStorage) to the store. LGTM.

libs/blog/articles/feature-article/src/lib/article-details/article-details.component.html (1)

56-56: Good: [articleCard] input correctly wired for author card rendering

This aligns with the new input contract and should enable the intended article-specific styling.

libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.ts (1)

48-49: Inputs added are clear and default-safe

hideGradient and articleCard are well-scoped booleans with sane defaults and are forwarded in the template. No functional concerns.

libs/blog/layouts/ui-navigation/src/lib/navigation/navigation.component.html (3)

17-19: Good: dynamic text color via whiteFont()

Using [ngClass] here keeps static spacing/weight styles separate from theme-dependent color. Clean pattern.


30-32: Good: consistent external link theming

Same pattern applied to external links maintains parity with internal anchors.


4-7: NgClass Already Imported

NgClass is correctly imported from @angular/common in navigation.component.ts, so no runtime error will occur. No further changes needed.

libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html (2)

2-5: Good: forwarding new inputs to the template

[articleCard] and [hideGradient] are correctly exposed to the template, matching the new API.


48-48: Good: text token aligns with theme

Adding text-al-foreground to the author name maintains readability across themes.

libs/shared/assets/src/lib/styles/main.scss (3)

8-24: LGTM! Well-structured theme token system implementation.

The implementation of theme-scoped CSS variables using data-theme attributes is well-structured and follows best practices. The token organization is logical, and the values are appropriately defined for each theme.


26-35: LGTM! Light theme tokens are properly defined.

The light theme tokens are well-defined with appropriate values. The contrast between dark and light themes is clearly established through the token values (e.g., background switching from dark 16 15 21 to light 255 255 255).


90-94: Dark mode configuration verified

Tailwind is set to darkMode: 'selector' and includes a plugin that adds light: and dark: variants scoped to [data-theme="light"] and [data-theme="dark"]. The class dark:text-blue-400 will correctly apply when data-theme="dark" is present. No further changes needed.

libs/blog/articles/ui-article-card/src/lib/components/article-regular-card/article-regular-card.component.html (3)

10-17: LGTM! Proper NgOptimizedImage implementation with priority support.

The featured image implementation correctly uses NgOptimizedImage with explicit dimensions and priority binding from the component input. The fallback to placeholder image is appropriate.


21-29: LGTM! Avatar component properly configured with priority support.

The avatar component correctly receives the priority input, ensuring consistent image loading behavior across the card. The author name styling uses the theme-aware primary-foreground color token.


48-50: LGTM! Excerpt styling uses theme-aware color tokens.

The excerpt paragraph correctly uses the *:text-al-pink color token and appropriate typography classes for consistent theming.

libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts (5)

1-1: LGTM! Proper Angular imports added.

The import statement correctly adds computed and input from Angular core to support the new reactive inputs and computed properties.


16-16: LGTM! Dynamic gradient control implementation.

The binding [hideGradient]="hideGradient()" properly connects the component input to the gradient card directive, enabling runtime control of the gradient visibility.


20-20: LGTM! Dynamic class binding implementation.

The class bindings using computed properties provide clean, reactive styling based on component inputs. This approach maintains good separation of concerns.

Also applies to: 24-24


43-44: LGTM! Well-structured component inputs.

The input properties are properly typed with sensible defaults. The hideGradient defaults to true and articleCard defaults to false, which align with the expected common usage patterns.


46-54: LGTM! Efficient computed properties for dynamic styling.

The computed properties provide clean, reactive class generation based on component state. The conditional logic properly handles both article card and standard layouts, and the theme-aware classes align with the CSS variable system.

(article().featuredImageUrl || 'assets/article-placeholder.webp') +
')'
"
class="relative h-full overflow-hidden rounded-lg bg-black bg-cover bg-no-repeat transition-transform hover:scale-105 motion-reduce:transition-none motion-reduce:hover:scale-100"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Hard-coded bg-black undermines light-mode theming

Using bg-black forces a dark card in all themes. For light mode, this should be theme-driven (CSS vars or theme variants), not a fixed color.

Consider replacing with a theme-aware class/token (examples, adjust to your setup):

  • If using data-theme variants: bg-white text-gray-900 [data-theme=dark]:bg-black [data-theme=dark]:text-white
  • If using project tokens: bg-al-background text-al-foreground
    Would you like me to generate a patch once you confirm the preferred tokens/variants?

#!/bin/bash
# Locate Tailwind config file
config_file=$(fd 'tailwind.config.*' -t f | head -n1)
echo "Tailwind config file: $config_file"
if [ -n "$config_file" ]; then
  echo "=== Showing first 200 lines of $config_file ==="
  sed -n '1,200p' "$config_file"
fi

# Check for DaisyUI plugin usage
echo "=== Searching for DaisyUI references ==="
rg -n "daisyui" .

# Check for custom theme tokens
echo "=== Searching for 'bg-al-background' ==="
rg -n "bg-al-background" .

echo "=== Searching for 'al-background' ==="
rg -n "al-background" .

# Check for data-theme attribute usage
echo "=== Searching for 'data-theme' ==="
rg -n "data-theme" .

# Check for Tailwind dark variant usage
echo "=== Searching for 'dark:' classes ==="
rg -n "dark:" .

🏁 Script executed:

#!/bin/bash
# Locate Tailwind config file
config_file=$(fd 'tailwind.config.*' -t f | head -n1)
echo "Tailwind config file: $config_file"
if [ -n "$config_file" ]; then
  echo "=== Showing first 200 lines of $config_file ==="
  sed -n '1,200p' "$config_file"
fi

# Check for DaisyUI plugin usage
echo "=== Searching for DaisyUI references ==="
rg -n "daisyui" .

# Check for custom theme tokens
echo "=== Searching for 'bg-al-background' ==="
rg -n "bg-al-background" .

echo "=== Searching for 'al-background' ==="
rg -n "al-background" .

# Check for data-theme attribute usage
echo "=== Searching for 'data-theme' ==="
rg -n "data-theme" .

# Check for Tailwind dark variant usage
echo "=== Searching for 'dark:' classes ==="
rg -n "dark:" .

Length of output: 9683


Hard-coded bg-black breaks light-mode theming
Replace the fixed black background with your project’s theme tokens so the card adapts to both light and dark modes. For example, to match the regular card component you could use the al-card token:

• File:
libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.html
• Lines: 3

Suggested diff:

--- a/libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.html
+++ b/libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.html
@@ -1,4 +1,4 @@
-    class="relative h-full overflow-hidden rounded-lg bg-black bg-cover bg-no-repeat transition-transform hover:scale-105 motion-reduce:transition-none motion-reduce:hover:scale-100"
+    class="relative h-full overflow-hidden rounded-lg bg-al-card bg-cover bg-no-repeat transition-transform hover:scale-105 motion-reduce:transition-none motion-reduce:hover:scale-100"

If you need a distinct dark-mode override, you can also add a dark: variant (e.g. dark:bg-al-background).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class="relative h-full overflow-hidden rounded-lg bg-black bg-cover bg-no-repeat transition-transform hover:scale-105 motion-reduce:transition-none motion-reduce:hover:scale-100"
class="relative h-full overflow-hidden rounded-lg bg-al-card bg-cover bg-no-repeat transition-transform hover:scale-105 motion-reduce:transition-none motion-reduce:hover:scale-100"
🤖 Prompt for AI Agents
In
libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.html
around line 3, the class uses a hard-coded bg-black which breaks light-mode
theming; replace bg-black with the project's theme token (e.g. bg-al-card) and
optionally add a dark: variant (e.g. dark:bg-al-background) so the card adapts
to both light and dark modes while preserving the other utility classes.

Comment on lines +6 to +13
<img
alt="Post featured image"
class="absolute h-auto w-full bg-contain opacity-20"
[ngSrc]="article().featuredImageUrl || 'assets/article-placeholder.webp'"
[priority]="imagePriority()"
width="1215"
height="750"
/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Absolute image needs correct positioning and object-fit; fix wrong Tailwind class; clarify accessibility; ensure priority boolean

  • The absolute img lacks positioning (top/left/inset), so it may not anchor to the container’s top-left.
  • bg-contain is a background-image utility; for use object-contain/object-cover.
  • The image appears decorative (background), so alt="" with aria-hidden is more appropriate to avoid noisy SR output.
  • [priority] expects boolean (NgOptimizedImage). Passing number|null relies on coercion. Be explicit.

Apply this diff:

-    <img
-      alt="Post featured image"
-      class="absolute h-auto w-full bg-contain opacity-20"
-      [ngSrc]="article().featuredImageUrl || 'assets/article-placeholder.webp'"
-      [priority]="imagePriority()"
-      width="1215"
-      height="750"
-    />
+    <img
+      alt=""
+      aria-hidden="true"
+      class="absolute inset-0 z-0 h-full w-full object-cover opacity-20"
+      [ngSrc]="article().featuredImageUrl || 'assets/article-placeholder.webp'"
+      [priority]="!!imagePriority()"
+      width="1215"
+      height="750"
+    />

Notes:

  • If you prefer to keep the image informative, bind alt to the title instead: alt="{{ article().title }}" (but avoid duplicating the visible title for SRs).
  • If cropping is undesirable, use object-contain object-center instead of object-cover.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<img
alt="Post featured image"
class="absolute h-auto w-full bg-contain opacity-20"
[ngSrc]="article().featuredImageUrl || 'assets/article-placeholder.webp'"
[priority]="imagePriority()"
width="1215"
height="750"
/>
<img
alt=""
aria-hidden="true"
class="absolute inset-0 z-0 h-full w-full object-cover opacity-20"
[ngSrc]="article().featuredImageUrl || 'assets/article-placeholder.webp'"
[priority]="!!imagePriority()"
width="1215"
height="750"
/>
🤖 Prompt for AI Agents
In
libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.html
around lines 6-13, the <img> is absolute but lacks positioning and uses a
background utility; change the Tailwind classes to include explicit positioning
(e.g. top-0 left-0 w-full h-full) and use an object-fit utility (object-cover or
object-contain object-center) instead of bg-contain; mark the image as purely
decorative by setting alt="" and aria-hidden="true" (or if you want it
informative bind alt to article().title instead), and make the priority binding
an explicit boolean (e.g. [priority]="!!imagePriority()" or
[priority]="imagePriority() === true") so NgOptimizedImage receives a boolean.

width="1215"
height="750"
/>
<div class="relative flex h-full flex-col justify-between text-[#fff]">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Text color hard-coded; add stacking safety for content layer

  • text-[#fff] bypasses theme tokens and may clash in light mode.
  • Ensure content is layered above the overlay/image explicitly.

Apply this diff to enforce stacking (and drop hard-coded hex if tokens exist):

-    <div class="relative flex h-full flex-col justify-between text-[#fff]">
+    <div class="relative z-20 flex h-full flex-col justify-between text-al-foreground">

If text-al-foreground is unavailable, use your theme variant equivalents (e.g., text-gray-900 [data-theme=dark]:text-white).
Additionally, update the overlay (outside this range) to sit between image and content and ignore pointer events:

<!-- Line 16 update example -->
<div class="absolute inset-0 z-10 h-full w-full pointer-events-none hover:bg-al-bottom-radial-gradient"></div>

@@ -1,6 +1,6 @@
<a [routerLink]="['/', article().slug] | alLocalize">
<article
class="bg-al-card md:hover:shadow-al-primary group relative h-full w-full rounded-lg border border-transparent shadow-none transition-transform motion-reduce:transition-none lg:hover:scale-105 lg:motion-reduce:hover:scale-100"
class="bg-al-card md:hover:shadow-al-primary group relative h-full w-full rounded-lg border shadow-none transition-transform motion-reduce:transition-none lg:hover:scale-105 lg:motion-reduce:hover:scale-100 dark:border-transparent"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Inconsistent border approach between themes.

The border styling uses border with dark:border-transparent, but this conflicts with the theme-scoped approach established in the main.scss file. Consider using the --border CSS variable consistently across both themes instead of overriding with Tailwind's dark variant.

-    class="bg-al-card md:hover:shadow-al-primary group relative h-full w-full rounded-lg border shadow-none transition-transform motion-reduce:transition-none lg:hover:scale-105 lg:motion-reduce:hover:scale-100 dark:border-transparent"
+    class="bg-al-card md:hover:shadow-al-primary group relative h-full w-full rounded-lg border-al-border shadow-none transition-transform motion-reduce:transition-none lg:hover:scale-105 lg:motion-reduce:hover:scale-100"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class="bg-al-card md:hover:shadow-al-primary group relative h-full w-full rounded-lg border shadow-none transition-transform motion-reduce:transition-none lg:hover:scale-105 lg:motion-reduce:hover:scale-100 dark:border-transparent"
class="bg-al-card md:hover:shadow-al-primary group relative h-full w-full rounded-lg border-al-border shadow-none transition-transform motion-reduce:transition-none lg:hover:scale-105 lg:motion-reduce:hover:scale-100"
🤖 Prompt for AI Agents
In
libs/blog/articles/ui-article-card/src/lib/components/article-regular-card/article-regular-card.component.html
around line 3, the element uses Tailwind's generic border class plus
dark:border-transparent which conflicts with the theme-scoped border variable;
replace the hard-coded border classes with the theme-aware border variable
approach (use the --border CSS variable for border color/width via an
appropriate utility or inline style and remove the dark: override) so both light
and dark themes rely on the main.scss --border value; ensure the element no
longer uses the plain "border" and "dark:border-transparent" classes and instead
applies the border using the --border variable consistent with the rest of the
app.

Comment on lines +28 to 30
Expand
Down
>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove extraneous text nodes from template.

The template contains standalone text nodes "Expand" and "Down" that appear to be leftover content or debugging artifacts and should be removed.

             <div
               class="flex w-full flex-col items-center gap-4 md:max-w-[360px]"
-              Expand
-              Down
             >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Expand
Down
>
<div
class="flex w-full flex-col items-center gap-4 md:max-w-[360px]"
>
🤖 Prompt for AI Agents
In
libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts
around lines 28 to 30, there are stray text nodes "Expand" and "Down" in the
template; remove these standalone text nodes so only intended elements and
bindings remain (delete the two words and any surrounding whitespace/newlines so
the template contains only valid markup and components).

@@ -3,7 +3,7 @@
>
@for (partner of partnersList(); track partner.asset_URL) {
<a
class="aspect-[2/1] w-full max-w-[160px] rounded-lg bg-white md:max-w-[200px] lg:transition-transform lg:hover:scale-105 lg:hover:cursor-pointer lg:motion-reduce:transition-none lg:motion-reduce:hover:scale-100"
class="light:border light:rounded-lg aspect-[2/1] w-full max-w-[160px] rounded-lg bg-white md:max-w-[200px] lg:transition-transform lg:hover:scale-105 lg:hover:cursor-pointer lg:motion-reduce:transition-none lg:motion-reduce:hover:scale-100"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Confirm light: variant configuration and consider explicit border color

Ensure the Tailwind theme-variants setup defines a light variant that matches your runtime selector. Also, consider specifying a light border color (e.g., light:border-gray-200) to avoid defaulting to currentColor, which may be inconsistent across themes.

If helpful, run this script to verify configuration and usages:


🏁 Script executed:

#!/bin/bash
# Check Tailwind configuration and usages of light: variant
rg -nA3 $'themeVariants|light:' --hidden

# Inspect darkMode selector configuration
rg -n $'darkMode\\s*:\\s*[\'"]selector[\'"]' --hidden

# Spot border without explicit color under light:
rg -n $'light:border(\\s|")' --hidden

Length of output: 3057


🏁 Script executed:

#!/bin/bash
# Display full Tailwind preset configuration to verify themeVariants plugin usage
cat tailwind.preset.js

Length of output: 2563


Light variant is configured – add explicit border color

The light: variant is correctly registered in tailwind.preset.js via your custom plugin, so the prefix will work at runtime. However, using light:border alone defaults the border color to currentColor, which may vary between themes. It’s clearer and more consistent to pick a specific color (for example your al-border token or a gray scale):

• File: libs/blog/partners/ui-partners/src/lib/partners-list/partners-list.component.html
Line 6

Suggested change:

- class="light:border light:rounded-lg aspect-[2/1] w-full max-w-[160px] rounded-lg bg-white …"
+ class="light:border-al-border light:rounded-lg aspect-[2/1] w-full max-w-[160px] rounded-lg bg-white …"

You may also want to update other instances (e.g., in ui-article-card) where light:border is used without a color.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class="light:border light:rounded-lg aspect-[2/1] w-full max-w-[160px] rounded-lg bg-white md:max-w-[200px] lg:transition-transform lg:hover:scale-105 lg:hover:cursor-pointer lg:motion-reduce:transition-none lg:motion-reduce:hover:scale-100"
class="light:border-al-border light:rounded-lg aspect-[2/1] w-full max-w-[160px] rounded-lg bg-white md:max-w-[200px] lg:transition-transform lg:hover:scale-105 lg:hover:cursor-pointer lg:motion-reduce:transition-none lg:motion-reduce:hover:scale-100"
🤖 Prompt for AI Agents
In
libs/blog/partners/ui-partners/src/lib/partners-list/partners-list.component.html
around line 6, the class uses the light: variant as light:border which leaves
the border color to currentColor; change it to an explicit color token such as
light:border-al-border or a specific gray like light:border-gray-200 to ensure
consistent styling across themes, and update any other occurrences (e.g.,
ui-article-card) where light:border is used without a color.

Comment on lines +47 to 49
'dark:shadow-al-full-background shadow-transparent':
isColorBackground(),
'shadow-al-full-border': !isColorBackground(),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Replace non-standard 'shadow-transparent' with 'shadow-none'

Tailwind doesn’t ship a shadow-transparent utility by default. If it isn’t defined in your preset/theme, this class will do nothing and could be purged. shadow-none is the standard way to remove shadows.

Apply this diff:

-              'dark:shadow-al-full-background shadow-transparent':
+              'dark:shadow-al-full-background shadow-none':
                 isColorBackground(),

🏁 Script executed:

#!/bin/bash
# Locate Tailwind configuration files
configs=$(fd 'tailwind.config.*' . || echo "")
if [ -n "$configs" ]; then
  echo "Found Tailwind config files:"
  echo "$configs"
  for c in $configs; do
    echo "----- $c -----"
    grep -R "shadow" "$c" -n || true
  done
else
  echo "No Tailwind config file found"
fi

# Search codebase for usage of shadow-transparent and shadow-none
echo "Occurrences of 'shadow-transparent':"
rg "shadow-transparent" -n || echo "None found"

echo "Occurrences of 'shadow-none':"
rg "shadow-none" -n || echo "None found"

Length of output: 1714


Replace non-standard shadow-transparent with shadow-none

Tailwind doesn’t ship a shadow-transparent utility by default—if it isn’t defined in your config, it will be purged and have no effect. Use the standard shadow-none to remove shadows, as seen elsewhere in the codebase.

• File: libs/blog/shared/ui-difficulty/src/lib/ui-difficulty.component.ts (lines 47–49)

- 'dark:shadow-al-full-background shadow-transparent': isColorBackground(),
+ 'dark:shadow-al-full-background shadow-none':      isColorBackground(),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
'dark:shadow-al-full-background shadow-transparent':
isColorBackground(),
'shadow-al-full-border': !isColorBackground(),
'dark:shadow-al-full-background shadow-none':
isColorBackground(),
'shadow-al-full-border': !isColorBackground(),
🤖 Prompt for AI Agents
In libs/blog/shared/ui-difficulty/src/lib/ui-difficulty.component.ts around
lines 47 to 49, the class map uses a non-standard Tailwind utility
'shadow-transparent' which may be purged or have no effect; replace it with the
standard 'shadow-none' wherever you intend to remove shadows (and keep
'shadow-al-full-border' when !isColorBackground()). Update the conditional
branch to use 'shadow-none' instead of 'shadow-transparent' so the shadow is
reliably removed.

@@ -23,6 +23,7 @@ import {
AdImageBanner,
AlBannerCarouselComponent,
} from '@angular-love/blog/shared/ad-banner';
import { AppThemeStore } from '@angular-love/data-access-app-theme';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify the import alias for AppThemeStore resolves in this repo

The alias '@angular-love/data-access-app-theme' may differ from your Nx library's configured path (often '@angular-love/blog/app-theme/data-access-app-theme'). Please verify the alias exists in tsconfig path mappings and that the library barrel exports AppThemeStore.

Run the following to verify the alias and exports:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate AppThemeStore source =="
fd -a 'app-theme.store.ts' | sed -n '1,50p'

echo "== Confirm AppThemeStore and Theme are exported =="
rg -n "export (const|type) AppThemeStore|export type Theme" -S

echo "== Check for existing imports using the same alias =="
rg -n "from ['\"]@angular-love/data-access-app-theme['\"]"

echo "== Look for HeaderComponent theme API (Input/Output) =="
fd -a 'header.component.ts' | while read -r f; do
  echo "File: $f"
  rg -n "@Input\\(\\)\\s*theme|@Output\\(\\)\\s*themeToggle" "$f" || true
done

Length of output: 2323


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check tsconfig path mapping for '@angular-love/data-access-app-theme' =="
rg -n '"@angular-love/data-access-app-theme"' tsconfig*.json

echo
echo "== Inspect library barrel at libs/blog/app-theme/data-access-app-theme/src/index.ts =="
INDEX_FILE="libs/blog/app-theme/data-access-app-theme/src/index.ts"
if [ -f "$INDEX_FILE" ]; then
  echo "Found $INDEX_FILE"
  rg -n "export .*AppThemeStore" "$INDEX_FILE" || echo "⚠️ No explicit export of AppThemeStore in barrel"
else
  echo "⚠️ $INDEX_FILE not found"
fi

Length of output: 957


Export AppThemeStore in the library barrel

The path alias @angular-love/data-access-app-theme is correctly configured in tsconfig.base.json, but the barrel at libs/blog/app-theme/data-access-app-theme/src/index.ts does not re-export AppThemeStore. This prevents the import in root-shell.component.ts from resolving.

Please update the barrel:

• File: libs/blog/app-theme/data-access-app-theme/src/index.ts

+ export { AppThemeStore, type Theme } from './app-theme.store';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { AppThemeStore } from '@angular-love/data-access-app-theme';
// libs/blog/app-theme/data-access-app-theme/src/index.ts
+ export { AppThemeStore, type Theme } from './app-theme.store';
🤖 Prompt for AI Agents
In libs/blog/shell/feature-shell-web/src/lib/root-shell.component.ts around line
26 the import from @angular-love/data-access-app-theme fails because the library
barrel does not re-export AppThemeStore; open
libs/blog/app-theme/data-access-app-theme/src/index.ts and add an export for
AppThemeStore (export { AppThemeStore } from
'./lib/<correct-file-or-folder-path-containing-AppThemeStore>';), save and run a
build or TypeScript watch to verify the import resolves.

@valueadd-robot
Copy link

PR is detected, will deploy to dev environment

@valueadd-robot
Copy link

Deployed to dev environment
Branch: feature/light-mode
BFF URL: https://458a7596-blog-bff-dev.contact-ef8.workers.dev
Deploy URL: https://a640235a.angular-love-client.pages.dev
Alias URL: https://feature-light-mode.angular-love-client.pages.dev

@valueadd-robot
Copy link

PR is detected, will deploy to dev environment

@valueadd-robot
Copy link

Deploy failed, please check the logs in jenkins for more details.

@valueadd-robot
Copy link

PR is detected, will deploy to dev environment

@valueadd-robot
Copy link

Deployed to dev environment
Branch: feature/light-mode
BFF URL: https://ee3bd58f-blog-bff-dev.contact-ef8.workers.dev
Deploy URL: https://ec16bc6b.angular-love-client.pages.dev
Alias URL: https://feature-light-mode.angular-love-client.pages.dev

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🔭 Outside diff range comments (2)
libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-basic-node/roadmap-basic-node.component.ts (1)

26-33: Fix theme variant usage and color contrast on the button; don’t use “-foreground” tokens as backgrounds

  • The light variant class light:bg-al-primary-foreground is likely incorrect for two reasons:
    • Theme integration: The app toggles a cc--darkmode class on the html element (per CCAppThemeConsumer), so the canonical variant hook is dark:, not light:. Unless you explicitly configured a light: variant, this won’t apply.
    • Token semantics: -foreground tokens are intended for text color placed atop their paired background (e.g., text-al-primary-foreground on bg-al-primary). Using bg-al-primary-foreground as a background is semantically wrong and risks unreadable combinations.
  • Accessibility: text-[#FDF5FD] on a white background has extremely low contrast.
  • Add type="button" to avoid accidental form submission when this component is placed inside a form.

Suggested fix (assuming dark mode variant is configured via .cc--darkmode):

-    <button
-      class="node light:bg-al-primary-foreground relative w-full text-nowrap rounded-lg bg-[#fff] text-[#FDF5FD]"
+    <button
+      type="button"
+      class="node relative w-full text-nowrap rounded-lg bg-white text-al-grey dark:bg-al-primary-foreground dark:text-white"

If you did intentionally introduce a light: variant, keep it—but still avoid using a -foreground token as a background and fix the contrast:

-    <button
-      class="node light:bg-al-primary-foreground relative w-full text-nowrap rounded-lg bg-[#fff] text-[#FDF5FD]"
+    <button
+      type="button"
+      class="node relative w-full text-nowrap rounded-lg bg-white text-al-grey light:bg-white light:text-al-grey dark:bg-al-primary-foreground dark:text-white"
libs/shared/assets/src/lib/styles/main.scss (1)

8-24: Critical: add :root fallback for CSS variables & fix invalid Tailwind arbitrary classes — app-theme.store.ts already sets data-theme

Short summary: The earlier claim that the AppThemeStore never sets data-theme is incorrect — libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts calls document.documentElement.setAttribute('data-theme', theme) (line ~50). Still, many SCSS files only declare variables under :root[data-theme='...'], so if the attribute isn’t present at first paint you can get invalid rgb(var(--...)) values / FOUC. Also there are invalid Tailwind arbitrary usages that will emit bad CSS.

Files/locations needing attention

  • Add a safe fallback (:root) for CSS variables so they exist before JS runs:
    • libs/shared/assets/src/lib/styles/main.scss (currently only has :root[data-theme='dark'] / :root[data-theme='light'])
  • Ensure theme attribute is applied early (verify app-theme.store.ts runs before first paint, or use a minimal inline bootstrap if needed):
    • libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts — sets data-theme (line ~50)
  • Fix other SCSS files that only define theme variables:
    • libs/blog/articles/ui-article-content/src/lib/article-content/article-content.component.scss
    • libs/shared/assets/src/lib/styles/cookies-consent.scss
  • Fix invalid Tailwind arbitrary classes (will produce invalid CSS):
    • libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-cluster/roadmap-cluster.component.ts
      • Line ~10 current: class="bg-al-roadmap-secondary light:border-[--primary-foreground] …"
        • Replace light:border-[--primary-foreground] with light:border-[color:var(--primary-foreground)] (or light:border-[var(--primary-foreground)]).
      • Line ~26 current: '... from-[#100F15] to-[#3B0019] light:from-[al-primary] light:to-[al-primary] ... light:border-[--primary-foreground] ...'
        • Replace light:from-[al-primary] / light:to-[al-primary] with light:from-al-primary / light:to-al-primary (use named color utility, not bracketed arbitrary) OR use explicit variable: light:from-[var(--roadmap-primary)] / light:to-[var(--roadmap-primary)].
        • Replace light:border-[--primary-foreground] as above.

Suggested diff for main.scss (add default fallback — choose dark as fallback):

 @layer base {
-  :root[data-theme='dark'] {
+  :root {
+    /* Default (fallback) theme — mirrors dark. Ensures variables exist before JS sets data-theme */
+    --primary: 255 0 106;
+    --foreground: 255 255 255;
+    --primary-foreground: 255 255 255;
+    --muted: 190 196 202;
+    --border: 46 47 59;
+    --card: 25 26 34;
+    --background: 16 15 21;
+    --roadmap-primary: 179 0 74;
+    --roadmap-secondary: 102 0 43;
+    --roadmap-accent: 72 28 171;
+    --roadmap-hover-primary: 146 60 255;
+    --roadmap-hover-secondary: 255 0 106;
+    --roadmap-label-optional: 199 151 1;
+    --roadmap-label-comingSoon: 0 139 56;
+    --grey: 46 47 59;
+  }
+
+  :root[data-theme='dark'] {
     --primary: 255 0 106;
     --foreground: 255 255 255;
     --primary-foreground: 255 255 255;
@@
     --grey: 46 47 59;
   }
 
   :root[data-theme='light'] {
@@
   }

Conclusion / action items

  • Add the fallback block to main.scss (or centralize variables into a single fallback file).
  • Fix the Tailwind class usages in roadmap-cluster.component.ts as shown above.
  • Confirm app-theme.store.ts runs early enough; if not, set data-theme on first paint (inline script) or keep the CSS fallback.
🧹 Nitpick comments (10)
libs/blog/roadmap/feature-roadmap/src/lib/roadmap-dialog-manager.service.ts (4)

12-19: Ensure overlays inherit the active theme (light/dark) from the app root

Dialogs render inside cdk-overlay-container (outside your app root). If your theme is applied via data-theme on html/body/app root, the overlay may not inherit it, causing mismatched colors in light mode. Verify that the overlay container receives the same theme attribute/class.

If missing, consider syncing the attribute:

  • Mirror data-theme onto cdk-overlay-container.
  • Update it on theme changes (MutationObserver or your theme store events).

Example service to sync data-theme:

import { Injectable, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { OverlayContainer } from '@angular/cdk/overlay';

@Injectable({ providedIn: 'root' })
export class OverlayThemeSyncService {
  private observer = new MutationObserver(() => this.applyTheme());

  constructor(
    private overlay: OverlayContainer,
    @Inject(DOCUMENT) private doc: Document
  ) {
    this.applyTheme();
    this.observer.observe(this.doc.documentElement, {
      attributes: true,
      attributeFilter: ['data-theme'],
    });
  }

  private applyTheme(): void {
    const theme = this.doc.documentElement.getAttribute('data-theme');
    const el = this.overlay.getContainerElement();
    if (theme) {
      el.setAttribute('data-theme', theme);
    } else {
      el.removeAttribute('data-theme');
    }
  }
}

14-15: Verify the autoFocus selector targets a focusable element; consider cdkFocusInitial

autoFocus: '.dialog' assumes an element with class dialog exists and can receive focus. If not focusable, focusing may fail. Prefer marking the primary action with cdkFocusInitial for predictable a11y.

Example in the dialog component template:

<button cdkFocusInitial>Primary action</button>

16-16: Redundant config: disableClose defaults to false

You can omit disableClose: false to reduce noise.

Apply this diff:

-      disableClose: false,

12-12: Consider typing the close result instead of Observable

If the dialog returns a known result type (e.g., void/boolean/data), pass the appropriate generics to Dialog.open so .closed is strongly typed. This improves call-site safety and avoids casts later.

libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-basic-node/roadmap-basic-node.component.ts (3)

62-73: Co-locate text color with variant styles to guarantee contrast per background

Today the text color is set at the button level, while the background is chosen inside class(). That risks poor contrast when variants change or themes override backgrounds. Prefer returning both background and text color together per variant.

Example (conceptual):

protected readonly class = computed(() => {
  switch (this.variant()) {
    case 'primary':
      return 'm-[2px] bg-al-roadmap-primary text-white text-[24px]';
    case 'secondary':
      return 'm-[2px] bg-al-roadmap-secondary text-white text-[20px]';
    case 'angular-love':
      return 'm-[4px] bg-gradient-to-r from-al-roadmap-secondary to-al-roadmap-accent text-white text-[24px]';
    default:
      return '';
  }
});

This keeps contrast decisions in one place with the background choice. Adjust exact tokens/colors per your design system.


54-61: Ensure the document-level pointerup listener is always cleaned up (destroy/pointercancel)

If the component is destroyed before pointerup fires (e.g., route change), the document listener remains registered. Also consider handling pointercancel.

Add cleanup in ngOnDestroy and optionally listen for pointercancel:

// Add alongside your class members
private pointerCancelEventListener = (event: PointerEvent) => {
  this.onPointerUp(event);
  document.removeEventListener('pointercancel', this.pointerCancelEventListener);
};

// In onPointerDown, also add:
document.addEventListener('pointercancel', this.pointerCancelEventListener);

// Add lifecycle cleanup
ngOnDestroy(): void {
  document.removeEventListener('pointerup', this.pointerUpEventListener);
  document.removeEventListener('pointercancel', this.pointerCancelEventListener);
}

92-96: Prevent default on Space/Enter to avoid double-activation and scroll jitter

Pressing Space on a focused button can scroll the page. Browsers also synthesize click events for Enter/Space on buttons; while you don’t handle click here, future handlers could cause double-activation.

Consider:

protected onKeyDown(event: KeyboardEvent): void {
  if (event.code === 'Enter' || event.code === 'Space') {
    event.preventDefault();
    this._roadmapDialogNotifierService.notifyNodeClicked(this.node());
  }
}
libs/blog/roadmap/ui-roadmap/src/lib/components/connected-nodes/connected-nodes.component.html (1)

10-17: Optional: mark decorative SVG as non-accessible

If this path is purely decorative, consider preventing it from being announced by screen readers.

Apply this diff to the svg element:

   <svg
     [attr.height]="connectorHeight"
     [class.flipped]="isLeftDrawingDirection"
     overflow="visible"
     width="100%"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:svg="http://www.w3.org/2000/svg"
+    aria-hidden="true"
+    focusable="false"
   >
libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-cluster/roadmap-cluster.component.ts (1)

10-14: Optional: prefer roadmap tokens for the gradient as well

To be fully tokenized and consistent with roadmap theming, consider replacing the dark-mode hexes with roadmap tokens (e.g., from-al-roadmap-primary to-al-roadmap-secondary).

Example:

- '... bg-gradient-to-br from-[#100F15] to-[#3B0019] ...'
+ '... bg-gradient-to-br from-al-roadmap-primary to-al-roadmap-secondary ...'
libs/shared/assets/src/lib/styles/main.scss (1)

97-101: Global al-link color changed; confirm intended brand behavior

Switching .al-link to default text-red-500 and dark:text-blue-400 is a notable brand shift and may clash with existing design. If the intent is to follow theme tokens, prefer tokenized colors (e.g., text-al-primary) to keep consistency.

Example:

-.al-link { @apply text-red-500 hover:underline dark:text-blue-400; }
+.al-link { @apply text-al-primary hover:underline; }

If you truly need per-theme divergence beyond tokens, document the rationale to avoid regressions.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 18a4c96 and 097903d.

📒 Files selected for processing (9)
  • libs/blog/roadmap/feature-roadmap/src/lib/roadmap-dialog-manager.service.ts (1 hunks)
  • libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-footer/roadmap-dialog-footer.component.ts (1 hunks)
  • libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog.component.html (1 hunks)
  • libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-basic-node/roadmap-basic-node.component.ts (1 hunks)
  • libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-cluster/roadmap-cluster.component.ts (2 hunks)
  • libs/blog/roadmap/ui-roadmap/src/lib/components/connected-nodes/connected-nodes.component.html (1 hunks)
  • libs/blog/roadmap/ui-roadmap/src/lib/components/vertical-connector-arrow/vertical-connector-arrow.component.scss (0 hunks)
  • libs/blog/roadmap/ui-roadmap/src/lib/components/vertical-connector-arrow/vertical-connector-arrow.component.ts (1 hunks)
  • libs/shared/assets/src/lib/styles/main.scss (3 hunks)
💤 Files with no reviewable changes (1)
  • libs/blog/roadmap/ui-roadmap/src/lib/components/vertical-connector-arrow/vertical-connector-arrow.component.scss
✅ Files skipped from review due to trivial changes (1)
  • libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-footer/roadmap-dialog-footer.component.ts
🧰 Additional context used
🧬 Code Graph Analysis (4)
libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-cluster/roadmap-cluster.component.ts (2)
libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts (2)
  • CCAppThemeConsumer (37-49)
  • setThemeClass (38-48)
libs/blog/shared/ui-card/src/lib/card.component.ts (1)
  • DarkCardDirective (80-85)
libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog.component.html (1)
libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts (2)
  • CCAppThemeConsumer (37-49)
  • setThemeClass (38-48)
libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-basic-node/roadmap-basic-node.component.ts (2)
libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts (2)
  • CCAppThemeConsumer (37-49)
  • setThemeClass (38-48)
libs/blog/shared/ui-button/src/lib/button/button.component.ts (1)
  • ButtonComponent (53-64)
libs/shared/assets/src/lib/styles/main.scss (1)
libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts (3)
  • CCAppThemeConsumer (37-49)
  • setThemeClass (38-48)
  • AppThemeStore (7-9)
🔇 Additional comments (5)
libs/blog/roadmap/feature-roadmap/src/lib/roadmap-dialog-manager.service.ts (1)

17-17: panelClass switched to string[] — correct and future-proof

Using an array for panelClass aligns with the CDK API (string | string[]) and makes it easier to append additional classes (e.g., theme or responsive variants) later.

libs/blog/roadmap/ui-roadmap/src/lib/components/vertical-connector-arrow/vertical-connector-arrow.component.ts (2)

6-9: Triangle orientation: verify intent; border-t draws an upward arrow

With the CSS triangle technique, coloring the top border creates an upward-pointing triangle. If this arrow is intended to point downward (common for “connector” arrows), switch to coloring the bottom border instead.

Apply if a downward-pointing arrow is desired:

-      class="h-0 w-0 border-l-[16px] border-r-[16px] border-t-[30px] border-l-transparent border-r-transparent border-t-[var(--primary)]"
+      class="h-0 w-0 border-l-[16px] border-r-[16px] border-b-[30px] border-l-transparent border-r-transparent border-b-[var(--primary)]"

6-9: Confirmed — Tailwind 3.x is present and supports side-specific arbitrary border-color

Tailwind CSS v3.4.17 is installed in this repo (pnpm-lock/node_modules and package.json dependency), so classes like border-l-[var(--primary)] and border-t-[var(--primary)] are supported and should compile.

Files to note:

  • libs/blog/roadmap/ui-roadmap/src/lib/components/vertical-connector-arrow/vertical-connector-arrow.component.ts — lines with the classes (lines ~6 and ~8)
  • package.json / pnpm-lock.yaml & node_modules showing [email protected]

No fallback required.

libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-basic-node/roadmap-basic-node.component.ts (1)

26-33: Ignore cc--darkmode — Tailwind is already configured to use [data-theme] and the light: variant

Verified — the repo uses data-theme attributes and the Tailwind preset defines light/dark variants, so light: utilities (e.g. light:bg-al-primary-foreground) are valid.

Relevant locations:

  • tailwind.preset.js — defines tokens (e.g. al-primary-foreground) and the theme selectors:
    • &:where([data-theme="light"], [data-theme="light"] *)
    • addVariant('dark', '&:where([data-theme="dark"], [data-theme="dark"] *)')
  • libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts — toggles theme via document.documentElement.setAttribute('data-theme', theme)
  • Example usages of light: (including the file under review):
    • libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-basic-node/roadmap-basic-node.component.ts
    • libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog.component.html
    • several other components (search returned multiple light: usages)

Result: no change required to the component — the assumption about CCAppThemeConsumer toggling cc--darkmode is not aligned with this codebase.

Likely an incorrect or invalid review comment.

libs/blog/roadmap/ui-roadmap/src/lib/components/connected-nodes/connected-nodes.component.html (1)

22-25: Good move: stroke now theme-aware via currentColor

Switching to currentColor allows the connector stroke to follow the active theme. This aligns with the tokenized color system.

@@ -1,5 +1,5 @@
<div
class="dialog w-full overflow-hidden rounded-lg border-2 border-white bg-gradient-to-br from-[#100f15] to-[#3b0019] text-white"
class="dialog light:border-al-primary-foreground w-full overflow-hidden rounded-lg border-2 border-white bg-gradient-to-br from-[#100f15] to-[#3b0019] text-white"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Light-mode border added, but text/gradient remain hard-coded for dark; switch to tokens for full theming

The container still forces text-white and a dark gradient regardless of theme, which can hurt contrast in light mode. Prefer tokenized classes so light/dark switch cleanly.

Apply this minimal diff to align border and text with tokens (keeps your existing gradient as-is):

-  class="dialog light:border-al-primary-foreground w-full overflow-hidden rounded-lg border-2 border-white bg-gradient-to-br from-[#100f15] to-[#3b0019] text-white"
+  class="dialog w-full overflow-hidden rounded-lg border-2 border-al-primary-foreground light:border-al-primary-foreground bg-gradient-to-br from-[#100f15] to-[#3b0019] text-al-foreground"

If you want the background to be lighter in light mode, you can additionally extend with:

+ light:from-white light:to-al-grey
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class="dialog light:border-al-primary-foreground w-full overflow-hidden rounded-lg border-2 border-white bg-gradient-to-br from-[#100f15] to-[#3b0019] text-white"
class="dialog w-full overflow-hidden rounded-lg border-2 border-al-primary-foreground light:border-al-primary-foreground bg-gradient-to-br from-[#100f15] to-[#3b0019] text-al-foreground"
🤖 Prompt for AI Agents
In libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog.component.html
around line 2, the container uses hard-coded text-white and a dark gradient
which breaks light-theme contrast; replace those hard-coded classes with theme
tokens/variants so the border, text color and background respond to light/dark.
Specifically, swap text-white for the app's foreground text token (e.g.
text-foreground or the project's token name) and convert the gradient classes to
tokenized or theme-prefixed variants (use light:... and dark:... or token-based
from/to classes) so the existing dark gradient is preserved in dark mode while
light mode uses the appropriate tokenized text and background.

Comment on lines 10 to 14
class="bg-al-roadmap-secondary light:border-[--primary-foreground] relative z-10 m-[-2px] rounded-lg border-2 border-[#FDF5FD] px-6 py-4"
[attr.node-id]="cluster().id"
>
<div class="text-[20px]">{{ cluster().title }}</div>
<div class="text-[20px] text-[#FDF5FD]">{{ cluster().title }}</div>
</div>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix invalid Tailwind arbitrary values and hard-coded colors

  • light:border-[--primary-foreground] should be a token (or use var()).
  • light:from-[al-primary] / light:to-[al-primary] are invalid; use tokenized gradient stops.
  • Avoid hard-coded #FDF5FD; use al-primary-foreground so theme drives both modes.

These issues will result in invalid CSS and broken theming in light mode.

Apply this diff:

@@
-    <div
-      class="bg-al-roadmap-secondary  light:border-[--primary-foreground] relative z-10 m-[-2px] rounded-lg border-2 border-[#FDF5FD]  px-6 py-4"
+    <div
+      class="bg-al-roadmap-secondary relative z-10 m-[-2px] rounded-lg border-2 border-al-primary-foreground light:border-al-primary-foreground px-6 py-4"
@@
-      <div class="text-[20px] text-[#FDF5FD]">{{ cluster().title }}</div>
+      <div class="text-[20px] text-al-primary-foreground">{{ cluster().title }}</div>
@@
-    class:
-      'block bg-gradient-to-br from-[#100F15] to-[#3B0019] light:from-[al-primary] light:to-[al-primary] rounded-lg text-center border-2 light:border-[--primary-foreground] border-[#FDF5FD]',
+    class:
+      'block bg-gradient-to-br from-[#100F15] to-[#3B0019] light:from-al-primary light:to-al-primary rounded-lg text-center border-2 border-al-primary-foreground light:border-al-primary-foreground',

Note: If your Tailwind preset defines al-primary as rgb(var(--primary)) and al-primary-foreground as rgb(var(--primary-foreground)), the above will compile correctly and respect both themes.

Also applies to: 26-26

🤖 Prompt for AI Agents
In
libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-cluster/roadmap-cluster.component.ts
around lines 10-14 (and also apply same fix at line 26), replace invalid
Tailwind arbitrary values and hard-coded colors: change
light:border-[--primary-foreground] to use a CSS variable or token (e.g.
light:border-[var(--al-primary-foreground)] or the tokenized class that your
preset provides), replace any light:from-[al-primary] / light:to-[al-primary]
gradient stop usages with the tokenized gradient stop classes or var(...)
equivalents provided by your Tailwind preset, and replace hard-coded #FDF5FD
with the al-primary-foreground token (or var(--al-primary-foreground)) so
theming works in both modes.

Comment on lines +6 to +9
<div class="flex-grow border-l-[6px] border-l-[var(--primary)]"></div>
<div
class="h-0 w-0 border-l-[16px] border-r-[16px] border-t-[30px] border-l-transparent border-r-transparent border-t-[var(--primary)]"
></div>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Hide decorative elements from assistive tech

These two divs are purely presentational. Mark them as hidden to avoid screen reader noise and improve accessibility.

Apply:

-    <div class="flex-grow border-l-[6px] border-l-[var(--primary)]"></div>
+    <div aria-hidden="true" class="flex-grow border-l-[6px] border-l-[var(--primary)]"></div>
@@
-    <div
-      class="h-0 w-0 border-l-[16px] border-r-[16px] border-t-[30px] border-l-transparent border-r-transparent border-t-[var(--primary)]"
-    ></div>
+    <div
+      aria-hidden="true"
+      class="h-0 w-0 border-l-[16px] border-r-[16px] border-t-[30px] border-l-transparent border-r-transparent border-t-[var(--primary)]"
+    ></div>

If this graphic carries semantic meaning, instead use role="img" with an aria-label.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div class="flex-grow border-l-[6px] border-l-[var(--primary)]"></div>
<div
class="h-0 w-0 border-l-[16px] border-r-[16px] border-t-[30px] border-l-transparent border-r-transparent border-t-[var(--primary)]"
></div>
<div aria-hidden="true" class="flex-grow border-l-[6px] border-l-[var(--primary)]"></div>
<div
aria-hidden="true"
class="h-0 w-0 border-l-[16px] border-r-[16px] border-t-[30px] border-l-transparent border-r-transparent border-t-[var(--primary)]"
></div>
🤖 Prompt for AI Agents
In
libs/blog/roadmap/ui-roadmap/src/lib/components/vertical-connector-arrow/vertical-connector-arrow.component.ts
around lines 6 to 9, the two divs are purely decorative and should be hidden
from assistive technology; add aria-hidden="true" (or tabindex="-1" if desired)
to both divs so screen readers ignore them, and if the graphic actually conveys
meaning replace the decorative markup with role="img" plus a clear aria-label
instead of aria-hidden.

@valueadd-robot
Copy link

PR is detected, will deploy to dev environment

@valueadd-robot
Copy link

Deployed to dev environment
Branch: feature/light-mode
BFF URL: https://afa13a34-blog-bff-dev.contact-ef8.workers.dev
Deploy URL: https://e5f5715f.angular-love-client.pages.dev
Alias URL: https://feature-light-mode.angular-love-client.pages.dev

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-basic-node/roadmap-basic-node.component.ts (1)

26-33: Fix Tailwind utility typo and set explicit button type

  • Tailwind uses whitespace-nowrap, not text-nowrap.
  • Add type="button" to avoid unintended form submission when used inside forms.

Apply:

-    <button
-      class="node light:bg-al-primary-foreground text-al-primary-foreground relative w-full text-nowrap rounded-lg bg-[#fff]"
+    <button
+      type="button"
+      class="node light:bg-al-primary-foreground text-al-primary-foreground relative w-full whitespace-nowrap rounded-lg bg-[#fff]"
🧹 Nitpick comments (6)
libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-creators/roadmap-dialog-creators.component.ts (1)

12-16: Reduce duplication and harden external links (move color to UL, add rel, and track by stable id).

  • Avoid repeating the text color on each li; set it once on the UL.
  • Add rel="noopener noreferrer" to target="_blank" links to prevent reverse tabnabbing.
  • Prefer tracking by a unique/stable key (slug) instead of name.

Apply:

-      <ul class="list-disc px-6 pt-4">
-        @for (creator of creators(); track creator.name) {
-          <li class="text-al-primary-foreground py-1 underline">
-            <a [href]="'author/' + creator.slug" target="_blank">
+      <ul class="text-al-primary-foreground list-disc px-6 pt-4">
+        @for (creator of creators(); track creator.slug) {
+          <li class="py-1 underline">
+            <a [href]="'/author/' + creator.slug" target="_blank" rel="noopener noreferrer">
libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-regular-content/roadmap-dialog-regular-content.component.ts (1)

13-16: Harden external links and use a more stable trackBy.

  • Add rel="noopener noreferrer" to the anchor with target="_blank".
  • If resource.url is unique, track by it instead of name to reduce DOM churn.
-        @for (resource of resources(); track resource.name) {
+        @for (resource of resources(); track resource.url) {
           <li class="py-1 underline">
-            <a [href]="resource.url" target="_blank">
+            <a [href]="resource.url" target="_blank" rel="noopener noreferrer">
libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-header/roadmap-dialog-header.component.ts (1)

19-27: Consider setting text color for the 'angular-love' (gradient) variant as well.

Primary/secondary add text-al-primary-foreground; the 'angular-love' gradient branch doesn’t. Depending on background/gradient brightness in light-mode, the header text could have insufficient contrast.

If consistent foreground is desired, add text-al-primary-foreground to that branch too.

-      case 'angular-love':
-        return 'from-al-roadmap-secondary to-al-roadmap-accent bg-gradient-to-r';
+      case 'angular-love':
+        return 'from-al-roadmap-secondary to-al-roadmap-accent bg-gradient-to-r text-al-primary-foreground';

Please verify in the light theme that the current gradient ensures sufficient contrast without this change; if not, the above update will align all three variants.

libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-basic-node/roadmap-basic-node.component.ts (1)

27-27: Verify intent: using a “foreground” token as button background in light mode

light:bg-al-primary-foreground applies a text/foreground token as a background. If the intent was a neutral/card surface for the outer border, consider light:bg-al-card (or another surface token) instead.

Optional tweak:

-      class="node light:bg-al-primary-foreground text-al-primary-foreground relative w-full whitespace-nowrap rounded-lg bg-[#fff]"
+      class="node light:bg-al-card text-al-primary-foreground relative w-full whitespace-nowrap rounded-lg bg-[#fff]"
tailwind.preset.js (2)

53-61: Avoid redefining the built-in dark variant; rely on darkMode selector

You currently add a custom dark variant via addVariant(...) while also using darkMode. Prefer one approach. With darkMode: ['selector', '[data-theme="dark"]'], Tailwind’s built-in dark: will already target [data-theme="dark"].

Apply:

   plugins: [
     function ({ addVariant }) {
       addVariant(
         'light',
         '&:where([data-theme="light"], [data-theme="light"] *)',
       );
-      addVariant('dark', '&:where([data-theme="dark"], [data-theme="dark"] *)');
     },
   ],

1-1: Remove unused dependency import

const { themeVariants } = require('tailwindcss-theme-variants'); is not used. Drop it to keep the preset minimal.

-const { themeVariants } = require('tailwindcss-theme-variants');
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 097903d and 44ba780.

📒 Files selected for processing (10)
  • libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-additional-description/roadmap-dialog-additional-description.component.ts (1 hunks)
  • libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-creators/roadmap-dialog-creators.component.ts (1 hunks)
  • libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-description/roadmap-dialog-description.component.ts (1 hunks)
  • libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-header/roadmap-dialog-header.component.ts (2 hunks)
  • libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-regular-content/roadmap-dialog-regular-content.component.ts (1 hunks)
  • libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-subtitle/roadmap-dialog-subtitle.component.ts (1 hunks)
  • libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog.component.html (1 hunks)
  • libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-basic-node/roadmap-basic-node.component.ts (2 hunks)
  • libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-cluster/roadmap-cluster.component.ts (2 hunks)
  • tailwind.preset.js (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-description/roadmap-dialog-description.component.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog.component.html
  • libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-cluster/roadmap-cluster.component.ts
🧰 Additional context used
🧬 Code Graph Analysis (4)
libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-subtitle/roadmap-dialog-subtitle.component.ts (1)
libs/blog/shared/ui-card/src/lib/card.component.ts (2)
  • GradientCardDirective (69-74)
  • DarkCardDirective (80-85)
libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-header/roadmap-dialog-header.component.ts (2)
libs/blog/shared/ui-difficulty/src/lib/ui-difficulty.component.ts (1)
  • UiDifficultyComponent (94-105)
libs/blog/shared/ui-button/src/lib/button/button.component.ts (1)
  • ButtonComponent (53-64)
libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-basic-node/roadmap-basic-node.component.ts (2)
libs/blog/shared/ui-button/src/lib/button/button.component.ts (1)
  • ButtonComponent (53-64)
libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts (2)
  • CCAppThemeConsumer (37-49)
  • setThemeClass (38-48)
tailwind.preset.js (1)
libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts (1)
  • CCAppThemeConsumer (37-49)
🔇 Additional comments (7)
libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-creators/roadmap-dialog-creators.component.ts (1)

14-14: Theming alignment looks good.

Applying text-al-primary-foreground to the list items is consistent with the PR’s light-mode theming approach and tokens.

libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-regular-content/roadmap-dialog-regular-content.component.ts (1)

12-12: LGTM on foreground color.

Setting text-al-primary-foreground on the UL matches the updated theming strategy and avoids per-item duplication.

libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-additional-description/roadmap-dialog-additional-description.component.ts (1)

12-12: Consistent theming on container — good call.

Applying text-al-primary-foreground at the container level keeps child elements consistent across themes.

libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-subtitle/roadmap-dialog-subtitle.component.ts (1)

6-10: Subtitle and divider theming are consistent with tokens.

Using text-al-primary-foreground for the title and bg-al-primary-foreground for the divider aligns with light/dark variants and the host’s flex layout.

libs/blog/roadmap/ui-roadmap-dialog/src/lib/roadmap-dialog-header/roadmap-dialog-header.component.ts (1)

9-9: Switch to [class]="class()" is appropriate.

Property rename is internal (protected) and the template update is correct. Border using border-current ties neatly to the computed foreground color.

libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-basic-node/roadmap-basic-node.component.ts (1)

65-70: Variants look consistent; light-mode overlays align with token strategy

The added light-mode backgrounds/gradients on variants are consistent with the new tokens and theming strategy. The explicit white text for the gradient variant is reasonable.

tailwind.preset.js (1)

13-15: New theme tokens and gradients look good

  • al-primary-foreground, al-grey, and al-radial-gradient-strong additions are consistent with the data-attribute theming strategy.
  • Switching al-full-border to use --grey reads well with the new token.

Also applies to: 34-34, 39-40, 49-49

/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: ['class'],
darkMode: 'selector',
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Invalid Tailwind darkMode configuration

darkMode: 'selector' is not valid on its own. If you intend to scope the built-in dark: variant to a data-attribute, specify the selector tuple.

Apply:

-  darkMode: 'selector',
+  darkMode: ['selector', '[data-theme="dark"]'],

If you keep the custom dark variant below, consider removing it to avoid overriding/duplicating Tailwind’s built-in dark: behavior (see next comment).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
darkMode: 'selector',
darkMode: ['selector', '[data-theme="dark"]'],
🤖 Prompt for AI Agents
In tailwind.preset.js around line 5, the current darkMode: 'selector' is
invalid; replace it with a valid setting such as darkMode: ['class',
'[data-theme="dark"]'] (or simply 'class' or 'media' depending on desired
behavior) to correctly scope Tailwind’s built-in dark: variant to a selector,
and if you keep the custom dark variant defined elsewhere in this file remove
that custom variant to avoid overriding/duplicating Tailwind’s built-in dark:
behavior.

@valueadd-robot
Copy link

PR is detected, will deploy to dev environment

@valueadd-robot
Copy link

Deployed to dev environment
Branch: feature/light-mode
BFF URL: https://c2d0a27d-blog-bff-dev.contact-ef8.workers.dev
Deploy URL: https://07eed5cc.angular-love-client.pages.dev
Alias URL: https://feature-light-mode.angular-love-client.pages.dev

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
tailwind.preset.js (2)

5-5: Invalid Tailwind darkMode configuration — use the selector tuple

darkMode: 'selector' is not valid on its own. Provide the selector string to scope the built-in dark: variant.

Apply:

-  darkMode: 'selector',
+  darkMode: ['selector', '[data-theme="dark"]'],

52-60: Do not redefine dark variant — conflicts with Tailwind’s built-in dark:

You’re adding a custom dark variant while also enabling dark mode via darkMode. This will override/duplicate Tailwind’s built-in dark: behavior and can cause unexpected selector output. Keep the custom light variant (Tailwind has no built-in light) and remove the custom dark.

Apply:

   plugins: [
     function ({ addVariant }) {
       addVariant(
         'light',
         '&:where([data-theme="light"], [data-theme="light"] *)',
       );
-      addVariant('dark', '&:where([data-theme="dark"], [data-theme="dark"] *)');
     },
   ],
🧹 Nitpick comments (1)
tailwind.preset.js (1)

1-1: Remove unused tailwindcss-theme-variants import and dependency

The themeVariants import in tailwind.preset.js (line 1) isn’t referenced anywhere in the codebase, and the tailwindcss-theme-variants package remains unused. Please either remove it entirely or wire it up in your Tailwind plugins.

• tailwind.preset.js

- const { themeVariants } = require('tailwindcss-theme-variants');

• package.json

-   "tailwindcss-theme-variants": "2.0.0-beta.0",

If you plan to use it, add it to your plugins section instead of importing it without use:

plugins: [
  themeVariants({
    themes: {
      light: '[data-theme="light"]',
      // rename if you need a custom dark variant
      // themedDark: '[data-theme="dark"]',
    },
  }),
]
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 44ba780 and 102f365.

📒 Files selected for processing (2)
  • libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-basic-node/roadmap-basic-node.component.ts (2 hunks)
  • tailwind.preset.js (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • libs/blog/roadmap/ui-roadmap-node/src/lib/components/roadmap-basic-node/roadmap-basic-node.component.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
tailwind.preset.js (1)
libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts (1)
  • CCAppThemeConsumer (37-49)
🔇 Additional comments (3)
tailwind.preset.js (3)

13-14: LGTM: new token color al-primary-foreground

Consistent with CSS variable color pattern and supports alpha.


34-34: LGTM: new token color al-grey

Matches the token strategy and unifies shadow/border usage.


48-48: LGTM: box-shadow now uses --grey for full-border

This aligns the border overlay with your new grey token.

Comment on lines +52 to +60
plugins: [
function ({ addVariant }) {
addVariant(
'light',
'&:where([data-theme="light"], [data-theme="light"] *)',
);
addVariant('dark', '&:where([data-theme="dark"], [data-theme="dark"] *)');
},
],
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Theme toggle mismatch — consumer sets class, variants expect data-attribute

Your variants target [data-theme="light"|"dark"], but the app currently toggles a cc--darkmode class (see libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts). Without setting data-theme, neither your custom light: nor the selector-based dark: will activate.

Update the theme consumer (outside this file):

// libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts
class CCAppThemeConsumer {
  setThemeClass(theme: 'light' | 'dark'): void {
    const htmlElement = document.documentElement;
    htmlElement.setAttribute('data-theme', theme);
    // Optional: keep/remove legacy class during transition
    htmlElement.classList.toggle('cc--darkmode', theme === 'dark');
  }
}

Verification script to ensure Tailwind version supports selector-based dark mode (>= 3.4) and to find legacy class usage:


🏁 Script executed:

#!/bin/bash
# Tailwind version (dev or deps)
echo "tailwindcss version:"
jq -r '.devDependencies.tailwindcss // .dependencies.tailwindcss // "not found"' package.json
echo

echo "References to legacy class-based dark mode:"
rg -n -C2 'cc--darkmode|document\.documentElement\.classList\.(add|remove|toggle)\('

echo
echo "Places that set the data-theme attribute (should exist after your change):"
rg -n -C2 'setAttribute\(\s*[\'"]data-theme[\'"]\s*,'

Length of output: 1869


🏁 Script executed:

#!/bin/bash
# Search for data-theme attribute setter usage
echo "Places where data-theme attribute is set:"
rg -n "setAttribute('data-theme'" || true

Length of output: 230


Update theme consumer to set data-theme attribute

Your custom light: and dark: variants depend on the [data-theme="…"] attribute, but the current setThemeClass only toggles the cc--darkmode class. Without setting data-theme, neither variant will ever match.

Please update libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts:

  • In setThemeClass(theme: 'light' | 'dark'), add:

    const html = document.documentElement;
    html.setAttribute('data-theme', theme);
    // Optional: preserve or remove the legacy class toggle
    html.classList.toggle('cc--darkmode', theme === 'dark');
  • Remove any assumptions that cc--darkmode alone will trigger your Tailwind variants.

This change is required to activate your selector-based light:/dark: utilities.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants