Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cold-papayas-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@indielayer/ui": minor
---

feat(table): optional multiple sort
5 changes: 5 additions & 0 deletions .changeset/component-defaults.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@indielayer/ui": minor
---

Add `defaults` option on `UIOptions` for app-wide component prop defaults (e.g. `Alert: { outlined: true }`). Defaults merge in `useTheme` and via `useResolvedComponentProps` for template usage. Themed components use `optionalBooleanProp()` for variant/layout booleans so omitted props stay `undefined` and receive app defaults (Vue otherwise coerces plain `Boolean` to `false`).
5 changes: 5 additions & 0 deletions .changeset/empty-component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@indielayer/ui": minor
---

Add `XEmpty` component for empty states with title, description, icon, actions slot, and optional bordered layout.
5 changes: 5 additions & 0 deletions .changeset/input-group-component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@indielayer/ui": minor
---

Add `XInputGroup` for inline multi-field controls with a shared label and InputFooter. Supports `XInput`, `XTextarea`, `XSelect`, and `XDatepicker` as children.
7 changes: 7 additions & 0 deletions .changeset/stepper-v2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@indielayer/ui": minor
---

feat(stepper)!: rebuild as multi-step wizard with named slots and navigation API

BREAKING CHANGE: `XStepper` no longer uses manual `status` or `label` on steps. Use `value`, `title`, named panel slots (`#stepId`), optional `#summary-stepId` slots, and exposed `next()` / `prev()` / `goTo()` / `reset()` methods. `v-model` is the active step `value` (string or number), not a numeric index.
20 changes: 20 additions & 0 deletions .changeset/tailwind-v4-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
"@indielayer/ui": major
---

Migrate to Tailwind CSS v4 with a CSS-first public API.

**Breaking changes**

- Peer dependency is now `tailwindcss@^4.0.0` (requires Safari 16.4+, Chrome 111+, Firefox 128+).
- Removed `@indielayer/ui/tailwind.preset` β€” use `@import "@indielayer/ui/tailwind.css"` in your app stylesheet instead.
- Configure content scanning with `@source` directives; JavaScript `tailwind.config.js` presets are no longer used.

**Migration**

1. Upgrade Tailwind and add `@tailwindcss/postcss` (Vite: `css.postcss.plugins`; Nuxt: `postcss.plugins`).
2. Replace `@tailwind` directives with `@import "tailwindcss"` and import `@indielayer/ui/tailwind.css`.
3. Add `@source` paths including `node_modules/@indielayer/ui/{lib,src}/**/*`.
4. Update renamed utilities (`shadow-sm` β†’ `shadow-xs`, `flex-grow` β†’ `grow`, `outline-none` β†’ `outline-hidden`, etc.) if you copied v3 class names.

See the [Tailwind upgrade guide](https://tailwindcss.com/docs/upgrade-guide) and the docs getting-started page.
4 changes: 2 additions & 2 deletions .cursor/rules/docs.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ alwaysApply: false
- Import components from `@indielayer/ui`; use `?raw` imports for code preview snippets
- Wire `back` / `next` to adjacent component folder names (lowercase)
- Wrap content in `<document-page>` β€” see `docs/pages/component/button/index.vue`
- After adding docs: `cd packages/ui && pnpm gen:search && pnpm gen:llms`
- After editing docs: `pnpm eslint --cache --fix --ext .js,.ts,.vue packages/ui/docs` and `pnpm lint:style` when styles changed β€” CI runs `pnpm lint:ui` (includes `docs/`) and `pnpm lint:style`
- After adding docs: `cd packages/ui && pnpm gen:search && pnpm gen:llms` (writes `llms.txt` and `llms-full.txt`)
- After editing docs: `pnpm eslint --cache --fix --ext .js,.ts,.vue packages/ui/docs` β€” CI runs `pnpm lint:ui` (includes `docs/`)
2 changes: 1 addition & 1 deletion .cursor/rules/project.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ alwaysApply: true
- Primary package: `packages/ui` (`@indielayer/ui`)
- Node.js 24 and pnpm 11 (see root `package.json` `packageManager`)
- Use `pnpm` (not npm/yarn) from repo root
- Before finishing any change under `packages/ui`: run `pnpm eslint --cache --fix --ext .js,.ts,.vue <changed-paths>` then `pnpm lint:ui` and `pnpm lint:style` (must pass with zero errors) and `pnpm test:ci` when library code changed
- Before finishing any change under `packages/ui`: run `pnpm eslint --cache --fix --ext .js,.ts,.vue <changed-paths>` then `pnpm lint:ui` and `pnpm typecheck` (must pass with zero errors) and `pnpm test:ci` when library code changed
- **Tests in agents/CI**: never run bare `pnpm test` in non-interactive terminals β€” Vitest defaults to watch mode and the process will not exit. Use `pnpm test:ci` (or `CI=true pnpm test`) so tests run once and exit
- Do not leave new ESLint errors or warnings in files you edited; fix manually if `--fix` does not resolve them
- Do not edit `lib/` or other build output
Expand Down
1 change: 1 addition & 0 deletions .cursor/skills/add-component/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ From repo root:

```bash
pnpm lint:ui
pnpm typecheck
pnpm test:ci
```

Expand Down
4 changes: 4 additions & 0 deletions .cursor/skills/component-theme/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,7 @@ Key must match the theme name used in `useTheme('<Name>', ...)`.
When changing layout, states, or tokens in one variant, apply the same logical change to the other unless the carbon design intentionally differs.

Reference: `packages/ui/src/components/button/theme/Button.base.theme.ts`

## App-level `defaults`

Variant/layout booleans that should respect `app.use(UI, { defaults })` must use `optionalBooleanProp()` from `packages/ui/src/common/props.ts` (not plain `Boolean`). Use `useResolvedComponentProps` when the template or script reads those props outside `useTheme`.
2 changes: 1 addition & 1 deletion .cursor/skills/docs-page/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ From `packages/ui`:

```bash
pnpm gen:search
pnpm gen:llms
pnpm gen:llms # also writes public/llms-full.txt
```

## Verify
Expand Down
1 change: 1 addition & 0 deletions .cursor/skills/release/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Do not bump `packages/ui/package.json` version in the feature PR; Changesets han

```bash
pnpm lint:ui
pnpm typecheck
pnpm test:ci
pnpm build
```
Expand Down
2 changes: 1 addition & 1 deletion .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ $ pnpm build

Contributors using Cursor or other coding agents should read [AGENTS.md](../AGENTS.md) at the repo root. Project rules live in `.cursor/rules/`; workflows for new components, themes, docs, and releases are in `.cursor/skills/`.

The docs site publishes [llms.txt](https://indielayer.com/llms.txt) for LLM-friendly navigation; regenerate it with `cd packages/ui && pnpm gen:llms` after adding component documentation.
The docs site publishes [llms.txt](https://indielayer.com/llms.txt) and [llms-full.txt](https://indielayer.com/llms-full.txt) for LLM-friendly navigation; regenerate both with `cd packages/ui && pnpm gen:llms` after adding component documentation.
4 changes: 1 addition & 3 deletions .github/workflows/pr_check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ jobs:
run: pnpm install --ignore-scripts

- name: Linting
run: |
pnpm run lint:ui
pnpm run lint:style
run: pnpm run lint:ui

- name: Unit tests
run: pnpm run test
Expand Down
1 change: 0 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"recommendations": [
"vue.volar",
"dbaeumer.vscode-eslint",
"stylelint.vscode-stylelint",
"indielayer.vscode-indielayer-theme",
"indielayer.indielayer-vue-snippets"
]
Expand Down
10 changes: 1 addition & 9 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
},
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "always",
"source.fixAll.stylelint": "always"
"source.fixAll.eslint": "always"
},
"eslint.validate": [
"javascript",
Expand All @@ -18,12 +17,5 @@
"eslint.workingDirectories": [
{ "directory": "packages/ui", "changeProcessCWD": true }
],
"stylelint.validate": [
"css",
"scss",
"sass",
"postcss",
"vue"
],
"typescript.tsdk": "node_modules/typescript/lib",
}
23 changes: 17 additions & 6 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ From the repo root:
```bash
pnpm i
pnpm dev # docs + component dev (packages/ui)
pnpm lint:ui && pnpm lint:style && pnpm test:ci # required before UI PRs (CI enforces this)
pnpm lint:ui && pnpm typecheck && pnpm test:ci # required before UI PRs
pnpm build:docs # production docs build
pnpm changeset # user-facing library changes (before merge)
```
Expand All @@ -30,15 +30,26 @@ CI=true pnpm test # equivalent (CI env disables watch mode)

Do **not** run bare `pnpm test` in non-interactive sessions.

### Typecheck (required when library code changes)

From the repo root:

```bash
pnpm typecheck # vue-tsc in packages/ui
```

Run after editing `packages/ui` TypeScript or Vue files (components, composables, themes, tests). Fix all errors before finishing.

### Linting (required)

- **CI**: `.github/workflows/pr_check.yml` runs `pnpm lint:ui` and `pnpm lint:style` on every PR.
- **Pre-commit**: `lint-staged` runs `eslint --cache --fix` on staged `*.{js,ts,vue}` and `stylelint --fix` on staged `packages/ui/**/*.{css,vue,postcss,scss,sass}` (via `simple-git-hooks`; enabled after `pnpm i`).
- **CI**: `.github/workflows/pr_check.yml` runs `pnpm lint:ui` and `pnpm typecheck` on every PR.
- **Pre-commit**: `lint-staged` runs `eslint --cache --fix` on staged `*.{js,ts,vue}` (via `simple-git-hooks`; enabled after `pnpm i`).
- **Agents / editors**: After editing files, run ESLint on touched paths before finishing:

```bash
pnpm eslint --cache --fix --ext .js,.ts,.vue packages/ui/docs # docs example
pnpm lint:ui && pnpm lint:style # must exit 0 before merge
pnpm lint:ui # must exit 0 before merge
pnpm typecheck # when packages/ui src changed
```

- **VS Code**: `.vscode/settings.json` enables ESLint fix-on-save when the ESLint extension is installed.
Expand All @@ -47,7 +58,7 @@ From `packages/ui`:

```bash
pnpm gen:search # regenerate docs search index
pnpm gen:llms # regenerate public/llms.txt
pnpm gen:llms # regenerate public/llms.txt and llms-full.txt
pnpm gen:sitemap # regenerate public/sitemap.xml
```

Expand All @@ -64,7 +75,7 @@ pnpm gen:sitemap # regenerate public/sitemap.xml
| [.cursor/rules/](.cursor/rules/) | Always-on and file-scoped coding rules |
| [.cursor/skills/](.cursor/skills/) | Workflows: new component, themes, docs, release |
| [packages/ui/public/llms.txt](packages/ui/public/llms.txt) | LLM index for the docs site ([spec](https://llmstxt.org/)) |
| [packages/ui/public/llms-full.txt](packages/ui/public/llms-full.txt) | Full library reference (large; update manually when APIs change) |
| [packages/ui/public/llms-full.txt](packages/ui/public/llms-full.txt) | Full library reference (generated by `pnpm gen:llms`; preamble in `.scripts/llms-full-preamble.md`) |

## Reference implementation

Expand Down
6 changes: 1 addition & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
"lint": "eslint --ext .js,.ts,.vue .",
"lint:ui": "eslint --ext .js,.ts,.vue ./packages/ui",
"lint:fix": "eslint --cache --fix --ext .js,.ts,.vue ./packages/ui",
"lint:style": "cd packages/ui && pnpm run stylelint",
"lint:style:fix": "cd packages/ui && pnpm run stylelint:fix",
"typecheck": "cd packages/ui && pnpm typecheck",
"test": "cd packages/ui && pnpm test",
"test:ci": "cd packages/ui && pnpm test:ci",
"changeset": "changeset",
Expand Down Expand Up @@ -46,9 +45,6 @@
"lint-staged": {
"*.{cjs,js,jsx,ts,tsx,vue}": [
"eslint --cache --fix"
],
"packages/ui/**/*.{css,vue,postcss,scss,sass}": [
"pnpm --dir packages/ui exec stylelint --fix"
]
},
"simple-git-hooks": {
Expand Down
68 changes: 65 additions & 3 deletions packages/create-ui/templates/nuxt/base/assets/tailwind.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,65 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@import "tailwindcss";
@import "@indielayer/ui/tailwind.css";

@source "../index.html";
@source "../app.vue";
@source "./**/*.{vue,js,ts}";
@source "../node_modules/@indielayer/ui/{lib,src}/**/*";

@theme {
--color-primary-50: var(--color-emerald-50);
--color-primary-100: var(--color-emerald-100);
--color-primary-200: var(--color-emerald-200);
--color-primary-300: var(--color-emerald-300);
--color-primary-400: var(--color-emerald-400);
--color-primary-500: var(--color-emerald-500);
--color-primary-600: var(--color-emerald-600);
--color-primary-700: var(--color-emerald-700);
--color-primary-800: var(--color-emerald-800);
--color-primary-900: var(--color-emerald-900);
--color-primary-950: var(--color-emerald-950);
--color-secondary-50: var(--color-slate-50);
--color-secondary-100: var(--color-slate-100);
--color-secondary-200: var(--color-slate-200);
--color-secondary-300: var(--color-slate-300);
--color-secondary-400: var(--color-slate-400);
--color-secondary-500: var(--color-slate-500);
--color-secondary-600: var(--color-slate-600);
--color-secondary-700: var(--color-slate-700);
--color-secondary-800: var(--color-slate-800);
--color-secondary-900: var(--color-slate-900);
--color-secondary-950: var(--color-slate-950);
--color-success-50: var(--color-green-50);
--color-success-100: var(--color-green-100);
--color-success-200: var(--color-green-200);
--color-success-300: var(--color-green-300);
--color-success-400: var(--color-green-400);
--color-success-500: var(--color-green-500);
--color-success-600: var(--color-green-600);
--color-success-700: var(--color-green-700);
--color-success-800: var(--color-green-800);
--color-success-900: var(--color-green-900);
--color-success-950: var(--color-green-950);
--color-warning-50: var(--color-yellow-50);
--color-warning-100: var(--color-yellow-100);
--color-warning-200: var(--color-yellow-200);
--color-warning-300: var(--color-yellow-300);
--color-warning-400: var(--color-yellow-400);
--color-warning-500: var(--color-yellow-500);
--color-warning-600: var(--color-yellow-600);
--color-warning-700: var(--color-yellow-700);
--color-warning-800: var(--color-yellow-800);
--color-warning-900: var(--color-yellow-900);
--color-warning-950: var(--color-yellow-950);
--color-error-50: var(--color-red-50);
--color-error-100: var(--color-red-100);
--color-error-200: var(--color-red-200);
--color-error-300: var(--color-red-300);
--color-error-400: var(--color-red-400);
--color-error-500: var(--color-red-500);
--color-error-600: var(--color-red-600);
--color-error-700: var(--color-red-700);
--color-error-800: var(--color-red-800);
--color-error-900: var(--color-red-900);
--color-error-950: var(--color-red-950);
}
4 changes: 1 addition & 3 deletions packages/create-ui/templates/nuxt/base/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ export default defineNuxtConfig({
},
postcss: {
plugins: {
'tailwindcss/nesting': {},
tailwindcss: {},
autoprefixer: {},
'@tailwindcss/postcss': {},
},
},
})
4 changes: 2 additions & 2 deletions packages/create-ui/templates/nuxt/base/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
"@types/node": "^18",
"@vuepic/vue-datepicker": "^11.0.1",
"@vueuse/core": "^11.1.0",
"autoprefixer": "^10.4.0",
"@tailwindcss/postcss": "^4.0.0",
"floating-vue": "^5.2.2",
"nuxt": "^3.10.1",
"postcss": "^8.4.24",
"tailwindcss": "^3.3.2"
"tailwindcss": "^4.0.0"
}
}
28 changes: 0 additions & 28 deletions packages/create-ui/templates/nuxt/base/tailwind.config.js

This file was deleted.

9 changes: 4 additions & 5 deletions packages/create-ui/templates/vue/base/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@
},
"devDependencies": {
"@indielayer/ui": "^1.0.9",
"@vitejs/plugin-vue": "^4.2.3",
"autoprefixer": "^10.4.14",
"postcss": "^8.4.24",
"tailwindcss": "^3.3.2",
"vite": "^4.4.11"
"@vitejs/plugin-vue": "^6.0.7",
"@tailwindcss/postcss": "^4.0.0",
"tailwindcss": "^4.0.0",
"vite": "^8.0.0"
}
}
7 changes: 0 additions & 7 deletions packages/create-ui/templates/vue/base/postcss.config.js

This file was deleted.

Loading