Shipbytes design system · v0.1
Rendered from the actual Blade components rather than drawn to look like them — so if one is broken, this page is broken too. That is the only kind of gallery worth reviewing against.
Four variants, three sizes. The app writes this eight different ways today; every one of them was trying to be this.
Five tones, three variants. Replaces roughly fifty hand-written badges across nine colour families.
Heroicons v2, with the v1 names the app still uses aliased so they resolve instead of rendering nothing.
x → x-mark
search → magnifying-glass
mail → envelope
cog → cog-6-tooth
dots-vertical → ellipsis-vertical
location-marker → map-pin
A Catalyst two-layer field. In the app this is a ~40-line class string pasted at roughly forty sites.
Fifteen hand-written flash blocks across twelve files, all trying to be these four.
Export ready
Your plan expires in 3 days
Import failed
Fifteen instances across the dashboard and admin, with the count-up duplicated verbatim five times in one file.
A bordered container with an optional header and a divided body. Four copies on the dashboard alone.
Twelve admin screens share one recipe. Columns are passed as data, not written as markup.
| User | Role | Status | Projects | Joined | |
|---|---|---|---|---|---|
| Amara Reyes | 14 | Mar 04, 2026 | |||
| Tobias Okonkwo | 2 | Aug 19, 2026 | |||
| Sunniva Kall | 7 | Jan 22, 2026 |
| User | Role | Joined |
|---|---|---|
|
No users found. |
||
The mobile form of a modal or drawer. In the app it is the “More” menu — the largest single block in the shell.
The surface that blocks the page until the reader deals with it. The desktop form of what the sheet does on a phone.
transform, which makes it the containing block for a fixed child. So this is the actual component with its actual scrim, boxed rather than redrawn.sm
md
lg
xl
2xl
3xl
4xl
full
full is capped at 96rem: uncapped it measures 2528px on a 2560 monitor, which is a line length nobody reads. Below a ~1568px viewport the cap does nothing at all. Past roughly 3xl, ask whether it wants to be a page. Something needing 900px of horizontal room usually also wants a URL and a back button.A menu of verbs anchored to the control that opened it. Not a select — a select holds values and posts them; this holds actions and performs them.
An image when there is one, initials when there is not. Round is a person; square is a company, a project or a file.
Ada King Lovelace is AL, because the middle name is the part nobody uses.An ordered list, because the order is the meaning. The current page is text, not a link — a link to where you already are goes nowhere and costs a tab stop.
Most emptiness is the beginning, not a failure. The dashed edge says something belongs here and does not exist yet.
No reports yet
Reports appear here once a project has run for a full day.
Nothing matched
Try a broader date range.
Import failed
The file could not be read.
A picture of content that does not exist yet. The fill is fg/10 so one value works on the card, on the ground behind it, and in dark.
The native input, styled with appearance-none — not a hidden input beside a decorated span. The trick loses high-contrast rendering and forced-colors support, and every one of those failures is invisible in a normal browser.
The active underline is fg, not accent. A tab row is structure, not a link — colouring the active one accent makes the inactive tabs look like the links.
role="tablist" promises arrow keys and in-place content; put it on page links and both halves are false.hidden ATTRIBUTE, so an inactive one leaves the tab order for free.
A listbox, for where the native popup’s unstyleable chrome is the problem. The native one is still right on anything phone-first — it gets typeahead and the platform’s own scrolling for free.
Supplementary, never the only copy. It does not exist on a touch screen, in a printout, or once the pointer moves — so the button keeps its own accessible name and the tip only describes it.
Surface with a border, not the alert’s tinted wash: it floats over unknown content and has to paint an opaque ground. The tone lives in the icon alone, so four stacked toasts do not become a colour chart.
Report exported
Export failed
Report archived
The third blocking overlay. A modal is answered; a drawer is worked in. The tell is how long the reader stays.
sm
md
lg
xl
2xl
full
full is calc(100vw − 3rem), not max-w-none. The container is fixed inset-0 with no padding, so edge-to-edge would leave nothing of the page visible — and a panel covering everything is a screen, not a drawer. The sliver is what says the thing you came from is one click away.A setting that takes effect. role="switch" makes a screen reader say “on” and “off” — “unchecked”, for a setting that is simply off, reads as a form the reader failed to fill in.
Sections that expand one at a time. The one component in the system that holds state — exclusivity is a relationship between items, so no single item can enforce it.
overflow: hidden. That takes its content out of the tab order AND the accessibility tree; a collapsed section whose links are still tabbable is the classic broken accordion, and it looks perfect.A select with a text filter. multiple is a mode of it, not a second component — chips and aria-multiselectable are the whole difference.
A calendar for one date or a range. Every value is a Y-m-d string, never a Date — new Date('2026-03-29') is UTC midnight, which west of Greenwich is the 28th.
A styled file field with drag-and-drop and local previews. It does not upload anything — progress needs somewhere to upload to, and that is a backend contract nothing else here has.
<input type="file"> is stretched over the whole zone at zero opacity, so the entire area is the control and drag-and-drop lands on the element that owns the files.Choose files or drag them here
The components on a real surface, so spacing and weight can be judged in context rather than in isolation.
19 documents
Every token names a job, not a colour. Both themes are shown side by side because that is the only way drift between them is visible.
| surface | the card content sits on | ||
| surface-sunken | the ground behind it | ||
| surface-subtle | table heads, row hover | ||
| surface-inverse | primary buttons, the FAB | ||
| border | the default hairline | ||
| border-strong | a card edge that must read as raised | ||
| fg | headings | ||
| fg-body | running copy | ||
| fg-muted | labels, meta, timestamps | ||
| fg-subtle | icons that repeat an adjacent label | ||
| accent | links | ||
| success | success | ||
| warning | warning | ||
| danger | danger |
| display | 30/32 · 600 | The quick brown fox jumps |
| heading | 20/32 · 600 | The quick brown fox jumps |
| section | 14/20 · 600 | The quick brown fox jumps |
| body | 14/24 · 400 | The quick brown fox jumps |
| body-touch | 16/24 · 400 | The quick brown fox jumps |
| meta | 12/16 · 400 | The quick brown fox jumps |
| overline | 12/16 · 500 | The quick brown fox jumps |