Skip to content

Commit d3c4639

Browse files
committed
Merge origin/main (0.2.0 release, stickers extraction) into expander branch
Conflict resolutions: - src/elements/index.ts, src/jsx-runtime.ts, src/general_types.ts: keep the a-expander exports/types, follow main's removal of the sticker elements (now @antadesign/stickers). - CHANGELOG.md: the auto-merge landed the Expander bullet inside the already-released 0.2.0 section; moved it to a new Unreleased section. Verified post-merge: anta build + typecheck + site build pass; React 19 and Preact smoke suites (17 assertions each) all pass against the merged dist. https://claude.ai/code/session_01A9PoyMtVzmBJshb5gneqVQ
2 parents 4913d1d + 2baad41 commit d3c4639

254 files changed

Lines changed: 1457 additions & 747 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,9 @@ jobs:
1616
- run: pnpm install --frozen-lockfile
1717
- run: pnpm run build
1818
- run: pnpm run typecheck
19+
- name: Build stickers
20+
run: pnpm --filter @antadesign/stickers run build
21+
- name: Typecheck stickers
22+
run: pnpm --filter @antadesign/stickers run typecheck
1923
- name: Build site
2024
run: pnpm --filter anta-site build

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ node-compile-cache/
33
.claude/
44
.playwright-mcp/
55
/dist/
6+
stickers/dist/
67
site/dist/
78
site/.astro/
89
site/src/api.json
910
site/src/pages/index.mdx
11+
site/src/generated/
1012
site/public/esbuild.wasm
1113
site/public/iframe-anta-runtime.js
1214
.DS_Store

CHANGELOG.md

Lines changed: 37 additions & 10 deletions
Large diffs are not rendered by default.

CLAUDE.md

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
Published as `@antadesign/anta` on npm. Portable UI component library. Works in React apps out of the box, in Preact via compat aliasing (`react``preact/compat`), and in custom runtimes via `configure()`.
44

5+
This repo is a pnpm workspace with **two publishable packages** plus the docs site:
6+
- `@antadesign/anta` — this package, at the repo root (`src/`, `dist/`).
7+
- `@antadesign/stickers` — the sticker pack, in top-level [`stickers/`](stickers/CLAUDE.md). It owns the `<a-sticker>` / `<a-sticker-animated>` elements, the `Sticker` / `StickerAnimated` wrappers, the artwork, and the **only** `lottie-web` dependency. It depends on `@antadesign/anta` for the JSX runtime and shared helpers. Kept separate so anta carries no animation runtime. **Anything sticker-related — components, tokens, docs page, the generator — lives there, not here.**
8+
- `site/` — the docs site (not published).
9+
510
## Architecture
611

712
Two tiers per component:
@@ -13,11 +18,14 @@ The tiers are decoupled — JSX wrappers emit `<a-*>` tags but never import elem
1318

1419
### Key files
1520

16-
- `src/jsx-runtime.ts` — Custom JSX runtime. Defaults to `React.createElement`. Call `configure(h)` to swap.
17-
- `src/types.d.ts` — CSS module type declarations and `JSX.IntrinsicElements` for `a-*` custom elements.
21+
- `src/jsx-runtime.ts` — Custom JSX runtime. Defaults to `React.createElement`. Call `configure(h)` to swap. **Owns the `JSX.IntrinsicElements` declarations for `a-*` tags** — they must live here (not elsewhere) because tsc's `jsxImportSource` mechanism resolves JSX element types from the `JSX` namespace exported by `<source>/jsx-runtime`, and because companion packages augment this exact module (`@antadesign/stickers` does `declare module '@antadesign/anta/jsx-runtime'` to add its tags).
22+
- `src/general_types.ts` — Shared `BaseProps` / `BaseAttributes` plus the per-element `A{Name}Attributes` interfaces. A regular `.ts` module (never a `.d.ts` — tsc doesn't copy declaration inputs to `dist`) published as the `@antadesign/anta/general_types` subpath; `@antadesign/stickers` and all JSX wrappers import from it.
23+
- `src/types.d.ts` — Internal-only ambient declarations: the wildcard `declare module '*.module.css'`. Can't merge into the files above — wildcard ambient module declarations are only legal in a global (non-module) declaration file. Not shipped to `dist`.
1824
- `src/elements/index.ts` — Barrel export that auto-registers all web components in browser contexts. **Must only be imported client-side**`HTMLElement` does not exist in Node/SSR.
1925
- `src/index.ts` — Barrel export for JSX components and `configure()`.
2026

27+
These three type locations are each pinned by a different TypeScript mechanism (see above) — don't try to consolidate them.
28+
2129
## Build & dev
2230

2331
Source lives in `src/`. Build output goes to `dist/`. `dist/` is gitignored — `pnpm install` regenerates it via the `prepare` lifecycle script, and `npm publish` regenerates it via `prepublishOnly` so the published tarball is always fresh. The package is distributed only through npm; the GitHub-URL install path is not supported.
@@ -34,7 +42,7 @@ pnpm run typecheck # Type check without emit
3442

3543
**For any dev work — editing the anta package *or* the docs site — run `pnpm run dev` from the repo root** (run it in the background; it's long-lived). It does both halves together:
3644

37-
- a `nodemon -w src` watcher that **rebuilds `dist`** (and regenerates the site's `docs:*` artifacts) on every change to anta's `src/**/*.{ts,tsx,css}`, and
45+
- a `nodemon -w src -w stickers/src` watcher that **rebuilds `dist`** (anta, then `@antadesign/stickers`) and regenerates the site's `docs:*` artifacts on every change to either package's `src/**/*.{ts,tsx,css}`, and
3846
- the docs site's `astro dev` (HMR for `site/`).
3947

4048
The docs site consumes anta from the built `dist/` (workspace symlink), so this is what propagates an anta-source change through to the running site. **Do not** run `cd site && pnpm run dev` for package work — that starts only the site's Astro dev and will *not* rebuild `dist`, so anta `src` edits won't show up and you'd be stuck manually rebuilding + restarting. Pure `site/` edits (`.mdx`, Astro/Preact components) HMR fine under either, but the root command is the one to use so package edits Just Work too.
@@ -74,16 +82,31 @@ useEffect(() => { import('@antadesign/anta/elements') }, [])
7482

7583
## npm publishing
7684

85+
Two packages publish from this repo: **`@antadesign/anta`** (root) and **`@antadesign/stickers`** (`stickers/`). Both go out as prereleases under the npm `dev` dist-tag. Each version string is immutable on npm — **always bump before publishing**.
86+
87+
> **If asked to publish — or to recall how — walk the user through this, in order.** The order and the `pnpm` vs `npm` distinction are the two easy things to get wrong.
88+
89+
**Publish anta first, then stickers.** `@antadesign/stickers` depends on `@antadesign/anta` via `workspace:*`, which pnpm rewrites to anta's **exact current version** at pack time. So the anta version stickers will pin must already be on npm — and it must be the version that carries whatever exports stickers imports (e.g. `./anta_helpers`, `./general_types`). Publishing stickers against an anta version that isn't published yet (or predates an export it needs) makes `npm install @antadesign/stickers` unresolvable.
90+
7791
```sh
78-
npm version prerelease --preid=dev # Bump: 0.1.1-dev.1 → 0.1.1-dev.2
79-
npm publish --access public --tag dev # Publish prerelease under "dev" tag
92+
# 1) anta — from repo root
93+
npm version prerelease --preid=dev # 0.1.1-dev.8 → 0.1.1-dev.9 (or bump the version field by hand)
94+
npm publish --access public --tag dev # prepublishOnly rebuilds dist
95+
96+
# 2) stickers — from stickers/
97+
cd stickers
98+
pnpm publish --no-git-checks # access/tag come from its publishConfig
8099
```
81100

82-
Each version string is immutable on npm — always bump before publishing.
101+
- **Use `pnpm publish` for `stickers`, not `npm publish`.** Only pnpm rewrites the `workspace:*` protocol to a real version; `npm publish` would leave `workspace:*` in the tarball and the package would be uninstallable. (anta has no workspace deps, so `npm publish` is fine there.)
102+
- `stickers/package.json` has `publishConfig: { access: "public", tag: "dev" }`, so its publish needs no `--access` / `--tag` flags. anta passes them explicitly.
103+
- `prepublishOnly` (anta) / `prepare` (both) rebuild `dist` before the tarball is created, so published output is always fresh.
104+
- Bumping the `version` field by hand (vs `npm version`) skips the auto git commit + tag. If you tag releases, create the tag manually; otherwise no action needed.
105+
- 2FA: append `--otp=<code>` if your npm account requires it.
83106

84107
## Changelog
85108

86-
`CHANGELOG.md` at the repo root documents changes to **the `@antadesign/anta` package only** — code shipped to npm consumers (anything under `src/` and `dist/`, plus root files in the published tarball). The docs site under `site/` is its own thing and **does not** belong in the changelog. New site pages, component-docs polish, demos, layout tweaks — all of that ships only on `antadesign.dev` and isn't a consumer-facing change.
109+
`CHANGELOG.md` at the repo root documents changes to **the `@antadesign/anta` package only** — code shipped to npm consumers (anything under `src/` and `dist/`, plus root files in the published tarball). The docs site under `site/` is its own thing and **does not** belong in the changelog. New site pages, component-docs polish, demos, layout tweaks — all of that ships only on `anta.design` and isn't a consumer-facing change.
87110

88111
When in doubt: would a consumer who installs this version see this change in their app? If no, leave it out of `CHANGELOG.md`. Use commit messages and PR descriptions for the docs-site narrative.
89112

@@ -143,8 +166,8 @@ The same rule applies anywhere we lighten/darken/desaturate a color: prefer `col
143166
- **Default variant in union types** — Include default value explicitly in the type union (e.g. `tone?: 'neutral' | 'info'`).
144167
- **CSS modules only on JSX wrappers**, plain CSS for web components. Use `.container` as the top-level class in CSS modules.
145168
- **Types** — Use React global types (e.g. `React.CSSProperties`) without importing React. Components must be compatible with both React and Preact.
146-
- **Auto-registration (granular + barrel)** — each `a-{name}` module self-registers and imports its own CSS when loaded, so a granular `import '@antadesign/anta/elements/a-{name}'` registers just that element (and won't drag in other elements' deps — e.g. only `a-sticker-animated` pulls `lottie-web`). The `elements/index.ts` barrel re-exports every module, so `import '@antadesign/anta/elements'` registers them all. Registration is guarded against missing `customElements` (SSR-safe), but elements should still only be imported client-side.
147-
- **Component-token-first** — Each component defines its own CSS custom properties. Global tokens will be added later.
169+
- **Auto-registration (granular + barrel)** — each `a-{name}` module self-registers and imports its own CSS when loaded, so a granular `import '@antadesign/anta/elements/a-{name}'` registers just that element (and won't drag in other elements' code or deps). The `elements/index.ts` barrel re-exports every module, so `import '@antadesign/anta/elements'` registers them all. Registration is guarded against missing `customElements` (SSR-safe), but elements should still only be imported client-side. (The same pattern powers `@antadesign/stickers/elements` — its granular `a-sticker` path keeps `lottie-web` out, since only `a-sticker-animated` pulls it.)
170+
- **Component-token-first; the only global tokens are color roles.** The global token vocabulary is deliberately tiny and lives in `src/tokens.css`: theme-aware *role* scales for **text** (`--text-*`), **container background** (`--bg-*`), and **container border** (`--border-*`), per tone, plus fonts and link colors. A component points at these roles only when a value clearly *is* one of those three things (see `a-tag.css` — that's also what makes its dark mode free). Everything else — sizes, spacing, radii, interaction-state colors, timings — is defined per component as `--{component}-*` with literal values, **on purpose**: values are still being tuned back and forth, and component-level definitions keep every part independently changeable. Component-local literal values are policy, not debt — do **not** "clean them up" by routing them through global tokens, and do **not** introduce primitive palette tokens or global spacing/size scales. New global role families (e.g. interactive fills) only by explicit decision, once the values have actually stabilized across components.
148171
- **Document defaults with `@defaultValue`** — Every optional prop whose default isn't obvious (enums, numbers like `size`/`level`/`max`, a default tone/priority) **must** carry a `@defaultValue <value>` TSDoc tag on its declaration in `src/components/<Name>.tsx`. This is the single source of truth: TypeDoc captures it into `site/src/api.json`, `PropsTable.astro` renders it as the **Default** column, and the playground's `props-form.ts` reads it for control defaults. State the default *only* in the tag — don't also write "Defaults to …" in the prose description (the Default column would duplicate it). Skip the tag for booleans that default to `false` (obvious) and for required props (no default).
149172
- **Docs-in-sync** — When you rename a component prop, rename a `--{component}-*` token, add a token, or remove one, **update `site/src/pages/components/{name}.mdx` in the same change** so the docs page tracks the source of truth. The same applies to default values, prop type unions, and to any consumer-facing API note in `README.md`. Drift between the source and the docs site is the single most common bug report — easier to keep them in lockstep than to chase the divergence later.
150173

@@ -156,7 +179,7 @@ The same rule applies anywhere we lighten/darken/desaturate a color: prefer `col
156179
4. Create `src/components/{Name}.tsx` — JSX wrapper, import CSS module
157180
5. Create `src/components/{Name}.module.css` — scoped styles for wrapper layout
158181
6. Add to `src/index.ts` — re-export the component
159-
7. Add `a-{name}` to `JSX.IntrinsicElements` in `src/types.d.ts`
182+
7. Define `A{Name}Attributes` in `src/general_types.ts` (extending `BaseAttributes`), then add `a-{name}` to `JSX.IntrinsicElements` in `src/jsx-runtime.ts`
160183
8. Add entry points to `build:js` script in `package.json`
161184
9. Add CSS files to `build:css` script in `package.json`
162185
10. Run `pnpm run build` to verify

DESIGN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ components:
4848

4949
Anta is a portable UI component library built on a two-tier architecture: web components (`elements/`) provide the rendering layer via shadow DOM, and JSX wrappers (`components/`) provide a typed component API. The tiers are decoupled — wrappers emit custom element tags but never import element definitions.
5050

51-
Anta follows a **component-token-first** philosophy. Each component defines its own CSS custom properties (e.g., `--progress-indicator-bg`) rather than depending on a global token system. Global tokens will be introduced later for cross-component consistency, but component tokens remain the primary styling mechanism.
51+
Anta follows a **component-token-first** philosophy. Each component defines its own CSS custom properties (e.g., `--progress-indicator-bg`) as the primary styling mechanism. The only global tokens are the theme-aware color *roles* in `src/tokens.css` — text (`--text-*`), container background (`--bg-*`), and container border (`--border-*`) scales, plus fonts and link colors — which components consume when a value is clearly one of those roles. There is deliberately no primitive color palette and no global spacing/size scales: while the system is young and values are still being tuned, component-local definitions keep every part independently changeable.
5252

5353
# Components
5454

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ This constraint shapes the architecture: the web components carry the core styli
1010

1111
`@antadesign/anta` is an NPM package, so you can `npm install @antadesign/anta` or do that with `pnpm` / `bun`.
1212

13-
Since Anta is in active development we suggest using the latest dev version: `"@antadesign/anta": "dev"` in your `package.json`. For production builds we suggest pinning to a stable version from npm.
13+
Use the latest version from npm, but **always pin an exact version**`"@antadesign/anta": "0.2.0"` in your `package.json` — rather than a floating tag like `"latest"` or `"dev"`, which can change between installs.
1414

1515
### Usage
1616

@@ -36,7 +36,7 @@ Anta exposes four independent imports. Tokens + elements + the JSX layer are the
3636

3737
The chain matters: the per-element CSS that ships with `/elements` references variables like `var(--text-1)` and `var(--bg-2)`. Those variables are *only defined* by `tokens.css`. Skip the tokens import and the components render with whatever the surrounding cascade provides — usually nothing styled at all.
3838

39-
`@antadesign/anta/elements` registers **all** elements — convenient, but it includes every element's code (and deps). To keep your bundle lean, import only the elements you use from their per-element entry points instead: `import '@antadesign/anta/elements/a-tooltip'` registers just `<a-tooltip>` **and loads just its CSS**. Unused elements — and their dependencies, e.g. `lottie-web` (needed only by `<a-sticker-animated>`) — then never enter your bundle. See [Registering elements](#registering-elements).
39+
`@antadesign/anta/elements` registers **all** elements — convenient, but it includes every element's code (and deps). To keep your bundle lean, import only the elements you use from their per-element entry points instead: `import '@antadesign/anta/elements/a-tooltip'` registers just `<a-tooltip>` **and loads just its CSS**. Unused elements — and any dependencies they pull in — then never enter your bundle. See [Registering elements](#registering-elements).
4040

4141
### Cascade layers
4242

@@ -79,7 +79,7 @@ import '@antadesign/anta/elements/a-tooltip' // only <a-tooltip> + its CSS
7979
import '@antadesign/anta/elements/a-button' // only <a-button> + its CSS
8080
```
8181
82-
Both styles are side-effect imports (the act of importing registers the element), and both are idempotent and SSR-safe. The granular form keeps unused elements — and their dependencies, e.g. `lottie-web`, which only `<a-sticker-animated>` pulls in — out of your bundle.
82+
Both styles are side-effect imports (the act of importing registers the element), and both are idempotent and SSR-safe. The granular form keeps unused elements — and any dependencies they pull in — out of your bundle.
8383
8484
The cleanest pattern is a **static, synchronous import at your app's entry file** — outside any component, outside any hook:
8585

0 commit comments

Comments
 (0)