Graffiti

github

Elements

Single-purpose UI elements.

These are common, non-complex UI elements that just need a class or two. Forms, cards, buttons, and more.

Buttons

Button styling for `<button>` elements and `.button` class for links.

When to use: Buttons and links styled as actions.

Classes: .button, .primary, .success, .warning, .error, .ghost, .minimal, .reset, .mini

Reference Notes
Reset Button

Use .reset when you need a truly unstyled button and want to build custom chrome.

It removes background, border, radius, shadow, and padding while inheriting typography and color.

Styling Details
  • All buttons have consistent padding and border-radius
  • Hover, focus, and active states included
  • Disabled state reduces opacity and prevents interaction

Chips

Interactive pill-shaped elements for filters, categories, and selections.

When to use: Selectable pills for filters and segmented choices.

Classes: .chip, .selected, .mini

Reference Notes

Use for multi-select interfaces, tag filters, or skill selectors.

With Icons

Icons are automatically sized to 1em.

Styling Details
  • Pill shape with border-radius: var(--br-xxl)
  • Border: var(--border-1)
  • Selected state: primary color background
  • Hover/focus/active states included
  • Fluid typography at --fl: -1 (smaller text)
Chips vs Tags
  • Chips are interactive (clickable, selectable)
  • Tags are for display (category labels, metadata)

Tags

Subtle category labels with customizable colors.

When to use: Status or category labels.

Classes: .tag, .success, .warning, .error, .info, .muted

Reference Notes

Use for metadata, categories, or status indicators.

Custom Colors

For custom categories, use --tag-color as a fallback when semantic variants are not a fit:

Available colors: --red, --orange, --yellow, --green, --teal, --blue, --indigo, --purple, --pink, --gray, --slate

With Icons

Icons are automatically sized to 1em.

Styling Details
  • Soft background (12% opacity of tag color)
  • Text color auto-adjusts for light/dark themes
  • Subtle border (20% opacity of tag color)
  • Fluid typography at --fl: -1 (smaller text)
  • Pill shape with border-radius: var(--br-xxl)
Tags vs Chips
  • Tags are for display (category labels, metadata)
  • Chips are interactive (clickable, selectable)

Avatar

Circular avatar for user images or initials.

When to use: User photos or initials with size variants.

Classes: .avatar, .xs, .s, .l, .xl, .bordered

Reference Notes
Styling Details
  • Circular shape (border-radius: 50%)
  • Images use object-fit: cover
  • Initials have subtle background (--fg-1)
  • Text scales with avatar size

Boxes

Container styles for cards and content blocks.

When to use: Container surface styles and quick panel variants.

Classes: .box, .glow, .semi-gloss, .ghost, .invisible

Reference Notes
Styling Details
  • .box - Tint background, padding, border-radius, border
  • .box.glow - Inset glow shadow effect
  • .box.semi-gloss - Gradient background, premium feel
  • .box.ghost - Transparent, border outline only
  • .box.invisible - No visual styling, just structure

Callouts

Informational boxes for tips, warnings, errors, and success messages.

When to use: Inline informational or status callout blocks.

Classes: .callout, .warning, .error, .success, .ghost, .hard, .fill

Reference Notes
CSS Variables
  • --callout-color - Background color
  • --callout-border-color - Border color

Card

Structured content container with optional header, body, and footer.

When to use: Structured content cards and linked card patterns.

Classes: .card, .card-body, .card.linked, .card.featured

Reference Notes
Notes
  • .card applies border, radius, shadow, and clips media.
  • Direct header and footer get padding and separators.
  • Use .card-body, main, or section for padded content.

Bubble

Chat-friendly message container with configurable colors, width, and spacing.

When to use: Chat message presentation and conversation snippets.

Classes: .bubble, .chat-thread, .chat-row, .chat-row.self, .chat-message, .chat-composer

Reference Notes

.bubble uses a rounded fallback shape and upgrades to squircle corners in browsers that support corner-shape.

Chat Layout Helpers

Use these helpers to build complete chat threads:

  • .chat-thread - Vertical message stack with configurable spacing/padding
  • .chat-row - Left-aligned row
  • .chat-row.self - Right-aligned row
  • .chat-message - Width-constrained wrapper for each message
  • .chat-composer - Composer row where .input-group expands to fill space
CSS Variables
  • --bubble-bg - Bubble background color
  • --bubble-border - Bubble border color
  • --bubble-max-inline - Max bubble width
  • --bubble-pad-block - Block-axis padding
  • --bubble-pad-inline - Inline-axis padding
  • --bubble-radius - Fallback rounded corner radius
  • --bubble-flow-space - Spacing between child elements

Horizontal scrolling with CSS scroll-snap. No JavaScript required.

When to use: Horizontal scroll-snap for cards or media strips.

Classes: .carousel

Reference Notes
Styling Details
  • display: flex with horizontal overflow
  • scroll-snap-type: x mandatory for snapping
  • Children have scroll-snap-align: start
  • Thin scrollbar (scrollbar-width: thin)
  • Default gap of 1rem
How It Works
  • Drag, swipe, or scroll horizontally
  • Items snap to start position
  • Works with mouse, touch, trackpad, and keyboard
  • No JavaScript needed for basic functionality

Reel

Vertical scrolling with CSS scroll-snap. Like carousel but vertical.

When to use: Vertical scroll-snap list or feed.

Classes: .reel

Reference Notes
CSS Variables
  • --reel-height - Container height (default: 80vh)
  • --gap - Gap between panels (default: 1rem)
Styling Details
  • display: flex with flex-direction: column
  • scroll-snap-type: y mandatory for snapping
  • Children have scroll-snap-align: start
  • Vertical overflow with thin scrollbar
How It Works
  • Scroll vertically to navigate panels
  • Panels snap to top
  • Works with mouse wheel, touch, and keyboard

Tables

Responsive table wrapper with clean data table styling.

When to use: Responsive table wrapper and default table styling.

Classes: .table

Reference Notes
Why the Wrapper?

The .table wrapper provides:

  • Horizontal scrolling on small screens
  • Border and border-radius on the container
  • Proper overflow handling
Styling Details
  • Tables are 100% width with collapsed borders
  • Headers have bottom border separator
  • Cells have consistent padding
  • Last row has no bottom border
  • Wrapper has overflow-x: auto for responsiveness
CSS Variables
  • --table-border - Custom border-radius for wrapper

Dialog

Native HTML `<dialog>` element with open/close animations.

When to use: Native modal flows and confirmations.

Classes: dialog, .close

Reference Notes

No JavaScript required when using HTML invokers.

How It Works
  • commandfor points to the dialog's id
  • command="show-modal" opens the dialog as a modal
  • command="close" closes the dialog
  • No JavaScript needed for basic open/close
Close Button

The .close class creates a circular red button. When inside a <dialog>, it's automatically positioned in the top-right corner.

Styling Details
  • max-width: 40ch - Character-based width for good proportions
  • Dark backdrop overlay
  • Smooth scale/opacity animation on open/close
  • Works in light and dark themes automatically

Tabs

Pure CSS tabs using `<details>` and `<summary>` with CSS Grid and Subgrid.

When to use: CSS-only tabbed content using details/summary.

Classes: .tabs, .tabs.boxed, .tabs.pill

Reference Notes

No JavaScript required.

How It Works
  • The name attribute on <details> ensures only one tab can be open at a time (native HTML behavior)
  • --n CSS variable positions each tab's summary in the correct grid column
  • --tab-count on the container sets the number of columns (default: 3)
Important Notes
  1. Unique names: Each tab group needs a unique name attribute
  2. Open one by default: Add open to the tab that should be visible initially
  3. Sequential --n values: Must match the visual order (1, 2, 3, etc.)
  4. Match --tab-count: If you have more than 3 tabs, set --tab-count to match
Styling Details
  • Uses CSS Grid with Subgrid for alignment
  • Smooth opacity transitions with @starting-style
  • Works in light and dark modes
  • Keyboard accessible (native details/summary behavior)
  • Active tab has underline indicator (default), card connection (boxed), or sliding thumb segment (pill)

Tooltip

Hover tooltips using CSS anchor positioning. No JavaScript required.

When to use: Popover-based tooltips with CSS anchor positioning.

Classes: .tooltip, .tooltip-content, .bottom, .left, .right

Reference Notes
Styling Details
  • Uses CSS anchor positioning (anchor-scope, position-anchor, position-area)
  • Background: var(--bg)
  • Border: var(--border-1)
  • Shadow: var(--shadow-3)
  • Max width: 30ch (wraps longer text)
  • Shows on :hover and :focus-within
  • Smooth opacity transition
Accessibility
  • Triggers work with focus (:focus-within) for keyboard users
  • Use buttons or links as triggers when possible
  • Tooltip content is always in DOM (just hidden via opacity)

List Navigation

Navigation list with clickable rows for settings pages, menus, and navigation indexes.

When to use: Grouped list-style navigation rows.

Classes: .list-nav, .list-nav.bordered

Reference Notes

Each item is a card with squircle shape and subtle shadow.

Use Cases
  • Settings pages
  • Mobile app menus
  • Feature indexes
  • Dashboard navigation
  • Account/profile menus
Item Structure

Items are direct <a> or <button> children of .list-nav. No additional classes needed.

Each item can contain:

  1. <svg> - Icon on the left (sized to 1.25em)
  2. Text - Title text
  3. <small> - Optional description (muted, smaller text)
Styling

Each item automatically gets:

  • Squircle shape - Rounded corners with corner-shape: squircle
  • Subtle shadow - var(--shadow-1) for elevated card appearance
  • Background - Uses var(--bg) for proper theming
  • Gap - var(--pad-m) spacing between items
States
  • Default: Card with squircle shape and subtle shadow
  • Hover: Background highlight, icon brightens
  • Focus: 2px solid outline (inset)
  • Active: Slightly darker background
  • Disabled: 50% opacity, no pointer events
Differences from Sidebar Nav
FeatureList NavSidebar Nav
Item styleIndividual cards with shadowFlat items in a list
DescriptionSupported via <small>Not supported
Use caseStandalone navigation rowsSticky sidebar menus
NestingNot supportedSupports details/summary
Visual weightHigher (cards with shadow)Lower (compact)
Accessibility
  • Use semantic <nav> container
  • Use <a> for navigation links, <button> for actions
  • Disabled buttons use disabled attribute
  • Links can use aria-disabled="true" when needed
  • Focus states are clearly visible

Toggle Switch

Accessible toggle/switch input using native checkbox.

When to use: Boolean settings with checkbox semantics.

Classes: .toggle, .compact

Reference Notes

<span id="forms">

CSS Variables
  • --toggle-color - Color when checked (default: var(--primary))
  • --toggle-width - Track width
  • --toggle-height - Track height
Accessibility

The toggle uses a native checkbox, so it:

  • Works with keyboard (Space to toggle)
  • Announces state to screen readers
  • Respects prefers-reduced-motion

Input Group

Input field with connected button.

When to use: Input plus attached action button patterns.

Classes: .input-group

Reference Notes

Use for copy-to-clipboard, search with button, URL sharing, or any input that needs an action.

Styling Details
  • Input stretches to fill available space
  • Button stays sized to content
  • Connected with no gap, shared border-radius
  • Works with all button variants (.primary, .ghost, etc.)

Search input with icon positioned inside.

When to use: Search field with icon and compact action behavior.

Classes: .search

Reference Notes
Icon Source

Get icons from Phosphor Icons. The magnifying glass icon shown above is the "MagnifyingGlass" icon.

Styling Details
  • Icon is absolutely positioned, vertically centered
  • Input has left padding to accommodate the icon
  • Icon color matches input text color

File Dropzone

Drag-and-drop file upload zone with click-to-upload fallback.

When to use: Drag-and-drop upload zones with native fallback.

Classes: .dropzone, .dragover

Reference Notes
Icon Source

Get icons from Phosphor Icons. The upload icon shown above is the "UploadSimple" icon.

CSS Variables
  • --dropzone-padding - Padding inside (default: var(--pad-xxl))
  • --dropzone-border-radius - Border radius (default: var(--br-m))
Styling Details
  • Dashed border (2px dashed var(--fg-2))
  • Centered flex layout for icon and text
  • File input is hidden but covers entire area
  • Click anywhere to trigger file picker
  • .dragover state shows accent color border