Skip to content

markmead/hyperux

Repository files navigation

HyperUX

Behavior-first Alpine.js patterns you can copy, adapt, and ship.

Most component libraries hand you markup and an opinion about how it should look. HyperUX only hands you the behavior — keyboard handling, focus management, ARIA state, event contracts — as a single Alpine.data() registration. Bring your own markup, your own classes, your own design system.

https://js.hyperui.dev

Quick look

<div x-data="huxDialog({ dialogId: 'confirm-delete' })">
  <button type="button" x-on:click="openDialog()">Delete account</button>

  <div
    x-cloak
    x-show="isOpen"
    role="dialog"
    aria-modal="true"
    x-bind:aria-labelledby="dialogTitleId"
  >
    <h2 x-bind:id="dialogTitleId">Delete your account?</h2>
    <button type="button" x-on:click="closeDialog()">Cancel</button>
  </div>
</div>

That's the whole pattern: open/close state, an id for aria-labelledby, and nothing telling you what a dialog should look like. Copy the registration script and markup from js.hyperui.dev, then style it however you like.

Patterns

Pattern What it does
huxCombobox Filterable listbox, single or multi-select
huxCommandPalette Command-palette dialog, composes huxDialog + huxCombobox
huxCopy Clipboard copy via data-hux-copy attribute targets
huxDialog Modal/dialog with optional persistence and seamless modes
huxInlineEditor Click-to-edit with commit/revert and focus management
huxDropdown Accessible dropdown menu with roving-tabindex keyboard navigation
huxResizable Drag-to-resize container with breakpoint tracking
huxScrollSpy TOC + scroll position tracking via IntersectionObserver
huxStepper Multi-step stepper (foundation for a wizard pattern)
huxInfiniteScroll Sentinel watcher that fires load-more; fetching is up to you
huxTabs / huxTabPanel Tabs with roving tabindex, optional hash sync, decoupled panels

Full API, options, defaults, and behavior contracts for each pattern are documented at js.hyperui.dev.

Focus styling

HyperUX ships behavior, not looks — and that includes keyboard focus. The demo markup deliberately omits focus-ring utility classes; the site applies a single global :focus-visible outline in src/styles/global.css. Because that global rule is not part of a copied snippet, copied elements fall back to the browser's default focus outline until you add your own — a global :focus-visible rule or your framework's focus-visible: utilities. This applies to every pattern.

Development

pnpm dev       # wrangler types + astro dev
pnpm build     # wrangler types + astro build
pnpm check     # astro type-check
pnpm lint      # eslint
pnpm format    # prettier

Built with Astro, deployed to Cloudflare Pages.

Contributing

Found a bug, or have an idea for a pattern? Open an issue.

About

Behavior-first Alpine.js patterns you can copy, adapt, and ship.

Resources

Stars

21 stars

Watchers

0 watching

Forks

Contributors