Skip to content

release: cut over to 3.0.0-rc.1 - #575

Merged
aerovulpe merged 27 commits into
mainfrom
develop
Aug 8, 2026
Merged

release: cut over to 3.0.0-rc.1#575
aerovulpe merged 27 commits into
mainfrom
develop

Conversation

@aerovulpe

Copy link
Copy Markdown
Member

Summary

  • replace the legacy V2 implementation on the default branch with the typed Vue 3 and framework-neutral web-component library
  • publish the release candidate as an ESM-only package with rolled declarations, packed-consumer verification, MIT and third-party notices, and tag-based trusted publishing
  • audit and correct the README, Storybook documentation, integration guides, public story copy, security guidance, and project governance
  • preserve the stable V2 source on the v2 branch and keep vue-advanced-chat@2.1.2 as a separate npm release line

Release

Validation

  • npm ci
  • npm audit --audit-level=moderate (0 vulnerabilities)
  • npm run verify
  • full Storybook MCP interaction and accessibility suite (214 passing stories)
  • strict packed TypeScript consumers for Bundler and NodeNext
  • packed Vite CSS consumer and Node SSR imports
  • Chromium web-component package verification
  • valid local PNG, JPEG, PDF, WAV, and MP4 Storybook fixtures

Migration

V3 is not a drop-in V2 upgrade. The migration guide documents package, model, event, slot, theming, and web-component changes.

aerovulpe and others added 27 commits March 10, 2026 00:10
Brings the V3 rewrite on `develop` to a feature-complete `3.0.0-alpha.1`
state and adds the working planning record under `rewrite/`.

Surface and behavior:
- Wire reply/edit message actions through `Chat` → `ChatFooter` so
  the footer pre-fills state and exposes cancel-edit/cancel-reply.
- `Chats` exposes `chatActions` + `customSearchEnabled` and re-emits
  `chat-action-handler`; the local search filter is wired by default.
- `AdvancedChat` forwards every consumer-facing event and gains
  `chatsLoaded`, `chatActions`, `messageSelectionActions`, `showSearch`,
  `showAddChat`, `showFiles`, `showEmojis`, `showFooter`, `showSendIcon`,
  `showReactionEmojis`, `showNewMessagesDivider`, `acceptedFiles`,
  `multipleFiles`, `captureFiles`, `customSearchEnabled`,
  `chatInfoEnabled`.
- `ChatFooter` exposes `acceptedFiles`/`multipleFiles`/`captureFiles`,
  emits `focus-textarea`/`blur-textarea`, and renders cancel-edit and
  cancel-reply controls.
- `Message` renders `system` and `edited` variants and respects
  `disableActions`/`disableReactions`. The failure indicator is now a
  themed retry pill instead of a tiny `!` glyph.
- `MessageActions` is a chip floating below the bubble (not over the
  content); reactions/menu open upward.
- `MessageTemplate` always renders message text — partial
  `formattingOptions` overrides merge with defaults.
- `useThemeStyles` follows `prefers-color-scheme` reactively.

Localization: new keys `chat.empty`, `chat.messages.empty`,
`chat.messages.new`, `chat.message.placeholder`, `chat.message.deleted`,
`chat.message.failure`, `chat.cancel-reply`, `chat.cancel-edit`.

Theming: darker muted-text variables to clear WCAG 4.5:1 contrast,
new `--chat-message-color-failure`/`--chat-message-bg-color-failure`
for the retry pill, `microphone`/`deleted` icon CSS bindings.

Packaging: `vue` moved to `peerDependencies`; transitive
`micromark-*` packages declared as direct `dependencies`.

Stories: added Loading/Empty/NoChatSelected/Reply/Audio/Deleted/System/
Failure/Search-filter variants; populated empty default args; wrapped
the absolute-positioned `MessageActions`/`ChatEmojis`/`ChatUserTag`
demos in proper relative containers so they render correctly.

Tooling: new `verify:storybook-ui` and `verify:storybook-flows`
scripts that drive the static Storybook with Playwright; CHANGELOG,
RELEASING, LICENSE, .nvmrc, GitHub workflows, and `rewrite/` planning
docs (`architecture.md`, `parity-checklist.md`, `issue-triage.md`,
`release-plan.md`, `v2-feature-catalog.md`).

Bumps `package.json` to `3.0.0-alpha.1`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
229 tests across 35 files driving the library through Storybook
(Vitest browser project, Chromium via Playwright) plus a node-side
unit project for pure modules.

Coverage with `npm run test:coverage`:
- Statements: 86.07% (was 61.66%)
- Branches:   79.10% (was 54.58%)
- Functions:  84.51% (was 51.52%)
- Lines:      87.78% (was 63.11%)

Storybook play() interaction tests for every component:
- ChatFooter: typing, Enter sends, Shift+Enter newline, send-disabled
  toggle, click-send-icon, emoji & user-tag autocomplete (click and
  arrow-key paths), reply/edit cancel, focus/blur events, edit
  pre-fill.
- ChatHeader: toggle, standalone hides toggle, info click, menu
  action, selection toolbar fire/cancel, typing indicator, online
  status.
- Chats / ChatsItem / ChatsSearch: search filter, custom search
  bypass, open chat, action handler bubble-up, add-chat, action
  visibility for empty action arrays, unread badge, typing, audio
  last-message preview.
- Message / MessageActions / MessageReactions / MessageReply /
  MessageTemplate / MessageFile / MessageFiles / ChatMessage:
  reaction picker open + emit, dropdown menu open + emit, failure
  click, selection click, reactions render and click, deleted/system
  hide actions, reply variants for image/video/audio/file, markdown
  rendering, single-line collapse, user-tag click.
- MediaPreview: backdrop click, close button, Escape key.
- AudioControl: percentage rendering, mousedown emit, drag (mousemove)
  with bounds clamping, hover on/off, selection-mode block.
- EmojiPicker: opened mounts custom element, closed removes it.
- AdvancedChat: end-to-end search→list filter, open chat, send
  message, reply pre-fills footer, theme override, header menu
  action, chat info, chat-action handler.

Unit tests (jsdom + node):
- utils/deep-merge, filter-items, media-types, prune-keys.
- models/findUserById, typingUsersString.
- localization/getLocalizationStrings.
- themes/getThemeStyles (auto, override, dark/light, no-window fallback).
- plugin/AdvancedChatPlugin (provide injection + global helper).
- text-formatter/formatText (markdown, GFM, underline, user-tag,
  linkify, single-line, checklist a11y).

Component fixes surfaced by the tests:
- Replace clickable `<div>` menu items with `<button role="menuitem">`
  in ChatHeader, ChatsItem, MessageActions to satisfy
  scrollable-region a11y rule.
- Darken `--chat-header-color-info`, `--chat-message-color-new-messages`,
  and `--chat-message-bg-color-selected` to meet WCAG 4.5:1 contrast
  for typing indicator, new-message divider, and selected message
  timestamp respectively.

Tooling:
- vite.config.ts gains a `coverage` block (v8 provider, html + json-summary
  reporters) and a separate `unit` test project for `*.spec.ts`.
- New `test:unit`, `test:coverage` scripts; `test` runs both suites.
- jsdom installed as a devDependency for the unit project.
- coverage/ added to .gitignore.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Implements the priority-zero items from `rewrite/architecture-review.md`:

Pagination + auto-scroll
- `Chat` emits `fetch-messages` when the message list scrolls within
  60 px of the top (suppressed by `loadingMessages` or `messagesLoaded`).
- Auto-scrolls to the latest on mount, on chat switch, on send, and
  on receive when the user is already near the bottom.
- "Scroll to latest" pill with a `message.new` count badge appears when
  the user has scrolled away.
- New `chat.scroll-to-bottom` localization key.
- `AdvancedChat` exposes `messagesLoaded` and re-emits `fetch-messages`.

Event naming standardized to kebab-case
- BREAKING: `opened:file` → `open-file`, `clicked:user-tag` → `click-user-tag`
  across MessageActions, Message, MessageFile, MessageFiles,
  MessageTemplate, ChatMessage, Chat, AdvancedChat (and their stories).

Chats infinite-scroll inversion fixed
- `Chats.chatsLoaded` now follows v2's `rooms-loaded` semantics: `true`
  means "stop fetching". The previous inverted guard made
  `fetch-more-chats` unreachable through the watch path.
- The `loadingMoreChats` watcher is registered before the immediate
  chats watch so the initial pass through `loadMoreChats` emits both
  `fetch-more-chats` and `loading-more-chats: true`.

Action constants exported
- New `src/components/actions.ts` exports `REPLY_ACTION`, `EDIT_ACTION`,
  and `BuiltInActionName`. Consumers no longer rely on magic strings
  to opt into the built-in reply/edit footer pre-fill.

Type exports aggregated
- `src/index.ts` re-exports every per-component `*Props` / `*Events`
  interface, the `ChatHeaderMessageSelection`, `ChatFileItem`,
  domain models, theme/localization primitives, plugin types, and
  `formatText` text-formatter helpers.

@ts-nocheck eliminated
- `deep-merge`, `filter-items`, `text-formatter/autolink`,
  `text-formatter/underline`, `text-formatter/user-tag` are now
  type-checked. New `text-formatter/types.d.ts` augments
  `micromark-util-types`'s `TokenTypeMap` with the custom token names
  this library emits.

Tailwind dropped
- BREAKING: removed `@tailwindcss/vite` and `tailwindcss` deps and the
  unused `@import 'tailwindcss';` from `src/assets/style.css`. No
  template used Tailwind utility classes; the bundled preflight cost
  consumers ~5 KB. CSS bundle now 31.77 KB / 5.83 KB gz (was 37.20 /
  7.48).

`v-click-outside` migrated to @vueuse/components
- Replaced the 200-line internal fork (`src/utils/on-click-outside.ts`)
  with `@vueuse/components`'s `vOnClickOutside` directive across
  ChatHeader, ChatsItem, MessageActions.

Theme contrast
- File-attachment progress overlay darkened (rgba 0.3 → 0.6) and the
  nested `.vac-text-extension` color overridden to white so it clears
  WCAG 4.5:1 contrast under the loader.

Tests
- Restored the deleted `Chats > FewerThanMinimumTriggersLoadMore`
  test and added `StopsLoadingMoreWhenAllLoaded`.
- Added Chat pagination stories: `ScrollToTopFiresFetchMessages`,
  `NoFetchWhenLoaded`, `NoFetchWhileLoadingMessages`.
- 177 Storybook play() tests + 56 unit tests, all green.

Docs
- New `rewrite/architecture-review.md` records the original review
  this commit responds to (links P0/P1/notes for traceability).
- README index updated with the review.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
After fixing the Chats inversion (chatsLoaded=true now means
"stop fetching"), the Storybook Default and AdvancedChat stories
that pass the full sample fixture were rendering a perpetual
infinite-rooms loader because the watcher kept asking for more.

Set `chatsLoaded: true` and `messagesLoaded: true` on the
demo defaults that ship the complete sample data, and override
back to false on the pagination interaction tests
(`ScrollToTopFiresFetchMessages`, `FewerThanMinimumTriggersLoadMore`)
that assert the watcher fires.

Visual review confirms light + dark AdvancedChat now load to
the bottom of the message thread (auto-scroll-on-mount working)
with no spurious chats loader, and all 177 Storybook play tests
still pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Companion to architecture-review.md, focused on the consumer-facing
surface: field names, prop shapes, localization type, event payloads.

Headline issues (all P0 for 3.0 GA):

Data model
- Chat.icon → Chat.avatar (industry term; v2 used this).
- User has no avatar field; per-user avatars never render. Add
  User.avatar so 1:1 chat fallbacks and group-chat author rows
  display correctly.
- Message has three overlapping booleans (saved/delivered/read) plus
  a fourth (failure). Replace with status: 'sending' | 'sent' |
  'delivered' | 'read' | 'failed'.
- Message.new is too generic for "is in the unread batch" — rename
  to unread.
- Message.sender: User forces full denormalization on every message.
  Accept UserReference and resolve against chat.users.
- MessageFile.audio is redundant; isAudioFile already derives.

Naming consistency
- Action.name + Action.title is non-standard; rename to id + label.
- "user" (viewer) vs "users" (participants) — same word root, two
  meanings, ambiguous in TypeScript hovering. Rename viewer prop.
- "room" terminology lingering in slot names (room-header,
  rooms-empty, room-list-item_<id>, etc.) even though the rest of
  the v3 surface renamed to "chat". Final v2 → v3 slot sweep.
- count-suffixed counters: unreadCount ✓ vs selectedMessagesTotal ✗.
- HTML attribute mirrors (acceptedFiles, multipleFiles, captureFiles)
  should match the platform names (accept, multiple, capture).

Localization
- Strings type forces the full dictionary; adding a key is breaking
  for typed consumers even though the plugin merges defaults at
  runtime. Plugin should accept Partial<Strings>.

Event payloads
- ChatHeader emits menu-action-handler with just `action`;
  AdvancedChat re-emits with { chat, action }. Same listener wired
  through different layers gets different shapes. Standardize on
  { chat, action } (or { message, action }) everywhere.
- One-field payload wraps ({ message }) inconsistent with multi-field
  ones. Pick a convention.

Plus the recommended landing order (nine small P0 PRs, none
depending on each other except the message-status enum which is
the one bigger change).

README index updated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes the nine P0 items from rewrite/ergonomics-review.md.
Every item below is a breaking change vs 3.0.0-alpha.1.

Action contract
- Action.name → Action.id
- Action.title → Action.label
- (REPLY_ACTION/EDIT_ACTION constants unchanged; they're now the
  documented values for Action.id)

Avatars
- Chat.icon → Chat.avatar
- New User.avatar?: string. Rendered in ChatUserTag, falls back
  for Chat.avatar in 1:1 chats. Test fixtures gain avatar URLs.

Localization typing
- typingUsersString accepts Pick<Strings, 'chat.typing'> instead of
  the full type, so the test fixtures can pass partials.
  AdvancedChatPlugin already accepted Partial<Strings> at runtime;
  this aligns the helper API.

Message status enum
- Replaced four overlapping booleans (saved/delivered/read/failure)
  with Message.status?: 'sending' | 'sent' | 'delivered' | 'read' |
  'failed'. New exported MessageStatus type.
- Message.new → Message.unread.

Slot v2 → v3 sweep (templates only; CSS classes unchanged)
- room-header → chat-header
- room-header-avatar → chat-header-avatar
- room-header-info → chat-header-info
- room-options → chat-options
- rooms-empty → chats-empty
- room-list-item_<id> → chat-list-item_<id>
- room-list-avatar_<id> → chat-list-avatar_<id>
- room-list-info_<id> → chat-list-info_<id>
- room-list-options_<id> → chat-list-options_<id>
- room-list-options-icon_<id> → chat-list-options-icon_<id>
- spinner-icon-rooms → spinner-icon-chats
- spinner-icon-infinite-rooms → spinner-icon-infinite-chats

Id narrowed
- Id = string (was string | number). Removes ~12 defensive
  .toString() calls and a class of '1' === 1 bugs. Consumers map
  numeric backend ids with String(id) at the API boundary.

Event payload standardization
- ChatHeader emits menu-action-handler / message-selection-action-
  handler with { chat, action } (was just Action). Shape is
  consistent whether the listener is wired on Chat directly or via
  AdvancedChat.
- ChatsItem emits chat-action-handler with { chat, action } (was
  Action). Chats no longer wraps before re-emitting.
- open-failed-message emits the Message directly, not wrapped in
  { message }.

MessageFile cleanup
- Dropped MessageFile.audio (redundant with isAudioFile() helper).

Bumped to 3.0.0-alpha.2. CHANGELOG documents the migration recipe
in a single table at the top of the entry.

Tests / verify
- 177 Storybook play tests + 56 unit tests, all green.
- Visual review confirms avatars render in light + dark, action
  chips remain below bubbles, failure pill renders correctly,
  selection mode toolbar still emits properly through the new
  payload shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes the consumer-facing P1 items from rewrite/ergonomics-review.md.
Composables extraction and autocomplete unification stay deferred —
they're internal-only refactors that don't gate the release.

Every item is breaking vs 3.0.0-alpha.2; CHANGELOG has the migration
recipe at the top.

Selection mode self-contained
- The packed messageSelection: { enabled, actions } prop on Chat
  and ChatHeader (and AdvancedChat's messageSelectionActions) is
  collapsed into a single selectionActions: Action[]. Non-empty
  enables selection mode. Drops the ChatHeaderMessageSelection type.

File-input props match the platform
- acceptedFiles → accept
- multipleFiles → multiple
- captureFiles → capture
  Prop names now match the underlying HTML <input type="file">
  attributes; stops being a private aliasing layer.

Disambiguating viewer prop
- user (the viewer) → currentUser everywhere it appears (AdvancedChat,
  Chat, Chats, ChatHeader, ChatsItem, Message, ChatMessage,
  MessageActions, MessageReactions, MessageFile, MessageFiles).
  Eliminates the user-vs-users (viewer-vs-participants) collision in
  TypeScript hovering.

Action shape polish
- Action.onlyMe → Action.ownMessageOnly. Reads as semantic intent.
- New Action.icon?: string. Optional leading icon for dropdown
  items, resolves to a built-in SvgIcon name (`'pencil'` for Edit,
  `'deleted'` for Delete in the sample fixture).

Naming consistency
- ChatHeader.selectedMessagesTotal → selectedCount. Matches the
  *Count suffix of unreadCount.

Centralized text formatting
- New Chat.textFormatting / AdvancedChat.textFormatting prop:
  Partial<TextFormattingOptions>. Threads through to every
  MessageTemplate render via Message → MessageReply / MessageFiles.
  Restores v2's top-level text-formatting config; per-render overrides
  (single-line previews, system-message render) compose on top.

Type tightening
- Introduce MessageSummary (id, sender, content, createdAt, status,
  deleted, edited, files). Use for Chat.lastMessage and Message.reply
  so the recursive case (a reply to a reply to a reply…) doesn't fall
  out of the model. Existing Message values are still assignable.
- ChatsItem renders the "new message" styling from chat.unreadCount
  (was chat.lastMessage.unread, which doesn't exist on
  MessageSummary).

Tests / verify
- 177 Storybook play tests + 56 unit tests, all green.
- Visual review confirms avatars, action chip placement, failure
  pill, voice-note, deleted/system messages all unchanged.

Bumped to 3.0.0-alpha.3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes the deferred items from `rewrite/ergonomics-review.md`:
extracts the active-index, message-selection, reply/edit,
infinite-scroll and local-search state machines into reusable
composables, and unifies the emoji and user-tag suggestion menus
behind a generic `<AutocompleteMenu>` base. Also lands three
correctness fixes surfaced during the alpha.4 review pass.

- Add `useAutocomplete`, `useMessageSelection`, `useReplyEdit`,
  `useInfiniteScroll`, `useLocalSearch` to the public surface and
  rewire `Chat`, `Chats`, `ChatEmojis`, `ChatUserTag` through them.
- Add `<AutocompleteMenu>` as the slotted, generic base for the
  two built-in autocomplete surfaces; consumers can use it for
  slash-command menus or other autocompletes without re-deriving
  the active-index logic.
- `Chat.vue` now clears the message selection automatically after
  a `message-selection-action-handler` dispatch.
- Guard `formatText({ singleLine: true })` behind a `typeof
  document` check with a tag-strip fallback for SSR.
- `MessageFile`'s image preloader now also listens for `error` so
  a broken URL clears the loading spinner.
- `ChatFooter` shares a single `URL.createObjectURL` between
  `url` and `localUrl` so `removeFile` / `resetMessage` revoke
  both at once.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a spec per composable so the active-index, selection,
reply/edit, infinite-scroll and local-search state machines are
contract-tested before they ship as part of the public API. Also
includes `test:unit` in the `verify` chain so future drift fails CI
the same way Storybook test failures do.

- 47 unit tests across the five composables; pure-logic ones use
  `effectScope` for setup-context, the IntersectionObserver helper
  uses jsdom + `createApp` and stubs the global observer.
- `verify` now runs `test:unit` before `test:storybook`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tightens a handful of small public-API gaps surfaced during the
alpha.4 review. No behavior changes for existing consumers; the
`useInfiniteScroll` option types widen and `Layout` gains a
previously-unused override path.

- `useInfiniteScroll` now accepts `MaybeRefOrGetter<HTMLElement |
  null>` for `target` / `scrollRoot` (and `MaybeRefOrGetter<boolean>`
  for `exhausted`). `Chats.vue` drops its manual `querySelector` /
  `nextTick` dance and uses two `useTemplateRef`s on the conditional
  list / sentinel divs instead.
- `Layout` now applies the previously-declared but unused
  `styles?: Partial<Styles>` prop as the final layer over the
  resolved theme map.
- `ChatHeader`'s 300 ms selection-toolbar timeout is cleared on
  `onBeforeUnmount` so an unmount mid-animation doesn't mutate a
  destroyed ref.
- `localization.getLocalizationStrings('auto')` collapses its dead
  branch and gains a `TODO` for future locale negotiation.
- `useLocalizationStrings()` warns under `import.meta.env.DEV` when
  no `AdvancedChatPlugin` provider is installed, so consumers don't
  silently miss their string overrides.
- ESLint re-enables `@typescript-eslint/ban-ts-comment` (zero
  current usages); keeps `vue/multi-word-component-names` disabled
  with a comment explaining the deliberate single-word public API
  components (`Chat`, `Chats`, `Layout`, `Loader`, `Message`).
- README gains a "Security model" section documenting which
  user-supplied URL fields are interpolated into CSS without
  sanitization, plus the `Layout.styles` override path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both items came out of the alpha.4 code review (commit b22a8e1) but
neither blocks the alpha.4 publish. They're worth picking up before
tagging beta.0; recording them in release-plan.md so they don't fall
through.

- Drop `deep: true` from `useAutocomplete`'s items watcher (perf for
  consumers wiring up large autocomplete lists; needs a benchmark).
- Untangle `Chats.vue`'s two parallel load-more paths (pure refactor;
  no behavior change today).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…, locale, slots

Closes the items left on `rewrite/release-plan.md` step 4 — the last
GA gaps before tagging beta. Each behavior change ships with a
Storybook regression test; each new public surface is exported and
documented.

- ChatFooter gains `maxFiles` and `maxFileSize` props (both default
  `0` = disabled), forwarded by `Chat`/`AdvancedChat`. Files past
  the cap are emitted as a new `invalid-file: { file, reason }`
  event so hosts can surface their own error UI. Closes #461, #474.
- Chat gains `typingIndicatorPosition: 'header' | 'composer' |
  'both' | 'none'` (default `'header'`). When the policy includes
  `composer`, Chat renders a typing line above ChatFooter; the new
  `composer-typing` scoped slot exposes the resolved string for
  full customization. Closes #513.
- Chat gains `autoScroll: { onMount?, onChatSwitch?, onSend?,
  onReceive? }` policy prop. Each leg defaults `true` to match the
  alpha.2 hard-coded behavior; consumers can opt out per leg.
- `getLocalizationStrings('auto')` now actually negotiates against
  `navigator.language` via the new exported `negotiateLocale()`
  helper. Resolves to `'en'` for English locales (no behavior
  change). For unsupported locales, still resolves to `'en'` but
  warns under DEV so the gap is visible. SSR-safe (returns `'en'`
  when `navigator` is undefined).
- Slot inventory documented inline (`<!-- @slot ... -->`) on every
  public slot in Chat / Chats / ChatHeader / ChatFooter / Message.
  Storybook autodocs picks them up; README adds a single-page slot
  reference table.
- ChatHeader gains internal `showTypingIndicator` prop so Chat can
  suppress the header's typing line when the policy renders it
  somewhere else.
- Refresh `rewrite/issue-triage.md` against alpha.2-5 (move shipped
  items from "Bundle" buckets into a new "Bundle into 3.0 — landed"
  table with version columns; add post-2024 architecture-resolved
  noise to the resolved bucket; add #573 / #546 / #531 as the
  remaining bundle-into-beta candidates).
- Refresh `rewrite/release-plan.md` step 4 to reflect what shipped
  in alpha.2 vs what landed now in alpha.5; bring the versioning
  ladder up to date.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stand up the V3 documentation site as Storybook autodocs + MDX prose
pages, deployed to GitHub Pages on every push to develop. README
pivots from a self-contained reference into a landing page that
points at the deployed docs.

Storybook + deploy:

- New `.github/workflows/deploy-docs.yml` builds `storybook-static`
  and publishes it to GitHub Pages via `actions/deploy-pages@v4`.
  Concurrency-limited to one in-flight deploy per branch.
- `.storybook/main.ts` widens the `stories` glob to also pick up
  `*.mdx` files under `src/` and `docs/`. The Vite `base` is
  overridable via `STORYBOOK_BASE_URL` for the Pages subpath.
- `.storybook/preview.ts` defines a manual `storySort` order so the
  prose / cookbook / composables / reference sections sit ahead of
  the per-component story tree.

Prose guides (`docs/`):

- `00-introduction.mdx`, `01-quick-start.mdx`, `02-composition.mdx`,
  `03-theming.mdx`, `04-localization.mdx`, `05-security.mdx`,
  `06-ssr.mdx`, `07-migration-from-v2.mdx`. The migration page
  carries the curated v2 → V3 prop / event / type table; SSR page
  documents what works and what to wrap in `<ClientOnly>`; security
  page lists every URL field interpolated into CSS.

Composables reference (`docs/composables/`):

- One MDX page each for `useAutocomplete`, `useMessageSelection`,
  `useReplyEdit`, `useInfiniteScroll`, `useLocalSearch` with full
  options / returns tables and a worked example.

Cookbook (`docs/cookbook/`):

- `backend-integration.mdx` (Firestore example, transferable to any
  backend), `file-uploads.mdx` (upload-on-send + optimistic patterns,
  `maxFiles` / `maxFileSize` constraints), `pagination.mdx`
  (`fetch-messages` + scroll-position preservation), and
  `custom-actions.mdx` (the four action menus + selection mode).

API reference (`docs/api-reference.mdx`):

- Single-page enumeration of every exported symbol from
  `src/index.ts` — components, composables, models, theming,
  localization, helpers — with cross-links to the per-component
  pages.

JSDoc completeness pass on the remaining component prop / event
interfaces (every `*Props` field and `*Events` payload now has a
JSDoc line, so Storybook autodocs renders rich tables for each):

- AdvancedChat, AudioControl, AudioPlayer, ChatEmojis, ChatFile,
  ChatFiles, ChatHeader, ChatMessage, ChatUserTag, ChatsItem,
  ChatsSearch, EmojiPicker, MediaPreview, MessageActions,
  MessageFile, MessageFiles, MessageReactions, MessageReply,
  MessageTemplate.

README pivot:

- Trims the body in half. Keeps the badges, the value prop, the
  v2/V3 track explanation, install commands, a 30-line working
  example, and the `npm run` cheat sheet. Everything else is now
  on the docs site.

`npm run verify` is green: format, types, lint, 97 unit tests,
all Storybook story plays, build, pack contract, Storybook static
(now including the 18 new MDX pages).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@aerovulpe
aerovulpe merged commit cc042fe into main Aug 8, 2026
1 check passed
@aerovulpe
aerovulpe deleted the develop branch August 8, 2026 23:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant