-
Notifications
You must be signed in to change notification settings - Fork 671
Custom Accent support #35096
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
base: feature/26_2_new_fluent_theme_with_design_tokens
Are you sure you want to change the base?
Custom Accent support #35096
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,26 @@ | ||||||||||||||
| @supports (color: oklch(from red l c h)) { | ||||||||||||||
| :root { | ||||||||||||||
| --dx-accent-color-source: var(--dx-accent-color); | ||||||||||||||
| --dx-accent-lightness-max: 0.95; | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These three numbers are Blazor's, and they fit Blazor's palette: there the lightest step really has lightness 0.95. Our palette is different. When the design tokens moved to 262.6.0, a new, even lighter step was added on top (our step 10 is I ran the formula from each of the 11 designed palettes and compared the result with the designed steps (perceptual colour difference, where 5 is clearly visible):
The most visible case: a user who picks "the same blue" Suggestion: tune the three numbers to our palette instead of copying them. The final numbers are for design to decide; the mechanics do not change. |
||||||||||||||
| --dx-accent-lightness-min: 0.15; | ||||||||||||||
| --dx-accent-chroma-min: 0.04; | ||||||||||||||
| --dx-accent-color-10: oklch(from var(--dx-accent-color-source) calc(l + 9 * (var(--dx-accent-lightness-max) - min(l, var(--dx-accent-lightness-max))) / 9) calc(c - 9 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 9) h); | ||||||||||||||
| --dx-accent-color-20: oklch(from var(--dx-accent-color-source) calc(l + 8 * (var(--dx-accent-lightness-max) - min(l, var(--dx-accent-lightness-max))) / 9) calc(c - 8 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 9) h); | ||||||||||||||
| --dx-accent-color-30: oklch(from var(--dx-accent-color-source) calc(l + 7 * (var(--dx-accent-lightness-max) - min(l, var(--dx-accent-lightness-max))) / 9) calc(c - 7 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 9) h); | ||||||||||||||
| --dx-accent-color-40: oklch(from var(--dx-accent-color-source) calc(l + 6 * (var(--dx-accent-lightness-max) - min(l, var(--dx-accent-lightness-max))) / 9) calc(c - 6 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 9) h); | ||||||||||||||
| --dx-accent-color-50: oklch(from var(--dx-accent-color-source) calc(l + 5 * (var(--dx-accent-lightness-max) - min(l, var(--dx-accent-lightness-max))) / 9) calc(c - 5 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 9) h); | ||||||||||||||
| --dx-accent-color-60: oklch(from var(--dx-accent-color-source) calc(l + 4 * (var(--dx-accent-lightness-max) - min(l, var(--dx-accent-lightness-max))) / 9) calc(c - 4 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 9) h); | ||||||||||||||
| --dx-accent-color-70: oklch(from var(--dx-accent-color-source) calc(l + 3 * (var(--dx-accent-lightness-max) - min(l, var(--dx-accent-lightness-max))) / 9) calc(c - 3 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 9) h); | ||||||||||||||
| --dx-accent-color-80: oklch(from var(--dx-accent-color-source) calc(l + 2 * (var(--dx-accent-lightness-max) - min(l, var(--dx-accent-lightness-max))) / 9) calc(c - 2 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 9) h); | ||||||||||||||
| --dx-accent-color-90: oklch(from var(--dx-accent-color-source) calc(l + 1 * (var(--dx-accent-lightness-max) - min(l, var(--dx-accent-lightness-max))) / 9) calc(c - 1 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 9) h); | ||||||||||||||
| --dx-accent-color-100: oklch(from var(--dx-accent-color-source) l c h); | ||||||||||||||
| --dx-accent-color-110: oklch(from var(--dx-accent-color-source) calc(l - 1 * (max(l, var(--dx-accent-lightness-min)) - var(--dx-accent-lightness-min)) / 8) calc(c - 1 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 8) h); | ||||||||||||||
| --dx-accent-color-120: oklch(from var(--dx-accent-color-source) calc(l - 2 * (max(l, var(--dx-accent-lightness-min)) - var(--dx-accent-lightness-min)) / 8) calc(c - 2 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 8) h); | ||||||||||||||
| --dx-accent-color-130: oklch(from var(--dx-accent-color-source) calc(l - 3 * (max(l, var(--dx-accent-lightness-min)) - var(--dx-accent-lightness-min)) / 8) calc(c - 3 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 8) h); | ||||||||||||||
| --dx-accent-color-140: oklch(from var(--dx-accent-color-source) calc(l - 4 * (max(l, var(--dx-accent-lightness-min)) - var(--dx-accent-lightness-min)) / 8) calc(c - 4 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 8) h); | ||||||||||||||
| --dx-accent-color-150: oklch(from var(--dx-accent-color-source) calc(l - 5 * (max(l, var(--dx-accent-lightness-min)) - var(--dx-accent-lightness-min)) / 8) calc(c - 5 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 8) h); | ||||||||||||||
| --dx-accent-color-160: oklch(from var(--dx-accent-color-source) calc(l - 6 * (max(l, var(--dx-accent-lightness-min)) - var(--dx-accent-lightness-min)) / 8) calc(c - 6 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 8) h); | ||||||||||||||
| --dx-accent-color-170: oklch(from var(--dx-accent-color-source) calc(l - 7 * (max(l, var(--dx-accent-lightness-min)) - var(--dx-accent-lightness-min)) / 8) calc(c - 7 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 8) h); | ||||||||||||||
| --dx-accent-color-180: oklch(from var(--dx-accent-color-source) calc(l - 8 * (max(l, var(--dx-accent-lightness-min)) - var(--dx-accent-lightness-min)) / 8) calc(c - 8 * (max(c, var(--dx-accent-chroma-min)) - var(--dx-accent-chroma-min)) / 8) h); | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The lightest and the darkest steps come out wrong in one browser build. In Chromium 148, with
Steps 20 to 170 are exact. Chrome 149, Chrome 152 and Firefox 155 compute everything correctly, so this is a browser bug that has already been fixed upstream, but embedded browsers and WebViews on older Chromium builds still have it. What triggers it is the shape of the expression: "multiply by 8, then divide by 8" (and "by 9 / by 9" for step 10). When the multiplier equals the divisor, that browser simplifies the whole thing to The fix is free: the two edge steps are, mathematically, just a minimum and a maximum, so they can be written that way and need no arithmetic at all: --dx-accent-color-10: oklch(from var(--dx-accent-color-source) max(l, var(--dx-accent-lightness-max)) min(c, var(--dx-accent-chroma-min)) h);
--dx-accent-color-180: oklch(from var(--dx-accent-color-source) min(l, var(--dx-accent-lightness-min)) min(c, var(--dx-accent-chroma-min)) h);I checked this form in all four browsers: 0.95 / 0.04 / 0.15 everywhere. Good news: the theme itself never uses steps 10 and 180 (light mode uses 20 to 140, dark mode uses 70 to 160), so no widget renders wrong. It only matters for people who read |
||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,18 +1,18 @@ | ||
| { | ||
| "dx.fluent-next.blue.dark.compact.css": { | ||
| "calcOccurrences": 359, | ||
| "calcOccurrences": 393, | ||
| "declarationsWithDeepCalc": 5 | ||
| }, | ||
| "dx.fluent-next.blue.dark.css": { | ||
| "calcOccurrences": 359, | ||
| "calcOccurrences": 393, | ||
| "declarationsWithDeepCalc": 5 | ||
| }, | ||
| "dx.fluent-next.blue.light.compact.css": { | ||
| "calcOccurrences": 359, | ||
| "calcOccurrences": 393, | ||
| "declarationsWithDeepCalc": 5 | ||
| }, | ||
| "dx.fluent-next.blue.light.css": { | ||
| "calcOccurrences": 359, | ||
| "calcOccurrences": 393, | ||
| "declarationsWithDeepCalc": 5 | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -492,6 +492,28 @@ | |
| "crossWidgetStarImports": [], | ||
| "deadVariables": [], | ||
| "publicSurfaceUnused": [ | ||
| "--dx-accent-chroma-min", | ||
| "--dx-accent-color-10", | ||
| "--dx-accent-color-100", | ||
| "--dx-accent-color-110", | ||
| "--dx-accent-color-120", | ||
| "--dx-accent-color-130", | ||
| "--dx-accent-color-140", | ||
| "--dx-accent-color-150", | ||
| "--dx-accent-color-160", | ||
| "--dx-accent-color-170", | ||
| "--dx-accent-color-180", | ||
| "--dx-accent-color-20", | ||
| "--dx-accent-color-30", | ||
| "--dx-accent-color-40", | ||
| "--dx-accent-color-50", | ||
| "--dx-accent-color-60", | ||
| "--dx-accent-color-70", | ||
| "--dx-accent-color-80", | ||
| "--dx-accent-color-90", | ||
| "--dx-accent-color-source", | ||
| "--dx-accent-lightness-max", | ||
| "--dx-accent-lightness-min", | ||
| "--dx-button-padding-inline", | ||
| "--dx-color-shadow", | ||
| "--dx-component-height", | ||
|
|
@@ -511,8 +533,53 @@ | |
| "--dx-toolbar-height" | ||
| ], | ||
| "publicSurfaceUndeclared": [], | ||
| "publicSurfaceDifferences": [], | ||
| "publicSurfaceDifferences": [ | ||
| "--dx-accent-chroma-min: only in fluent-next", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See the note in the test itself: these 22 entries undo a check that was at zero. If the accent variables get their own category in the test, this list becomes empty again and the snapshot does not need to be regenerated. |
||
| "--dx-accent-color-10: only in fluent-next", | ||
| "--dx-accent-color-100: only in fluent-next", | ||
| "--dx-accent-color-110: only in fluent-next", | ||
| "--dx-accent-color-120: only in fluent-next", | ||
| "--dx-accent-color-130: only in fluent-next", | ||
| "--dx-accent-color-140: only in fluent-next", | ||
| "--dx-accent-color-150: only in fluent-next", | ||
| "--dx-accent-color-160: only in fluent-next", | ||
| "--dx-accent-color-170: only in fluent-next", | ||
| "--dx-accent-color-180: only in fluent-next", | ||
| "--dx-accent-color-20: only in fluent-next", | ||
| "--dx-accent-color-30: only in fluent-next", | ||
| "--dx-accent-color-40: only in fluent-next", | ||
| "--dx-accent-color-50: only in fluent-next", | ||
| "--dx-accent-color-60: only in fluent-next", | ||
| "--dx-accent-color-70: only in fluent-next", | ||
| "--dx-accent-color-80: only in fluent-next", | ||
| "--dx-accent-color-90: only in fluent-next", | ||
| "--dx-accent-color-source: only in fluent-next", | ||
| "--dx-accent-lightness-max: only in fluent-next", | ||
| "--dx-accent-lightness-min: only in fluent-next" | ||
| ], | ||
| "publicTierManualDeclarations": [ | ||
| "fluent-next/_accent-color.scss: --dx-accent-chroma-min", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-10", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-100", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-110", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-120", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-130", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-140", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-150", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-160", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-170", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-180", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-20", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-30", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-40", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-50", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-60", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-70", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-80", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-90", | ||
| "fluent-next/_accent-color.scss: --dx-accent-color-source", | ||
| "fluent-next/_accent-color.scss: --dx-accent-lightness-max", | ||
| "fluent-next/_accent-color.scss: --dx-accent-lightness-min", | ||
| "fluent-next/_colors.scss: --dx-color-border", | ||
| "fluent-next/_colors.scss: --dx-color-danger", | ||
| "fluent-next/_colors.scss: --dx-color-icon", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -323,6 +323,10 @@ const RUNTIME_CONTRACT = new Set([ | |
| '--dx-scheduler-animation-top', | ||
| ]); | ||
|
|
||
| const DECLARED_BY_APPLICATION = new Set([ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This list only excuses reading The rule exists for a reason: a These 22 names are neither old surface nor component variables. They are settings an application writes plus the formula's own parameters, so they deserve their own small category in this test, the same way the variables set by JavaScript already have one ( |
||
| '--dx-accent-color', | ||
| ]); | ||
|
|
||
| /** Every `--dx-*` read anywhere outside the theme sources, or null when the monorepo is unavailable. */ | ||
| const publicNameConsumers = (): Set<string> | null => { | ||
| const roots = [ | ||
|
|
@@ -1174,6 +1178,7 @@ test('component tier: every var(--dx-…) read in the theme resolves to a declar | |
| const declared = new Set([ | ||
| ...[...tierDeclared.keys()].map((variable) => `--dx-${variable.slice(1)}`), | ||
| ...RUNTIME_CONTRACT, | ||
| ...DECLARED_BY_APPLICATION, | ||
| ...findings.publicTierManualDeclarations.map((entry) => entry.slice(entry.indexOf(': ') + 2)), | ||
| ]); | ||
| const offenders = walk(themeRoot, '.scss').flatMap((file) => [ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,8 +13,7 @@ | |
| "targetDirectory": "./artifacts", | ||
| "excludePatterns": [ | ||
| "./artifacts/css", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change has nothing to do with the accent: |
||
| "./artifacts/npm/devextreme/package.json", | ||
| "./artifacts/npm/devextreme-dist" | ||
| "./artifacts/npm/devextreme/package.json" | ||
| ] | ||
| } | ||
| }, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check only fires when nothing at all was wrapped. If one day a token gets a description, Style Dictionary prints it as a comment after the semicolon, the pattern stops matching that one line, and 17 of 18 steps get wrapped while the check stays silent. Safer to require the exact number: 18, or however many
primarysteps the dictionary contains.