fix: Wave 3 — Sass deprecations, deep combinator, and template fixes#428
fix: Wave 3 — Sass deprecations, deep combinator, and template fixes#428tobydrinkall wants to merge 2 commits into
Conversation
- Replace @import with @use/@forward across all SCSS files - Replace / division operator with math.div() in error-message and themes - Replace darken() with color.adjust() in _themes.scss - Replace deprecated >>> deep combinator with ::ng-deep - Add @use 'sass:math' and @use 'sass:color' where needed Co-Authored-By: Toby Drinkall <toby.drinkall@cognition.ai>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
| @use "../../shared/scss/theme_variables" as *; | ||
|
|
||
| :host >>> { | ||
| ::ng-deep { |
There was a problem hiding this comment.
🔴 Comment link styles leak globally to all links in the application
Deep style rules for links are applied without host scoping (::ng-deep at src/app/item-details/comment/comment.component.scss:4) instead of being scoped to the component's host, so all <a> tags across the entire application become bold with no text-decoration.
Impact: Every link in the app gets overridden with bold weight and no underline, breaking the intended styling of other components.
Mechanism: :host scoping removed during deep combinator migration
The original code was :host >>> { a { ... } }. In Angular's emulated view encapsulation, :host >>> (or equivalently :host ::ng-deep) compiles to [_nghost-xxx] selector, meaning the deep styles only apply to descendants of this component's host element. This was intentional — the component uses [innerHTML]="comment.content" (src/app/item-details/comment/comment.component.html:9) to render user-generated HTML that contains <a> tags which don't receive Angular's encapsulation attributes.
The new code ::ng-deep { a { ... } } without :host compiles to just a { ... } globally (no scoping attribute is added). This means the bold/no-decoration styles leak to every link in the application.
The correct migration is :host ::ng-deep { a { ... } } which preserves the original scoping behavior.
| ::ng-deep { | |
| :host ::ng-deep { |
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Fixed — added :host prefix so styles remain scoped to the component's host element: :host ::ng-deep {.
| @use "../shared/scss/theme_variables" as *; | ||
|
|
||
| :host >>> pre { | ||
| ::ng-deep pre { |
There was a problem hiding this comment.
🟡 User component's pre-wrap style leaks globally to all pre elements
The deep style rule for <pre> elements is applied without host scoping (::ng-deep pre at src/app/user/user.component.scss:4) instead of being scoped to the component's host, so all <pre> tags across the entire application get the white-space: pre-wrap style.
Impact: All <pre> elements in the app are forced to pre-wrap, which may break formatting in other components that rely on default <pre> behavior.
Mechanism: :host scoping removed during deep combinator migration
The original code was :host >>> pre { white-space: pre-wrap; }. In Angular's emulated view encapsulation, :host >>> compiles to [_nghost-xxx] pre, scoping the style to <pre> elements that are descendants of this component's host. The component uses [innerHTML]="user.about" (src/app/user/user.component.html:17) which may contain <pre> tags that don't receive Angular's encapsulation attributes.
The new code ::ng-deep pre { ... } without :host compiles to just pre { ... } globally. The correct migration is :host ::ng-deep pre { ... }.
| ::ng-deep pre { | |
| :host ::ng-deep pre { |
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Fixed — added :host prefix: :host ::ng-deep pre {.
| $theme-amoledblack-text-color, | ||
| $theme-amoledblack-text-color, | ||
| darken($theme-amoledblack-text-color, 33%), | ||
| color.adjust($theme-amoledblack-text-color, $lightness: -33%), |
There was a problem hiding this comment.
📝 Info: darken() to color.adjust() conversion is semantically equivalent
The conversion from darken($theme-amoledblack-text-color, 33%) to color.adjust($theme-amoledblack-text-color, $lightness: -33%) at src/app/shared/scss/_themes.scss:235 is correct. Sass's darken($color, $amount) is defined as equivalent to color.adjust($color, $lightness: -$amount) — both subtract the given percentage points from the HSL lightness value. The input color $theme-amoledblack-text-color is rgba(255, 255, 255, 0.75) (defined at src/app/shared/scss/_theme_variables.scss:35), which has lightness 100%, so subtracting 33 percentage points yields lightness 67% — identical behavior to the original.
Was this helpful? React with 👍 or 👎 to provide feedback.
| ::ng-deep { | ||
| a { | ||
| font-weight: bold; | ||
| text-decoration: none; |
There was a problem hiding this comment.
📝 Info: ::ng-deep is itself deprecated and will eventually be removed
While this PR correctly migrates away from the :host >>> syntax (which was removed in newer Angular versions), the replacement ::ng-deep is also deprecated by Angular. The Angular team has not yet provided a full replacement, but the deprecation means this code will need another migration in the future. For now, ::ng-deep is the only available mechanism for piercing view encapsulation to style dynamically-inserted innerHTML content (as used in src/app/item-details/comment/comment.component.html:9 and src/app/user/user.component.html:17). This is acceptable as a transitional solution.
(Refers to lines 4-12)
Was this helpful? React with 👍 or 👎 to provide feedback.
| @@ -1,4 +1,4 @@ | |||
| @import "./app/shared/scss/themes"; | |||
| @use "./app/shared/scss/themes"; | |||
There was a problem hiding this comment.
📝 *Info: styles.scss uses @use without 'as ' correctly for side-effect-only import
The @use "./app/shared/scss/themes" at src/styles.scss:1 intentionally omits as * because this file doesn't need to access any variables or mixins from the themes partial — it only needs the CSS output generated by the @include theme(...) calls within _themes.scss. The default namespaced import (accessible as themes.$var if needed) is fine here since no members are referenced. This differs from the component SCSS files which use as * to access $mobile-only, $laptop-only, etc. without a namespace prefix.
Was this helpful? React with 👍 or 👎 to provide feedback.
Co-Authored-By: Toby Drinkall <toby.drinkall@cognition.ai>
Summary
Resolves Sass deprecations and CSS deep combinator issues that would become errors in Dart Sass 2.0, as part of the Angular 9→20 migration.
Sass
@import→@use/@forwardacross all 13 SCSS files:/division →math.div()inerror-message.component.scssand_themes.scss:darken()→color.adjust()in_themes.scss::host >>>→:host ::ng-deepincomment.component.scssanduser.component.scss::hostprefix preserved to keep styles scoped to the component and prevent global leaks.No template or component API breaking changes found — all components already use
standalone: false, no@ViewChild/@ContentChildusage, and NgModule patterns are compatible with Angular 20. Build passes cleanly withnpx ng build.Link to Devin session: https://app.devin.ai/sessions/fb28a14a2b814b00944621984df964be
Requested by: @tobydrinkall
Devin Review