Color never works alone
Every role color sits beside its name, and status hues are kept off data, so the page reads in grayscale and for colorblind users.
ClassLink · Frost · Dashboard test set
Three views (Logins, Unique Users, Peak Day) restyled in Frost v.03: role colors, people-and-bars charts, and motion that plays once when a component is in view. Reskin only; the same data as the shipping page.
01 · Purpose
A test set for a modern data-visualization approach in Analytics+. Open the prototype and use the KPI cards to switch views; this page lists the color, component, type, interaction and motion rules behind it.
02 · Rules
Approved means it comes from an approved Frost source. Proposal means new in this test set and open for review.
| Part | Rule | Token | Status |
|---|---|---|---|
| Role color | One hue per role, darker means more. Same color for the same role on every chart. | --role-students / teachers / parents / admins | Proposal |
| Role label | The role is always named in text beside its color. Color is never the only cue. | chip · legend · direct label | Approved |
| Measure color | Counts per day, month or hour use the brand blue ramp. A split measure uses two steps of it. | --role-all-s1…s5 | Approved |
| Emphasis | Peak month or hour takes the darkest step; the rest stay light. | #0A4D7F vs #A9CDEE | Proposal |
| Status colors | Green and pink are reserved for status and never used for a role or a series. | Frost badge inks | Approved |
| Chart forms | No donuts, pies or rings. People field, tally ticks, columns, small multiples instead. | n/a | Proposal |
| Type | Frost v.03 Inter roles only. One hero number per view; everything else steps down. | hero-num 48/800 · metric-secondary 28/700 | Approved |
| Spacing | Every card header is 68px (title 25px from the top edge) with 30px under the last element. | 68 · 25 · 30 px | Proposal |
| Controls | Lucide icons at 1.5px non-scaling stroke; Frost date pickers and icon buttons. | Frost controls layer | Approved |
| Hover and focus | Hovered mark darkens, neighbours quiet down, tooltip names it. Keyboard focus does the same. | tooltip · role highlight | Proposal |
| Motion | Every component plays once when fully in view. 0.4 to 1.2 seconds, one easing, staggered. | cubic-bezier(.2,.7,.2,1) | Proposal |
| Reduced motion | All motion off; every component shows its final state. | prefers-reduced-motion | Approved |
03 · Concepts
Four ideas hold the set together. They draw on Tufte's Envisioning Information: small multiples, direct labels and data-ink over decoration.
Every role color sits beside its name, and status hues are kept off data, so the page reads in grayscale and for colorblind users.
Only the Logins KPI is large. Role percentages, minutes and counts step down to 28/700 so the eye lands once.
Nothing animates unseen, and nothing repeats while you scroll. One easing and short durations keep it supple.
Glyphs and columns can be counted and compared; donut slices cannot.
04 · Watch for
Parents indigo is a proposal. Any fourth role hue fails a separation check, so Parents leans on text labels and icons as well as color.
Teachers and Admins colors differ from the legacy page: gold moves from Teachers to Admins.
Data is mock, read from screenshots. Logins by Day and Per Hour figures follow the legacy page and do not match the 670,219 KPI.
Light theme only. Date pickers and download are prototype stand-ins, sidebar items are inert, and the sidebar icons use an internal-only licensed font subset.
05 · Compare
06 · Implementation
/* roles (hue = role, darker = more) */ --role-students:#018484; /* teal, mark = step 4 */ --role-teachers:#7257C2; /* violet, mark = step 5 */ --role-parents:#2E2E9E; /* indigo, PROPOSAL */ --role-admins:#966A02; /* gold, mark = step 4 */ /* measures: brand blue ramp (All roles) */ --measure-s1:#DCEBF8; --measure-s2:#A9CDEE; --measure-s3:#6FAAD9; --measure-s4:#2F78B3; --measure-s5:#0A4D7F; /* School Hours = s4, Non-School = s2, peak = s5 */
/* hidden start state only while motion is allowed */
.ls-anim .bars:not(.in) path{transform:scaleY(0)}
.ls-anim .bars.in path{animation:colIn .5s cubic-bezier(.2,.7,.2,1) backwards;
animation-delay:calc(var(--i) * 45ms)}
/* play once, when the whole card is on screen (below the sticky top bar) */
new IntersectionObserver(cb, {threshold:[0,.05,…,1], rootMargin:'-<topbar>px 0 0 0'})07 · Acceptance
Checks an implementer can run, each pass or fail.
08 · Feedback
Short answers are fine. Comment by view (Logins, Unique Users, Peak Day) and they will go into the next pass.
It replaces the Total Logins by Role donut and the Unique Users by Role bars with a 1% glyph field.
Decision: Pending
It clears the separation checks but sits between brand blue and Teachers violet. Alternatives: azure, ruby.
Decision: Pending
Alternative: animate only the main component on each view and keep the rest still.
Decision: Pending
Type, spacing, icons, pickers, tooltips. Comment by view: Logins, Unique Users, Peak Day.
Decision: Pending