Skip to content

feat(palette): desaturate the cube faces and add NoDataIcon - #1334

Merged
tenphi merged 2 commits into
mainfrom
feat/isometric-cube-faces
Aug 20, 2026
Merged

feat(palette): desaturate the cube faces and add NoDataIcon#1334
tenphi merged 2 commits into
mainfrom
feat/isometric-cube-faces

Conversation

@tenphi

@tenphi tenphi commented Aug 20, 2026

Copy link
Copy Markdown
Member

LoadingAnimation is retuned to sit next to the current monochrome CubeLogo, and the empty-crate illustration cubejs-enterprise has been carrying locally ships as NoDataIcon, drawn from the same three tokens.

The faces are near-neutral now

loading-face-1..3 took a fraction of the brand seed saturation (0.3 / 0.62 / 0.66), which put the shadowed face at chroma 0.0676 — eight times border — so a spinner rendered as a purple gradient beside a logo drawn in currentColor. They now take baseChroma(0.2), the same normalised share of the surface saturation the neutral chrome takes (border, placeholder, the text ramp), landing at 0.0059 / 0.0161 / 0.0248. The brand hue still carries, as a tint rather than as a color, and still follows a re-seeded palette.

Contrast, not tone, is the spec

A relative tone delta is uniform on the OKHST scale, but the dark scheme resolves it inside the darkTone window, which compressed the ramp to ~75% of its light span. Measured against surface:

face-1 face-2 face-3
light, before 1.063 1.320 1.915
dark, before 1.053 1.264 1.735
light, after 1.201 1.653 2.409
dark, after 1.212 1.666 2.424

Glaze has no per-color darkTone, so the intent moves into a WCAG floor against surface and each scheme solves for it. The authored tone: '-2' is deliberately short of every floor, so all three faces are pinned by the ratio rather than by a delta that means something different in each scheme — light and dark now agree to within 1%, and the whole ramp is roughly a third stronger than it was (Oklab ΔL 0.271 in light, 0.231 in dark, against 0.204 / 0.154).

WCAG rather than APCA, against the grain of the accent tokens: APCA's low-contrast clamp scores every step of a ramp this subtle as Lc 0, so it cannot express the difference between these three faces at all. Polarity-blindness — the reason APCA wins for text — costs nothing for a decorative fill whose only job is to separate from the page.

High contrast used to be identical to the normal tier here, because an unconstrained tone delta had nothing to escalate. The [1.35, 2.1, 3.2] HC entries roughly double each step's distance from the page.

NoDataIcon

The isometric open crate used for empty tables and empty lists, moved off cubejs-enterprise's local copy — which hard-coded #e5e5ec / #b4b4c5 / #69697c and re-derived a dark variant in JS on every scheme change — and onto the shared tokens.

It ships as an illustration component under src/components/other/ alongside CubeLogo, not as a member of the icon set, because it is not an icon in the two ways that matter: it is a three-tone drawing rather than a currentColor glyph (so it ignores color — flattening the faces to one tone loses the box), and it is drawn full-bleed rather than inset in a 24×24 grid (so it belongs at size="8x" and up, not inline with text). It is still built on Icon, so sizing and style props behave exactly as they do for one. Own stories and docs page under Other/NoDataIcon; the icons barrel and the icons story are untouched.

<NoDataIcon /> is a drop-in for Cloud's @/icons/NoData, so that file and its adaptiveColorResolved plumbing can go.

Verified

pnpm probe:browser render --screenshot in all three schemes — the animation and the crate side by side, reading with the same weight in each:

  • light — top faces near the page, shadowed side clearly separated
  • dark — the ramp inverts (raised = lighter, as it always has here) but now holds its separation instead of going flat
  • high contrast — visibly stronger than the normal tier, which it previously matched exactly

Two new tests in palette.test.ts pin the property rather than only the colors: each face holds its floor (and does not overshoot it by more than 2%) in all four scheme variants, and no face is more tinted than #disabled, the most tinted of the greys. So a regression reads as "dark went flat again" instead of as three changed oklch strings.

pnpm test 1990 passed · pnpm size 499.77 kB / 505 kB · tsc --noEmit clean for the touched files.

Follow-up outside this PR

Token names stay loading-face-* so Cloud's theme color map keeps resolving. That map (packages/console-ui/src/modules/app-theme/engine/default-color-map.ts) mirrors the recipe by hand, including the old tone: '-2' / '-9' / '-21' and saturation: 0.3 / 0.62 / 0.66 entries — it needs the same edit, or a themed Cloud will keep emitting the old purple ramp.

🤖 Generated with Claude Code


Note

Cursor Bugbot is generating a summary for commit cc9f7ea. Configure here.

The three isometric cube-face tokens took a fraction of the brand seed
saturation, putting the shadowed face at eight times `border`'s chroma —
a purple gradient beside a monochrome `CubeLogo`. They now take the same
normalised share of the surface saturation the neutral chrome takes.

Their position is stated as a WCAG floor against `surface` instead of a
tone delta: the dark scheme resolved a delta inside the `darkTone` window
and flattened the ramp to ~75% of its light span, and Glaze has no
per-color `darkTone`. Light and dark now agree to within 1%, and high
contrast escalates instead of matching the normal tier.

`NoDataIcon` — the empty isometric crate Cube Cloud carried locally with
hard-coded hexes and a JS-derived dark variant — ships here drawn from
the same three tokens.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Aug 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 8d32692

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@cube-dev/ui-kit Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Aug 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cube-ui-kit Ready Ready Preview Aug 20, 2026 9:57am

Request Review

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

📦 NPM canary release

Deployed canary version 0.0.0-canary-795e47c.

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

🏋️ Size limit report

Name Size Passed?
All 491.96 KB (+0.06% 🔺) Yes 🎉
Tree shaking (just a Button) 120.43 KB (0% 🟰) Yes 🎉

Compared against main at cd07258run 32285841581, 2026-08-19T18:10:32Z.

To see which modules changed, download the size-limit-statoscope-report artifact from this run and open report.html.

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

🧪 Storybook is successfully deployed!

It is not an icon in the two ways that matter: it is a three-tone
drawing rather than a `currentColor` glyph, and it is drawn full-bleed
rather than inset in a 24x24 grid. So it moves out of `src/icons/` and
in beside `CubeLogo` — the existing precedent for `Icon`-based artwork
that is not part of the set — with its own stories and docs page. The
icons barrel and the icons story go back to what they were.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tenphi
tenphi merged commit ffd1c7b into main Aug 20, 2026
16 checks passed
@tenphi
tenphi deleted the feat/isometric-cube-faces branch August 20, 2026 10:14
@tenphi tenphi mentioned this pull request Aug 20, 2026
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