{"_id":"@alisonquinter17/alieta-ui","_rev":"2-2a55a26be0fcffca7e7eaed0a5cf311e","name":"@alisonquinter17/alieta-ui","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@alisonquinter17/alieta-ui","version":"0.1.0","_id":"@alisonquinter17/alieta-ui@0.1.0","maintainers":[{"name":"alisonquinter17","email":"alisondanellaquintero@hotmail.com"}],"homepage":"https://github.com/AlisonQuinter17/Alieta-UI#readme","bugs":{"url":"https://github.com/AlisonQuinter17/Alieta-UI/issues"},"dist":{"shasum":"bcc16661d7035eb53c4304f9462565a153c5cd31","tarball":"https://registry.npmjs.org/@alisonquinter17/alieta-ui/-/alieta-ui-0.1.0.tgz","fileCount":30,"integrity":"sha512-9EA+762ImUJM2hQYjMjGbWWIbIQZ5Xx1ythFrHQqAaR61U6YxBzdxevVeqrG2YzGudJ1mhMWrjOamfCTpWRC7g==","signatures":[{"sig":"MEUCIHdUCgdWF4pkDPHTWLNv0dgJCO5F/oa8On+rlTJ2uRlTAiEAq17MN1Lg7BJgs3/nVltD1WY8cCmK1REP8LhMlbrU5o0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":119942},"main":"dist/index.cjs.js","types":"dist/index.d.ts","module":"dist/index.es.js","gitHead":"ed847196514c772a9859cf17000e2c785dee589d","private":false,"scripts":{"dev":"next dev --turbopack","lint":"next lint","build":"vite build && node extract-classes.js","start":"next start","build:lib":"vite build","storybook":"storybook dev -p 6006","build-storybook":"storybook build","generate-safelist":"node extract-classes.js"},"_npmUser":{"name":"alisonquinter17","email":"alisondanellaquintero@hotmail.com"},"repository":{"url":"git+https://github.com/AlisonQuinter17/Alieta-UI.git","type":"git"},"_npmVersion":"11.4.2","description":"This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","dependencies":{"clsx":"^2.1.1","next":"15.4.2","ionicons":"^7.2.2"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.0.6","react":"19.1.0","eslint":"^9","vitest":"^3.2.4","postcss":"^8.5.6","react-dom":"19.1.0","storybook":"^9.0.17","playwright":"^1.54.1","typescript":"^5","@types/node":"^20","tailwindcss":"^3.4.1","@types/ionic":"^0.0.35","@types/react":"^19","autoprefixer":"^10.4.21","@vitest/browser":"^3.2.4","vite-plugin-dts":"^4.5.4","@eslint/eslintrc":"^3","@types/react-dom":"^19","eslint-config-next":"15.4.2","@vitest/coverage-v8":"^3.2.4","@vitejs/plugin-react":"^4.7.0","@storybook/addon-a11y":"^9.0.17","@storybook/addon-docs":"^9.0.17","@storybook/nextjs-vite":"^9.0.17","@storybook/addon-vitest":"^9.0.17","eslint-plugin-storybook":"^9.0.17","@chromatic-com/storybook":"^4.0.1"},"_npmOperationalInternal":{"tmp":"tmp/alieta-ui_0.1.0_1753405922131_0.22678718149697374","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"_id":"@alisonquinter17/alieta-ui@0.2.0","bugs":{"url":"https://github.com/AlisonQuinter17/Alieta-UI/issues"},"dist":{"shasum":"88a3c3e09c76a170693332b36f124913a93ee961","tarball":"https://registry.npmjs.org/@alisonquinter17/alieta-ui/-/alieta-ui-0.2.0.tgz","fileCount":11,"integrity":"sha512-FrI6mJyJp+xX0hEXh3R9Ad17BUf3e82bnkxbWv9cE+jGsr2h+iaVmMZELpp4ybWku151Z7wcLQE804b3QuTXqw==","signatures":[{"sig":"MEYCIQC17BE+1SW/HoCBOJTeBRi5pg7jCqLJaYZPcrgkdMXGwgIhAMVEqEfyfzcFJ+CzT4i3WqpBp36NylCakTCIln1g4sl9","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDHbJTiTRbO9XSi+vLvnJVPQAVqsztQm3DhgGHJw/JOFAIgapBt9c36HUSR70Vbgivx4YRursQQkJgG54iLmNGNS0A="}],"unpackedSize":62186},"main":"./dist/index.js","name":"@alisonquinter17/alieta-ui","type":"module","types":"./dist/index.d.ts","author":{"name":"Alison Quintero"},"module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"1e17b29a6c3d67bfd08b80f021e02935d2d24030","license":"MIT","scripts":{"dev":"npm run storybook","lint":"eslint .","test":"vitest run","build":"vite build","check":"npm run lint && npm run typecheck && npm run test && npm run build","prepack":"npm run check","storybook":"storybook dev -p 6006","typecheck":"tsc --noEmit","test:watch":"vitest","build:storybook":"storybook build"},"version":"0.2.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:c55714c5-0017-483c-8634-ee36d6176c33"}},"homepage":"https://github.com/AlisonQuinter17/Alieta-UI#readme","keywords":["react","components","ui-library","typescript","tailwindcss","design-system"],"repository":{"url":"git+https://github.com/AlisonQuinter17/Alieta-UI.git","type":"git"},"_npmVersion":"11.19.0","description":"A small, accessible React component library themed with CSS variables","directories":{},"maintainers":[{"name":"alisonquinter17","email":"alisondanellaquintero@hotmail.com"}],"sideEffects":["**/*.css"],"_nodeVersion":"24.20.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.0.6","jsdom":"^26.1.0","react":"^19.1.0","eslint":"^9.39.1","vitest":"^3.2.4","react-dom":"^19.1.0","storybook":"^9.1.20","@eslint/js":"^9.39.1","typescript":"^5.9.2","@types/node":"^20.19.11","tailwindcss":"^4.3.3","@types/react":"^19.1.9","vite-plugin-dts":"^4.5.4","@types/react-dom":"^19.1.7","@tailwindcss/vite":"^4.3.3","typescript-eslint":"^8.46.4","@testing-library/dom":"^10.4.1","@vitejs/plugin-react":"^4.7.0","@storybook/addon-a11y":"^9.1.20","@storybook/addon-docs":"^9.1.20","@storybook/react-vite":"^9.1.20","@testing-library/react":"^16.3.3","eslint-plugin-storybook":"^9.1.20","@testing-library/jest-dom":"^6.9.1","eslint-plugin-react-hooks":"^5.2.0"},"peerDependencies":{"react":"^18.2.0 || ^19.0.0","react-dom":"^18.2.0 || ^19.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/alieta-ui_0.2.0_1790216695198_0.5380052540353986"}}},"time":{"created":"2025-07-25T01:12:02.024Z","modified":"2026-09-24T02:24:55.431Z","0.1.0":"2025-07-25T01:12:02.390Z","0.2.0":"2026-09-24T02:24:55.298Z"},"bugs":{"url":"https://github.com/AlisonQuinter17/Alieta-UI/issues"},"homepage":"https://github.com/AlisonQuinter17/Alieta-UI#readme","repository":{"url":"git+https://github.com/AlisonQuinter17/Alieta-UI.git","type":"git"},"description":"A small, accessible React component library themed with CSS variables","maintainers":[{"name":"alisonquinter17","email":"alisondanellaquintero@hotmail.com"}],"readme":"# Alieta UI\n\nA small React component library: `Button`, `Icon`, `Loader` and `Spinner`.\n\nAlieta ships a **compiled stylesheet**, so you do not need Tailwind, a\n`safelist`, or any build configuration to use it. Everything visual is driven by\nCSS variables you can override.\n\n> **Pre-1.0 — the API can still change.** While the version is `0.x`, a minor\n> bump (`0.1.x` → `0.2.0`) may contain breaking changes. Pin an exact version if\n> that matters to you.\n\n## Requirements\n\n- React **18.2** or **19** (and the matching `react-dom`)\n- Any React setup: Next.js, Vite, Remix, CRA — Alieta is framework-agnostic and\n  has **zero runtime dependencies**\n\n## Installation\n\n```bash\nnpm install @alisonquinter17/alieta-ui\n```\n\nThen import the stylesheet **once**, at the root of your app:\n\n```ts\nimport \"@alisonquinter17/alieta-ui/styles.css\";\n```\n\nThat is the entire setup. The stylesheet contains no reset and no Tailwind\nPreflight, so it will not restyle your headings, lists or form controls. Every\nclass it defines is namespaced `alieta:*` and every variable `--alieta-*`, so it\ncannot collide with your own CSS.\n\n## Components\n\n### Button\n\n```tsx\nimport { Button } from \"@alisonquinter17/alieta-ui\";\n\n<Button onClick={save}>Save</Button>\n<Button variant=\"secondary\" size=\"large\">Cancel</Button>\n<Button variant=\"destructive\" onClick={remove}>Delete</Button>\n<Button isLoading>Saving...</Button>\n```\n\nA real `<button>`: it forwards its ref, accepts every native button prop, and\ndefaults to `type=\"button\"` so it never submits a form by accident.\n\n| Prop        | Type                                                       | Default     | Notes                                                        |\n| ----------- | ---------------------------------------------------------- | ----------- | ------------------------------------------------------------ |\n| `variant`   | `\"primary\" \\| \"secondary\" \\| \"ghost\" \\| \"destructive\"`      | `\"primary\"` |                                                              |\n| `size`      | `\"small\" \\| \"medium\" \\| \"large\"`                            | `\"medium\"`  |                                                              |\n| `icon`      | `ReactNode`                                                 | —           | Rendered before the label, exactly as given                  |\n| `isLoading` | `boolean`                                                   | `false`     | Disables the button and sets `aria-busy=\"true\"`              |\n| `disabled`  | `boolean`                                                   | `false`     | `isLoading` also disables; `disabled={false}` cannot undo it |\n\nPlus every prop of `React.ButtonHTMLAttributes<HTMLButtonElement>`.\n\n`icon` takes any node — Alieta's `<Icon>`, your own SVG, or a component from an\nicon package:\n\n```tsx\n<Button icon={<Icon name=\"blumio\" iconSize=\"sm\" />}>Bundled icon</Button>\n<Button icon={<MyCheckIcon />}>Your own SVG</Button>\n```\n\nAn icon-only button needs its own accessible name:\n\n```tsx\n<Button aria-label=\"Delete\" icon={<TrashIcon />} />\n```\n\n### Icon\n\n```tsx\nimport { Icon } from \"@alisonquinter17/alieta-ui\";\n\n<Icon name=\"blumio\" iconSize=\"xl\" />            {/* decorative */}\n<Icon name=\"blumio\" iconSize=\"xl\" label=\"Blumio\" /> {/* meaningful */}\n```\n\nIcons are bundled React components — no CDN script, no `<ion-icon>` custom\nelement to register, no icon font. `name` is typed, so only icons that actually\nship can be requested.\n\n| Prop       | Type                                                | Default | Notes                                        |\n| ---------- | --------------------------------------------------- | ------- | -------------------------------------------- |\n| `name`     | `\"blumio\"`                                          | —       | Typed; unknown names are rejected at compile time |\n| `iconSize` | `\"xs\"` … `\"6xl\"`                                    | `\"md\"`  | 12px, 16px, 24px, 36px, 48px, 64px, 96px, 128px, 160px, 192px |\n| `label`    | `string`                                            | —       | Omit for decorative icons (they get `aria-hidden`); set it when the icon carries the meaning |\n\nThe library intentionally ships a **small** registry — right now just the Blumio\nmark. For anything else, pass your own SVG straight to the component that needs\nit. The mark uses `currentColor`, so it takes the colour of its container.\n\n`Icon` is **presentational, not a control.** It renders a `<span>`, which is not\nfocusable and not reachable by keyboard, so it should never be used as a button.\nThe type enforces this: every event handler (`onClick`, `onKeyDown`,\n`onPointerDown`, …), `role`, `tabIndex`, `accessKey`, `autoFocus`,\n`contentEditable` and `draggable` are rejected at compile time. `children` and\n`dangerouslySetInnerHTML` are rejected too, and so are `aria-label` and\n`aria-hidden`, which `Icon` derives from `label`. `className`, `style`, `id`,\n`title`, `data-*` and descriptive `aria-*` attributes are still accepted.\n\nAny interaction belongs on a real control. For a clickable icon, put it inside a\n`Button`:\n\n```tsx\n<Button aria-label=\"Delete\" icon={<Icon name=\"blumio\" iconSize=\"sm\" />} />\n```\n\nThe same goes for interactive tooltips: the trigger must be a focusable element\nsuch as a `Button`, not the icon itself, or keyboard users cannot open it.\n\nA dedicated `IconButton` component is planned for a later release.\n\n### Loader and Spinner\n\n```tsx\nimport { Loader, Spinner } from \"@alisonquinter17/alieta-ui\";\n\n<Loader />                                   {/* full-viewport overlay */}\n<Loader message=\"Loading data...\" />\n<Loader showOverlay={false} />               {/* fills its container */}\n<Spinner label=\"Saving\" />                   {/* inline indicator */}\n```\n\n`Loader` is a single `role=\"status\"` live region containing a decorative\nspinner, so the busy state is announced exactly **once**.\n\n| Prop (`Loader`) | Type        | Default     | Notes                                                    |\n| --------------- | ----------- | ----------- | -------------------------------------------------------- |\n| `message`       | `ReactNode` | —           | A plain string also becomes the accessible name           |\n| `showOverlay`   | `boolean`   | `true`      | Renders as a `position: fixed` full-viewport layer        |\n| `label`         | `string`    | `\"Loading\"` | Accessible name when `message` is absent or not plain text |\n\n**About the overlay:** it is a plain positioned element. It adds no global\nstyles and does **not** lock page scrolling — your app stays in control of that.\n\n| Prop (`Spinner`) | Type                                 | Default     | Notes                                            |\n| ---------------- | ------------------------------------ | ----------- | ------------------------------------------------ |\n| `size`           | `\"small\" \\| \"medium\" \\| \"large\"`     | `\"medium\"`  | 16px, 20px, 32px                                 |\n| `label`          | `string \\| null`                     | `\"Loading\"` | `null` hides it from screen readers — use it next to something that already announces the busy state |\n\nBoth accept `className` and their native element props.\n\n## Theming\n\nEvery colour and shape comes from a CSS variable with a sensible default.\nOverride the ones you care about in your own `:root` — unprefixed declarations\nbeat Tailwind's `@layer`, so you never need `!important`:\n\n```css\n:root {\n  --alieta-color-primary: #2f6f62;\n  --alieta-color-primary-hover: #255a4f;\n  --alieta-radius: 0.75rem;\n}\n```\n\nYou can scope an override to any subtree instead of the whole page:\n\n```tsx\n<section style={{ \"--alieta-color-primary\": \"#2f6f62\" } as React.CSSProperties}>\n  <Button>Themed just in here</Button>\n</section>\n```\n\n### Tokens\n\n| Token                             | Default   | Used by                                  |\n| --------------------------------- | --------- | ---------------------------------------- |\n| `--alieta-color-primary`          | `#6d28d9` | Primary button background                |\n| `--alieta-color-primary-hover`    | `#5b21b6` | Primary button hover                     |\n| `--alieta-color-primary-contrast` | `#ffffff` | Text on the primary background           |\n| `--alieta-color-secondary`        | `#6d28d9` | Secondary / ghost border and text        |\n| `--alieta-color-secondary-hover`  | `#5b21b6` | Secondary / ghost hover                  |\n| `--alieta-color-danger`           | `#be123c` | Destructive button                       |\n| `--alieta-color-danger-hover`     | `#9f1239` | Destructive button hover                 |\n| `--alieta-color-surface`          | `#ffffff` | Loader overlay background                |\n| `--alieta-color-border`           | `#d4d4d8` | Border of disabled outlined buttons      |\n| `--alieta-color-muted`            | `#52525b` | Loader message text                      |\n| `--alieta-color-disabled-surface` | `#e4e4e7` | Disabled button background               |\n| `--alieta-color-disabled-content` | `#71717a` | Disabled button text                     |\n| `--alieta-radius`                 | `0.5rem`  | Button corner radius                     |\n| `--alieta-focus-ring`             | `2px solid var(--alieta-color-primary)` | `:focus-visible` outline |\n| `--alieta-focus-ring-offset`      | `2px`     | Gap between the ring and the element      |\n| `--alieta-text-body-s/m/l`        | `0.875` / `0.9375` / `1rem` | Small / medium / large button text |\n\nThe defaults meet WCAG AA: white on `--alieta-color-primary` is 7.1:1, and\n`--alieta-color-danger` on white is 6.3:1. If you change these colours, check\nthe contrast of your own pair.\n\n## Usage in Next.js\n\nAlieta is a plain React library — it does **not** depend on Next.js and will not\npull a copy of it into your project. Import the stylesheet in your root layout:\n\n```tsx\n// app/layout.tsx\nimport \"@alisonquinter17/alieta-ui/styles.css\";\nimport \"./globals.css\"; // your own CSS last, so your token overrides win\n\nexport default function RootLayout({ children }: { children: React.ReactNode }) {\n  return (\n    <html lang=\"en\">\n      <body>{children}</body>\n    </html>\n  );\n}\n```\n\nThe components are plain client-side React. They have no `\"use client\"`\ndirective, so import them from a Client Component (or add the directive in your\nown wrapper) when you need interactivity.\n\n## Usage in Vite\n\n```tsx\n// src/main.tsx\nimport \"@alisonquinter17/alieta-ui/styles.css\";\n```\n\nNothing else to configure.\n\n## Local development\n\n```bash\nnpm ci                  # install\nnpm run dev             # Storybook on http://localhost:6006\nnpm run lint            # ESLint\nnpm run typecheck       # tsc --noEmit\nnpm test                # Vitest, once\nnpm run test:watch      # Vitest, watch mode\nnpm run build           # build dist/ (JS, styles.css, .d.ts)\nnpm run build:storybook # static Storybook\nnpm run check           # lint + typecheck + test + build\n```\n\n### Storybook\n\n`npm run dev` (or `npm run storybook`) opens Storybook on port 6006. It loads\nthe same `styles.css` that ships in the package, so what you see there is what\nconsumers get. The a11y addon reports accessibility violations in its panel.\n\n### Tests\n\nVitest with jsdom and Testing Library. No browser download is needed, so\n`npm test` works the same locally and in CI.\n\n### Build\n\nVite in library mode produces:\n\n- `dist/index.js` — ESM. React and the JSX runtime stay external.\n- `dist/styles.css` — the compiled stylesheet (Tailwind v4 with `prefix(alieta)`, no Preflight).\n- `dist/**/*.d.ts` — type declarations, excluding stories and tests.\n\nTailwind is a **build-time** tool here. It never reaches the consumer.\n\n## Publishing\n\n`npm publish` is not run by hand. Publishing happens through GitHub Actions\nusing npm **Trusted Publishing** (OIDC) — there is no `NPM_TOKEN` and no secret\nanywhere in the repository.\n\n1. Update the version with `npm version <patch|minor|major>` and push the commit\n   and tag.\n2. Create a **GitHub Release** for that tag.\n3. Publishing the release runs `.github/workflows/publish.yml`, which installs,\n   lints, typechecks, tests, builds, and only then publishes. If any step fails,\n   nothing is published.\n\n### One-time npm setup\n\nOn npmjs.com, under the package's **Settings → Trusted Publisher**, register\nexactly:\n\n| Field             | Value             |\n| ----------------- | ----------------- |\n| GitHub owner      | `AlisonQuinter17` |\n| Repository        | `Alieta-UI`       |\n| Workflow filename | `publish.yml`     |\n| Allowed action    | `npm publish`     |\n\nLeave the environment field empty (the workflow does not use one).\n\n## Versioning\n\n[Semantic Versioning](https://semver.org). While the package is `0.x`, minor\nreleases may break the API — see the pre-1.0 note at the top.\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","readmeFilename":"README.md","keywords":["react","components","ui-library","typescript","tailwindcss","design-system"],"author":{"name":"Alison Quintero"},"license":"MIT"}