diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 207bd7377..00a665f55 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,3 +1,13 @@ +## Copilot Code Review + +When performing a code review, read [CONTRIBUTING.md](../CONTRIBUTING.md), apply +its [Component PR Rationale and Evidence](../CONTRIBUTING.md#component-pr-rationale-and-evidence) +requirements, and follow its [Reviewing Component Guidance](../CONTRIBUTING.md#reviewing-component-guidance) +procedure. Treat missing or misleading selection guidance and crosslinks as +review findings, not merely optional prose improvements. Scope findings to new +or materially changed components and guidance affected by the PR; do not demand +a catalog-wide documentation rewrite for an unrelated change. + ## Code Quality Principles diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b732badc4..b42fe4533 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' cache: 'pnpm' - name: Install dependencies @@ -62,7 +62,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' cache: 'pnpm' - name: Install dependencies @@ -98,7 +98,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' cache: 'pnpm' - name: Install dependencies @@ -146,7 +146,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' cache: 'pnpm' - name: Install dependencies @@ -188,7 +188,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' cache: 'pnpm' - name: Install dependencies @@ -245,7 +245,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' cache: 'pnpm' - name: Run security audit diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index cdc0f0fb2..8b4f0b10c 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -33,7 +33,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' cache: 'pnpm' - name: Configure Git diff --git a/.storybook/public/dashboard-preview.png b/.storybook/public/dashboard-preview.png new file mode 100644 index 000000000..acbd2587a Binary files /dev/null and b/.storybook/public/dashboard-preview.png differ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8d250bb52..f4917c41e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,16 +15,39 @@ mind whenever you write docs or code comments. | **Consumer** (app developer) | Use a component, theme it, migrate an app | [README.md](README.md), [Storybook](https://ui.mieweb.org), [lessons/](lessons/README.md) | | **Provider / Maintainer** (you) | Add/change a component, fix a bug, cut a release | **This file** + per-component [`MAINTAINERS.md`](#per-component-maintainer-notes) | -Rule of thumb: **consumer docs answer "how do I use it"; provider docs answer "how -do I change it."** Don't mix the two — keep usage in Storybook autodocs and the -README, keep internals/invariants/gotchas in `CONTRIBUTING.md` and `MAINTAINERS.md`. +Rule of thumb: **consumer docs answer "why should I choose it, when should I not, +and how does it fit" as well as "how do I use it"; provider docs answer "how do I +change it."** Keep component guidance in Storybook and internals in this guide +and per-component `MAINTAINERS.md` files. + +## Documentation ownership + +- **Shared introduction:** edit [README.md](README.md). GitHub and npm display it; + [src/Introduction.mdx](src/Introduction.mdx) imports it as raw Markdown and renders + it in Storybook. Keep that wrapper free of a second copy of onboarding prose. +- **Portable content:** use ordinary Markdown and absolute links to published + documentation or GitHub files. Repository-relative links break when rendered + inside Storybook. Heading anchors must work in both renderers. +- **Component guidance:** keep rationale, limitations, alternatives, related + components, and composition examples with the component's stories. Link to + detailed guidance from the introduction instead of maintaining another copy. +- **Agent setup:** the introduction links to [agent/](agent/README.md). Agent rules + and component policy must agree; this shared introduction does not itself + synchronize those separate documents or enforce PR review. +- **Contributor setup and releases:** maintain them here, not in the README. + +When changing the README, check the Introduction page in local Storybook, +including code blocks, tables, heading links, and mobile layout. The README is +included in the npm package's `files` list. GitHub shows changes on the selected +branch; Storybook and npm show the content from their latest deployment or +release, not necessarily the latest Git commit. ## Repository layout ``` src/ index.ts # Public barrel — the main entry point - ag-grid.ts # Separate entry: @mieweb/ui/ag-grid (optional ag-grid deps) + ag-grid.ts # Deprecated entry retained for existing consumers only datavis.ts # Separate entry: @mieweb/ui/datavis (optional datavis-ace dep) esheet.ts # Separate entry: @mieweb/ui/esheet (optional @esheet/* deps) tailwind-preset.ts # Tailwind preset consumers extend @@ -53,6 +76,18 @@ pnpm storybook # http://localhost:6006 If you cloned without `--recurse-submodules`, run `git submodule update --init --recursive` and re-run `pnpm install`. +Use Node.js 24 (the version used by CI) and the pnpm version declared in +`package.json`. The `prestorybook` hook builds eSheet when its required artifacts +are missing; it does not detect every stale build after a submodule update. To +rebuild updated eSheet sources explicitly: + +```bash +pnpm --dir packages/esheet --filter '@esheet/builder...' --filter '@esheet/renderer...' build +``` + +Storybook uses HMR for source and documentation edits. Do not restart it after +each edit; restart when configuration or dependencies change. + ## Everyday commands | Command | Purpose | @@ -67,6 +102,22 @@ If you cloned without `--recurse-submodules`, run | `pnpm test:visual` | Playwright visual regression (serves `storybook-static`; run `pnpm build-storybook` first) | | `pnpm build` | Full library build (tsup + CSS + brand CSS) | +`pnpm dev` rebuilds the library for locally linked consumers; it does not start +Storybook. To try a local build in another application, build the library and use +your package manager's local linking or `file:` dependency support. Import the +same public entry points as a published consumer, including +`@mieweb/ui/styles.css`. + +For a static Storybook build, run `pnpm build-storybook`; output is written to +`storybook-static`. Do not hand-edit generated output. + +### AI story configuration + +For Ozwell-backed stories, follow +[the Ozwell backend guide](src/components/AI/OZWELL-BACKEND.md) for endpoint, +browser-local configuration, and proxy options. Never commit API keys or embed +them in a public Storybook build. + ## Quality gates (must pass before opening a PR) ```bash @@ -103,6 +154,10 @@ Coding conventions (the full standard lives in focus. Modal/overlay components trap focus and close on `Escape`. - **Icons** from `lucide-react`; dates via `luxon`. +For new date parsing, formatting, and comparisons, use Luxon's `DateTime`. Keep +business timezones explicit with IANA identifiers such as `America/New_York`; +prefer ISO-8601 values in storage and transport and localize at the UI boundary. + After adding a component, export it from [src/index.ts](src/index.ts) and (if it should be individually importable) add a `tsup` entry — see [Exports & tree-shaking](#exports-entry-points--tree-shaking). @@ -128,23 +183,25 @@ file should: - The public API is the barrel [src/index.ts](src/index.ts). Everything a consumer can `import { X } from '@mieweb/ui'` must be re-exported there. - **Heavy/optional integrations get their own subpath entry** so they stay out - of the default bundle: `@mieweb/ui/ag-grid`, `@mieweb/ui/datavis`, - `@mieweb/ui/esheet`. These map to `src/ag-grid.ts`, `src/datavis.ts`, - `src/esheet.ts` and to dedicated `tsup` entries. + of the default bundle: `@mieweb/ui/datavis` and `@mieweb/ui/esheet` map to + `src/datavis.ts`, `src/esheet.ts`, and dedicated `tsup` entries. + The deprecated `@mieweb/ui/ag-grid` entry remains for existing consumers only; + do not use it as a starting point for new integrations. - Individually tree-shakeable components are listed explicitly in the `entry` map in [tsup.config.ts](tsup.config.ts). Add yours there if it should be importable as `@mieweb/ui/components/`. - `package.json` `sideEffects` is `["**/*.css"]` — CSS is intentionally side-effectful so it isn't tree-shaken away. Keep JS/TS modules side-effect - free (the AGGrid `ModuleRegistry` call is a deliberate, documented exception). + free (the deprecated AGGrid integration's `ModuleRegistry` call is a legacy + exception, not a pattern for new components). ## Build & bundle - **Bundler:** [tsup](tsup.config.ts) → dual **ESM + CJS**, `target: es2022`, `.d.ts` emitted, sourcemaps, `treeshake` + `splitting` on. JSX is `automatic`. Types build against [tsconfig.build.json](tsconfig.build.json). -- **External:** `react`, `react-dom`, `ag-grid-*`, `datavis-ace`, `@esheet/*` - are never bundled (they're peers). +- **External:** `react`, `react-dom`, `datavis-ace`, and `@esheet/*` are never + bundled (they're peers). Legacy `ag-grid-*` peers remain external for compatibility. - **CSS:** `pnpm build:css` compiles `src/styles/base.css` → `dist/styles.css` via the Tailwind CLI; brand CSS is copied into `dist/brands/`. - **Submodule builds:** `prebuild` runs `build:esheet`, which builds the @@ -196,15 +253,16 @@ If a submodule-backed component fails to resolve, run ## Optional peer dependencies `react` / `react-dom` are required peers. Everything else heavy is **optional**: -`ag-grid-community`, `ag-grid-react`, `datavis-ace`, `@mieweb/datavis`, +`datavis-ace`, `@mieweb/datavis`, `@esheet/builder`, `@esheet/renderer`, `wavesurfer.js`. Components that need them must live behind a subpath entry (not the main barrel) so consumers who don't use them aren't forced to install them. -> **Grids: AGGrid is deprecated — use NITRO DataVis.** `ag-grid-*` is heavy and -> [AGGrid](src/components/AGGrid/MAINTAINERS.md) is deprecated with no new usages -> allowed. Use [DataVisNITRO](src/components/DataVisNITRO/MAINTAINERS.md) -> (`@mieweb/ui/datavis`) for all tables. See those notes for details. +> **Grids: use DataVis NITRO for new work.** The `@mieweb/ui` AGGrid integration +> is deprecated; `ag-grid-community` and `ag-grid-react` remain optional peers +> only for existing consumers. Its source and maintainer notes document legacy +> maintenance, not a recommended choice. Use +> [DataVisNITRO](src/components/DataVisNITRO/MAINTAINERS.md) (`@mieweb/ui/datavis`). ## Per-component maintainer notes @@ -216,14 +274,14 @@ submodule, a module-level side effect, or a non-obvious extension point. Current notes: -| Module | Why it has notes | -| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | -| [AI](src/components/AI/MAINTAINERS.md) | `renderTextContent` extension point; host owns sanitization; reuses the Messaging composer | -| [AGGrid](src/components/AGGrid/MAINTAINERS.md) | Registers AG Grid modules at import; optional peers; brand theming; base vs. enhanced split | -| [ESheet](src/components/ESheet/MAINTAINERS.md) | Implementation is a submodule (nx); needs `build:esheet`; Storybook-only `src` | -| [DataVisNITRO](src/components/DataVisNITRO/MAINTAINERS.md) | Wraps `datavis-ace` + the `@mieweb/datavis` npm package; context/source/grid wiring | -| [FloatingWindow](src/components/FloatingWindow/MAINTAINERS.md) | Manual drag/resize math; modal vs. floating modes; fully controlled | -| [YChart](src/components/YChart/MAINTAINERS.md) | Vanilla editor in a submodule, dynamically imported; not in the public API | +| Module | Why it has notes | +| -------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| [AI](src/components/AI/MAINTAINERS.md) | `renderTextContent` extension point; host owns sanitization; reuses the Messaging composer | +| [AGGrid (deprecated)](src/components/AGGrid/MAINTAINERS.md) | Legacy maintenance only; retained for existing consumers. Use [DataVis NITRO](src/components/DataVisNITRO/MAINTAINERS.md) for new work. | +| [ESheet](src/components/ESheet/MAINTAINERS.md) | Implementation is a submodule (nx); needs `build:esheet`; Storybook-only `src` | +| [DataVisNITRO](src/components/DataVisNITRO/MAINTAINERS.md) | Wraps `datavis-ace` + the `@mieweb/datavis` npm package; context/source/grid wiring | +| [FloatingWindow](src/components/FloatingWindow/MAINTAINERS.md) | Manual drag/resize math; modal vs. floating modes; fully controlled | +| [YChart](src/components/YChart/MAINTAINERS.md) | Vanilla editor in a submodule, dynamically imported; not in the public API | ## Commits, versioning & releases @@ -234,8 +292,155 @@ Current notes: - `prepublishOnly` runs a full build. Never publish from a dirty/un-built tree. - **Never publish without explicit confirmation.** +### Release channels + +| Channel | Install | Source | +| ------------------- | ----------------------------- | --------------------------------------------- | +| Stable (`latest`) | `npm install @mieweb/ui` | Stable version tags | +| Prerelease (`next`) | `npm install @mieweb/ui@next` | Eligible pushes to `main` and prerelease tags | + +The [release workflow](.github/workflows/release.yml) defines the triggers and +path exclusions. A push changing only root-level Markdown files (such as +`README.md`) does not trigger a `main` prerelease, so a README-only update reaches +npm with the next release. Markdown in subdirectories, such as `lessons/`, is not +excluded by `*.md` and can trigger a prerelease. Changes under `.github/` are also +excluded, except for the release workflow itself. + +For a stable release, use GitHub Actions' **Create Stable Release** workflow and +select the semantic version bump. It updates the package version and creates the +tag that triggers publishing. Maintainers can also publish through a deliberate +`v*` tag; inspect the workflow and obtain approval before creating or pushing one. + +## Developing Components From a Consuming Application + +Before proposing a new component, read this guide and audit the component +catalog, related examples, and existing composition patterns. Evaluate candidates +by behavior and user need, not only by name. Document why using, configuring, +composing, or extending existing components does not adequately solve the problem. +Present the gap and supporting evidence before implementation. + +When a reusable gap remains, develop the component so it can be contributed +upstream. Follow the [component checklist](#adding-a-new-component-checklist), +including documentation, accessibility, internationalization, theming, and tests. +Keep application-specific data access and business rules in the consuming +application; expose reusable behavior through a clear public API. Do not invent a +generic abstraction solely to make project-specific code contributable. + +### Coordinated Development With a Submodule + +1. Obtain approval before introducing a submodule or changing the consuming + project's dependency strategy. Reuse an existing checkout when available; + otherwise add `mieweb/ui` as a Git submodule using the project's vendor-directory + convention and an upstream repository or fork accessible to collaborators. +2. Create a focused feature branch in the submodule for development and the + upstream PR. A submodule pins an **exact commit**, not a branch; branch tracking + does not replace the commit recorded by the consuming repository. +3. Configure the application to consume the submodule checkout through its + established build and dependency tooling. Adding a submodule alone does not + replace an installed npm dependency. Verify that the application actually uses + the changed build and does not load a second React runtime. +4. Implement and test the reusable change in the submodule, then verify its + integration in the consuming application. With the required approvals, commit + and push the submodule change before recording its tested revision in the + consumer. The pinned commit must be fetchable by collaborators and CI. +5. Open the upstream and consumer PRs using the process below. After upstream + release, update the consumer to the released package or corresponding submodule + commit according to its dependency policy, removing temporary overrides. + +### Opening the Pull Requests + +Follow each repository's approval requirements for commits, pushes, and PR +creation. This guide is not authorization to publish changes. + +1. Run the [quality gates](#quality-gates-must-pass-before-opening-a-pr) and the + integration checks relevant to the change. Record results and known gaps. +2. Push the feature branch to the upstream repository, or your fork if you lack + write access. Open a PR targeting `mieweb/ui`'s `main` branch using GitHub's + **Compare & pull request** flow or `gh pr create`. For a fork, select + `mieweb/ui:main` as the base and your fork's feature branch as the head. +3. Supply the rationale and evidence below. Use a draft PR while the API, examples, + or required checks are incomplete. Request maintainer review. +4. Open a separate consumer PR for the integration and pinned submodule revision. + Link the two PRs in both directions and state any merge or release dependency. + Do not include application-specific code or private data in the upstream PR. + +### Component PR Rationale and Evidence + +Every new or materially extended reusable component PR must explain: + +- **Problem:** the user need and why it belongs in a shared library. +- **Alternatives:** existing components considered and why reuse, composition, + or extension was insufficient. +- **Relationships:** what it complements, overlaps with, or replaces, with links + and selection guidance discoverable from the affected component pages. +- **Boundaries:** when not to use it, known limitations, and application-owned + responsibilities. +- **Evidence:** a realistic composition example and verification of interactions, + mobile and desktop layouts, light and dark themes, brand switching, + accessibility, translated text expansion, and RTL behavior. Explain any + inapplicable checks or unverified requirements. +- **Compatibility:** API impact, dependencies, and migration guidance where needed. + +Put enduring guidance in the component documentation and link to it from the PR. +Use the PR description for change-specific reasoning and verification evidence, +not a second copy of the documentation. Reviewers should be able to understand +why to choose the component, when to choose something else, and how it fits with +the rest of the library without reading its implementation. + +### Reviewing Component Guidance + +Human and Copilot reviewers should apply the +[rationale and evidence requirements](#component-pr-rationale-and-evidence), +not just check for section headings: + +1. Identify the new or materially changed components. Read their implementation, + consumer-facing docs, stories, and relevant alternatives. Check whether the + stated rationale is supported by actual behavior; props documentation alone + does not explain why to choose a component or when not to use it. +2. Follow related-component links and verify their targets. Each relationship + should explain the choice or composition, not just say "see also." Check that + the guidance is discoverable from both affected component pages, either through + reciprocal links or a shared comparison linked from each. Do not require + arbitrary links when no meaningful relationship exists; assess the author's + explanation of the alternatives considered. +3. Check that examples support the claimed composition, including state ownership + and limitations. Similar appearance does not establish duplication: for example, + ReadingProgressBar and TableOfContents may serve complementary needs. Do not + invent a replacement recommendation or deprecation without evidence. +4. Report each actionable gap with a file or story reference, the unmet requirement, + its effect on a developer's choice, and a concrete correction. Distinguish + verified findings from questions and unavailable evidence. Keep enduring + guidance in component docs, with links from the PR rather than copied prose. + +Apply these checks to the change and affected relationships, not all historical +documentation debt. A documentation-only PR should be checked for inaccurate +guidance and broken links without requiring a new component or composition story. + +### Requesting Copilot Review + +Our [repository instructions](.github/copilot-instructions.md) direct Copilot code +review to the requirements above. On the GitHub PR, request **Copilot** under +**Reviewers**, alongside a human maintainer. After addressing feedback, request a +re-review; new pushes are not automatically reviewed unless that option is enabled. +See [Using GitHub Copilot code review](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/request-a-code-review/use-code-review). + +Repository administrators can configure +[automatic reviews and Review new pushes](https://docs.github.com/en/copilot/how-tos/copilot-on-github/set-up-copilot/configure-automatic-review). +Instruction files alone do not enable automatic review or block merging. Use +repository rulesets for required checks and approvals, and retain human judgment +for component selection and documented exceptions. Copilot comments alone are +not proof that the contribution requirements have been satisfied. + +GitHub currently reads custom review instructions from the PR's head branch, so +instruction changes can be tested in the same PR. Review changes to these rules +and this guide explicitly; they are not a tamper-proof enforcement boundary. + ## Adding a new component (checklist) +First complete the [alternatives audit and contribution workflow](#developing-components-from-a-consuming-application). +For work directly in this repository, the consumer submodule steps apply only +when a consuming application is involved; the audit and PR requirements still apply. + 1. `src/components//` with `index.ts`, `.tsx`, `.stories.tsx`. 2. Follow the [anatomy](#anatomy-of-a-component) conventions (CVA, `cn`, `forwardRef`, theme tokens, a11y). diff --git a/README.md b/README.md index 4aea150df..1bd32836d 100644 --- a/README.md +++ b/README.md @@ -1,619 +1,136 @@ # @mieweb/ui -A themeable, accessible React component library built with Tailwind CSS 4. - -## Features - -- 🎨 **Fully Themeable** - Customize colors, fonts, border radius, and more using CSS variables -- 🏢 **Multi-Brand Support** - Pre-configured themes for BlueHive, Enterprise Health, WebChart, Waggleline, and MIE -- ♿ **Accessible** - Built with WCAG guidelines in mind, including proper ARIA attributes and keyboard navigation -- 🌳 **Tree-Shakeable** - Import only the components you need -- 🌙 **Dark Mode** - Built-in dark mode support with system preference detection -- 📦 **Dual Format** - ESM and CommonJS support -- 🎯 **TypeScript** - Full TypeScript support with comprehensive type definitions -- 📚 **Storybook** - Interactive documentation and component playground - -## Table of Contents - -- [Installation](#installation) -- [Quick Start](#quick-start) -- [Development](#development) -- [Date & Time Standard](#date--time-standard) -- [Storybook](#storybook) -- [Using in Other Projects](#using-in-other-projects) -- [Brand System](#brand-system) -- [Theming](#theming) -- [Components](#components) -- [Hooks](#hooks) -- [Utilities](#utilities) -- [Releases](#releases) -- [Contributing](#contributing) - -## Installation +**Build applications that feel familiar from the first interaction.** -```bash -npm install @mieweb/ui -# or -yarn add @mieweb/ui -# or -pnpm add @mieweb/ui -``` - -### Peer Dependencies - -This library requires React 18+ and React DOM 18+: - -```bash -npm install react react-dom -``` - -### Optional Add-ons - -Heavy or specialized dependencies are kept in separate entry points so they don't bloat the core bundle. Install the peer dependencies for the add-ons you need: - -| Entry point | Install | Import path | -| ------------------------ | --------------------------------------------- | -------------------- | -| **AG Grid** (deprecated) | `npm install ag-grid-community ag-grid-react` | `@mieweb/ui/ag-grid` | -| **DataVis** | `npm install @mieweb/datavis datavis-ace` | `@mieweb/ui/datavis` | - -> ⚠️ **AGGrid is deprecated.** Use DataVis NITRO (`@mieweb/ui/datavis`) for all -> tables. The `@mieweb/ui/ag-grid` entry remains available for existing -> consumers but will be removed in a future major release. - -### AI Agent Rules - -Working with AI coding agents (Copilot, Claude Code, Cursor, …)? Install -@mieweb/ui's agent rules into your repo so agents use library components -(DataVis NITRO for tables, `Button`/`Badge`/`Modal`/… instead of raw HTML): - -```bash -npx @mieweb/ui init-agent -``` - -This writes `.github/instructions/mieweb-ui.instructions.md` (auto-applied by -VS Code Copilot) and a marked block in `AGENTS.md` (the cross-tool convention). -Idempotent — rerun after upgrading to refresh the rules. See [agent/](agent/). - -## Quick Start - -### Option 1: With Tailwind CSS (Recommended) - -If your project uses Tailwind CSS 4, you can use the library's Tailwind preset for the best experience: - -1. Add the preset to your `tailwind.config.js`: - -```js -// tailwind.config.js -module.exports = { - presets: [require('@mieweb/ui/tailwind-preset')], - content: [ - // ... your content - './node_modules/@mieweb/ui/dist/**/*.js', - ], - // Override theme values to match your brand - theme: { - extend: { - colors: { - primary: { - 500: '#your-brand-color', - }, - }, - }, - }, -}; -``` +People should not have to relearn how to navigate, fill out a form, or recover +from an error every time they open another application. Clean, consistent +interfaces let users carry what they already know from one task to the next. +Predictable controls and clear feedback reduce hesitation and leave more +attention for the work that matters. -2. Import and use components: +That consistency should extend beyond appearance. A coherent experience adapts +from mobile to desktop, remains legible in light and dark mode, accommodates +different languages and right-to-left layouts, and supports keyboard and +assistive-technology users. Responsive design, internationalization (i18n), and +accessibility (a11y) belong in the foundation, not on a finishing checklist. -```tsx -import { Button, Card, Input } from '@mieweb/ui'; +`@mieweb/ui` brings that approach to your browser interface through reusable +controls, navigation, forms, feedback, and data displays. Shared interaction +patterns provide familiarity; theme and brand tokens give you room to make the +application your own. Developed at MIE, the library is available for applications +in any domain under its [license terms](#license), not just MIE products. -function App() { - return ( - - - - - ); -} -``` +The components are built with React, but your application does not have to be. +Use them throughout a React application or embed them in selected areas of +Bootstrap-based, server-rendered, or other non-React pages. Adopt a component or +a workflow at a time without rewriting the rest of your interface. -### Option 2: Pre-compiled CSS +Start with a common foundation and spend more time on what makes your application +valuable. The components support inclusive design; they do not automatically +translate your content or guarantee accessibility. Validate their composition, +language, and behavior with the people and devices your application serves. -If you're not using Tailwind CSS, you can import the pre-compiled stylesheet: +**The library is `@mieweb/ui`. Storybook is its documentation and experimentation +environment**, where you can explore those components without building an app +first. This introduction is shared by GitHub, npm, and Storybook. -```tsx -import '@mieweb/ui/styles.css'; -import { Button } from '@mieweb/ui'; -``` +- [See it in action](#see-it-in-action), no installation needed. +- [Get started](#get-started), with or without an AI coding agent. +- [Explore and compose components](#explore-and-compose-components). +- [Contribute or run locally](#contribute-or-run-locally). -## Development +## See It In Action -### Getting Started +[![Open the interactive dashboard demo: navigation, summary cards, recent orders, and activity](https://ui.mieweb.org/dashboard-preview.png)](https://ui.mieweb.org/?path=/story/product-feature-modules-dashboard--dashboard) -1. **Clone the repository (including submodules):** +**[Open the interactive dashboard](https://ui.mieweb.org/?path=/story/product-feature-modules-dashboard--dashboard)** +to see navigation, headers, cards, and data displays working together in an +application layout. Try the brand and theme switchers to see how the same +components adapt. No installation required. -```bash -git clone --recurse-submodules https://github.com/mieweb/ui.git -cd ui -``` +## Get Started -> `--recurse-submodules` is strongly recommended for first clone so the `packages/esheet` and `packages/ychart` submodules are populated immediately. Without them, the eSheet and YChart stories will not work. DataVis NITRO is not a submodule — it ships as the published `@mieweb/datavis` npm package. +### Install in Your Application -If you already cloned without submodules, run: - -```bash -git submodule update --init --recursive -``` - -2. **Install dependencies:** - -```bash -npm install -``` - -Use one package manager consistently per clone. The commands below use npm. - -3. **eSheet packages build automatically.** A `prestorybook` hook runs `npm run build:esheet` before Storybook starts, so the `@esheet/*` packages are compiled on first run with no manual step. It's a near-instant no-op on later runs once the artifacts exist. - -If `packages/esheet` is updated later (submodule update, branch switch, or pull) and you need to force a fresh rebuild, remove the built artifacts and run the build again: - -```bash -rm -f packages/esheet/packages/core/dist/index.d.ts packages/esheet/packages/renderer/src/index.output.css -npm run build:esheet -``` - -4. **Start Storybook:** - -```bash -npm run storybook -``` - -This starts the Storybook development server at [http://localhost:6006](http://localhost:6006) with all components, including eSheet, DataVis NITRO, and YChart. - -### How the Sub-Packages Are Wired - -Storybook integrates three sibling MIE projects, each sourced differently: - -- **DataVis NITRO** — npm package `@mieweb/datavis`. No build step; consumed as a published package (no submodule needed). -- **eSheet** — git submodule `packages/esheet`. Built automatically by the `prestorybook` hook; rebuilds only when its artifacts are missing. -- **YChart** — git submodule `packages/ychart`. No build step; the story imports it directly from source via a relative dynamic import, and Storybook's Vite config adds a `virtual:git-info` plugin, a `__YCHART_VERSION__` define, and dependency pre-bundling (`optimizeDeps`). - -### Library Development (watch mode) - -To rebuild the library on file changes (for consumers that link this repo locally): - -```bash -npm run dev -``` - -This watches for source changes and rebuilds automatically. It does **not** start Storybook. - -### Available Scripts - -| Script | Description | -| ------------------------- | ------------------------------------------------------------------------------------------------- | -| `npm run dev` | Watch & rebuild the library (for local consumers, not Storybook) | -| `npm run build:esheet` | Build eSheet submodule packages (auto-run by `prestorybook`/`prebuild`; skips when already built) | -| `npm run build` | Build the library for production | -| `npm run storybook` | Start Storybook development server | -| `npm run build-storybook` | Build Storybook for static hosting | -| `npm run typecheck` | Run TypeScript type checking | -| `npm run lint` | Run ESLint | -| `npm run lint:fix` | Run ESLint with auto-fix | -| `npm run format` | Check code formatting with Prettier | -| `npm run format:fix` | Fix code formatting with Prettier | -| `npm run test` | Run tests | -| `npm run test:watch` | Run tests in watch mode | - -## Date & Time Standard - -For UI/UX date and time behavior, this project uses **Luxon** as the preferred library. - -### Guidelines - -- Use `DateTime` from `luxon` for all new date/time parsing, formatting, and comparisons. -- Keep timezone explicit when logic depends on business rules (for example: office hours, “open now”, appointment windows). -- Use IANA timezone identifiers (for example: `America/New_York`) instead of abbreviations. -- Prefer storing/transmitting ISO-8601 values and convert for display at the component edge. -- Avoid adding new date logic with raw `Date` math unless there is a clear performance or compatibility reason. - -### Examples - -```ts -import { DateTime } from 'luxon'; - -const localDisplay = DateTime.fromISO(timestamp).toFormat('LLL d, yyyy h:mm a'); - -const inProviderZone = DateTime.fromISO(timestamp, { - zone: 'America/New_York', -}); - -const isOpen = - DateTime.now().setZone('America/New_York') < - inProviderZone.plus({ hours: 1 }); -``` - -## Storybook - -Storybook provides interactive documentation and a component playground where you can explore all components with different props and themes. - -### Running Storybook - -```bash -npm run storybook -``` - -This starts the Storybook development server at [http://localhost:6006](http://localhost:6006). - -### Features in Storybook - -- **Component Explorer**: Browse all components with live examples -- **Props Documentation**: See all available props for each component -- **Theme Switcher**: Toggle between light and dark modes -- **Brand Switcher**: Preview components with different brand themes (BlueHive, Enterprise Health, WebChart, Waggleline, MIE) -- **Accessibility Panel**: Check accessibility compliance for each component -- **Controls**: Interactively modify component props - -### Building Storybook - -To build a static version of Storybook for deployment: - -```bash -npm run build-storybook -``` - -The output will be in the `storybook-static` directory. - -### Configuring the Ozwell API (AI stories) - -The AI stories (AIChat, Hands-Free Chat, and the DataVis NITRO **Ozwell Assistant** -story) call the real Ozwell backend when a key is configured and fall back to a -canned reply when it isn't. Set the key and endpoint from the browser console: - -```js -// Recommended — survives reloads and is shared with the story iframe: -localStorage.setItem( - 'ozwellConfig', - JSON.stringify({ apiKey: 'YOUR_KEY', baseURL: 'https://your-ozwell-host' }) -); -``` - -`baseURL` is optional (defaults to `https://api.ozwell.ai`); other optional keys are -`model`, `system`, and `temperature`. Never commit a key — see -[src/components/AI/OZWELL-BACKEND.md](src/components/AI/OZWELL-BACKEND.md) for full -details, including why `window.__ozwell` is unreliable inside Storybook iframes and -how to proxy the key for public deploys. - -## Using in Other Projects - -### Method 1: NPM Package (Recommended) - -Once published, install the package in your project: +The components require React 18+ and React DOM 18+ to render, including when +embedded in a non-React page. If your project already has those dependencies: ```bash npm install @mieweb/ui ``` -Then import components: - -```tsx -import { Button, Card, Input, ThemeProvider } from '@mieweb/ui'; -import '@mieweb/ui/styles.css'; // or use a brand CSS file - -function App() { - return ( - - - - Welcome - - - - - - - - ); -} -``` - -### Method 2: Local Development (npm link) - -For local development across projects: +Use `pnpm add @mieweb/ui` or `yarn add @mieweb/ui` if that is your project's +package manager. You do not need to clone this repository or run Storybook to use +the library. -1. **In the @mieweb/ui directory:** +For a project without React, install the rendering dependencies: ```bash -cd /path/to/mieweb-ui -npm run build -npm link +npm install react react-dom ``` -2. **In your consuming project:** - -```bash -cd /path/to/your-project -npm link @mieweb/ui -``` +Using an AI coding agent? [Set up its instructions](#set-up-your-ai-coding-agent) +and [read the component-selection and integration rules](https://github.com/mieweb/ui/blob/main/agent/mieweb-ui.instructions.md) +before asking it to add components to your application. -3. **Import and use components:** +Mount components into a dedicated DOM element with React DOM's `createRoot`, leaving the rest of +the page under its existing framework's control. Unmount the React root when the +host removes that area. This requires a JavaScript build that supports React; +the components are not framework-free HTML widgets. -```tsx -import { Button } from '@mieweb/ui'; -import '@mieweb/ui/dist/styles.css'; -``` +When embedding alongside Bootstrap or other stylesheets, check CSS resets, +global selectors, and theme styles for conflicts. Mounting into a separate DOM +element does not isolate CSS. -### Method 3: Direct Path Import +### Set Up Your AI Coding Agent -For monorepo setups or when you want to reference the source directly: +From your application's repository root, run: -```tsx -// In your consuming project's package.json -{ - "dependencies": { - "@mieweb/ui": "file:../mieweb-ui" - } -} +```bash +npx @mieweb/ui init-agent ``` -Then run `npm install` and import as usual. +This installs component-selection, composition, theming, and accessibility rules +so your agent can start with existing library components. It writes +`mieweb-ui.instructions.md` in `.github/instructions/` for VS Code Copilot and +updates a managed block in `AGENTS.md` for agents that read that file. Rerun after upgrading +`@mieweb/ui` to refresh the rules. -### Using with Different Frameworks - -#### Next.js - -```tsx -// app/layout.tsx or pages/_app.tsx -import '@mieweb/ui/brands/bluehive.css'; -import { ThemeProvider } from '@mieweb/ui'; +Read the [agent setup guide and rules](https://github.com/mieweb/ui/tree/main/agent). +These are instructions for coding agents, not an automatic PR reviewer or merge +gate. Agent-assisted and manual development use the same library and setup below. -export default function RootLayout({ children }) { - return ( - - - {children} - - - ); -} -``` - -#### Vite - -```tsx -// main.tsx -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import '@mieweb/ui/brands/enterprise-health.css'; -import { ThemeProvider } from '@mieweb/ui'; -import App from './App'; - -ReactDOM.createRoot(document.getElementById('root')!).render( - - - - - -); -``` +### Render Your First Component -#### Meteor +Import the precompiled stylesheet once in your application's entry point or root +layout. Import a brand stylesheet after it when you want that brand's tokens: ```tsx -// client/main.tsx -import { Meteor } from 'meteor/meteor'; -import React from 'react'; -import { createRoot } from 'react-dom/client'; +import '@mieweb/ui/styles.css'; import '@mieweb/ui/brands/bluehive.css'; -import { ThemeProvider } from '@mieweb/ui'; -import App from '/imports/ui/App'; - -Meteor.startup(() => { - const container = document.getElementById('react-target'); - const root = createRoot(container!); - root.render( - - - - ); -}); -``` - -## Brand System - -The library includes pre-configured themes for multiple brands. Each brand has its own design system with unique colors, typography, border radius, and shadows. - -### Available Brands - -| Brand | Primary Color | Font | Description | -| --------------------- | -------------------- | ------ | ------------------------------------------------- | -| **BlueHive** | `#27AAE1` (Blue) | Nunito | DOT Physical scheduling and healthcare compliance | -| **Enterprise Health** | `#6E2B68` (Burgundy) | Jost | Employee health and occupational medicine | -| **WebChart** | `#F5841F` (Orange) | Inter | Future-ready electronic health record system | -| **Waggleline** | `#17AEED` (Blue) | Inter | Experience visualization and orchestration | -| **MIE** | `#27AE60` (Green) | Inter | Healthcare software and services | - -### Using a Brand Theme - -#### Method 1: Import the brand CSS file - -```tsx -// Import the brand's CSS file -import '@mieweb/ui/brands/enterprise-health.css'; - -import { Button, Card } from '@mieweb/ui'; ``` -#### Method 2: Use the ThemeProvider with brand +This CSS path does not require Tailwind in your application. For a first interactive +example, render a theme switcher inside the provider: ```tsx -import { ThemeProvider } from '@mieweb/ui'; -import { enterpriseHealthBrand } from '@mieweb/ui/brands'; - -function App() { - return ( - - - - ); -} -``` - -#### Method 3: Tailwind CSS preset - -```js -// tailwind.config.js -const { enterpriseHealthBrand } = require('@mieweb/ui/brands'); -const { createBrandPreset } = require('@mieweb/ui/brands/types'); - -module.exports = { - presets: [createBrandPreset(enterpriseHealthBrand)], - // ... -}; -``` - -### Brand Design Tokens - -Each brand defines the following design tokens: - -#### Enterprise Health - -Extracted from [enterprisehealth.com](https://enterprisehealth.com): - -```css -/* Primary: Burgundy/Purple */ ---mieweb-primary-600: #6e2b68; - -/* Secondary: Deep Teal Blue (for gradients) */ ---mieweb-secondary: #00497a; - -/* Accent: Gold/Yellow (logo) */ ---mieweb-accent: #f8b700; - -/* Brand Gradient */ ---mieweb-gradient: linear-gradient(111.02deg, #00497a, #6e2b68); - -/* Typography */ ---mieweb-font-sans: 'Jost', ui-sans-serif, system-ui, sans-serif; - -/* Border Radius (larger, more rounded) */ ---mieweb-radius-sm: 0.375rem; /* 6px - badges */ ---mieweb-radius-md: 0.625rem; /* 10px - buttons */ ---mieweb-radius-lg: 0.75rem; /* 12px - inputs */ ---mieweb-radius-2xl: 1.5rem; /* 24px - cards */ - -/* Shadows (subtle, layered) */ ---mieweb-shadow-card: - 0 16px 32px 0 rgba(34, 35, 38, 0.05), 0 8px 16px 0 rgba(34, 35, 38, 0.05); -``` - -#### BlueHive - -```css -/* Primary: Blue */ ---mieweb-primary-500: #27aae1; - -/* Typography */ ---mieweb-font-sans: 'Nunito', ui-sans-serif, system-ui, sans-serif; -``` - -### Creating a Custom Brand - -You can create your own brand configuration: - -```ts -import type { BrandConfig } from '@mieweb/ui/brands/types'; - -export const myBrand: BrandConfig = { - name: 'my-brand', - displayName: 'My Brand', - description: 'Custom brand for my application', - - colors: { - primary: { - 50: '#f0f9ff', - // ... full color scale 50-950 - 600: '#0284c7', // Main brand color - // ... - }, - light: { - background: '#ffffff', - foreground: '#171717', - // ... semantic colors - }, - dark: { - background: '#171717', - foreground: '#fafafa', - // ... semantic colors - }, - }, - - typography: { - fontFamily: { - sans: ['Your Font', 'ui-sans-serif', 'system-ui', 'sans-serif'], - mono: ['ui-monospace', 'SFMono-Regular', 'Menlo', 'monospace'], - }, - }, - - borderRadius: { - none: '0', - sm: '0.25rem', - md: '0.5rem', - lg: '0.75rem', - xl: '1rem', - '2xl': '1.5rem', - full: '9999px', - }, - - boxShadow: { - card: '0 1px 3px 0 rgb(0 0 0 / 0.1)', - dropdown: '0 4px 6px -1px rgb(0 0 0 / 0.1)', - modal: '0 10px 15px -3px rgb(0 0 0 / 0.1)', - }, -}; -``` - -## Theming - -The library uses CSS custom properties for theming. Override these variables to customize the appearance: - -```css -:root { - /* Primary color scale */ - --mieweb-primary-500: #27aae1; - - /* Semantic colors */ - --mieweb-background: hsl(0 0% 100%); - --mieweb-foreground: hsl(222.2 84% 4.9%); - - /* Border radius */ - --mieweb-radius-md: 0.5rem; - - /* Font */ - --mieweb-font-sans: 'Your Font', sans-serif; -} -``` - -### Dark Mode - -The library supports dark mode via the `.dark` class or `data-theme="dark"` attribute on a parent element: - -```tsx -import { ThemeProvider, useThemeContext, Button } from '@mieweb/ui'; +import { Button, ThemeProvider, useThemeContext } from '@mieweb/ui'; function ThemeToggle() { const { resolvedTheme, setTheme } = useThemeContext(); + return ( ); } -function App() { +export default function App() { return ( @@ -622,186 +139,92 @@ function App() { } ``` -## Components - -### Primitives - -- `Button` - Multi-variant button with loading state -- `Input` - Text input with label, error, and helper text -- `Card` - Container component with header, content, and footer -- `Text` - Typography component with variants -- `Badge` - Status indicators and labels -- `Alert` - Feedback messages - -### Specialized Inputs - -- `PhoneInput` - US phone number formatting -- `DateInput` - Date input with validation modes (DOB, expiration, etc.) - -### Overlays - -- `Tooltip` - Accessible tooltip with multiple placements -- `Dropdown` - Dropdown menu with items, separators, and labels - -### Utilities - -- `VisuallyHidden` - Screen reader only content -- `ThemeProvider` - Theme context provider - -## Hooks - -- `useTheme()` - Theme state management -- `useClickOutside()` - Detect clicks outside an element -- `useEscapeKey()` - Handle escape key press -- `useFocusTrap()` - Trap focus within a container -- `usePrefersReducedMotion()` - Detect reduced motion preference - -## Utilities - -### Class Names - -```tsx -import { cn } from '@mieweb/ui/utils'; - -// Merge classes with Tailwind conflict resolution -cn('px-4 py-2', isActive && 'bg-primary-500', className); -``` - -### Phone Utilities - -```tsx -import { formatPhoneNumber, isValidPhoneNumber } from '@mieweb/ui/utils'; - -formatPhoneNumber('5551234567'); // "(555) 123-4567" -isValidPhoneNumber('5551234567'); // true -``` - -### Date Utilities - -```tsx -import { formatDateValue, calculateAge, isValidDate } from '@mieweb/ui/utils'; - -formatDateValue('01152024'); // "01/15/2024" -calculateAge('01/15/1990'); // 34 -isValidDate('01/15/2024'); // true -``` - -## Tree-Shaking - -Import components directly for optimal bundle size: - -```tsx -// Import only what you need -import { Button } from '@mieweb/ui/components/Button'; -import { useTheme } from '@mieweb/ui/hooks'; -import { cn } from '@mieweb/ui/utils'; -``` - -## TypeScript - -All components are fully typed. Import types as needed: - -```tsx -import type { ButtonProps, InputProps, Theme } from '@mieweb/ui'; -``` - -## Releases - -This package uses automated releases via GitHub Actions. There are two release channels: - -### Release Channels - -| Channel | npm Tag | Install Command | Description | -| -------------- | -------- | ----------------------------- | ------------------------- | -| **Stable** | `latest` | `npm install @mieweb/ui` | Production-ready releases | -| **Prerelease** | `next` | `npm install @mieweb/ui@next` | Latest from `main` branch | - -### Prerelease (Automatic) - -Every push to the `main` branch automatically publishes a prerelease version to npm: - -- **Version format:** `x.y.z-dev.{run_number}` (e.g., `0.1.0-dev.45`) -- **npm tag:** `next` -- **Install:** `npm install @mieweb/ui@next` - -This allows consumers to test the latest changes before a stable release. - -### Stable Release (Manual) - -To create a stable release: - -1. Go to the repository on GitHub -2. Navigate to **Actions** → **Create Stable Release** -3. Click **Run workflow** -4. Select the version bump type: - - `patch` - Bug fixes (0.1.0 → 0.1.1) - - `minor` - New features (0.1.0 → 0.2.0) - - `major` - Breaking changes (0.1.0 → 1.0.0) -5. Click **Run workflow** - -The workflow will: - -1. Bump the version in `package.json` -2. Commit and push the change -3. Create a git tag (e.g., `v0.2.0`) -4. Trigger the release workflow which publishes to npm and creates a GitHub Release - -### Manual Tag Release - -You can also create a release by pushing a version tag directly: - -```bash -# Create and push a tag -git tag v1.0.0 -git push origin v1.0.0 -``` - -The release workflow will automatically: - -- Run tests and build -- Publish to npm with the appropriate tag (`latest` for stable, `next` for prereleases like `v1.0.0-beta.1`) -- Create a GitHub Release with auto-generated release notes - -### Version Guidelines - -We follow [Semantic Versioning](https://semver.org/): - -- **MAJOR** version for incompatible API changes -- **MINOR** version for backwards-compatible functionality additions -- **PATCH** version for backwards-compatible bug fixes - -## Contributing - -We welcome contributions! This README and the [Storybook](https://ui.mieweb.org) -are the **consumer** docs (how to _use_ the library). If you want to _build or -change_ the library itself, the **provider / maintainer** guide is -**[CONTRIBUTING.md](CONTRIBUTING.md)** — it covers repo layout, the component -anatomy and conventions, the autodocs story pattern, exports & tree-shaking, -build, testing (unit + visual baselines), submodules, brands, and the release -process. - -Quick start for contributors: - -```bash -git clone --recurse-submodules https://github.com/mieweb/ui.git -cd ui && pnpm install -pnpm storybook # http://localhost:6006 -# before opening a PR: -pnpm typecheck && pnpm lint && pnpm format && pnpm test -``` - -Non-trivial modules also carry a `MAINTAINERS.md` next to the code with internals, -invariants, and gotchas for that module — see the table in -[CONTRIBUTING.md](CONTRIBUTING.md#per-component-maintainer-notes). +In production, supply translated labels through your application's i18n system. +In Next.js App Router, put this interactive example in a client component and +import global styles from the root layout. + +Already using Tailwind? Follow the +[Tailwind 4 integration guide](https://github.com/mieweb/ui/blob/main/lessons/tailwind4-integration.md) +for CSS-first configuration, `@source`, and theme tokens. Tailwind 3 consumers can +use `@mieweb/ui/tailwind-preset`. Do not apply a Tailwind 3 configuration as a +Tailwind 4 setup. + +### Add Specialized Capabilities When Needed + +Heavy integrations use separate entry points and optional peer dependencies so +you only install what you need: + +- **Data grids:** [DataVis NITRO](https://ui.mieweb.org/?path=/docs/components-text-data-display-datavis-nitro--docs), imported from `@mieweb/ui/datavis`. +- **Form authoring and rendering:** [eSheet integration](https://github.com/mieweb/ui/blob/main/src/components/ESheet/MAINTAINERS.md), imported from `@mieweb/ui/esheet`. +- **Rich text and code editing:** [Kerebron editor setup](https://github.com/mieweb/ui/tree/main/src/components/RichEditor), imported from `@mieweb/ui/kerebron`. + +Check the selected integration's dependencies before importing its entry point. +AGGrid is deprecated for new work; start with DataVis NITRO for tabular data. + +## Explore and Compose Components + +Open [the component explorer](https://ui.mieweb.org/). Storybook is the wrapper +around the examples: its sidebar selects components, a **story** demonstrates a +particular configuration, and **Docs** presents guidance and the API. **Controls** +change example props; theme and brand tools let you inspect different appearances. +Those tools belong to Storybook, not to the component you install. + +Start with the user's task, then compare components before choosing an API: + +- **Browse and work with records:** start with [DataVis NITRO](https://ui.mieweb.org/?path=/docs/components-text-data-display-datavis-nitro--docs) + and compare [Table](https://ui.mieweb.org/?path=/docs/components-layout-structure-table--docs). + NITRO provides integrated data tooling; Table provides lower-level markup. + Consider the behavior your application would need to supply and consult the + selection rules before choosing an exception. +- **Navigate a long document:** compare [TableOfContents](https://ui.mieweb.org/?path=/docs/components-navigation-tableofcontents--docs) + and [ReadingProgressBar](https://ui.mieweb.org/?path=/docs/components-feedback-readingprogressbar--docs). + A TOC provides named destinations and navigation. A reading bar is a decorative + document-scroll cue, not navigation or proof of reading. They can complement + each other; neither may be needed for short content. +- **Assemble an application view:** explore the [Dashboard example](https://ui.mieweb.org/?path=/story/product-feature-modules-dashboard--dashboard). + Inspect how navigation, headers, and content fit together, then adapt the + composition to your workflow rather than copying the layout indiscriminately. + +For each choice, ask why it fits, when an alternative would be better, what state +your application owns, and how it behaves alongside neighboring components. +Exercise loading, empty, error, keyboard, and narrow-screen states in the actual +application, not only the isolated story. + +The catalog is still being improved: not every component has comparison or +composition guidance yet. Do not treat an isolated example as evidence that no +related component exists. Use the +[component policy](https://github.com/mieweb/ui/blob/main/lessons/component-policy.md) +and flag missing or conflicting guidance in a +[documentation issue](https://github.com/mieweb/ui/issues/new). + +### Go Deeper + +- [Branding](https://ui.mieweb.org/?path=/docs/branding--docs): the brand system and visual tokens. +- [Adoption guides](https://github.com/mieweb/ui/blob/main/lessons/README.md): integration pitfalls and migration paths for existing applications. +- [AI-assisted migration plan](https://github.com/mieweb/ui/blob/main/lessons/execution-plan.md): an ordered approach to adopting the library. +- [Meteor migration](https://github.com/mieweb/ui/blob/main/lessons/migration-meteor-blaze-to-react.md): framework-specific migration guidance. + +## Contribute or Run Locally + +To change the library, improve its guidance, or run your own Storybook, follow +[CONTRIBUTING.md](https://github.com/mieweb/ui/blob/main/CONTRIBUTING.md). It covers +repository setup, local development, tests, component conventions, and releases. +Those steps are not required to consume the npm package. + +Found unclear selection advice or an undocumented relationship? Documentation +contributions are welcome alongside component fixes. +[Edit this introduction](https://github.com/mieweb/ui/edit/main/README.md) to +improve the shared GitHub, npm, and Storybook content. Published copies update +when the package is released or the documentation site is deployed. ## License Copyright © 2026 Medical Informatics Engineering, Inc. All rights reserved. -This software is **source available** with the following terms: +This software is **source available**: -- ✅ **Free for open source projects** - Use, modify, and distribute freely in open source projects with attribution -- ✅ **Free for non-commercial use** - Personal projects, education, research -- 💼 **Commercial license required** - For proprietary products or commercial use, contact [licensing@mieweb.com](mailto:licensing@mieweb.com) +- **Free for open source projects:** use, modify, and distribute in open source projects with attribution. +- **Free for non-commercial use:** personal projects, education, and research. +- **Commercial license required:** for proprietary products or commercial use, contact [licensing@mieweb.com](mailto:licensing@mieweb.com). -See the [LICENSE](LICENSE) file for full details. +See the [LICENSE](https://github.com/mieweb/ui/blob/main/LICENSE) for full terms. diff --git a/agent/mieweb-ui.instructions.md b/agent/mieweb-ui.instructions.md index d0772cfe0..326030f95 100644 --- a/agent/mieweb-ui.instructions.md +++ b/agent/mieweb-ui.instructions.md @@ -164,6 +164,21 @@ Tailwind: on Tailwind 4, add an `@source` for `@mieweb/ui` so library classes ar If JSDoc, the console, or the docs mark something deprecated (`AGGrid` today), do not use it in new code and do not suppress the warning. Use the documented replacement. -## Rule 14: When no component exists - -First verify it truly doesn't exist — check https://ui.mieweb.org (Storybook) rather than guessing. Then build it locally, but in `@mieweb/ui` style: Tailwind utility classes with the library's design tokens, ARIA labels on interactive elements, and externalized user-facing text. Prefer composing existing primitives (`Card`, `Text`, `Badge`) over new bespoke markup. If the pattern is generic, propose contributing it upstream to `@mieweb/ui`. +## Rule 14: When existing components do not meet the need + +Before creating or materially extending a reusable component, read the +[upstream contribution guide](https://github.com/mieweb/ui/blob/main/CONTRIBUTING.md) +and follow its +[Developing Components From a Consuming Application](https://github.com/mieweb/ui/blob/main/CONTRIBUTING.md#developing-components-from-a-consuming-application) +process, including the alternatives audit, contribution-ready implementation, +submodule workflow, and PR requirements. If the guide is unavailable, report that +limitation and obtain it before proceeding with the contribution workflow. + +Present the gap and supporting evidence before implementation. Obtain approval +before introducing a submodule or changing the consuming project's dependency +strategy. Keep project-specific behavior local, and do not create a generic +abstraction solely to make it contributable. + +Follow the repository's permissions and approval requirements for commits, +pushes, and PR creation. Do not treat these instructions as authorization to +publish changes. diff --git a/src/Introduction.mdx b/src/Introduction.mdx index 433958d48..244d72266 100644 --- a/src/Introduction.mdx +++ b/src/Introduction.mdx @@ -1,1173 +1,11 @@ -import { Meta } from '@storybook/addon-docs/blocks'; -import { ArrowRight } from 'lucide-react'; -import { Button } from './components/Button'; +import { Markdown, Meta } from '@storybook/addon-docs/blocks'; +import readme from '../README.md?raw'; -# MIE Web UI - -
- npm version - React 18+ - Tailwind CSS 4 - TypeScript -
- -A **themeable, accessible React component library** built with Tailwind CSS 4. Designed for MIE's suite of healthcare applications including BlueHive, Enterprise Health, WebChart, and Waggleline. - ---- - -## 🎯 See It In Action - -
-
- - 🚀 Full Dashboard Example - - - Want to see how all the components work together? Check out a complete - dashboard implementation featuring Sidebar navigation, AppHeader, Cards, - Data tables, and more. - -
- -
- ---- - -## 📚 What is Storybook? - -This documentation site is built with **Storybook** — an interactive component explorer that lets you browse, test, and understand each component in isolation. - -
-
- 📁 Sidebar (Left Panel) - - Browse all available components organized by category. Click on any - component to see its documentation, interactive examples, and all - available variants. - -
-
- 🎮 Controls Panel - - Interact with component props in real-time. Adjust sizes, colors, states, - and content to see how components behave with different configurations. - -
-
- 🔧 Toolbar (Top) - - Switch between brand themes, toggle dark/light mode, adjust viewport - sizes, and access accessibility testing tools. - -
-
- ---- - -## ✨ Features - -
-
- 🎨 Fully Themeable - - Customize colors, fonts, border radius, and more using CSS variables - -
-
- 🏢 Multi-Brand Support - - Pre-configured themes for BlueHive, Enterprise Health, WebChart, - Waggleline, and MIE - -
-
- ♿ Accessible - - Built with WCAG guidelines, proper ARIA attributes, and keyboard - navigation - -
-
- 🌙 Dark Mode - - Built-in dark mode support with system preference detection - -
-
- 🌳 Tree-Shakeable - - Import only the components you need for optimal bundle size - -
-
- 📦 TypeScript - - Full TypeScript support with comprehensive type definitions - -
-
- ---- - -## 🚀 Quick Start - -### Installation - -```bash -npm install @mieweb/ui -# or -yarn add @mieweb/ui -# or -pnpm add @mieweb/ui -``` - -### Basic Usage - -```tsx -import { Button, Card, Input, ThemeProvider } from '@mieweb/ui'; -import '@mieweb/ui/styles.css'; - -function App() { - return ( - - - - Welcome - - - - - - - - ); -} -``` - -### With Tailwind CSS (Recommended) - -If your project uses Tailwind CSS 4, add the library's preset: - -```js -// tailwind.config.js -module.exports = { - presets: [require('@mieweb/ui/tailwind-preset')], - content: [ - // ... your content - './node_modules/@mieweb/ui/dist/**/*.js', - ], -}; -``` - ---- - -## 🎨 Brand Themes - -This library includes pre-built themes for MIE's product suite. Use the **Brand** selector in the toolbar above to preview components with different brand styles. - -
-
- BlueHive -
- #27aae1 -
- - DOT Physical scheduling platform - -
-
- Enterprise Health -
- #2563eb -
- - Occupational health management - -
-
- WebChart -
- #16a34a -
- - Electronic health records - -
-
- Waggleline -
- #17aeed -
- - Experience visualization platform - -
-
- MIE -
- #6366f1 -
- - Medical Informatics Engineering - -
-
- -### Using a Brand Theme - -```tsx -// Import the brand CSS -import '@mieweb/ui/brands/bluehive.css'; - -// Or apply programmatically -import { bluehiveBrand } from '@mieweb/ui/brands/bluehive'; -``` - ---- - -## 📖 Exploring Components - -Use the **sidebar on the left** to browse available components. Each component page includes: - -- **Interactive examples** — Live preview with real-time prop controls -- **Props documentation** — Full API reference with types and defaults -- **Accessibility notes** — Keyboard shortcuts and ARIA information -- **Code snippets** — Copy-paste ready implementation examples - -### Component Categories - -| Category | Components | -| ---------------- | ----------------------------------------------------------------------- | -| **Forms** | Input, Select, Checkbox, Radio, Switch, Textarea, DateInput, PhoneInput | -| **Buttons** | Button, Dropdown | -| **Layout** | Card, Modal, Sidebar, AppHeader, CommandPalette | -| **Feedback** | Alert, Progress, Toast, Spinner, Skeleton, Tooltip | -| **Navigation** | Breadcrumb, Pagination | -| **Data Display** | Table, Badge, Avatar | - -
- 💡 Pro Tip: Use{' '} - - ⌘ - {' '} - +{' '} - - K - {' '} - to quickly search for any component in Storybook. -
- ---- - -## 📝 eSheet — Form Builder & Renderer - -`@mieweb/ui` includes optional support for **eSheet**, a modular form builder and renderer toolkit. eSheet components are exported from a **separate entry point** (`@mieweb/ui/esheet`) so they stay out of your main bundle unless you need them. - -### What You Get - -| Export | Description | -| ---------------------- | ----------------------------------------------------------------------------------- | -| `EsheetBuilder` | Visual drag-and-drop form builder for creating and editing form definitions | -| `EsheetRenderer` | Lightweight form renderer for end-users to fill out forms | -| `FormDefinition` | TypeScript type for the form schema (from `@esheet/core`) | -| `EsheetBuilderProps` | Props type for the builder component | -| `EsheetRendererProps` | Props type for the renderer component | -| `EsheetRendererHandle` | Ref handle type for imperative renderer control (`getResponse`, `getValidResponse`) | - -### Installation - -eSheet packages are **optional peer dependencies** of `@mieweb/ui`. Install only what you need: - -```bash -# Builder + Renderer (most common) -npm install @esheet/builder @esheet/renderer - -# Renderer only (form fill-out, no editing UI) -npm install @esheet/renderer - -# Builder only (form authoring, no fill-out UI) -npm install @esheet/builder -``` - -> `@esheet/core` and `@esheet/fields` are included transitively — no need to install them separately. - -### Usage - -```tsx -import { - EsheetBuilder, - EsheetRenderer, - type FormDefinition, - type EsheetRendererHandle, -} from '@mieweb/ui/esheet'; -import '@mieweb/ui/styles.css'; -import { useRef, useState } from 'react'; - -function FormEditor() { - const [form, setForm] = useState({ - id: 'my-form', - title: 'My Form', - fields: [], - }); - - return ; -} - -function FormFillOut({ form }: { form: FormDefinition }) { - const rendererRef = useRef(null); - - const handleSubmit = () => { - if (!rendererRef.current) return; - const result = rendererRef.current.getValidResponse(); - if (result.errors.length > 0) { - console.warn('Validation errors:', result.errors); - } else { - console.log('Form response:', result.response); - } - }; - - return ( - <> - - - - ); -} -``` - -### Key Points - -- **Import path**: Always import from `@mieweb/ui/esheet`, not from `@esheet/*` directly. This ensures proper theme integration with `@mieweb/ui` brand CSS. -- **Styles**: eSheet components use `@mieweb/ui` design tokens automatically. No additional CSS import is needed beyond `@mieweb/ui/styles.css`. -- **Theming**: eSheet respects your active brand theme (BlueHive, Enterprise Health, WebChart, etc.) and dark/light mode — no extra configuration. -- **Bundle impact**: The `@mieweb/ui/esheet` entry point is tree-shaken separately from the main `@mieweb/ui` export. If you don't import it, it adds zero bytes to your bundle. - -### Full eSheet Documentation - -For advanced usage — custom field types, conditional logic, standalone/Blaze renderers, and the full API reference — see the [eSheet documentation](https://esheet-docs.os.mieweb.org). - ---- - -## 🛠️ Running Storybook Locally - -Want to develop components, browse the full library on your machine, or contribute? Getting this Storybook running locally is a two-command flow. - -### Prerequisites - -- **Node.js** ≥ 20 -- **pnpm** 10.29.1 — pinned via the repo's `packageManager` field. Enable it with `corepack enable`. -- **Git** with submodule support - -### Setup - -```bash -# 1. Clone with submodules (esheet and ychart are git submodules) -git clone --recurse-submodules https://github.com/mieweb/ui.git -cd ui - -# 2. Install dependencies -# A preinstall hook auto-inits/updates submodules — so even if you -# forgot --recurse-submodules above, this step pulls them in. -pnpm install - -# 3. Start Storybook on http://localhost:6006 -pnpm storybook -``` - -That's the whole flow — `pnpm install && pnpm storybook`. A `prestorybook` hook builds the eSheet packages automatically on first run, so the eSheet stories work out of the box with no manual build step (it's a near-instant no-op on later runs once the artifacts exist). - -
- Already cloned without submodules? - - Run git submodule update --init --recursive — or just{' '} - pnpm install, which does it for you. - -
- -### How the Sub-Packages Are Wired - -`@mieweb/ui`'s Storybook integrates three sibling MIE projects, each sourced differently: - -- **DataVis NITRO** — npm package `@mieweb/datavis`. _No build step:_ consumed as a published package (not a submodule). Powers the DataVis NITRO data-grid stories. -- **eSheet** — git submodule `packages/esheet`. _Built automatically_ by the `prestorybook` hook (nx) before Storybook starts; rebuilds only when its artifacts are missing. The form builder/renderer toolkit. -- **YChart** — git submodule `packages/ychart`. _No build step:_ the story imports it directly from source via a relative dynamic import; Storybook's Vite config supplies a `virtual:git-info` plugin, a `__YCHART_VERSION__` define, and dependency pre-bundling (`optimizeDeps`). Org-chart / visualization toolkit. - -> **Heads up:** DataVis NITRO is consumed from the published `@mieweb/datavis` npm package — it is not a git submodule, and a fresh clone does not build DataVis from source. - -### Common Commands - -- `pnpm storybook` — Run Storybook in dev mode on port 6006 -- `pnpm build-storybook` — Build the static Storybook site -- `pnpm build` — Build the publishable `@mieweb/ui` library -- `pnpm test` — Run the unit test suite (Vitest) -- `pnpm test:visual` — Run Playwright visual regression tests -- `pnpm typecheck` — Type-check without emitting -- `pnpm lint` — Lint `src/**` - ---- - -## 🔗 Resources - -- [GitHub Repository](https://github.com/mieweb/ui) — Source code and issue tracker -- [NPM Package](https://www.npmjs.com/package/@mieweb/ui) — Package registry -- [Changelog](https://github.com/mieweb/ui/releases) — Version history - ---- - -## 🤖 Migrating Your App to MIE Web UI - -Have an existing React + Tailwind project and want to adopt `@mieweb/ui`? We've built a **10-step execution plan** designed for AI agents (like GitHub Copilot, Claude, etc.) and human developers alike. Feed your AI the plan and it will systematically convert your app — replacing local/shadcn components, wiring up brand theming, cleaning up dead dependencies, and producing a structured migration report. - -This process has been **iteratively tested and validated** across 5 test cycles to achieve 100% single-pass completion. - -### How It Works - -
- - 📋 Feed these 3 files to your AI agent — in this order: - -
-
- - 1. - -
- - tailwind4-integration.md - - - Full @theme block with all CSS variable mappings and hex - fallbacks. Critical — Step 2 cannot be completed - without it. - -
-
-
- - 2. - -
- - component-policy.md - - - Complete list of 126+ available @mieweb/ui components. - Needed for Steps 4–5 to know what replacements exist. - -
-
-
- - 3. - -
- - execution-plan.md - - - The 10-step procedure. Must come last so the reference data from files - 1–2 is in context when the AI starts executing. - -
-
-
-
- Order matters — AI models lose attention on earlier content as the prompt - grows. Reference data before procedure ensures the best results. -
-
- - Then send this prompt: - - - Migrate this project to @mieweb/ui following the execution plan. Work step - by step, create the migration report first, and update it after each step. - -
-
- -Once the AI has all 3 files, it will audit your project, identify your framework, existing components, and theme system, then proceed through the migration step by step — validating each step before the next begins. - -### The 10 Steps - -
-
- Step 1 — Install - - Add @mieweb/ui as a dependency using your project's package - manager. - -
-
- Step 2 — CSS Foundation - - Wire up the brand CSS, Tailwind 4 theme block, dark mode variant, and - PostCSS configuration — the foundation everything else depends on. - -
-
- Step 3 — Brand Switching - - Set up runtime brand switching with a useBrand hook and{' '} - BrandInitializer so users can change themes on the fly. - -
-
- Step 4 — Component Swap - - Replace local or shadcn/ui components with @mieweb/ui{' '} - equivalents — Buttons first, then Modals, Forms, Data Display, Feedback, - Navigation, and Overlays. - -
-
- Step 5 — Icon Migration - - Standardize on lucide-react icons, replacing any other icon - libraries or inline SVGs. - -
-
- Step 6 — Clean Up - - Migrate cn() imports to @mieweb/ui, remove - unused dependencies (Radix, clsx, cva), and delete empty wrapper files. - -
-
- Step 7 — Accessibility Pass - - Audit interactive elements for missing ARIA labels, verify keyboard - navigation, and ensure screen reader compatibility. - -
-
- Step 8 — Testing & Verification - - Visual smoke tests across light/dark/brand combinations, responsive - checks, build verification, and a compliance audit. - -
-
- Step 9 — Gap Detection - - Identify components without @mieweb/ui equivalents, document - remaining local components, and flag candidates for upstream contribution. - -
-
- Step 10 — Migration Report - - Generate a structured MIEWEB-UI-MIGRATION.md documenting - everything: wrapper audit, compliance metrics, import map, files changed, - known gaps, and variant mappings. - -
-
- -### What You'll Get - -
- - 📄 A complete MIEWEB-UI-MIGRATION.md report including: - -
- - ✅ Project profile & framework details - - ✅ Export availability matrix - - ✅ Full wrapper file audit (every file) - - - ✅ Pattern audit (raw HTML, badges, cards) - - ✅ Post-migration import map - ✅ Before/after compliance metrics - ✅ Known gaps & kept components - - ✅ Files modified, created, and deleted - -
- - This report serves as the permanent record for PR reviewers, future - maintainers, and cross-project comparison. - -
- -### Additional Guides - -The [`lessons/`](https://github.com/mieweb/ui/tree/main/lessons) directory also includes optional reference guides: - -| Guide | Purpose | -| --------------------------------------------------------------------------------------------- | --------------------------------------------------- | -| [adopting-mieweb-ui.md](https://github.com/mieweb/ui/blob/main/lessons/adopting-mieweb-ui.md) | Audit methodology and component mapping | -| [compliance-prompt.md](https://github.com/mieweb/ui/blob/main/lessons/compliance-prompt.md) | Copy-paste AI prompt for a single-session migration | - -### Framework Support - -The plan works across frameworks — **Next.js**, **Vite**, **Remix**, **Meteor**, and more. Each step includes framework-specific notes where setup differs. - ---- - -
- 💡 Tip: Use the toolbar above to toggle dark mode and switch - between brand themes while browsing components. -
+ + {readme.replace( + 'https://ui.mieweb.org/dashboard-preview.png', + './dashboard-preview.png' + )} +