Skip to content

feat(ui): support explicit dagster/ui_color tags for asset backgrounds#33670

Open
vidiyala99 wants to merge 2 commits intodagster-io:masterfrom
vidiyala99:feature/user-defined-asset-colors-33663
Open

feat(ui): support explicit dagster/ui_color tags for asset backgrounds#33670
vidiyala99 wants to merge 2 commits intodagster-io:masterfrom
vidiyala99:feature/user-defined-asset-colors-33663

Conversation

@vidiyala99
Copy link
Copy Markdown

Summary

Test Plan

  • Verified yarn run ts locally.
  • Hardened component rendering with Typescript strict null-safety checks.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 25, 2026

Greptile Summary

This PR adds support for a new dagster/ui_color asset tag that lets users customize the background color of asset nodes in the DAG view. When the tag is present, getCustomBackgroundForAsset maps the tag value to a predefined Colors token (red, yellow, green, blue, olive, cyan, lime, gray) and passes it as a $customBackground prop to AssetNodeBox.

The implementation is clean and type-safe, correctly using existing Dagster Colors tokens for dark/light mode compatibility.

Gaps and suggestions:

  • Minimal views not updated: AssetNodeMinimalWithHealth and AssetNodeMinimalWithoutHealth (the zoomed-out representations) do not call getCustomBackgroundForAsset, so the custom color disappears when the DAG is zoomed out. If this is intentional (to avoid overriding status-based coloring), it should be documented.
  • Header background unchanged: AssetName (the name header inside AssetNodeBox) has its own hardcoded background that won't reflect $customBackground, causing the custom tint to only appear on the body rows below the header.
  • Dual tag key support undocumented: The function accepts both dagster/ui_color and dagster/ui/color without a comment explaining the intent; the PR description only mentions dagster/ui_color.

Confidence Score: 4/5

  • Safe to merge with minor gaps in coverage and documentation that should be addressed in a follow-up.
  • The change is small, type-safe, and additive — it can't break existing behavior. It correctly uses established Colors tokens for theme compatibility. The main gaps (minimal views not updated, name header color unchanged, undocumented dual tag key support) are non-critical P2 suggestions that don't affect correctness or cause runtime errors, but may leave users with a confusing partial-coloring experience when the DAG is zoomed out.
  • js_modules/ui-core/src/asset-graph/AssetNode.tsx — review coverage of minimal view components and name-header background

Important Files Changed

Filename Overview
js_modules/ui-core/src/asset-graph/AssetNode.tsx Adds getCustomBackgroundForAsset helper and $customBackground styled-component prop to AssetNodeBox to support dagster/ui_color tag-driven background colors. The feature is well-scoped and uses existing Colors tokens correctly, but has coverage gaps: the minimal (zoomed-out) views are not updated, the name-header row keeps its own background, and two tag key variants are accepted without documentation.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[AssetNodeFragment.tags] --> B{Find dagster/ui_color\nor dagster/ui/color tag}
    B -- Not found --> C[return undefined]
    B -- Found --> D{tag value\nlowercase}
    D -- red --> E1[Colors.backgroundRed]
    D -- yellow --> E2[Colors.backgroundYellow]
    D -- green --> E3[Colors.backgroundGreen]
    D -- blue --> E4[Colors.backgroundBlue]
    D -- olive --> E5[Colors.backgroundOlive]
    D -- cyan --> E6[Colors.backgroundCyan]
    D -- lime --> E7[Colors.backgroundLime]
    D -- gray --> E8[Colors.backgroundGray]
    D -- other --> C
    E1 & E2 & E3 & E4 & E5 & E6 & E7 & E8 --> F[$customBackground prop]
    C --> G[Colors.backgroundDefault fallback]
    F --> H[AssetNodeBox background CSS]
    G --> H
    H -.->|NOT applied| I[AssetNodeMinimalWithHealth\nAssetNodeMinimalWithoutHealth\nAssetName header]
Loading

Comments Outside Diff (1)

  1. js_modules/ui-core/src/asset-graph/AssetNode.tsx, line 586-609 (link)

    P2 Custom background not applied to minimal (zoomed-out) views

    The dagster/ui_color tag is only respected in the full AssetNodeBox view. The AssetNodeMinimalWithHealth and AssetNodeMinimalWithoutHealth components (used when the DAG is zoomed out) still derive their background from health/status data only. A user who sets a dagster/ui_color tag will see the custom color only when zoomed in, creating an inconsistent experience.

    If this is intentional (e.g., to avoid conflicting with status-based coloring in the minimal view), it's worth noting this limitation in a comment or in the PR description so future contributors know it's a deliberate choice.

    Consider applying getCustomBackgroundForAsset in both minimal-view components when present, or at least document why it's excluded.

Reviews (1): Last reviewed commit: "feat(ui): support explicit dagster/ui_co..." | Re-trigger Greptile

Comment on lines +46 to +49
tags?: {key: string; value: string}[],
): string | undefined => {
const uiColorTag = tags?.find(
(t) => t.key === 'dagster/ui_color' || t.key === 'dagster/ui/color',
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.

P2 Accepting two tag key formats without documentation

The function silently accepts both dagster/ui_color (underscore) and dagster/ui/color (slash). These are semantically distinct tag keys — dagster/ui_color is in the dagster namespace with key ui_color, while dagster/ui/color would be interpreted as being under the dagster/ui namespace. The PR description only mentions dagster/ui_color.

Supporting both quietly means users may unknowingly set either form and have it work, leading to inconsistent tag usage across codebases. If dagster/ui/color is intentional (e.g., as an alias for backward compat), consider documenting this in a comment.

Suggested change
tags?: {key: string; value: string}[],
): string | undefined => {
const uiColorTag = tags?.find(
(t) => t.key === 'dagster/ui_color' || t.key === 'dagster/ui/color',
const uiColorTag = tags?.find(
(t) => t.key === 'dagster/ui_color',
);

Or if the alias is intentional, add a clarifying comment:

Suggested change
tags?: {key: string; value: string}[],
): string | undefined => {
const uiColorTag = tags?.find(
(t) => t.key === 'dagster/ui_color' || t.key === 'dagster/ui/color',
// Accept both 'dagster/ui_color' and 'dagster/ui/color' as aliases
const uiColorTag = tags?.find(
(t) => t.key === 'dagster/ui_color' || t.key === 'dagster/ui/color',
);

Comment on lines 743 to +746
}`};
${(p) => p.$selected && `outline: 2px solid ${Colors.lineageNodeBorderSelected()}`};

background: ${Colors.backgroundDefault()};
background: ${(p) => p.$customBackground || Colors.backgroundDefault()};
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.

P2 Custom background visible only in body rows, not the name header

AssetNodeBox is the outer container, but AssetName (the header that displays the asset name) has its own hardcoded background property — Colors.lineageNodeBackground() or Colors.backgroundLight(). As a result, the $customBackground is only visible in the content rows below the header, while the name header always remains the default color. This may produce a visually inconsistent appearance (e.g., a red body with a default-color header).

If the intent is to tint the entire node, the AssetName background should also be updated. If tinting only the body is intentional, a comment here explaining the behavior would be helpful.

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.

1 participant