@spearheadops/ui
v1.0.2
Published
A Vue 3 component library extracted from the Spearhead project. It provides a set of pre-styled, accessible UI primitives intended for use by clients building custom forms and interfaces that integrate with Spearhead.
Readme
@spearheadops/ui
A Vue 3 component library extracted from the Spearhead project. It provides a set of pre-styled, accessible UI primitives intended for use by clients building custom forms and interfaces that integrate with Spearhead.
Installation
npm install @spearheadops/uiThis package requires Vue 3.5+ and Vue Router 4+ as peer dependencies.
Setup
Import the stylesheet once in your application entry point:
import '@spearheadops/ui/style.css'Then import components as needed:
import { SHButton, SHField, SHInput } from '@spearheadops/ui'Dark Mode
Components support dark mode via Vue's provide/inject system. Provide the DarkModeKey at the root of your app with a reactive boolean:
import { provide, ref } from 'vue'
import { DarkModeKey } from '@spearheadops/ui'
provide(DarkModeKey, ref(true)) // or false for light modeComponents
AppLink
A unified link component that renders as a <router-link> when given a to prop, or a plain <a> tag for external href links. Renders as a non-interactive <span> when disabled.
<AppLink :to="{ name: 'home' }">Go home</AppLink>
<AppLink href="https://example.com">External link</AppLink>
<AppLink disabled>Not clickable</AppLink>Props: to, href, disabled, active, block, prefix, activeClass, inactiveClass, exactActiveClass
SHAlert
A dismissible banner fixed to the top of the page. Supports an optional "Don't show again" checkbox and a countdown mode.
<SHAlert :visible="showBanner" @hide-alert="showBanner = false">
<template #message>Your session will expire soon.</template>
</SHAlert>
<!-- With "don't show again" option -->
<SHAlert :visible="show" dont-show-again @hide-alert="() => (show = false)">
<template #message>Welcome back!</template>
</SHAlert>Props: visible, dontShowAgain, countdown
Events: hide-alert(dontShowAgain?: boolean)
Slots: message, action, close
SHBadge
An inline label with a colored border, used to display status or category tags.
<SHBadge color="var(--color-primary)">Active</SHBadge>
<SHBadge color="var(--color-danger)" :reverse-color="true">Overdue</SHBadge>Props: color (CSS color string, default var(--color-surface-400)), reverseColor (fills background with the color), clickable
SHButton
A styled button with support for size variants, color themes, loading state, and optional router navigation.
<SHButton @click="save">Save</SHButton>
<SHButton color="danger" size="sm" @click="remove">Delete</SHButton>
<SHButton color="primary" :loading="isSaving">Saving…</SHButton>
<SHButton :to="{ name: 'dashboard' }">Go to Dashboard</SHButton>Props:
color—ButtonTheme:primary,secondary,danger,success,warning,info, orsurface-{0–900}(default:surface-200)size—sm|md|lg(default:md)disabled,loading,active,square,fullWidthto— Vue RouterRouteLocationNamedRawfor navigationhref— URL for external navigationinnerClass— class applied to the inner content span
SHCard
A bordered, shadowed container for grouping content. Supports optional header and footer slots.
<SHCard>
<template #header>Card Title</template>
<p>Card content goes here.</p>
<template #footer>Footer actions</template>
</SHCard>
<SHCard :archived="true">Archived item</SHCard>
<SHCard :no-border="true">Borderless card</SHCard>Props: archived (dashed border style), noBorder, noHover
Slots: header, default, footer
SHCheckBox
A checkbox with an optional label and built-in tooltip support. Binds via v-model.
<SHCheckBox v-model="isEnabled">Enable feature</SHCheckBox>
<SHCheckBox v-model="agreed" help="You must agree to continue.">I agree</SHCheckBox>
<SHCheckBox v-model="val" disabled />Props: id, disabled, help, alignRight, selectOnFocus, spellcheck
Model: boolean
SHDollarInput
A currency input that stores values in cents (integers) while displaying them in dollars. Extends SHNumberInput.
<SHDollarInput v-model="priceInCents" />A model value of 1000 displays as $10.00. Emits the rounded cent value on change.
Slots: prefix, suffix
Model: number | null
SHDropdown
A floating popup anchored to its trigger element, powered by Floating UI. Supports both click-to-toggle and hover modes.
<SHDropdown>
<SHButton>Open menu</SHButton>
<template #popup="{ close }">
<ul>
<li @click="close">Option 1</li>
<li @click="close">Option 2</li>
</ul>
</template>
</SHDropdown>
<!-- Tooltip on hover -->
<SHDropdown open-on-hover>
<span>Hover me</span>
<template #popup>More info here.</template>
</SHDropdown>Props: disabled, placement (default: bottom-start), strategy, offset, flip, shift, autoPlacement, matchWidth, openOnHover, teleportToBody
Slots: default (trigger), popup (receives { toggle, open, close, isOpen, isHovering })
Exposed: open(), close(), isOpen
SHField
A form field wrapper that pairs a label with an input. Handles required state, validation highlighting, inline error messages, and help tooltips.
<SHField label="Email" required :requirement-satisfied="!!email">
<SHInput v-model="email" type="email" />
</SHField>
<SHField label="Notes" block>
<SHTextarea v-model="notes" />
</SHField>
<SHField label="Amount" :invalid="errors.amount">
<SHDollarInput v-model="amount" />
</SHField>Props: label, required, requirementSatisfied, invalid (string shows inline error message, boolean highlights in red), disabled, hideLabel, help, block (stacks label above input), alignRight
Slots: default (the input, receives { myId }), label, labelRight, help
SHInput
A styled text input with support for prefix/suffix content, clearable state, and a loading indicator.
<SHInput v-model="name" placeholder="Enter name" />
<SHInput v-model="query" clearable>
<template #prefix>Search:</template>
</SHInput>
<SHInput v-model="url" type="url" :fetching="isLoading" />Props: id, type (text | number | time | email | tel | date | datetime-local | password), modelValue, placeholder, disabled, clearable, fetching, compact, alignRight, selectOnFocus, spellcheck
Slots: prefix, suffix
Exposed: inputEl, focus(), select()
SHNote
A colored callout block for contextual messages.
<SHNote theme="info">This is an informational note.</SHNote>
<SHNote theme="warning">Please review before continuing.</SHNote>
<SHNote theme="danger">This action cannot be undone.</SHNote>Props: theme — primary | secondary | info | success | warning | danger
SHNumberInput
A numeric input that displays a formatted value (via Intl.NumberFormat) when unfocused, and switches to a plain number input on focus. Useful for clean display of large numbers or decimals.
<SHNumberInput v-model="quantity" />
<SHNumberInput v-model="rate" :decimals="2" align-right />Props: modelValue (number | null), decimals, formatter (Intl.NumberFormat), alignRight
Slots: prefix, suffix
Exposed: focus(), select()
SHPill
A two-section pill badge with a filled left side and a light right side, useful for key/value labels.
<SHPill left="Status" right="Active" color="var(--color-success)" />
<SHPill color="var(--color-primary)" hover-color="var(--color-primary-up-200)">
<template #left>Priority</template>
<template #right>High</template>
</SHPill>Props: left, right, color (default: var(--color-primary)), hoverColor (enables hover effect)
SHSpinner
An animated loading spinner. Used internally by SHButton and SHInput, but available standalone.
<SHSpinner />
<SHSpinner size="sm" />
<SHSpinner size="xs" />Props: size (default: 2x)
SHTextarea
A styled <textarea> with optional auto-resize and compact (underline-only) modes.
<SHTextarea v-model="notes" />
<SHTextarea v-model="bio" auto-resize />
<SHTextarea v-model="comment" compact />Props: compact, autoResize
Model: string | null | undefined
SHToggle
An on/off toggle switch. Binds via v-model.
<SHToggle v-model="isEnabled" />
<SHToggle v-model="setting" disabled />Props: disabled
Model: boolean | null | undefined
SHUndoConfirm
A pair of Cancel/Submit buttons for form footers. Integrates with the DisableFormKey injection to disable submission globally.
<SHUndoConfirm
:confirm-enabled="isValid"
:loading="isSaving"
@undo="reset"
@confirm="submit"
/>
<SHUndoConfirm
confirm-text="Delete"
confirm-color="danger"
:confirm-enabled="true"
@undo="cancel"
@confirm="deleteItem"
/>Props: confirmEnabled, confirmColor (primary | danger | success, default: primary), confirmText (default: Submit), undoText (default: Cancel), hideUndo, loading
Events: undo, confirm
Slots: undo, confirm
SHValidationErrors
Displays a list of validation error messages with an animated striped warning background.
<SHValidationErrors :show="submitted" :errors="errors" />When errors is empty, shows a success state with a default "No invalid fields." message (overridable via the default slot).
Props: show (boolean), errors (string[])
Slots: default (empty-state message), extra
Utility Exports
Formatters
import { centsToDollars, dollarFormatter, formatUSD } from '@spearheadops/ui'
formatUSD(1099) // "$10.99"
centsToDollars(1099) // 10.99Provider Keys
import { DarkModeKey } from '@spearheadops/ui'
// Provide a Ref<boolean> at the app root to propagate dark mode to all componentsimport { DisableFormKey } from '@spearheadops/ui'
// Provide a Ref<boolean> to disable all SHUndoConfirm submit buttons in the subtree