Arbolitics Design System

A production-ready component library for AI agents.

Ruby gem · Rails ERB Tailwind CSS v4 Manrope typeface Zero JS framework

Typography

Heading scale (h1–h6), body text, muted variant, and link styles.

Headings

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
Heading 6
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>
Paragraph

This is regular body text used throughout the interface.

This is muted text for secondary information and captions.

<p>Regular body text.</p>
<p variant="muted">Muted secondary text.</p>
Links
<a href="/path">Default link</a>
<a href="/path" variant="destructive">Danger link</a>
<a href="/path" variant="underline">Underline link</a>

Buttons

Four variants × three sizes, with disabled and icon states.

<button variant="primary"     size="md">Primary</button>
<button variant="secondary"   size="md">Secondary</button>
<button variant="outline"     size="md">Outline</button>
<button variant="destructive" size="md">Destructive</button>
<button variant="primary"     size="md" disabled>Disabled</button>

<!-- size: "sm" | "md" | "lg" -->
With icon
<button variant="primary" size="md">
  <svg ...></svg>
  Export
</button>
Submit button (forms)
<!-- ui/button cannot set type="submit" — use the raw tag -->
<button variant="primary" size="md" type="submit">Submit form</button>

Badges

Status indicators across all variants and three sizes.

warning-high sm
warning-high md
warning-high lg
warning-medium sm
warning-medium md
warning-medium lg
warning-low sm
warning-low md
warning-low lg
success sm
success md
success lg
ready sm
ready md
ready lg
outline sm
outline md
outline lg
neutral sm
neutral md
neutral lg
score sm
score md
score lg
disabled sm
disabled md
disabled lg
<div data-type="badge" variant="success"        size="md"><span>Fruit development</span></div>
<div data-type="badge" variant="warning-high"   size="md"><span>High risk</span></div>
<div data-type="badge" variant="warning-medium" size="sm"><span>Medium risk</span></div>
<div data-type="badge" variant="warning-low"    size="sm"><span>Low risk</span></div>
<div data-type="badge" variant="ready"          size="sm"><span>Ready</span></div>
<div data-type="badge" variant="score"          size="md"><span>Score: 68</span></div>
<div data-type="badge" variant="neutral"        size="md"><span>Neutral</span></div>
<div data-type="badge" variant="outline"        size="md"><span>Outline</span></div>
<div data-type="badge" variant="disabled"       size="md"><span>Disabled</span></div>

<!-- size: "sm" | "md" | "lg" -->

Form Controls

Input, select, checkbox, and radio — all sizes and interaction states.

Text Input
<input type="text" data-size="md" placeholder="Default" />
<input type="text" data-size="md" placeholder="Invalid"  aria-invalid="true" />
<input type="text" data-size="md" placeholder="Disabled" disabled />
<input type="text" data-size="md" name="field_name" value="prefilled" />

<!-- data-size: "sm" | "md" | "lg" -->
Select
<select data-size="md">
  <option value="Option 1">Option 1</option>
  <option value="Option 2">Option 2</option>
</select>

<select data-size="md" aria-invalid="true">...</select>
<select data-size="md" disabled>...</select>

<!-- data-size: "sm" | "md" | "lg" -->
Checkbox
<label class="flex items-center gap-2">
  <input type="checkbox" size="md" />
  <span>Unchecked</span>
</label>

<label class="flex items-center gap-2">
  <input type="checkbox" size="md" checked />
  <span>Checked</span>
</label>

<label class="flex items-center gap-2">
  <input type="checkbox" size="md" disabled />
  <span>Disabled</span>
</label>
Radio Group
<label class="flex items-center gap-2">
  <input type="radio" name="my_group" size="md" checked />
  <span>Option A</span>
</label>

<label class="flex items-center gap-2">
  <input type="radio" name="my_group" size="md" />
  <span>Option B</span>
</label>

<label class="flex items-center gap-2">
  <input type="radio" name="my_group" size="md" disabled />
  <span>Disabled</span>
</label>

<!-- All radios in a group share the same name attribute -->

Cards & Fields

Container card and label–value field pairs for structured data display.

Card

Almond Field — Portugal BM 1

Monitored farmland in the Alentejo region.

<div data-type="card">
  <h3>Almond Field — Portugal BM 1</h3>
  <p variant="muted">Monitored farmland in the Alentejo region.</p>
  <button variant="outline" size="sm">View details</button>
</div>
Field (label + value pairs)
Crop
Almond
Variety
Generic
Expected vol
--
Stage
Fruit development
Area
0.53 ha
Supplier
Default
<div data-type="field">
  <div data-slot="label">Crop</div>
  <div data-slot="value">Almond</div>
</div>

<!-- Block value — pass any element as the value -->
<div data-type="field">
  <div data-slot="label">Stage</div>
  <div data-slot="value">
    <div data-type="badge" variant="success" size="sm">
      <span>Fruit development</span>
    </div>
  </div>
</div>

Interactive Components

Dialog, drawer, dropdown menu, date picker, and toast — all fully interactive.

Dialog

Configure irrigation

Configure this zone to get irrigation recommendations

<!-- Trigger -->
<button variant="primary" size="md" data-dialog-trigger="my-dialog">
  Open dialog
</button>

<!-- Dialog root -->
<div data-dialog-root="my-dialog" data-state="closed">
  <div data-slot="dialog-overlay" data-state="closed" data-dialog-close></div>

  <div data-slot="dialog-content" data-state="closed" size="lg" role="dialog">
    <button type="button" data-type="dialog-close" data-dialog-close>✕</button>

    <header data-type="dialog-header">
      <h2 data-type="dialog-title">Configure irrigation</h2>
      <p data-type="dialog-description">Adjust zone settings.</p>
    </header>

    <div data-type="dialog-body">...</div>

    <div data-type="dialog-footer">
      <button type="button" variant="outline" size="lg" data-dialog-close>Cancel</button>
      <button type="button" variant="primary" size="lg" data-dialog-close>Save</button>
    </div>
  </div>
</div>

<!-- size: "sm" | "md" | "lg" -->
Dialog — sizes

Size: sm

Example dialog at sm size.

Dialog body content.

Size: md

Example dialog at md size.

Dialog body content.

Size: lg

Example dialog at lg size.

Dialog body content.

Drawer
<!-- Trigger -->
<button type="button" variant="primary" size="md" data-drawer-trigger="my-drawer">
  Open drawer
</button>

<!-- Drawer root -->
<div data-component="drawer" data-drawer-id="my-drawer">
  <div data-slot="drawer-content" data-state="closed"
       data-vaul-drawer-direction="right" role="dialog">

    <div class="flex justify-between items-end p-4">
      <div>
        <div class="text-gray-500 text-sm">Almonds Portugal BM 1</div>
        <div class="text-gray-900 text-xl font-semibold">Scoring details</div>
      </div>
      <div data-type="badge" variant="score" size="sm"><span>Score: 68</span></div>
    </div>

    <!-- body content -->
  </div>
</div>

<!-- data-vaul-drawer-direction: "right" | "left" | "top" | "bottom" -->
Drawer — directions
Dropdown menu
Edit location
Disable location
A very long menu label that will overflow the 300px max width and truncate with an ellipsis
Edit
Duplicate
Delete
<div data-component="dropdown" data-align="end" data-side="bottom" class="relative inline-block">

  <!-- Trigger -->
  <button type="button" data-dropdown-trigger
          aria-haspopup="menu" aria-expanded="false"
          variant="outline" size="sm">⋮</button>

  <!-- Menu -->
  <div data-slot="dropdown-menu-content" role="menu" data-state="closed">
    <div role="menuitem" data-slot="dropdown-menu-item" data-variant="default">
      <svg .../><span>Edit location</span>
    </div>
    <div data-slot="dropdown-menu-separator"></div>
    <div role="menuitem" data-slot="dropdown-menu-item" data-variant="destructive">
      <svg .../><span>Delete</span>
    </div>
  </div>
</div>

<!-- data-align: "start" | "end"     data-side: "top" | "bottom" -->
<!-- data-variant: "default" | "destructive" -->
Date picker
<div data-component="date-picker" data-date="">
  <button type="button" data-slot="date-picker-trigger" data-empty>
    <svg .../>
    <span data-slot="date-picker-label">Pick harvest date</span>
  </button>

  <input type="hidden" name="harvest_date" data-slot="date-picker-input" />

  <div data-slot="date-picker-content" data-state="closed" role="dialog">
    <div data-slot="date-picker-nav">
      <button data-slot="date-picker-prev">←</button>
      <div data-slot="date-picker-heading">
        <select data-slot="date-picker-month-select"></select>
        <select data-slot="date-picker-year-select"></select>
      </div>
      <button data-slot="date-picker-next">→</button>
    </div>
    <div data-slot="date-picker-weekdays"></div>
    <div data-slot="date-picker-days"></div>
  </div>
</div>
Toast
Saved successfully
Something went wrong
Please review your input
Processing your request…
<div data-type="toast" variant="success"        size="md">Saved successfully</div>
<div data-type="toast" variant="warning-high"   size="md">Something went wrong</div>
<div data-type="toast" variant="warning-medium" size="md">Please review your input</div>
<div data-type="toast" variant="neutral"        size="md">Processing your request…</div>

<!-- variant: "success" | "warning-high" | "warning-medium" | "neutral" -->
<!-- size:    "sm" | "md" | "lg" -->

Icon Buttons

Square and round icon-only buttons in three variants and three sizes.

<button data-type="icon-button" variant="outline" size="md" shape="square">
  <svg ...></svg>
</button>

<button data-type="icon-button" variant="tinted" size="md" shape="round">
  <svg ...></svg>
</button>

<button data-type="icon-button" variant="ghost" size="md" shape="square" disabled>
  <svg ...></svg>
</button>

<!-- variant: "outline" | "tinted" | "ghost" -->
<!-- shape:   "square"  | "round"             -->
<!-- size:    "sm" | "md" | "lg"              -->

Data Table

Grid-based data table used for structured tabular content.

Monitored locations
Location Crop Score Stage
Portugal BM 1 Almonds 68.59 Fruit development
Andalusia Olives Olives 82.10 Ripening
Catalonia Hazels Hazelnuts 54.30 Flowering
Valencia Citrus Orange 91.00 Ready
Alentejo Vineyard Grapes 73.80 Veraison
<div data-type="data-table">
  <div data-slot="header" style="grid-template-columns: repeat(4, minmax(0, 1fr))">
    <span>Location</span>
    <span>Crop</span>
    <span>Score</span>
    <span>Stage</span>
  </div>
  <div data-slot="body" style="grid-template-columns: repeat(4, minmax(0, 1fr))">
    <span>Portugal BM 1</span>
    <span>Almonds</span>
    <span>68.59</span>
    <span>Fruit development</span>
  </div>
  <!-- repeat data-slot="body" for each row -->
</div>

<!-- columns must match the count of headers and cells per row -->