Closes#505, partly. The stylesheet ships one file to every route and 86% of its rules match nothing on the screen being rendered; the first of the three changes that reduce that is here.
What this changes
client/src/clr.scss compiles Clarity from its own sources: it is @clr/ui/src/utils/_components.clarity.scss - the file clr-ui.min.css is built from - with the components this app never instantiates removed (wizard, timeline, combobox, the login page, stepper, breadcrumbs, badges, datalist, number-input, password, range, file-input). typography/font-metropolis is left out, which is the same CSP reason the same-origin @font-face blocks in styles.scss exist for. Adding a component back is one line and a build.
styles.scss imports that instead of @clr/ui/clr-ui.min.css, and the duplicated handsontable.min.css import (it appeared on two consecutive lines) is gone.
angular.json gains stylePreprocessorOptions.includePaths: ["node_modules"] so the @clr/ui/src/... specifiers resolve, and a {"type": "bundle", "name": "styles"} budget.
Measurements
The curated entry is the real stylesheet minus the drops, not a different Clarity: compiling a mirror of the unmodified_components.clarity.scss from source produces 627,918 bytes against the shipped clr-ui.min.css at 621,259 - the 6.6 kB difference is the base64 Metropolis font-face blocks that scripts/strip-clr-base64-fonts.mjs strips at postinstall. So the comparison below is the drops alone.
production build, styles bundle
before 1,117,811 bytes raw gzip -9 125,807
after 1,002,159 bytes raw gzip -9 111,117 (-10.3% raw, -11.7% gzip)
Angular's own report: 1.12 MB / 90.60 kB transfer -> 1.00 MB / 80.60 kB
Verified in the built CSS: clr-wizard, clr-timeline, login-wrapper, clr-breadcrumb, clr-stepper are absent; clr-datagrid, clr-tree-node, clr-modal, clr-accordion, clr-alert, clr-tooltip and the Handsontable rules are all still there (rule count 6,514 -> 6,373).
The budget was proved to bite rather than assumed: built once with maximumWarning temporarily at 900kb, which failed the way it should -
Warning: styles exceeded maximum budget. Budget 900.00 kB was not met by
102.16 kB with a total of 1.00 MB.
then restored to 1.05mb, which leaves about 48 kB of headroom over today's file.
What this does not do, and why
Handsontable's CSS (162 kB + 27 kB theme) is the other block that is not needed on every route, and it is deliberately not in this change. Moving it into the grid components' styles is not a file move: DC's own grid customisations are interleaved through styles.scss in 55 constructs, inside app-editor, app-viewer, app-viewboxes, body[cds-theme='dark'] and ::ng-deep scopes, and two of them are exact selector ties with Handsontable's own rules (.handsontable .htAutocompleteArrow, .handsontable.listbox). Once the vendor CSS is injected with the component instead of at first paint, those ties resolve the other way. Doing that safely means moving the overrides with the vendor CSS and checking the result on a rendered grid, which needs a seeded estate - a separate PR with screenshots, not a footnote in a perf one.
What could not be verified here: the rendered app. There is no seeded estate on this box, so the visual check is CI's Cypress and Lighthouse runs, and I would want a reviewer's eye on the editor before this is called done. tsc -p tsconfig.app.json --noEmit was clean and two production builds ran to completion (exit 0); the only warnings are the pre-existing template and CommonJS ones.
Closes #505, partly. The stylesheet ships one file to every route and 86% of its rules match nothing on the screen being rendered; the first of the three changes that reduce that is here.
## What this changes
- `client/src/clr.scss` compiles Clarity from its own sources: it is `@clr/ui/src/utils/_components.clarity.scss` - the file `clr-ui.min.css` is built from - with the components this app never instantiates removed (wizard, timeline, combobox, the login page, stepper, breadcrumbs, badges, datalist, number-input, password, range, file-input). `typography/font-metropolis` is left out, which is the same CSP reason the same-origin `@font-face` blocks in `styles.scss` exist for. Adding a component back is one line and a build.
- `styles.scss` imports that instead of `@clr/ui/clr-ui.min.css`, and the duplicated `handsontable.min.css` import (it appeared on two consecutive lines) is gone.
- `angular.json` gains `stylePreprocessorOptions.includePaths: ["node_modules"]` so the `@clr/ui/src/...` specifiers resolve, and a `{"type": "bundle", "name": "styles"}` budget.
## Measurements
The curated entry is the real stylesheet minus the drops, not a different Clarity: compiling a mirror of the *unmodified* `_components.clarity.scss` from source produces 627,918 bytes against the shipped `clr-ui.min.css` at 621,259 - the 6.6 kB difference is the base64 Metropolis font-face blocks that `scripts/strip-clr-base64-fonts.mjs` strips at postinstall. So the comparison below is the drops alone.
```
production build, styles bundle
before 1,117,811 bytes raw gzip -9 125,807
after 1,002,159 bytes raw gzip -9 111,117 (-10.3% raw, -11.7% gzip)
Angular's own report: 1.12 MB / 90.60 kB transfer -> 1.00 MB / 80.60 kB
```
Verified in the built CSS: `clr-wizard`, `clr-timeline`, `login-wrapper`, `clr-breadcrumb`, `clr-stepper` are absent; `clr-datagrid`, `clr-tree-node`, `clr-modal`, `clr-accordion`, `clr-alert`, `clr-tooltip` and the Handsontable rules are all still there (rule count 6,514 -> 6,373).
The budget was proved to bite rather than assumed: built once with `maximumWarning` temporarily at `900kb`, which failed the way it should -
```
Warning: styles exceeded maximum budget. Budget 900.00 kB was not met by
102.16 kB with a total of 1.00 MB.
```
then restored to `1.05mb`, which leaves about 48 kB of headroom over today's file.
## What this does not do, and why
Handsontable's CSS (162 kB + 27 kB theme) is the other block that is not needed on every route, and it is deliberately **not** in this change. Moving it into the grid components' styles is not a file move: DC's own grid customisations are interleaved through `styles.scss` in 55 constructs, inside `app-editor`, `app-viewer`, `app-viewboxes`, `body[cds-theme='dark']` and `::ng-deep` scopes, and two of them are exact selector ties with Handsontable's own rules (`.handsontable .htAutocompleteArrow`, `.handsontable.listbox`). Once the vendor CSS is injected with the component instead of at first paint, those ties resolve the other way. Doing that safely means moving the overrides with the vendor CSS and checking the result on a rendered grid, which needs a seeded estate - a separate PR with screenshots, not a footnote in a perf one.
What could not be verified here: the rendered app. There is no seeded estate on this box, so the visual check is CI's Cypress and Lighthouse runs, and I would want a reviewer's eye on the editor before this is called done. `tsc -p tsconfig.app.json --noEmit` was clean and two production builds ran to completion (exit 0); the only warnings are the pre-existing template and CommonJS ones.
styles.scss imported @clr/ui/clr-ui.min.css, which is Clarity's whole
stylesheet: 621 kB minified, of which 86% of the rules match nothing on the
route being rendered. wizard, timeline, combobox, the login page, stepper,
breadcrumbs, badges and five form widgets are never instantiated here.
src/clr.scss is Clarity's own utils/_components.clarity.scss - the entry
clr-ui.min.css is built from - with those components removed, so the build
carries only what the app uses and adding one back is a line and a build.
typography/font-metropolis is left out for the CSP reason the font-face
blocks in styles.scss exist for.
Stylesheet 1,117,811 -> 1,002,159 bytes (-10.3%), gzip -9 125,807 -> 111,117.
A bundle budget pins it at 1.05 MB so the next import is a warning rather
than a silent 100 kB.
Lowest accessibility score: 0.95 (the gate is every route at 0.95).
Failing accessibility audits
#/home/excel-maps/BASEL-CR2 - aria-required-children: Elements with an ARIA [role] that require children to contain a specific [role] are missing some or all of those required children. (div.ht-root-wrapper > div.ht-grid > div.ht-grid-content > div#ht_9c104245062ceb82)
Reviewed the full diff at 464ea307: the curated Clarity entry file, its import, and the new styles budget.
Findings:
client/src/clr.scss:92 //Badges - the badges component is dropped from the curated list, but the app still uses Clarity's badge classes: client/src/app/shared/user-nav-dropdown/header-actions.component.html:40 and :47 (class="badge badge-danger", class="badge badge-info") and client/src/app/review/approve-details/approve-details.component.html:305, 309, 313 (<span class="badge">). In @clr/ui 17.9.0, .badge and the color modifiers come only from src/emphasis/_badges.clarity.scss; the app's own rules for the class (styles.scss:3985, 4010, 4077, 4855) set visibility and position only. With the import gone the failed-request and debug counters render as plain unstyled text. Re-add @forward '@clr/ui/src/emphasis/badges.clarity'; and its properties partial, or replace the six usages.
Checked and clean: no clr-breadcrumb, clr-badge, clr-wizard, clr-timeline, clr-stepper, clr-login or clr-combobox element remains in client/src, signpost and accordion (both kept) are the two of that group that do appear, and the login sidebar restyles itself in styles.scss:2136-2245 rather than leaning on Clarity's login component. The duplicated handsontable stylesheet import removed at styles.scss:3 was a genuine duplicate and the remaining one is the right one. CI at this head: all three checks success.
1 finding above for review.
Reviewed the full diff at 464ea307: the curated Clarity entry file, its import, and the new styles budget.
Findings:
- client/src/clr.scss:92 `//Badges` - the badges component is dropped from the curated list, but the app still uses Clarity's badge classes: client/src/app/shared/user-nav-dropdown/header-actions.component.html:40 and :47 (`class="badge badge-danger"`, `class="badge badge-info"`) and client/src/app/review/approve-details/approve-details.component.html:305, 309, 313 (`<span class="badge">`). In @clr/ui 17.9.0, `.badge` and the color modifiers come only from src/emphasis/_badges.clarity.scss; the app's own rules for the class (styles.scss:3985, 4010, 4077, 4855) set visibility and position only. With the import gone the failed-request and debug counters render as plain unstyled text. Re-add `@forward '@clr/ui/src/emphasis/badges.clarity';` and its properties partial, or replace the six usages.
Checked and clean: no clr-breadcrumb, clr-badge, clr-wizard, clr-timeline, clr-stepper, clr-login or clr-combobox element remains in client/src, signpost and accordion (both kept) are the two of that group that do appear, and the login sidebar restyles itself in styles.scss:2136-2245 rather than leaning on Clarity's login component. The duplicated handsontable stylesheet import removed at styles.scss:3 was a genuine duplicate and the remaining one is the right one. CI at this head: all three checks success.
1 finding above for review.
allan
merged commit 17f8039b4f into release/7.232026-11-09 21:38:22 +00:00
allan
deleted branch perf/curate-clarity-css2026-11-09 21:38:23 +00:00
Addressed on the other branch so this PR can merge unmodified: #559, commit 1b5e469a.
I took the second option you offered - replace the usages - rather than re-adding the module, because the module then has no users at all and this PR's premise holds without exception:
.badge.badge-danger -> .dc-badge.dc-badge--danger header-actions.component.html (2)
.badge -> .dc-badge approve-details.component.html (6, not 3 -
the table has a second block at 531/535/539)
styles.scss now owns .dc-badge and its two modifiers. The values are not invented - they are Clarity 17.9.0's rendered values, read from the running app by injecting an element with the old classes and asking for its computed style:
Measured again after the swap on the deployed build, and the two columns match exactly. Unit suite 1403 passing.
One thing your review implies but does not say, worth noting for the follow-up on #505: styles.scss still carries .badge rules at 3983, 4008, 4075 and .badge-warning at 4853 that now match nothing - dead once this lands, and they can go with the next slice.
Addressed on the other branch so this PR can merge unmodified: **#559**, commit `1b5e469a`.
I took the second option you offered - replace the usages - rather than re-adding the module, because the module then has no users at all and this PR's premise holds without exception:
```
.badge.badge-danger -> .dc-badge.dc-badge--danger header-actions.component.html (2)
.badge -> .dc-badge approve-details.component.html (6, not 3 -
the table has a second block at 531/535/539)
```
`styles.scss` now owns `.dc-badge` and its two modifiers. The values are not invented - they are Clarity 17.9.0's rendered values, read from the running app by injecting an element with the old classes and asking for its computed style:
```
old .badge new .dc-badge
background rgb(79,97,105) rgb(79,97,105)
.badge-danger rgb(224,34,0) rgb(224,34,0)
.badge-info rgb(0,121,173) rgb(0,121,173)
height / min-width 16px / 16px 16px / 16px
padding 2px 4px 2px 4px
border-radius 8px 8px
font-size / weight 10px / 500 10px / 500
letter-spacing 0.5px 0.5px
```
Measured again after the swap on the deployed build, and the two columns match exactly. Unit suite 1403 passing.
One thing your review implies but does not say, worth noting for the follow-up on #505: `styles.scss` still carries `.badge` rules at 3983, 4008, 4075 and `.badge-warning` at 4853 that now match nothing - dead once this lands, and they can go with the next slice.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #505, partly. The stylesheet ships one file to every route and 86% of its rules match nothing on the screen being rendered; the first of the three changes that reduce that is here.
What this changes
client/src/clr.scsscompiles Clarity from its own sources: it is@clr/ui/src/utils/_components.clarity.scss- the fileclr-ui.min.cssis built from - with the components this app never instantiates removed (wizard, timeline, combobox, the login page, stepper, breadcrumbs, badges, datalist, number-input, password, range, file-input).typography/font-metropolisis left out, which is the same CSP reason the same-origin@font-faceblocks instyles.scssexist for. Adding a component back is one line and a build.styles.scssimports that instead of@clr/ui/clr-ui.min.css, and the duplicatedhandsontable.min.cssimport (it appeared on two consecutive lines) is gone.angular.jsongainsstylePreprocessorOptions.includePaths: ["node_modules"]so the@clr/ui/src/...specifiers resolve, and a{"type": "bundle", "name": "styles"}budget.Measurements
The curated entry is the real stylesheet minus the drops, not a different Clarity: compiling a mirror of the unmodified
_components.clarity.scssfrom source produces 627,918 bytes against the shippedclr-ui.min.cssat 621,259 - the 6.6 kB difference is the base64 Metropolis font-face blocks thatscripts/strip-clr-base64-fonts.mjsstrips at postinstall. So the comparison below is the drops alone.Verified in the built CSS:
clr-wizard,clr-timeline,login-wrapper,clr-breadcrumb,clr-stepperare absent;clr-datagrid,clr-tree-node,clr-modal,clr-accordion,clr-alert,clr-tooltipand the Handsontable rules are all still there (rule count 6,514 -> 6,373).The budget was proved to bite rather than assumed: built once with
maximumWarningtemporarily at900kb, which failed the way it should -then restored to
1.05mb, which leaves about 48 kB of headroom over today's file.What this does not do, and why
Handsontable's CSS (162 kB + 27 kB theme) is the other block that is not needed on every route, and it is deliberately not in this change. Moving it into the grid components' styles is not a file move: DC's own grid customisations are interleaved through
styles.scssin 55 constructs, insideapp-editor,app-viewer,app-viewboxes,body[cds-theme='dark']and::ng-deepscopes, and two of them are exact selector ties with Handsontable's own rules (.handsontable .htAutocompleteArrow,.handsontable.listbox). Once the vendor CSS is injected with the component instead of at first paint, those ties resolve the other way. Doing that safely means moving the overrides with the vendor CSS and checking the result on a rendered grid, which needs a seeded estate - a separate PR with screenshots, not a footnote in a perf one.What could not be verified here: the rendered app. There is no seeded estate on this box, so the visual check is CI's Cypress and Lighthouse runs, and I would want a reviewer's eye on the editor before this is called done.
tsc -p tsconfig.app.json --noEmitwas clean and two production builds ran to completion (exit 0); the only warnings are the pre-existing template and CommonJS ones.Client unit coverage
Lowest covered files (40+ lines, 23 measured):
src/app/shared/viewboxes/viewboxes.component.tssrc/app/deploy/sections/automatic/automatic.component.tssrc/app/services/va-messaging.service.tssrc/app/services/sas-store.service.tssrc/app/shared/hot-export/hot-export.util.tssrc/app/shared/spreadsheet-util/spreadsheet-util.tssrc/app/services/app.service.tssrc/app/services/spreadsheet.service.tssrc/app/shared/dc-validator/dc-validator.tssrc/app/deploy/sections/sasjs-configurator/sasjs-configurator.component.tssrc/app/query/query.component.tssrc/app/deploy/sections/dc-location/dc-location.component.tsRun
npm run coverageinclientfor the full html report; this is a map of where the logic is unguarded, not a gate.Run: https://git.datacontroller.io/dc/dc/actions/runs/3643
Lighthouse
#/home/tables#/editor/DC996664.MPE_X_TEST#/view/data#/view/data/DC996664#/view/data/DC996664.MPE_X_TEST#/view/usernav/groups#/view/usernav/groups/1#/view/usernav/users/1#/home/excel-maps#/home/excel-maps/BASEL-CR2#/home/multi-load#/review/submitted#/review/approve#/review/history#/stage/DC20221006T142649516_059582_7169#/review/submitted/DC20221006T142649516_059582_7169#/systemLowest accessibility score: 0.95 (the gate is every route at 0.95).
Failing accessibility audits
#/home/excel-maps/BASEL-CR2-aria-required-children: Elements with an ARIA[role]that require children to contain a specific[role]are missing some or all of those required children. (div.ht-root-wrapper > div.ht-grid > div.ht-grid-content > div#ht_9c104245062ceb82)Run: https://git.datacontroller.io/dc/dc/actions/runs/3643
Reviewed the full diff at
464ea307: the curated Clarity entry file, its import, and the new styles budget.Findings:
//Badges- the badges component is dropped from the curated list, but the app still uses Clarity's badge classes: client/src/app/shared/user-nav-dropdown/header-actions.component.html:40 and :47 (class="badge badge-danger",class="badge badge-info") and client/src/app/review/approve-details/approve-details.component.html:305, 309, 313 (<span class="badge">). In @clr/ui 17.9.0,.badgeand the color modifiers come only from src/emphasis/_badges.clarity.scss; the app's own rules for the class (styles.scss:3985, 4010, 4077, 4855) set visibility and position only. With the import gone the failed-request and debug counters render as plain unstyled text. Re-add@forward '@clr/ui/src/emphasis/badges.clarity';and its properties partial, or replace the six usages.Checked and clean: no clr-breadcrumb, clr-badge, clr-wizard, clr-timeline, clr-stepper, clr-login or clr-combobox element remains in client/src, signpost and accordion (both kept) are the two of that group that do appear, and the login sidebar restyles itself in styles.scss:2136-2245 rather than leaning on Clarity's login component. The duplicated handsontable stylesheet import removed at styles.scss:3 was a genuine duplicate and the remaining one is the right one. CI at this head: all three checks success.
1 finding above for review.
Addressed on the other branch so this PR can merge unmodified: #559, commit
1b5e469a.I took the second option you offered - replace the usages - rather than re-adding the module, because the module then has no users at all and this PR's premise holds without exception:
styles.scssnow owns.dc-badgeand its two modifiers. The values are not invented - they are Clarity 17.9.0's rendered values, read from the running app by injecting an element with the old classes and asking for its computed style:Measured again after the swap on the deployed build, and the two columns match exactly. Unit suite 1403 passing.
One thing your review implies but does not say, worth noting for the follow-up on #505:
styles.scssstill carries.badgerules at 3983, 4008, 4075 and.badge-warningat 4853 that now match nothing - dead once this lands, and they can go with the next slice.