Every release of @comitor/ui, what changed in it, and what you have to change to move up. This is the canonical record — the package’s README points here rather than repeating it. The rest of this site documents the newest release.
Versioning changed at 1.0.0. From 1.0.0 on this is ordinary SemVer: breaking changes ship in a major bump, so an app pinning ^1.0.0 can update without reading this page first. The 0.x rule — breaking changes in a minor bump — explains only the entries below it.
Releases
Changed
AppLauncher's tile icon well is no longer a bg-app-accent fill; it is an IconAvatar with seed={app.id}. The old accent table made every app wait to be hand-assigned a colour, so the sixth product either collided with another or sat colourless until someone edited the table — now a new app has a colour the moment it exists, and the same colour in an email, on a canvas or in a PDF, because getAvatarToneColors reads the same tone table. AppDescriptor gains tone?: string — one name from AVATAR_TONE_NAMES — to pick that colour by hand when the derived one is not the one you want.
accent, accentInk and accentForeground on AppDescriptor are deprecated, and `AppLauncher` no longer reads them. They stay in the type so an existing app still compiles, but passing them to the launcher now does nothing. appAccentStyle() is still exported and still correct — an app that draws its own icon tile from the CSS variables keeps using it, and AppShell still applies it to the frame; only AppLauncher stopped calling it.
The locked tile stays grey through a className (bg-muted text-muted-foreground), not through a tone. "Not unlocked yet" is a state, and the tone table is identity colour; borrowing a tone to signal state is a category error. Both classes are solid, so the padlocked icon shows no crossing seam either.
MINOR, and nothing has to change to compile — but an app's colours will move on upgrade even if you touch nothing, on purpose: the launcher now derives each tile's colour from the app id rather than from whatever accent you had assigned. To hold a specific hue, set tone to that tone's name. The migration off the three deprecated props is to drop them and either pass tone or leave it blank for the derived colour.
Added
IconAvatar, the sibling of LetterAvatar. It shares the whole colour layer — the same eight tones, the same hash, the same image / content / sr-only branches — and differs only in what sits in the middle of the tile: an icon rather than an initial. It defaults to a square with rounded corners, the shape of a *thing* (an app, a workspace), instead of the round of a *person*, and rounded="full" reopens the round branch. It replaces the old shape — a hardcoded table of a few accent tokens, where the sixth product either matched another or waited for someone to edit the table — with one where a new app has a colour the moment it exists. The props: name (the accessible name, and the default colour seed); seed (the seed when it differs from the display name — an app must pass its `key`); icon / src (the glyph in the middle, where an uploaded srcbeatsicon); tone (pick one of the eight tone names by hand; an unknown name falls back to the derived colour); and size / rounded (the LetterAvatar size scale, with rounded="full" for the round branch).
AVATAR_TONE_NAMES and the AvatarToneName type are exported alongside it — the tone prop only means anything where the call site can enumerate the set it picks from. `AVATAR_TONES` and `getAvatarToneIndex` stay internal, deliberately: handing out the raw table and the hash is an invitation to rebuild the tone choice app-side, which is exactly how one identity ends up two colours across surfaces.
Fixed
The collapse button at the foot of the sidebar — the last case in the 1.8.3 sweep, and the only one that had to be split rather than recoloured whole. That button carries text when the rail is expanded, so its own colour is held to the 4.5:1 text threshold: measured on --sidebar in light, /60 flattens to #6C6E71 = 4.90:1 ✓, while --muted-foreground is only 3.67:1 ✗. So the button keeps /60 and the icon inside it is now painted separately with a solid token — an icon answers only to the 3:1 threshold.
Two measured warnings sit on IconAvatar. `seed` is not optional for an app: hashing the *translated* name flips 4/6 apps to a new colour when the user switches vi ⇄ en, while hashing the stable key flips 0/6 — so pass the key ("tasks", "crm") and let name stay the accessible string. And eight tones over a catalogue of six or more means collisions: the same measurement gives 5/6 distinct (starter and mes land together), which no different hash can fix — tone is the way out. The glyph is never given an alpha: the tone's background is an alpha tint, but the icon is always a solid ink step, because crossing strokes carrying alpha double-paint at the join — the 1.8.2 lesson.
Format follows Keep a Changelog; versions follow SemVer, strictly from 1.0.0 on and under the 0.x rule above before that.