@vvedantb/ui 0.4.0-rc.0 → 0.4.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,18 +4,15 @@ Shared React 19 web UI. Source-exported: no build step.
4
4
 
5
5
  | Import | What it is |
6
6
  | --- | --- |
7
- | `@vvedantb/ui` | Primitives (Radix-based), AI elements, `playChime` and `useReplyChime`. |
8
- | `@vvedantb/ui/sonner` | `SonnerToaster`, its helpers and `toast`. |
9
- | `@vvedantb/ui/composer` | `InputArea` (recommended) and its building blocks. Also the deprecated 0.3 `Composer`, `ComposerShell`, `ComposerGhostText`, `ComposerIconButton`, `useComposerPrediction` and the pure prediction helpers. |
10
- | `@vvedantb/ui/audio` | `playChime`, `useReplyChime`, `playTone` and the shared audio floor. |
11
- | `@vvedantb/ui/cn` | `cn` class helper (clsx + tailwind-merge). |
12
- | `@vvedantb/ui/shell` | Router-free `SidebarHeader`, `PillTabs` and `SessionsHoverCard`. |
13
- | `@vvedantb/ui/app` | Alt-click confirm skip, update watcher, settings chrome, `useStableAuth`. See `app/README.md` in the repository. |
14
- | `@vvedantb/ui/tokens` | `tokens.css`: colour, radius, shadow, ease and font tokens for Tailwind v4. |
15
- | `@vvedantb/ui/tokens/css/*.css` | `index`, `base`, `dialog`, `modal`, `tabs`, `tabs-pills`, `utilities`, `scrollbar-thin`, `animations`, `compat-shadcn-rgb`. |
16
- | `@vvedantb/ui/tokens/compat/shadcn-rgb.css` | Same file as `tokens/css/compat-shadcn-rgb.css`. |
17
- | `@vvedantb/ui/tokens/tailwind-preset` | Tailwind preset for apps that load a JS config with `@config`. |
18
- | `@vvedantb/ui/tokens/native` | JS colours, radii and spacing. No CSS, no React DOM. |
7
+ | `@vvedantb/ui` | The only JavaScript entry. Primitives (Radix-based), AI elements, audio (`playChime`, `useReplyChime`, `playTone`), `toast` and `SonnerToaster`, the composer (`InputArea`, deprecated 0.3 `Composer`), shell (`SidebarHeader`, `PillTabs`, `SessionsHoverCard`), app helpers (confirm skip, update watcher, settings chrome, `useStableAuth`), `cn`, and the native tokens `tokens` and `Tokens`. See `app/README.md` in the repository for the app helpers. |
8
+ | `@vvedantb/ui/tokens` | `tokens.css`: colour, radius, shadow, ease and font tokens for Tailwind v4. CSS. |
9
+ | `@vvedantb/ui/tokens/tokens.css` | Same file as `@vvedantb/ui/tokens`. CSS. |
10
+ | `@vvedantb/ui/tokens/css/*.css` | `index`, `base`, `dialog`, `modal`, `tabs`, `tabs-pills`, `utilities`, `scrollbar-thin`, `animations`, `compat-shadcn-rgb`. CSS. |
11
+ | `@vvedantb/ui/tokens/compat/shadcn-rgb.css` | Same file as `tokens/css/compat-shadcn-rgb.css`. CSS. |
12
+ | `@vvedantb/ui/tokens/tailwind-preset` | Tailwind preset (`.mjs`) for `@config "@vvedantb/ui/tokens/tailwind-preset"`. Kept as a build-tool entry: Tailwind needs a resolvable package path, and it is not a React API. |
13
+ | `@vvedantb/ui/package.json` | Package metadata. |
14
+
15
+ Removed in 0.4.0-rc.1: the `/cn`, `/sonner`, `/audio`, `/shell`, `/app`, `/composer` and `/tokens/native` subpaths. Import from `@vvedantb/ui`. See [`MIGRATION.md`](MIGRATION.md).
19
16
 
20
17
  ```css
21
18
  @import "tailwindcss";
@@ -34,7 +31,7 @@ useReplyChime({ enabled: soundOn, isStreaming, threadId });
34
31
  - `playChime()`: soft rising two-note chime (WebAudio). One shared `AudioContext`, created on first use. It is a no-op on the server and when autoplay blocks audio. Calls less than 1 second apart play once.
35
32
  - `playTone(tone | tones)`: plays `{ frequency, startOffsetS?, durationS?, peakGain?, type? }` through the same floor.
36
33
  - Audio floor: every package sound shares one 1 second minimum gap. Route your own sounds through it with `withAudioFloor(() => play())` or `if (tryAcquireAudioFloor()) play()`.
37
- - These are also available from `@vvedantb/ui/audio`, which does not load the rest of the root barrel.
34
+ - The root barrel has no top-level side effects, so an app that imports only the audio symbols bundles only audio code.
38
35
  - `useReplyChime`: chimes once when `isStreaming` goes from `true` to `false` for the same `threadId`. It is silent on the first sight of a thread, when `threadId` changes, and when `threadId` is null or undefined. While `enabled` is `false` it still tracks the edge, so enabling mid-turn does not replay a finish.
39
36
 
40
37
  ## Composer
@@ -44,7 +41,7 @@ useReplyChime({ enabled: soundOn, isStreaming, threadId });
44
41
  `InputArea` is the chat composer extracted from an app: a pill that grows into a card, a plus menu, dictate, stop and send, ghost text, a `/` menu, and slots for banners, a queue, attachments and chips. It is presentational. It makes no requests and reads no router, billing or storage. The app passes data in and handles callbacks. It adds its own `TooltipProvider` and `LazyMotion`, so it needs no app provider.
45
42
 
46
43
  ```tsx
47
- import { InputArea, InputBanners, buildComposerSlashItems } from "@vvedantb/ui/composer";
44
+ import { InputArea, InputBanners, buildComposerSlashItems } from "@vvedantb/ui";
48
45
 
49
46
  <InputArea
50
47
  value={draft}
@@ -84,16 +81,16 @@ import { InputArea, InputBanners, buildComposerSlashItems } from "@vvedantb/ui/c
84
81
  | `getPrediction`, `predictionEnabled` | off, `true` | Ghost text. Tab accepts, Esc dismisses. Paused while the `/` menu is open. |
85
82
  | `className`, `containerClassName`, `borderClassName`, `submitButtonClassName`, `submitIconClassName`, `placeholder` | none | The app passes its own class strings for an exact match. |
86
83
 
87
- Building blocks: `InputActions`, `ConnectionStatusMenuItem` (icon, label, description, `connected`, `onClick`, `title`), `InputBanners`, `PromoBanner` (`show`, `onUpgrade`, `onDismiss`, text as children), `FadePresence`, `ComposerSlashMenu`, `ComposerSlashRow`, and the hooks and helpers listed in the changelog. Parity against the original: `composer/examples/parity/PARITY.md`. App migration: `composer/MIGRATION.md`.
84
+ Building blocks: `InputActions`, `ConnectionStatusMenuItem` (icon, label, description, `connected`, `onClick`, `title`), `InputBanners`, `PromoBanner` (`show`, `onUpgrade`, `onDismiss`, text as children), `FadePresence`, `ComposerSlashMenu`, `ComposerSlashRow`, and the hooks and helpers listed in the changelog. Parity against the original: `composer/examples/parity/PARITY.md`. App migration: `composer/MIGRATION-INPUTAREA.md`.
88
85
 
89
86
  ### Composer (deprecated)
90
87
 
91
- > **Deprecated in 0.4.0.** Use `InputArea`. The 0.3 `Composer` was written from scratch and does not match the app composer. It stays exported and unchanged for existing consumers, and is not removed in 0.4.0.
88
+ > **Deprecated in 0.4.0-rc.1.** Use `InputArea`. The 0.3 `Composer` was written from scratch and does not match the app composer. It stays exported and unchanged for existing consumers, and is not removed in 0.4.0-rc.1.
92
89
 
93
90
  Chat composer with an autosizing textarea, a footer with a plus-menu slot, action slots and a send or stop button. It also shows optional ghost-text predictions. It makes no network calls: the app supplies `getPrediction`.
94
91
 
95
92
  ```tsx
96
- import { Composer, ComposerIconButton } from "@vvedantb/ui"; // or "@vvedantb/ui/composer"
93
+ import { Composer, ComposerIconButton } from "@vvedantb/ui";
97
94
 
98
95
  <Composer
99
96
  value={draft}
@@ -164,7 +161,7 @@ Rules for a custom input:
164
161
  To build without `Composer`, assemble the parts yourself. `useComposerPrediction` takes the draft string and reads no element. `ComposerGhostText` draws the draft invisibly, then the ghost text, so give it the same padding and font classes as your editor and place it under the editor.
165
162
 
166
163
  ```tsx
167
- import { ComposerGhostText, ComposerShell, useComposerPrediction } from "@vvedantb/ui/composer";
164
+ import { ComposerGhostText, ComposerShell, useComposerPrediction } from "@vvedantb/ui";
168
165
 
169
166
  function MentionComposer({ draft, setDraft, send }: Props) {
170
167
  const prediction = useComposerPrediction({ value: draft, enabled: true, getPrediction });
@@ -184,7 +181,7 @@ Fixture: `composer/examples/` (see its README). It has a `tokens.css` page and a
184
181
  ## Sessions hover card
185
182
 
186
183
  ```tsx
187
- import { SessionsHoverCard } from "@vvedantb/ui/shell";
184
+ import { SessionsHoverCard } from "@vvedantb/ui";
188
185
 
189
186
  <SessionsHoverCard
190
187
  header="Session title"
@@ -200,8 +197,7 @@ import { SessionsHoverCard } from "@vvedantb/ui/shell";
200
197
  ## Toaster
201
198
 
202
199
  ```tsx
203
- import { toast } from "sonner";
204
- import { SonnerToaster } from "@vvedantb/ui"; // or "@vvedantb/ui/sonner"
200
+ import { SonnerToaster, toast } from "@vvedantb/ui";
205
201
 
206
202
  <SonnerToaster
207
203
  theme={theme}
@@ -261,6 +257,6 @@ The compat file includes a fallback `glass-panel-strong` (`rgb(var(--card) / 0.9
261
257
 
262
258
  A fixture that renders the main components against sample light and dark RGB variables is in `tokens/examples/compat-shadcn-rgb/`.
263
259
 
264
- `@clerk/clerk-react`, `@tanstack/react-hotkeys` and `zod` are optional peers. Install them only if you import `@vvedantb/ui/app`.
260
+ `@clerk/clerk-react`, `@tanstack/react-hotkeys`, `motion` and `zod` are optional peers (`peerDependenciesMeta`). Install `@clerk/clerk-react` only to use `useStableAuth`, `@tanstack/react-hotkeys` and `zod` only for the features that use them, and `motion` only to use the motion presets, `InputArea`, the 0.3 `Composer` or the AI elements and primitives that animate.
265
261
 
266
262
  Full documentation: the repository `README.md`. Upgrading from `@vvedantb/tokens`, `@vvedantb/shell` or `@vvedantb/app-kit`: `MIGRATION.md`.
package/app/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # `@vvedantb/ui/app`
1
+ # App helpers (`@vvedantb/ui`)
2
2
 
3
3
  Shared web React helpers that were duplicated across apps. Source-exported as the `./app` subpath of `@vvedantb/ui`.
4
4
 
@@ -10,9 +10,9 @@ npm install @vvedantb/ui
10
10
 
11
11
  ## Peers
12
12
 
13
- Required: `react` and `react-dom` (>=19). Optional peers of `@vvedantb/ui`, needed only for this subpath: `@clerk/clerk-react` (`useStableAuth`), `@tanstack/react-hotkeys` and `zod`.
13
+ Required: `react` and `react-dom` (>=19). Optional peers of `@vvedantb/ui`, needed only for the app helpers: `@clerk/clerk-react` (`useStableAuth`), `@tanstack/react-hotkeys` and `zod`.
14
14
 
15
- `sonner` is not a dependency. The update watcher takes the toast API as an option. This subpath uses a local class join (`cn`), not the `cn` from `@vvedantb/ui`. Tailwind must scan `node_modules/@vvedantb/ui/app/src/**/*.{ts,tsx}` so the class names are generated, and the app needs the `@vvedantb/ui/tokens` names (`bg-surface-card`, `divide-separator`, `text-muted-foreground` and so on).
15
+ `sonner` is not a dependency. The update watcher takes the toast API as an option. The app source uses a local class join, which the root does not export (the root `cn` is the clsx and tailwind-merge one). Tailwind must scan `node_modules/@vvedantb/ui/app/src/**/*.{ts,tsx}` so the class names are generated, and the app needs the `@vvedantb/ui/tokens` names (`bg-surface-card`, `divide-separator`, `text-muted-foreground` and so on).
16
16
 
17
17
  ```css
18
18
  @source "../node_modules/@vvedantb/ui/app/src/**/*.{ts,tsx}";
@@ -21,7 +21,7 @@ Required: `react` and `react-dom` (>=19). Optional peers of `@vvedantb/ui`, need
21
21
  ## Confirm skip (Alt-click)
22
22
 
23
23
  ```tsx
24
- import { ConfirmSkipHint, skipConfirmTitle, useRequestConfirm } from "@vvedantb/ui/app";
24
+ import { ConfirmSkipHint, skipConfirmTitle, useRequestConfirm } from "@vvedantb/ui";
25
25
 
26
26
  const { request } = useRequestConfirm();
27
27
 
@@ -42,7 +42,7 @@ const { request } = useRequestConfirm();
42
42
 
43
43
  ```ts
44
44
  import { toast } from "sonner";
45
- import { startUpdateAvailableWatcher } from "@vvedantb/ui/app";
45
+ import { startUpdateAvailableWatcher } from "@vvedantb/ui";
46
46
 
47
47
  useEffect(
48
48
  () =>
@@ -61,7 +61,7 @@ Options: `origin`, `toast`, `closeConvex?`, `pollMs?` (default 60000), `toastId?
61
61
  ## Settings chrome
62
62
 
63
63
  ```tsx
64
- import { SettingsPage, SettingsSection, SettingsToggleRow } from "@vvedantb/ui/app";
64
+ import { SettingsPage, SettingsSection, SettingsToggleRow } from "@vvedantb/ui";
65
65
 
66
66
  <SettingsPage
67
67
  title="Notifications"
@@ -82,8 +82,8 @@ Exports: `SettingsSection`, `SettingsField`, `SettingsStack`, `SettingsToggleRow
82
82
  ## useStableAuth
83
83
 
84
84
  ```ts
85
- import { useStableAuth } from "@vvedantb/ui/app"; // 2000 ms debounce, wraps Clerk useAuth
86
- import { createUseStableAuth } from "@vvedantb/ui/app";
85
+ import { useStableAuth } from "@vvedantb/ui"; // 2000 ms debounce, wraps Clerk useAuth
86
+ import { createUseStableAuth } from "@vvedantb/ui";
87
87
 
88
88
  const useAuth = createUseStableAuth(useClerkAuth, { debounceMs: 3000 });
89
89
  ```
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@vvedantb/ui",
3
- "version": "0.4.0-rc.0",
3
+ "version": "0.4.0-rc.1",
4
4
  "license": "MIT",
5
- "description": "Shared React 19 UI for web apps: primitives, shell pieces, app helpers, design tokens, shared Tailwind v4 CSS and a Tailwind preset.",
5
+ "description": "Shared React 19 UI for web apps: one JavaScript entry (primitives, shell pieces, app helpers, native tokens), design-token CSS, shared Tailwind v4 CSS and a Tailwind preset.",
6
6
  "type": "module",
7
7
  "publishConfig": {
8
8
  "access": "public"
@@ -17,36 +17,8 @@
17
17
  "types": "./src/index.ts",
18
18
  "default": "./src/index.ts"
19
19
  },
20
- "./cn": {
21
- "types": "./src/utils/cn.ts",
22
- "default": "./src/utils/cn.ts"
23
- },
24
- "./sonner": {
25
- "types": "./src/sonner.ts",
26
- "default": "./src/sonner.ts"
27
- },
28
- "./audio": {
29
- "types": "./src/audio/index.ts",
30
- "default": "./src/audio/index.ts"
31
- },
32
- "./composer": {
33
- "types": "./src/composer/index.ts",
34
- "default": "./src/composer/index.ts"
35
- },
36
- "./shell": {
37
- "types": "./shell/src/index.ts",
38
- "default": "./shell/src/index.ts"
39
- },
40
- "./app": {
41
- "types": "./app/src/index.ts",
42
- "default": "./app/src/index.ts"
43
- },
44
20
  "./tokens": "./tokens/src/tokens.css",
45
21
  "./tokens/tokens.css": "./tokens/src/tokens.css",
46
- "./tokens/native": {
47
- "types": "./tokens/src/native.ts",
48
- "default": "./tokens/src/native.ts"
49
- },
50
22
  "./tokens/css/index.css": "./tokens/src/css/index.css",
51
23
  "./tokens/css/base.css": "./tokens/src/css/base.css",
52
24
  "./tokens/css/dialog.css": "./tokens/src/css/dialog.css",
@@ -193,6 +165,9 @@
193
165
  "@tanstack/react-hotkeys": {
194
166
  "optional": true
195
167
  },
168
+ "motion": {
169
+ "optional": true
170
+ },
196
171
  "zod": {
197
172
  "optional": true
198
173
  }
@@ -303,7 +303,7 @@ const ComposerGhostText = React.forwardRef<HTMLDivElement, ComposerGhostTextProp
303
303
  * Chat composer: autosizing textarea, plus-menu and action slots, send/stop
304
304
  * button and optional ghost-text predictions. The ref points at the textarea.
305
305
  */
306
- /** @deprecated Use `InputArea` from `@vvedantb/ui/composer`. Kept unchanged for existing consumers. */
306
+ /** @deprecated Use `InputArea` from `@vvedantb/ui`. Kept unchanged for existing consumers. */
307
307
  const Composer = React.forwardRef<HTMLTextAreaElement, ComposerProps>(function Composer(
308
308
  {
309
309
  value: valueProp,
@@ -37,6 +37,12 @@ const COMPACT_START_ADDON =
37
37
  const COMPACT_END_ADDON =
38
38
  "order-last shrink-0 justify-end gap-1 py-0 pr-1.5 pl-1 has-[>button]:mr-0";
39
39
 
40
+ /**
41
+ * Default ghost text class. It matches the original app composer, whose theme
42
+ * defines the bare muted utility. Pass `predictionTextClassName` to use another class.
43
+ */
44
+ export const DEFAULT_PREDICTION_TEXT_CLASS = "text-muted"; // check-tokens-allow: text-muted
45
+
40
46
  export const DEFAULT_ATTACH_ACCEPT =
41
47
  "image/png,image/jpeg,image/jpg,image/webp,application/pdf";
42
48
 
@@ -94,6 +100,8 @@ export type InputAreaProps = {
94
100
  /** Returns a continuation for the draft. Omit to turn ghost text off. */
95
101
  getPrediction?: (text: string) => Promise<string>;
96
102
  predictionEnabled?: boolean;
103
+ /** Classes on the ghost suggestion span. Default matches the original app composer. */
104
+ predictionTextClassName?: string;
97
105
 
98
106
  /** Wrapper around banners, queue and the input. */
99
107
  className?: string;
@@ -138,6 +146,7 @@ export function InputArea({
138
146
  renderSlashItem,
139
147
  getPrediction,
140
148
  predictionEnabled = true,
149
+ predictionTextClassName = DEFAULT_PREDICTION_TEXT_CLASS,
141
150
  className,
142
151
  containerClassName,
143
152
  borderClassName,
@@ -402,7 +411,7 @@ export function InputArea({
402
411
  )}
403
412
  >
404
413
  {input}
405
- <span className="text-muted-foreground">
414
+ <span className={predictionTextClassName}>
406
415
  {prediction.suggestion}
407
416
  </span>
408
417
  </div>
package/src/index.ts CHANGED
@@ -100,3 +100,24 @@ export * from "./ai-elements/suggestion";
100
100
  export * from "./audio";
101
101
 
102
102
  export * from "./composer";
103
+ export { toast } from "sonner";
104
+
105
+ // Shell: router-free pieces. Shell's own `cn` and `ClassValue` are not re-exported;
106
+ // use the root `cn` (clsx + tailwind-merge).
107
+ export { SidebarHeader } from "../shell/src/SidebarHeader";
108
+ export type { SidebarHeaderProps } from "../shell/src/SidebarHeader";
109
+ export { PillTabs } from "../shell/src/PillTabs";
110
+ export type { PillTabItem, PillTabsProps } from "../shell/src/PillTabs";
111
+ export { SessionsHoverCard } from "../shell/src/SessionsHoverCard";
112
+ export type {
113
+ SessionsHoverCardContext,
114
+ SessionsHoverCardProps,
115
+ SessionsHoverCardSurface,
116
+ } from "../shell/src/SessionsHoverCard";
117
+
118
+ // App helpers: confirm skip, update watcher, settings chrome, stable auth.
119
+ export * from "../app/src/index";
120
+
121
+ // Native tokens (JS values that match tokens.css).
122
+ export { tokens } from "../tokens/src/native";
123
+ export type { Tokens } from "../tokens/src/native";
package/tokens/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # `@vvedantb/ui/tokens`
2
2
 
3
- Design tokens and shared Tailwind v4 CSS for the vvedantb web apps, plus JS tokens for React Native. These are subpaths of `@vvedantb/ui`, source-exported: no build step. Paths in the `File` column are relative to `packages/ui/tokens/`.
3
+ Design tokens and shared Tailwind v4 CSS for the vvedantb web apps. The CSS and Tailwind preset are subpaths of `@vvedantb/ui`; the native JS tokens are named exports of the root (`tokens`, `Tokens`). Source-exported: no build step. Paths in the `File` column are relative to `packages/ui/tokens/`.
4
4
 
5
5
  ## Exports
6
6
 
7
7
  | Export | File | What it is |
8
8
  | --- | --- | --- |
9
9
  | `@vvedantb/ui/tokens`, `@vvedantb/ui/tokens/tokens.css` | `src/tokens.css` | Colour, radius, shadow, ease and font tokens (`@theme`), light/dark variables, `dark` variant, `*` border and `body` defaults. In 0.2.1 it also defines shadcn-style aliases (`primary`, `muted-foreground`, `secondary`, `destructive`, `card`, `popover`, `input`, `ring`) that point at the same tokens. |
10
- | `@vvedantb/ui/tokens/native` | `src/native.ts` | JS colours, radii and spacing for React Native. `@vvedantb/native-ui` keeps its own copy in `src/tokens.ts`; a test keeps the two equal. |
10
+ | `tokens` and `Tokens` from `@vvedantb/ui` | `src/native.ts` | JS colours, radii and spacing for React Native. `@vvedantb/native-ui` keeps its own copy in `src/tokens.ts`; a test keeps the two equal. |
11
11
  | `@vvedantb/ui/tokens/css/base.css` | `src/css/base.css` | `html` touch/accent, `::selection`, control transitions, pointer cursor, range accent (`@layer base`). |
12
12
  | `@vvedantb/ui/tokens/css/dialog.css` | `src/css/dialog.css` | Unlayered `max-width: none` for `@vvedantb/ui` compact (bottom-sheet) dialogs. |
13
13
  | `@vvedantb/ui/tokens/css/modal.css` | `src/css/modal.css` | `.t-modal`, `.is-open`, `.is-closing` and `t-modal-presence-wait` (`@layer components`). |
package/src/sonner.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from "./ui/sonner";
2
- export { toast } from "sonner";