Documentation

Complete list of Sprinkle directives, usage examples, and guides.


Input

autosize

On: <textarea>

<textarea autosize placeholder="Type here — it grows…"></textarea>

auto-width

On: <input>, <textarea>

<input auto-width placeholder="Full width input" />

clearable

On: <input>

<input clearable placeholder="Search…" />

character-count

On: <input>, <textarea>

<input character-count maxlength="16" />

auto-select

On: <input>

<input value="https://…" auto-select readonly />

enter-submit

On: <textarea>

<textarea enter-submit></textarea>

drop-zone

On: <label> wrapping <input type="file">. Supports drag-and-drop, click to browse, image preview, multiple files, and removal.

Single image (avatar):

Multiple files (any type):

<label drop-zone>
  <span>Drag your avatar here or click to browse</span>
  <input type="file" name="avatar" accept="image/*" />
</label>

leading / suffix

On: <input>

<input leading="search" />
<input type="password" leading="lock" suffix="eye" />

prefix

On: <input type="url">

<input type="url" prefix />
<input type="url" prefix="upper.do" />

combo-box

On: <select>

With leading / suffix icons:

Multi-select with multiple:

With category groups:

<select combo-box searchable>
  <option value="1" data-avatar="…">Upper Platform</option>
  <option value="2" data-avatar="…" selected>Nimbus Runtime</option>
  <option value="3" data-avatar="…">Forge Core</option>
</select>

Validation

error-message

On: any validated element

<input required error-message-required="Can't be blank." />

allowed-domains

On: <input type="email|url">

<input type="email" allowed-domains="upper.do,example.com" />

mask

On: <input type="tel|text">

<input type="tel" mask />
<input type="text" mask="00/00/0000" />

Date / Time

no-past / no-future

On: <input type="date|datetime-local">

<input type="date" no-past />
<input type="date" no-future />

disable-days

On: <input type="date|datetime-local">

<input type="date" disable-days="weekends" />

business-hours

On: <input type="datetime-local">

<input type="datetime-local" business-hours="09:00-18:00" />

date-range

On: <input type="date|datetime-local">. Add date-input to enable the custom calendar picker with dual-month range view.

<input type="date" date-input date-range="trip" data-range-type="start" />
<input type="date" date-input date-range="trip" data-range-type="end" />

date-input

On: <input type="date|datetime-local">. Replaces the native date picker with a custom calendar popup featuring month/year navigation, disabled date support, keyboard navigation (arrows, PageUp/Down, Home/End, Enter/Space, Escape), and full ARIA accessibility. When combined with date-range, displays two side-by-side months.

<input type="date" date-input />

<!-- With constraints -->
<input type="date" date-input no-past />
<input type="date" date-input disable-days="weekends" />

<!-- Range mode -->
<input type="date" date-input date-range="trip" data-range-type="start" />
<input type="date" date-input date-range="trip" data-range-type="end" />

Dialog

drawer

On: <dialog>

Navigation
<dialog drawer="left" close-outside id="nav">…</dialog>
<button command-for="nav" command="show-modal">Open</button>

Layout

shell + sidebar + nav + content

The page itself uses shell with sidebar="left" and content. Below is a second nested layout example — no inline styles, no extra classes:

Welcome to the Dashboard

This nested shell uses the same shell grid with sidebar + nav. The sidebar width and content padding come from sprinkle defaults.

card

On: <fieldset>

Basic card with <legend>:

Profile

Name: Jane Doe

Role: Engineer

<fieldset card>
  <legend>Profile</legend>
  <main>
    <p>Name: Jane Doe</p>
  </main>
</fieldset>

Card with <header>, <main>, and <footer>:

Notifications

You have 3 unread messages.

<fieldset card>
  <header>Notifications</header>
  <main>
    <p>You have 3 unread messages.</p>
  </main>
  <footer>
    <button loading>Mark all read</button>
  </footer>
</fieldset>

Clickable card with href:

Forge Sprinkle

Lightweight HTML attribute enhancements. No build step required.

<fieldset card href="/sprinkle">
  <header>Forge Sprinkle</header>
  <main>&hellip;</main>
  <footer>
    <a href="/sprinkle" class="card-link">Learn more →</a>
  </footer>
</fieldset>

Grid of cards:

Getting Started

Install the CSS and JS, add attributes to your HTML, and you're done.

Components

Dropdowns, accordions, modals, drawers, combo-box, and more.

Accessibility

Built on native HTML semantics. ARIA attributes are handled automatically.

<div style="display:grid;&hellip;">
  <fieldset card>
    <header>Getting Started</header>
    <main>&hellip;</main>
  </fieldset>
  &hellip;
</div>

count-up

On: any element, <progress>

Animates from start (default 0) to the element's text value using IntersectionObserver.

Total Deployments
7,342
Active Users
12,847
Uptime
99.97%
<strong count-up duration="2500">7,342</strong>
<span count-up duration="2000">12,847</span>
<span count-up start="90" duration="1500">99.97%</span>

On <progress> — animates the value attribute:

Storage Used

2,500 / 3,000 GB

<progress count-up value="2500" max="3000"></progress>
<span count-up duration="2000">2,500</span> / 3,000 GB

Disclosure

accordion

On: <details>

What is ForgeSprinkle?

A set of HTML attribute enhancements. Each directive is self-contained and degrades gracefully.

Does it require a build step?

No. Drop in the CSS and JS files. No bundler, no npm, no configuration.

What about accessibility?

Uses native <details> semantics. aria-expanded is handled automatically.

<details accordion="faq">
  <summary>Question</summary>
  <p>Answer.</p>
</details>

close-outside

On: <details>, <dialog>

Click me

Click outside to close this panel.

<details close-outside>
  <summary>Click me</summary>
  <p>Click outside to close.</p>
</details>

open-group / close-group

On: <button>

Item A

Content A

Item B

Content B

<button open-group="faq">Expand all</button>
<button close-group="faq">Collapse all</button>

Visual

sticky

On: any element

Scroll down — I stick to the top.

Scroll down to see the sticky element catch.

It should be stuck at the top of this box now.

More content to ensure scrolling.

<div sticky>I stick to the top.</div>

zoomable

On: <img>

Demo image
<img src="photo.jpg" zoomable />

copy / copy="#id"

On: any element

<button copy>Copy my label</button>
<input value="hello@example.com" copy />

loading

On: <button>

<button loading>Save</button>

switch

On: <input type="checkbox">

<input type="checkbox" switch />

truncate="N"

On: any element

This is a long paragraph that gets clamped to two lines. The "Show more" button appears at the end of the clamped text. Clicking it reveals the full content, and clicking "Show less" collapses it back. This pattern is useful for card previews, article excerpts, and comment threads where you want to show a preview before expanding. This is especially handy when you have variable-length content and want a consistent card height.

<p truncate="2">Long text&hellip;</p>

tooltip

On: any element

&#x2705; Verified
<button tooltip="This cannot be undone">Delete</button>
<span tooltip="Verified account">✅ Verified</span>

avatar

On: <img>

<img avatar="sm" />
<img avatar />
<img avatar="lg" />

Other

confirm-leave

On: <form>

<form confirm-leave>
  <textarea></textarea>
</form>

otp

On: <input>

<input type="number" min="6" max="6" otp />

enhance

On: <form>

Ajax form submission with loading states, validation errors, and server response handling.

<form enhance method="post" action="/api/submit">
  <input name="email" type="email" required />
  <button loading>Submit</button>
</form>

theme-toggle

On: any element

Toggles data-sprinkle-theme between light and dark on click. Persists to localStorage.

Click the sun icon button at the top of this page to toggle the theme.

<button theme-toggle>
  <svg>&hellip;</svg>
</button>

Guides

Icons

Place SVGs in /assets/svg/{name}.svg. Reference by name (no extension):

<input leading="search" placeholder="Search…" />
<input type="password" leading="lock" suffix="eye" />

Visibility toggle: suffix on type="password" swaps between {name}.svg and {name}-off.svg on click.

Clear button: suffix="close" or suffix="clear" clears the input on click.

Custom path: Override the SVG directory with a <meta> tag:

<meta name="sprinkle-svg-path" content="/custom/path/to/icons">

When suffix is present, clearable is ignored.

Accessibility

  • aria-live="polite" on character counters and drop-zone announcements
  • aria-expanded on truncate toggles and accordion summaries
  • role="switch" and aria-checked on switch toggles
  • role="alert" and aria-describedby on validation errors
  • role="tooltip" on tooltip elements
  • WAI-ARIA combobox pattern on [combo-box]: role="combobox", role="listbox", role="option", aria-expanded, aria-haspopup, aria-multiselectable, aria-selected, aria-posinset, aria-setsize
  • aria-current="page" automatically set on active links in ul[nav]
  • aria-label on drop-zone remove buttons
  • Keyboard navigation on OTP (arrow keys, backspace, auto-advance)
  • Native <details> / <summary> keyboard behavior preserved in dropdown mode

Extending

Custom directives can be added via the global ForgeSprinkle namespace:

ForgeSprinkle.register('my-attr', function (el) {
  el.style.border = '2px solid gold'
})

Register before DOMContentLoaded. The handler runs on matching elements at init and on dynamically added elements via MutationObserver.