@wentools/ui
@wentools/ui
Styled, accessible Svelte 5 interface primitives for Wentools applications.
The package provides scoped component styles and an optional reset-free foundation stylesheet. It does not provide fonts, application branding, or a global element reset.
Install
pnpm add @wentools/ui @wentools/iconic
Svelte 5.50 or newer and @wentools/iconic are peer dependencies. Breadcrumbs and SplitButton
also need the optional @wentools/overlay peer:
pnpm add @wentools/overlay
Setup
Load the default Wentools foundation before application overrides:
import '@wentools/ui/styles.css'
import './app.css'
Applications that already load compatible spacing, typography, and semantic theme tokens can omit the foundation stylesheet.
Usage
<script lang="ts">
import { Button, NavRow, ProgressBar } from '@wentools/ui'
</script>
<Button variant="primary">Save</Button>
<NavRow href="/settings" title="Settings" />
<ProgressBar mode="progress" value={65} label="Upload progress" />
Overlay-backed components use explicit subpaths so applications that do not use them do not need Overlay:
<script lang="ts">
import { Breadcrumbs } from '@wentools/ui/breadcrumbs'
import { SplitButton } from '@wentools/ui/split-button'
</script>
Icons
Components render string icon names through the application-owned @wentools/iconic resolver. Add
the names in UI_REQUIRED_ICONS to the resolver configured by the application root. With Lucide:
import { createIconResolver } from '@wentools/iconic'
import { AlertCircle, Check, ChevronDown, ChevronRight, Loader, Minus, X } from '@lucide/svelte'
export const iconResolver = createIconResolver({
'alert-circle': AlertCircle,
check: Check,
'chevron-down': ChevronDown,
'chevron-right': ChevronRight,
loader: Loader,
minus: Minus,
x: X,
})
Pass this resolver to setIconResolver in the application root. Components that accept icon props
can also use additional names from the same application resolver.
Exports
The root export includes:
- Button, IconButton, CycleButton, and Checkbox
- TextInput, Select, FilterSelect, FormField, Slider, and RangeSlider
- Modal, ConfirmModal, ModalActions, Details, and DescriptionList
- NavRow, Picker, TabPanels, Tag, SectionHeader, ProgressBar, and RotatingLoader
- Sortable and
useSortable UI_REQUIRED_ICONSand public component types
Focused exports are also available from @wentools/ui/cycle-button, filter-select, picker,
progress-bar, slider, sortable, and tab-panels. Sortable's pure helpers are exported from
@wentools/ui/sortable/logic.
Typography
Component typography uses semantic classes from @wentools/css-base. Raw font-size custom
properties are not part of the contract.
Development
pnpm run format
pnpm run verify
verify checks formatting and types, runs unit and DOM tests, audits the packed file list, and
builds temporary Vite consumers from the generated tarball. It also builds the static component
gallery, runs its desktop and mobile Chromium accessibility and interaction checks, and validates
both Cloudflare Worker configurations with Wrangler dry runs.
Run the local gallery at http://127.0.0.1:5190:
pnpm run gallery:dev
Hosted gallery
Protected release tags publish the tested gallery through Cloudflare Workers Static Assets:
- Beta tags deploy to
https://beta-ui.wentools.dev. - Stable tags deploy to
https://ui.wentools.dev.
The deployment starts only after the matching npm publication succeeds. It writes the tag and
commit to /deployment.json, deploys the build/ artifact produced by verification, and checks the
live metadata, representative routes, response headers, and 404 behavior before the pipeline can
pass. Publication and deployment share one oldest-first release lock, and deployment fails before
upload if its version is no longer the current npm dist-tag.
The GitLab project requires these protected CI/CD variables. Add each key twice, once with
environment scope beta-gallery and once with environment scope production-gallery. Do not use
the default * scope because verification jobs do not need Cloudflare access.
CLOUDFLARE_API_TOKEN: masked and hidden token created from Cloudflare's Edit Cloudflare Workers template, scoped to the account and thewentools.devzone.CLOUDFLARE_ACCOUNT_ID: protected account ID for the account that owns thewentools.devzone.
Wrangler custom domains manage the DNS records and TLS certificates. Do not create CNAME records
for ui.wentools.dev or beta-ui.wentools.dev. Never deploy the hosted gallery from a developer
machine.
Cloudflare retains previous Worker versions. If a live deployment is defective, roll it back in
the Cloudflare dashboard or, from an authorized operator shell, with
pnpm exec wrangler rollback --env beta or pnpm exec wrangler rollback --env production. Then
publish a corrected release. If npm publication passed but deployment failed, retry only the
deployment job because npm versions are immutable. Verified artifacts remain available for eight
days. After that, retry the verification job to recreate build/, then retry deployment without
rerunning publication.
Release
GitLab CI publishes only from protected version tags. Every release tag first runs the complete
verification suite and publishes the audited dist/ artifact from that job.
For a beta of the version in package.json, update local main from its remote before creating a
numbered prerelease tag:
git switch main
git pull --ff-only
VERSION="$(node -p "require('./package.json').version")"
git tag "v${VERSION}-beta.0"
git push origin "v${VERSION}-beta.0"
The pipeline publishes that version with the npm beta dist-tag. After validating the beta in a
consumer, publish the manifest version with a stable tag:
git switch main
git pull --ff-only
VERSION="$(node -p "require('./package.json').version")"
git tag "v${VERSION}"
git push origin "v${VERSION}"
Before starting a new release line, update package.json, run pnpm run verify, and commit the
version change. Wait for each release pipeline to finish before creating another release tag. The
pipeline rejects tags whose commit is not contained in main and versions that would move an npm
dist-tag backward. It then deploys and verifies the matching hosted gallery. Never publish or deploy
directly from a developer machine or from an untagged branch.