ans-vite-lib
v0.3.2
Published
Vue 3 component library of the ANS front-end apps, built on PrimeVue 3.37. ES module output, styles in `dist/style.css`.
Readme
ans-vite-lib
Vue 3 component library of the ANS front-end apps, built on PrimeVue 3.37. ES module output, styles in dist/style.css.
Package manager
pnpm is the single official package manager (version pinned in package.json).
corepack enable
pnpm install --frozen-lockfile
pnpm test:ciCommit only pnpm-lock.yaml; do not commit package-lock.json or yarn.lock.
Install and register
pnpm add ans-vite-lib vue@^3.2.47 primevue@^3.37.0In main.ts:
import App from "./App.vue";
import { createApp } from "vue";
import PrimeVue from "primevue/config";
import AnsLib from "ans-vite-lib";
import "ans-vite-lib/dist/style.css";
createApp(App).use(PrimeVue).use(AnsLib).mount("#app");vue ^3.2.47 and primevue ^3.37.0 are required peer dependencies.
Import your chosen PrimeVue theme in the host application before the library stylesheet. use(AnsLib) registers every component globally and registers PrimeVue's
ToastService only if the host (or another copy of the lib in a federated remote) did not register one.
You can also import components by name: import { VButton } from "ans-vite-lib".
Components
| Component | Notes |
|---|---|
| VButton | type: primary, secondary, tertiary, danger. size: sm, md, lg. Unknown types fall back to primary. |
| VInput | Text input with floating label and accessible validation errors. |
| VPInputText | Legacy text input; deprecated in favor of VInput. |
| VInputSelect | Single-choice dropdown. |
| VInputMultiSelect | Multiple-choice dropdown. |
| VTextArea | Multiline text input. |
| VInputNationalId | National ID input with validation. |
| VInputNumber | General numeric input. |
| VInputInteger | Integer input with accessible validation errors. |
| VInputDecimal | Decimal input with accessible validation errors. |
| VInputEmail | Email input with accessible validation errors. |
| VInputEmailChips | Multiple email addresses as chips. |
| VInputPhone | Phone input with accessible validation errors. |
| VInputMaskPhone | Masked phone input with optional country-code storage. |
| VInputMask | Text input with an input mask. |
| VInputHidden | Password input with a visibility toggle. |
| VToast + useAnsToast() | Mount <VToast /> once per PrimeVue copy (two in the same copy show every toast twice; a federated remote with its own PrimeVue copy needs its own); call useAnsToast().success/info/warn/error(summary, detail?, options?). Default life is 3000 ms; options support life, sticky and group. |
| VDialog | v-model:visible, header, modal, closable, width, footer slot. |
| VDataTable | Wraps PrimeVue DataTable: value, loading, emptyMessage, paginator, rows. Pass Column children. |
| VSafeHtml | Renders html through DOMPurify (scripts, event handlers, javascript: URLs, <style>, forms and iframes removed; inline style attributes are kept). Use it instead of v-html for any content that does not come from the code. |
| VCalendar | Date selection control. |
| VRadioButton | Radio selection control. |
| VInputSwitch | Boolean switch. |
| VTitle | Heading with primary (h1), secondary (h2) and tertiary (h3) variants. |
| VSpinner | Loading indicator with optional message. |
| VContainerBox | Container with configurable padding and background. |
See docs/components/input-matrix.md for validation and accessibility coverage by input variant.
VDialog uses its header as its accessible name; pass aria-label (the ariaLabel prop) to override the Spanish fallback “Diálogo” when omitting the header.
VInputBase is internal and is not exported from the public component entry.
Toast API
import { useAnsToast, type AnsToastOptions } from "ans-vite-lib";
const toast = useAnsToast();
const options: AnsToastOptions = { life: 6000, group: "orders" };
toast.success("Saved", "Order updated", options);
toast.info("Refreshing", undefined, { life: 4000 });
toast.warn("Review required");
toast.error("Save failed", "Try again", { sticky: true });All four methods accept (summary: string, detail?: string, options?: AnsToastOptions).
life is in milliseconds and defaults to the exported TOAST_LIFE (3000).
sticky: true omits life, keeping the toast until dismissed even if life is also set.
group routes to a matching <VToast group="orders" />; mount an ungrouped <VToast />
for messages without a group. Mount only one toast per group per PrimeVue copy.
Design tokens
Defined in src/assets/tokens.css and shipped in dist/style.css. It is the single source of truth for color, spacing,
radius, typography and shadow: the PrimeVue theme in prime-theme.css reads the primary token, and a host such as ans-portal
should read the same variables instead of redefining colors. Names are semantic, never values. New component CSS must use
them; pnpm lint warns on raw hex values.
| Group | Tokens | Notes |
|---|---|---|
| Brand and semantic color | --ans-color-primary, --ans-color-primary-contrast, --ans-color-brand-dark, --ans-color-error, --ans-color-success, --ans-color-warning, --ans-color-info | Palette decided in PRO-246: primary #6E3BDA (actions, links, focus), brand-dark #631E74 (brand accent and dark headers; no longer the primary), contrast #F7F7F8. |
| Neutrals | --ans-neutral-0, -10, -20, -40, -60, -80, -100 | White to black. |
| Spacing | --ans-space-1 to --ans-space-8 | 0.25rem steps. |
| Radius | --ans-radius-sm, -md, -lg, -pill | |
| Typography | --ans-font-xs to --ans-font-xl (size), --ans-font-family, --ans-font-family-display, --ans-font-weight-regular, -medium, -bold, --ans-line-height-tight, -base | |
| Shadow | --ans-shadow-sm, -md, -lg | |
A host app that does not load dist/style.css can still read the tokens on their own: import "ans-vite-lib/tokens.css"
(only the variables, no component styles). ans-portal does this so its Windi config and its own PrimeVue theme read the same values.
Changing the primary is one line in tokens.css. From 0.3.0, --ans-color-primary is #6E3BDA (it was #631E74): apps that
bump will see the PrimeVue theme and the lib components in the new primary. Apps that stay on an older version are not affected.
Moving an app from hex to tokens (PRO-248)
- Codemod, dry run by default:
node scripts/codemod/hex-to-tokens.mjs <app-dir>...reports, per app, how many hex it covers (exact= same value as the token,near= visually close, needs a visual review), what is left, and thefont-sizein px. The mapping isscripts/codemod/hex-token-map.json.--applywrites onlyexact, and only inside the<style>blocks of.vuefiles and in.css/.scss;--include-nearwidens it to the near mappings and--include-tsto hex outside<style>(.ts, and the template and<script>of.vue, wherevar(--token)only works if the value ends up in CSS, so review that diff). The report counts that hex under "Outside style blocks". It skipsprime-theme.css, specs,url(#...)anchors,&#...;entities and id selectors that look like a color (#abc { ... },#fade, .x { ... }); a hex used as a value is never skipped. Known limit: a hex inside a CSS comment is still counted. The latest run over everyfrontend.k8s.*is indocs/codemod/PRO-248-dry-run.md. - Stylelint, warnings only:
{ "extends": "ans-vite-lib/stylelint" }warns on raw hex (color-no-hex) andpxinfont-size. The app needsstylelintand, for.vuefiles,postcss-html; both are declared as optional peer dependencies (^15.11.0and^1.8.1), so your package manager warns if they are missing. Generated files (prime-theme.css,tokens.css) go in the app's ownignoreFiles. It does not cover thefontshorthand or hex inside<script>/<template>.
Develop
The repo uses pnpm (packageManager in package.json, lockfile pnpm-lock.yaml); run pnpm install --frozen-lockfile once.
| Command | What it does |
|---|---|
| pnpm dev | Local Vite playground on port 3001. |
| pnpm test | Run Jest unit tests. |
| pnpm storybook | Component catalog on http://localhost:6006 (stories live in stories/). |
| pnpm build-storybook | Static catalog in storybook-static/. |
| pnpm test:ci | Jest with coverage and thresholds. |
| pnpm typecheck | vue-tsc over src. |
| pnpm lint | Stylelint (raw hex colors are warnings). |
| pnpm build | Declarations plus ES bundle into dist/. |
pnpm test:ci writes HTML coverage to coverage/lcov-report/index.html.
Global thresholds are 85% statements, 60% branches, 80% functions and 85% lines.
Stories use a global autodocs tag. Docs pages are generated by @storybook/addon-docs.
Adding a component
- Write the spec in
src/tests/unit/<name>/first and watch it fail. - Add
src/components/<name>/V<Name>.vue, export it fromsrc/components/index.ts. - Use tokens, associate labels and errors with
for/aria-describedby, keep the focus order sane. - Add a story in
stories/V<Name>.stories.tscovering each variant and state. - Run
pnpm test:ci && pnpm typecheck && pnpm build.
Never export a non-component from src/components/index.ts: install() registers every export there as a global component.
Versioning
Versions are published manually by the lib owner. While the major is 0, a minor bump may contain breaking changes:
list them in CHANGELOG.md under that version. Deprecate before removing (@deprecated JSDoc plus a changelog line).
To release, a maintainer:
- Bumps
package.jsonto the intended version and updatesCHANGELOG.md, including breaking requirements. - Runs
pnpm install --frozen-lockfile,pnpm typecheck,pnpm lint,pnpm test:ci,pnpm buildandpnpm build-storybook. - Reviews and commits the release changes, then creates the matching
vX.Y.ZGit tag. - Publishes to the npm registry with
pnpm publish(maintainer only), then pushes the release commit and tag.
The library does not publish automatically. Consuming apps must align the peer dependencies before upgrading.
