Skip to content

Fluent design tokens pipeline - #34701

Merged
Raushen merged 11 commits into
DevExpress:feature/26_2_new_fluent_theme_with_design_tokensfrom
Raushen:feature/26_2_new_fluent_theme_with_design_tokens
Aug 12, 2026
Merged

Raushen merged 11 commits into
DevExpress:feature/26_2_new_fluent_theme_with_design_tokensfrom
Raushen:feature/26_2_new_fluent_theme_with_design_tokens

Conversation

@Raushen

@Raushen Raushen commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@Raushen Raushen self-assigned this Aug 8, 2026
@Raushen
Raushen requested a review from a team as a code owner August 8, 2026 01:13
@Raushen Raushen added the 26_2 label Aug 8, 2026
@Raushen
Raushen requested a review from a team as a code owner August 8, 2026 01:13
* names, but the index also carries the version for the message and needs no generated output.
* Reusing getBridgeFiles() is what keeps the scope from drifting away from the generator.
*/
async function validateConsumedTokens() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The check reads scss/widgets/fluent-next//*.scss, but build:tokens declares only {projectRoot}/build/tokens//* and pnpm-lock.yaml as inputs. So Nx replays the cache whenever only a stylesheet changed, and the check silently does not run.

Two options:

  • add {projectRoot}/scss/widgets/fluent-next/**/* to the build:tokens inputs, or
  • move the integration half into tests/consumed-tokens.test.ts - that target already has inputs: ["{projectRoot}/**/*"] and dependsOn: ["build:tokens"], and styles.yml runs it. The pure functions are already there, so the integration case fits naturally.

Comment thread .github/renovate.json
"@devexpress/design-tokens-internal"
],
"automerge": false,
"minimumReleaseAge": null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

automerge: false is right, but minimumReleaseAge: null drops the 7-day soak from the * rule, so a PR is opened immediately on every publish of this exact-pinned internal package. That PR then waits for the designers' signal while occupying 1 of only 2 prConcurrentLimit slots, starving every other dependency update for as long as it sits.

For "update manually on a signal", dependencyDashboardApproval: true fits better: the update is visible on the dashboard, no PR until someone approves, no slot taken. minimumReleaseAge: null only makes sense paired with that.

The repo also already has an idiom for packages that must be bumped by hand — {"matchPackageNames": ["devexpress-gantt", "devexpress-diagram", "rrule", "sass-embedded", "systemjs"], "enabled": false} - worth following if no PR is wanted at all.

}

$validation-summary-margin-block-start: ds.$spacing-200 !default;
$validation-message-padding: ds.$spacing-100 !default;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This name collides semantically with $validation-message-padding-block / $validation-message-padding-inline declared above: it reads as "the message's padding on all sides", but it actually feeds the base config $validation-message-content-padding - a different element. Please rename to $validation-message-content-padding to match the base parameter.

Also: both new declarations sit after the @if $size branches, ~15 lines away from the padding-block/padding-inline pair they clash with. Moving them up into the unconditional group makes the distinction visible.

* uncounted. That under-reports rather than failing wrongly, no theme stylesheet does it today, and
* fluent-next-naming.test.ts strips comments the same way.
*/
export const stripScssComments = (content: string): string => content

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

stripComments (line 65 of this file) is identical copy of stripScssComments.
That commit created the pure module precisely so this could be shared - import { stripScssComments } from '../build/tokens/consumed-tokens'; works from here.

* valid `spacing-40` and report the stylesheet as verified.
*/
export const collectTokenReferences = (content: string): string[] => [
...stripScssComments(content).matchAll(/\bds\.\$([\w-]+)/g),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The regex only scans ds.$, so var(--dxds-…) inside an at-rule parameter (e.g. @use "../../base/x" with ($y: var(--dxds-spacing-100))) survives all three layers: stylelint can't see at-rule params, this test doesn't look for that form, and the build check validates that the name exists but not the form. Adding var(\s*--dxds- alongside ds.$ closes it.

`components/core/theme/${THEME_NAME}`,
];
/*
* Source files behind the SCSS bridge. The component tier is deliberately absent: its 601 tokens

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The count 601 is hardcoded in prose here and again in _design-system.scss. The enforced copy lives in tools/naming/registries.json (componentTokenCount: 601, checked by the naming test); these two are unenforced and will rot on the next package bump - which is the exact scenario this PR is about. You already removed 1578 from this file in the last commit; same treatment here (drop the number or say "~600").


// adduse

$map-marker-tooltip-margin: ds.$spacing-100 !default;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

$map-marker-tooltip-margin: $map-marker-tooltip-margin reads as a no-op; it only works because @use "sizes" as * happens to be above and the base config key happens to have the identical name. The same commit uses the clearer namespaced form for validation (validationSizes.$…) - @use "sizes" as mapSizes; + mapSizes.$map-marker-tooltip-margin would be consistent.

@use "../../base/validation" as baseValidation with (
$validation-summary-margin-top: ds.$spacing-200,
$validation-message-content-padding: ds.$spacing-100,
$validation-summary-margin-top: validationSizes.$validation-summary-margin-block-start,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Two blank lines left over from the removed declaration.

"declaration-block-no-redundant-longhand-properties": null,
"declaration-no-important": true,
"declaration-property-value-disallowed-list": [
{ "/.*/": ["/var\\(\\s*--dxds-/"] },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same rule, same intent as line 17, but the message drops the closing "The public --dx-* properties are unaffected." - that's the sentence that stops someone from thinking the rule bans all custom properties, so it's worth keeping in both. The override above (line 78) also carries a "comment" key while this one doesn't.

]
},
"build:npm:scss": {
"executor": "devextreme-nx-infra-plugin:scss-assemble",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[high, question should be resolve] The commit message says "Earlier tokens were included in a package accidently", but this change guarantees they're included: scss-assemble globs scss//* with no excludes, so dependsOn: build:tokens makes scss/_design-system/ always present in the published npm scss.

If the message means "inclusion used to depend on build ordering, now it's deterministic" - the diff is right, and then the decision being made is internal design tokens ship in the public devextreme package. fluent-next is marked internal (themebuilder filters it out), yet its SCSS and the bridge do get copied to artifacts/npm/devextreme/scss. Could you state that intent explicitly, and confirm it with whoever owns packaging?

(No clean/copy race here, I checked: targetDefaults.build.dependsOn: ["^build"] makes devextreme-scss:build - which starts with clean:tokens - finish before devextreme:build, and build:npm:scss is uncached, so the new dependsOn can't serve a stale output.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Will revert to resolve on the next task

@github-actions github-actions Bot added the .d.ts label Aug 11, 2026
@Raushen
Raushen force-pushed the feature/26_2_new_fluent_theme_with_design_tokens branch from 65845e1 to b6c79cb Compare August 12, 2026 10:28
@Raushen
Raushen merged commit 50cd66a into DevExpress:feature/26_2_new_fluent_theme_with_design_tokens Aug 12, 2026
123 of 126 checks passed
EugeniyKiyashko pushed a commit that referenced this pull request Aug 18, 2026
EugeniyKiyashko pushed a commit that referenced this pull request Aug 25, 2026
pharret31 pushed a commit that referenced this pull request Aug 31, 2026
EugeniyKiyashko pushed a commit that referenced this pull request Sep 3, 2026
pharret31 pushed a commit that referenced this pull request Sep 4, 2026
pharret31 pushed a commit that referenced this pull request Sep 14, 2026
pharret31 pushed a commit that referenced this pull request Sep 16, 2026
pharret31 pushed a commit that referenced this pull request Sep 18, 2026
pharret31 pushed a commit that referenced this pull request Sep 21, 2026
pharret31 pushed a commit that referenced this pull request Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants