Design system

Buttle should feel calm, direct, and easy to scan

Use typography, spacing, and color to clarify hierarchy and state. Avoid decoration that does not help someone decide what to read or do next.

Foundations

Color tokens

Use semantic CSS variables from app/globals.css for product UI. Add new roles there first, then consume them with Tailwind arbitrary values.

--surface-pagePage background
--surface-panelCards, panels, sidebars
--surface-inputInputs and quiet controls
--surface-controlPills and tonal controls
--surface-hoverHover surface step
--text-primaryPrimary text
--text-secondarySecondary text and helper copy
--text-completedCompleted item text
--border-subtleForm and quiet control borders
--border-controlInteractive control borders
--border-strongPanel and card borders
--border-dividerInterior separators
--accent-primaryPrimary actions and focus
--accent-dangerDestructive actions

Foundations

Typography

Keep the type scale compact. Use the system sans stack for UI and reserve the display face for the Buttle wordmark.

Page titleProject listtext-2xl font-semibold
Product markHeader brandtext-lg font-semibold
Section labelRecent changestext-xs font-medium uppercase tracking-[0.08em] text-[var(--text-secondary)]
BodyDefault contenttext-sm text-[var(--text-primary)]
Supporting copyHelper texttext-sm text-[var(--text-secondary)]
Metadatav12text-xs font-medium tabular-nums

Actions

Buttons and links

Use shared button recipes for repeated tones. Filled buttons reduce opacity on hover, tonal and danger buttons use the hover surface, and text actions shift to the accent hover color.

Button tones

Icon and link buttons

Surfaces

Panels, cards, and sidebars

Panels use a quiet background with a strong border. Do not nest full panel surfaces for layout. Framed form question groups can sit inside a form panel when each group needs its own scanning boundary.

Pack for Friday demo

27/12

Cards summarize a thing, show compact metadata, and click through to details.

Checklist section

Forms

Inputs, checks, radios, and selects

Form controls use input surfaces, subtle borders, clear labels, visible focus, and immediate feedback for pending or changed states.

Text inputs

Choice controls

Feedback

Status, loading, and empty states

Every action needs a visible acknowledgement: active state, disabled pending state, optimistic row state, inline status text, or a spinner.

Pending

Disable the control while the server action is pending.

Inline status

Saved just now

Could not sync calendar

Skeletons and empty states

No projects yet.

Interests

Public profile and interest selection

Public profiles lead with identity, status, and clear interest choices. Interest cards and pills need selected, disabled, and read-only states because visitors use them to start a chat.

Profile header

A

Ada Reed

Online

@ada

Bio copy stays narrow and direct. The fallback avatar uses the display face, but the rest of the profile stays in the system sans.

Chat unavailable

Interest choices

03Read-only interest

Large ranked interest cards may use filled accent for selected state. Compact interest pills use the quieter outline selected state.

Interests

Interest composer states

The composer uses large ranked tiles for top interests, wrapped pills for the rest, and visible states for adding, dragging, editing, archiving, and empty slots.

Top interests

01Product strategy
02Drop here
03Archiving
Drag preview keeps the tile size and follows the pointer.

All interests and edit states

Optimistic new ideaArchiving interest

Rows

Expandable rows and activity

Dense lists reveal detail in place. Disclosure buttons sit inside the row, recurring badges stay attached to titles, and truncated groups use a small text action.

Expandable checklist row

Note reveal copy stays secondary and appears directly under the row.

Today

Questions and recent changes

What time should we start?

  • You marked "Book the room" as done.
  • Claude added three checklist items.

Scheduling

Booking and availability

Scheduling surfaces use panel shells, two-column slot grids on wider screens, radio-like rows, inline sentence selects, and plain privacy copy.

Slot picker

Pick a 10-minute slot. Slot rows use the same hover surface and selected accent as other option controls.

No open times this week.

Availability editor

Connect your calendar

Connected

We only store your busy times. We will not see event names, attendees, or locations.

Let people book up todays out withminutes notice.

Calls

Call requests and call chrome

Call UI is more immersive than admin UI. The live call surface is full-bleed, while request trays stay compact and action-oriented.

Host request tray

Live requests

Jules wants to chat about espresso gear

Waiting for 1 minute.

Video call controls

Remote video fills the call surface.

Trust

Consent and copyable URLs

Authorization and copy flows need explicit feedback. Show what is being approved or copied, make long URLs readable, and acknowledge success in place.

OAuth consent

Allow Local Agent to access Buttle?

This app was created recently. Check the redirect URL before you continue.

  • Read your projects.
  • Update project items.

https://example.localhost/oauth/callback?client_id=local-agent

Copyable URL field

http://buttle.localhost/api/mcp
Copied

Copyable URL fields should match the radius of surrounding form controls. Use rounded-sm only for dense inline chips or toolbar-scale controls. Copy feedback swaps the icon, updates nearby text, and announces the change with aria-live.

Implementation

Reuse and promotion rules

Keep one-off style ownership local. Promote styles when multiple files need the same behavior or when the behavior is easy to miss.

Use Tailwind locally

Keep local *ClassName constants when one component owns the style.

Use shared recipes

Use composeButtonClassName() for repeated button tones and composePanelClassName() for standard panels.

Use tokens first

Add new color roles in app/globals.css before using them in JSX.

Preserve interaction states

Every clickable element needs hover and active feedback, and pending actions need local acknowledgement.