Surfaces & data

Cards, stats, charts and tables on one lit surface.
Content panes take the denser glass tint so text keeps its contrast. Numbers are tabular, marks are the ion, and the chart series never renumber.
INSTALLS · THIS WEEK+12.4% vs. last week
Card · default
Welcome to Canvas
Rests at elevation sm. Lifts to md on hover, on the spring.
Card · raised
Canvas v4.0.0
107 components
MIT licensed. Web, iOS and Android from one tree.
Card · glass
glass-tint-content
Denser than the shell tint, so this paragraph stays at 4.5:1 over anything.
Card · selected
Team · 24 members
Selection is a 1px ion border and a 4px ring. Never a fill.
media slot · 16:9
Card · anatomy · modes
sub-components and special modes
Mobile release 6.3
Tab bar spacing and the Android blur rebuild.
QA checklist
14 / 18
Canvas v4.0.0 is live
107 components
featured
brand gradient
Glass ships in v4.0.0
promo
CTA on a wash
Grace Hopper
artwork
image fills the card
DESIGN.md · Shapes
A nested surface is never rounder than its container.
bnannier/canvas
reference
referenceKey · source
Note · glass is a theming mode
v6.3.0 · Oct 26
Experimental
inset panels
note · version · gate
Glass
controls
a settings surface
<Card> with <CardMedia> · <CardHeader> · <CardTitle> · <CardDescription> · <CardSeparator> · <CardContent> · <CardFooter> · modes: featured · promo · artwork · illustration · controls · referenceKey + referenceSource · inset note / version / gate
Revenue
$128.4k
+18.2%
Active members
1,204
72% of 1,680 invited
+6
p95 latency
212 ms
+41ms
Platforms
iOS 64% · Android 18% · Web 9%
<Stats items={…}> · deltas and sparks · <ProgressRing>
Members
2 selected · 6 rows · click a row
Member
Team
Status
Balance
Activity · 8w
Ada Lovelace
ada@ionize.io
Platform
Active
$12,480.00
Grace Hopper
grace@ionize.io
Compilers
Active
$9,120.50
Kira Tanaka
kira@ionize.io
Design
Invited
$4,300.00
Noor Park
noor@ionize.io
Mobile
Active
$7,845.25
Marcus Allen
marcus@ionize.io
Growth
Suspended
$0.00
Liang Bao
liang@ionize.io
Data
Active
$15,002.00
Showing 1–6 of 24
<DataTable selectable sortable> · rows select on press · cells take any node

Lists & disclosure

StackedList · GridList · MediaObject · Feed · DescriptionList · ActionPanel · Accordion · Collapsible
StackedList
avatar · two lines · meta
  • Ada Lovelace
    ada@ionize.io
    Owner · online
  • Grace Hopper
    grace@ionize.io
    Admin · 2h ago
  • Kira Tanaka
    kira@ionize.io
    Invited
  • Liang Bao
    liang@ionize.io
    Viewer · yesterday
<StackedList> · rows take onPress and the whole row is the target · inset hairlines on iOS
GridList
directory · collections
  • Noor Park
    Mobile lead
  • Marcus Allen
    Growth
  • TO
    Tokens
    48 roles
  • CH
    Charts
    27 types
<GridList> people directories · collections · galleries · tiles lift on the spring
MediaObject
media leads, text owns the rest
Kira Tanaka
The ion ring reads better at 4px than 3. Shipping it with the field update.
2m
Ready for review
#482 · Overlays move to glass-tint-dense
9:41
Designing for three skins
One tree becomes an iOS capsule, a Material stadium and a lit web control.
8 min read
<MediaObject> · avatar, Emblem or Image in the media slot · the base of every row above
Feed
activity · audit log
  • Kira merged #482 into main
    2 min ago
  • Bobby moved --hue from 285 to 205
    1 hour ago
  • Liang commented
    3 hours ago
  • v6.2.0 published to npm
    yesterday
<Feed> · the icon names the event · one hairline spine, never a card per row
DescriptionList · ActionPanel
update in place
Display name
Bobby Nannier
Email
bobby@nannier.com
Workspace
Riskora · 24 members
Active
Export workspace
Every board, token and asset as one .zip.
Delete workspace
Removes Riskora for all 24 members. There is no undo.
<DescriptionList> rows flagged update edit in place · ↵ saves, esc cancels · <ActionPanel> one decision, one action
Accordion · Collapsible
live
No. Glass is a theming mode: <ThemeProvider glass>. Each surface then takes its own tint layer, from sheer shells to dense menus.
<Accordion items={…}> a stack of disclosures · <Collapsible title="…"> exactly one

Content & media

CodeBlock · Carousel · Image · Video · QRCode
CodeBlock
tabs · emphasis · diff · copy
1
2
3
4
5
6
7
8
9
import { ThemeProvider, Button } from "@nannier/canvas";
export function Save() {
return (
<ThemeProvider dark glass>
<Button primary large>Save</Button>
</ThemeProvider>
);
}
<CodeBlock> highlight · line emphasis · diff · folding · tabbed alternatives · copy via expo-clipboard on native
Carousel
swipe · arrows · dots
01 · Material
Light is the material
<Carousel> one slide per page · slides take the card radius, 28 on Android
Image · Video · QRCode
media atoms
cover · crops
contain · letterboxes
0:00
0:00
canvas.nannier.com
Always dark on white so any camera reads it, whatever the scheme.
<Image cover> · <Image contain> · <Video poster autoplay muted loop> · <QRCode value="…">

Workspace

Calendar · Chat · Board · Drag & drop
Calendar
month · week · day · pick a day
October 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
<Calendar events={…}> · dots in the month grid, blocks on the week and day timelines
Chat
live · type and send
Canvas assistant
provider · Claude
online
  • Assistant
    Claude
    Hi. Ask how any Canvas component sizes itself, or which props it takes.
  • You
    Does Card take a style prop?
  • Assistant
    Claude
    No. There is no style escape hatch. Use the semantic booleans: <Card raised selected>.
<Chat> = <ChatThread> + <ChatMessage> + <ChatComposer> · replies render through <Markdown> · bubbles 18 with a 6 tail · composer 20 on glass
Board · Drag & drop
DropZone · Draggable · DragHandle
Backlog
3
Calendar week timeline
Timed blocks on the hour grid, glass under the now-line.
organism
GeoMap zoom clusters
P2
Tooltip on glass
Lifted 3°, ion ring, lg shadow.
atom
In progress
2
Overlays on glass-tint-dense
Dialog, sheet, popover, toast and the command palette move to the densest tint.
#482
Chart series palette
Review
1
Switch thumb spring
ready
<Board columns={…}> on <DragDropProvider> · every column is a <DropZone>, every card a <Draggable> with a <DragHandle>