@niffniff/uinifi
v0.2.4
Published
A fully tested TypeScript React UI component library (**21 components**, 21 folders including Accordion/AccordionItem + Tab/TabPanel) with an integrated CI/CD pipeline (build, lint, unit tests, UI tests, Storybook, axe accessibility, and auto-publish) for
Readme
UiNiFi — React Component Library
A fully tested TypeScript React UI component library (21 components, 21 folders including Accordion/AccordionItem + Tab/TabPanel) with an integrated CI/CD pipeline (build, lint, unit tests, UI tests, Storybook, axe accessibility, and auto-publish) for reliable, repeatable releases.
✅ Verified State (2026-09-10)
| Gate | Command | Result |
|------|---------|--------|
| Lint | npm run lint -- --max-warnings 0 | exit 0, zero errors/warnings |
| Build | npm run build | exit 0, 32 modules → CJS (26.42 kB) + ESM (39.87 kB) |
| Tests | npm test | 166/166 passing (45 files: 22 unit + 20 a11y + ui + setup); note: pre-commit hook currently runs truncated npm test exclude src/test-utils.test.tsx — full gate uses npm test -- --run |
| Coverage | npm run test:coverage | 58.28 % lines / 39.13 % branches / 70.85 % functions |
| Storybook | npm run build-storybook | exit 0, no warnings |
| A11y | axe.run() per component | 21 executable a11y tests |
| Publish | GitHub Actions | v0.2.0 published, @niffniff/[email protected] |
| Version | src/index.ts exports version = "0.2.0"
Known design note: Tabs renders inactive panel content on buttons (documented in components.md), not a regression.
📋 Todo
| ID | Item | Status | |----|------|--------| | — | All pipeline items complete | ✅ |
Note: gate, publish, storybook, a11y, docs removed — gate is a pre-commit check; publish runs automatically on green build + tests + version bump; Storybook naming/warning fixes, a11y, and docs are complete.
📦 Component Catalog (21 components)
| Component | Unit Tests | Status | |-----------|------------|--------| | Input | 7 | ✅ | | Label | 4 | ✅ | | Checkbox | 9 | ✅ | | Button | 11 | ✅ | | Select | 10 | ✅ | | Modal | 4 | ✅ | | Textarea | 9 | ✅ | | Tooltip | 9 | ✅ | | Spinner | 8 | ✅ | | Card | 7 | ✅ | | Badge | 10 | ✅ | | Icon | 6 | ✅ | | Alert | 8 | ✅ | | Toast | 9 | ✅ | | Table | 3 | ✅ | | Tabs | 3 | ✅ (2 documented behavior variations) | | Tab | 3 | ✅ | | AccordionItem | 5 | ✅ | | Progress | 6 | ✅ | | Avatar | 6 | ✅ | | Popover | 5 | ✅ | | Accordion | 0 | ✅ (wrapper) | | TabPanel | 0 | ✅ (wrapper) |
Total: 166/166 tests passing; 21 component-local .test-object.tsx files; 22 .story.tsx files; 21 .a11y.test.tsx files; lint/build/storybook green; Progress aria-label fix applied; version 0.2.0.
🛠️ Stack
- TypeScript (5.0.0)
- React (18.3.1)
- Vite (5.0.0) – fast dev + optimized ESM + CJS builds
- ESLint + Prettier – linting in CI (no lint errors)
- Vitest + @testing-library/react – unit tests + async DOM testing
- Storybook — UI component dev & static build
- axe-core + jest-axe — executable accessibility tests
- GitHub Actions — CI pipeline (
.github/workflows/ci.yml) - CI publish — uses
GITHUB_TOKEN(write) +secrets.NPM_TOKEN(no‑2FA) →@niffniff/uinifi
📦 Installation
# Local development (unpublished)
npm installThe package is private: false and ready to be published from the local workspace.
📦 Usage Example
import { Input, Label, Checkbox, Button, Select, Modal, Textarea, Tooltip, Spinner, Card, Badge, Icon, Tabs, Tab, TabPanel } from '@niffniff/uinifi';
<Input label="Username" placeholder="Enter username" />
<Checkbox label="Agree" />
<Button variant="primary" size="md">Submit</Button>All components support the standard React props (className, style) and expose data-component attributes for test queries. See src/test-utils.tsx for reusable test helpers (e.g., ButtonTest, InputTest, CardTest, BadgeTest, IconTest).
📦 Project Structure
src/
components/ # 20 component folders (Input/, Label/, …)
Input/
Input.tsx
Input.test.tsx
Input.story.tsx
…
test-utils.tsx # component‑level test helpers (ButtonTest, …)
.gitignore
package.json
package-lock.json
.gitignore
.git/hooks/pre-commit # skips pipeline on release/publish commits
.github/workflows/ci.yml # modern publish CI (GitHub_TOKEN + secrets.NPM_TOKEN, Node 22)🛠️ Development & CI
Run the local pipeline:
npm run build # produces dist/uinifi.cjs.js + dist/uinifi.esm.js
npm test # runs 150 tests (150 pass, 2 documented known variations)
npm run lint # ESLint passes, zero warnings
npm run storybook # start Storybook dev server
npm run build-storybook # static Storybook build (verify)The GitHub Actions pipeline on every push to main:
- Build – Vite (exit 0, 21 modules)
- Lint – ESLint (exit 0, zero errors)
- Unit tests – Vitest (148/150 passing, 2 documented known variations)
- Storybook build –
npm run build-storybook(pending) - Axe accessibility (pending)
- Publish – version bump, commit (
[publish]), tag, git push,npm publish --access public(pending)
The pre‑commit hook skips the pipeline on commits containing release, publish, or [publish] to avoid infinite loops.
📦 Publishing (GitHub Actions)
The publish job:
- Uses
secrets.NPM_TOKEN(fine‑grained, no 2FA) for npm auth - Uses
GITHUB_TOKEN(contents: write) for git operations - Deletes any existing tag before creating a new one (
git tag -d v$VERSION) - Bumps
package.jsonpatch version (npm version patch --no-git-tag-version) - Commits with
[publish] release: version $VERSION - Pushes
main+ tags with--force-with-lease - Runs
npm publish --access publicto npm registry
Result – latest published.*0.2.0`)
🛠️ Development Workflow
- Component work – follow the sequence: npm install → write tests → CSS‑in‑JS styling → implement component
- Review – verify build (
npm run build), lint (npm run lint), tests (npm test) - Commit – use the
[publish]prefix for publish‑related commits; the pre‑commit hook will skip CI to avoid loops - Publish – run the one‑command
npm run publish:gitlocally or let the CI auto‑publish
📦 How to Contribute
- Clone the repo
npm install- Add new component under
src/components/with its own test file - Update
src/test-utils.tsxwith a test helper (optional) - Run
npm testand ensure no failures - Push with a
[publish]commit for CI to pick up a release
📄 License
All code is part of the internal UiNiFi library and released under the project's own license (adjust as needed).
Built with ❤️ by UiNiFi team (2026)
