inline-chat-kit 0.59.2 → 0.61.0
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/CHANGELOG.md +129 -0
- package/README.md +17 -1
- package/dist/Button/KitButton.d.ts +28 -0
- package/dist/Button/hostButtonChecks.d.ts +15 -0
- package/dist/ChatExperience/ChatExperience.d.ts +11 -1
- package/dist/{ChatExperience-umh3nGe_.js → ChatExperience-BQgjY0-K.js} +1639 -1338
- package/dist/ChatExperience-BQgjY0-K.js.map +1 -0
- package/dist/ChatHeader/ChatHeader.d.ts +7 -0
- package/dist/ChatInput/AddCardsOverlay.d.ts +3 -1
- package/dist/ChatInput/ChatInput.d.ts +7 -0
- package/dist/ChatInput/useComposerControl.d.ts +18 -0
- package/dist/ChatTurnRow/ChatTurnRow.d.ts +23 -1
- package/dist/components/components.d.ts +102 -0
- package/dist/demo.js +10 -10
- package/dist/index.d.ts +2 -0
- package/dist/inline-chat-kit.css +1 -1
- package/dist/inline-chat-kit.js +8 -8
- package/dist/inline-chat-kit.js.map +1 -1
- package/package.json +1 -1
- package/theming.md +198 -0
- package/dist/ChatExperience-umh3nGe_.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,135 @@ The versions before 1.0 follow the pre-release convention: **a breaking change
|
|
|
8
8
|
or new public API bumps the minor**, and the patch is for fixes. Anything that would break an
|
|
9
9
|
existing install is called out under **Breaking**, with what to do about it.
|
|
10
10
|
|
|
11
|
+
## 0.61.0 — 2026-10-15
|
|
12
|
+
|
|
13
|
+
A host's own button, which 0.60.0 turned down. The reason it was turned down
|
|
14
|
+
still holds for one button, and only that one is kept back. Nothing changes for
|
|
15
|
+
a host that passes nothing: every story screenshotted against 0.60.0 in both
|
|
16
|
+
themes, 138 stories, identical but for the one that sets its own
|
|
17
|
+
`--ick-btn-radius` — its composer is concentric now, which is the point — and,
|
|
18
|
+
on a touch screen, the composer's "+" and microphone, below.
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **`components={{ Button }}` on `ChatExperience`**, and `ComponentsProvider`
|
|
23
|
+
for pieces assembled by hand, in the way of `LabelsProvider`. The host's
|
|
24
|
+
button is drawn for every role in theming.md's table but one: the
|
|
25
|
+
composer's send / stop / save, whose glyph morphs between the three inside
|
|
26
|
+
the button. That one stays the kit's and is themed by the tokens, as before.
|
|
27
|
+
- The kit keeps the layout and the behaviour, the host's button paints. It
|
|
28
|
+
is drawn inside a box the kit sizes from `--ick-control-*` (square when
|
|
29
|
+
it is only an icon), places, animates, and gives the 44px touch area —
|
|
30
|
+
the ring past the button's edge is the box's, and a press there is handed
|
|
31
|
+
to the button. The box sets the button's height over the host's own.
|
|
32
|
+
- `KitButtonProps` is the contract: `kitRole`, `variant`, `size`, `shape`
|
|
33
|
+
(`square`, `pill`, `default`), `icon`, `iconRight`, `children`,
|
|
34
|
+
`disabled`, `loading`, `pressed`, `type="button"`, the handlers, the
|
|
35
|
+
`aria-*` and `data-ick-*` attributes, and the ref. `kitRole` rather than
|
|
36
|
+
`role`, because a button that spread a `role` of `"send"` onto itself
|
|
37
|
+
would be an ARIA error — the ARIA `role` still arrives where there is one,
|
|
38
|
+
`menuitem` in the header's menu.
|
|
39
|
+
- The header's menu items go through it too. Its back control and an
|
|
40
|
+
action with an `href` are links and stay `<a>`.
|
|
41
|
+
- In development, a host's button that does not forward its ref, is not a
|
|
42
|
+
`<button>`, drops the `aria-*` or `data-ick-*` it was given, or looks no
|
|
43
|
+
different with keyboard focus is named in the console, once per role.
|
|
44
|
+
`process.env.NODE_ENV === "production"` returns before any of it.
|
|
45
|
+
- **`--ick-composer-control`**: the composer's send glyph, "+" and
|
|
46
|
+
microphone, which were 28px written into the component — four widths
|
|
47
|
+
Motion springs open, and an overlay offset by 36 and 44 — are
|
|
48
|
+
`--ick-control-s` now, and a host can move them on their own.
|
|
49
|
+
- **The composer's corner is concentric with its buttons**: `--ick-input-radius`
|
|
50
|
+
is `--ick-btn-radius` plus the surface's 8px padding, up to
|
|
51
|
+
`--ick-radius-xl`. A pill button leaves it at the 24 it was; a host's 6px
|
|
52
|
+
button gets a 14px composer instead of a 6px button in a 24px pill.
|
|
53
|
+
- **`BringYourOwnButton` stories** — the chat and the hand-assembled pieces
|
|
54
|
+
with a shadcn-style button (a 6px corner, 36px tall, its own focus ring),
|
|
55
|
+
and the same pieces with nothing provided — and "Bring your own button" in
|
|
56
|
+
theming.md: tokens, then per-role CSS, then the component.
|
|
57
|
+
|
|
58
|
+
### Fixed
|
|
59
|
+
|
|
60
|
+
- **On a touch screen the "+" and the microphone are round.** Their boxes
|
|
61
|
+
were 28 written in and their buttons as wide as `size="s"`, which the touch
|
|
62
|
+
block raises to 32: a 32 × 28 oval beside a 32 × 32 send, overflowing its
|
|
63
|
+
slot by 4px. All three are 32 × 32 there now, in 32px slots. On a pointer
|
|
64
|
+
nothing moves.
|
|
65
|
+
|
|
66
|
+
## 0.60.0 — 2026-10-15
|
|
67
|
+
|
|
68
|
+
Reported from a host running the kit in production, each one worked around
|
|
69
|
+
outside the kit there. Each was reproduced here before it was changed.
|
|
70
|
+
|
|
71
|
+
### Fixed
|
|
72
|
+
|
|
73
|
+
- **The header's "…" menu closes when "…" is pressed again.** The press
|
|
74
|
+
moved focus from the menu to the button, the menu closed on that blur, and
|
|
75
|
+
the click toggled it straight back open. Measured in Chromium and WebKit, by
|
|
76
|
+
mouse and by touch: it could not be closed that way at all.
|
|
77
|
+
- **And on a press anywhere outside it.** It closed only on a blur, and on iOS
|
|
78
|
+
a tap on something that takes no focus moves none — so the menu stayed open
|
|
79
|
+
over whatever was touched next.
|
|
80
|
+
- **`ChatExperience` fits its container on a page with no `box-sizing`
|
|
81
|
+
reset.** It was `width: 100%` plus 64px of padding, so in a 400px side
|
|
82
|
+
panel the end of every sent message sat under the panel's edge. A host
|
|
83
|
+
with a reset saw nothing change; one without now gets the column the
|
|
84
|
+
playground was designed with — 720px overall, not 784.
|
|
85
|
+
- **A short message is no longer faded, with "Read more" on it, because of
|
|
86
|
+
the width it had for one frame.** Whether a sent message is long was
|
|
87
|
+
measured once, a frame after the answer settled. In a host's side panel
|
|
88
|
+
still opening under an instant answer, that frame had the bubble 27px wide:
|
|
89
|
+
a one-line message measured 269px tall and stayed faded at 201×25. It is
|
|
90
|
+
measured again whenever it reflows, and the fade and the button go when it
|
|
91
|
+
is no longer long. A resting message mounted from history is measured too,
|
|
92
|
+
so it is clamped the same way a freshly sent one is.
|
|
93
|
+
- **An empty composer is never two lines.** Mounted a few pixels wide in the
|
|
94
|
+
same panel, the fresh composer decided it needed a second line, and the way
|
|
95
|
+
back compared against that width, so it never returned: 68px tall, its "+"
|
|
96
|
+
on a line of its own, for the rest of the session.
|
|
97
|
+
- **A docked composer no longer jumps on a send.** The fresh composer arrived
|
|
98
|
+
like any new turn — rising 16px into place — so the box at the bottom went
|
|
99
|
+
up and back every time a message was sent (840 → 824 → 840). It fades in
|
|
100
|
+
where it is now. A sent message still goes to the top, as before.
|
|
101
|
+
- **Docked, the question lands before its answer starts.** The answer's "…"
|
|
102
|
+
appeared at the top the moment a message was sent, while the message was
|
|
103
|
+
still travelling up from the composer — two things moving in opposite
|
|
104
|
+
directions, an answer begun above a question that had not arrived. The
|
|
105
|
+
answer now waits, still taking its room so the anchor does not move, until
|
|
106
|
+
the bubble has stopped: about 0.45s, measured at 1120×700 and 390×844, and
|
|
107
|
+
for a model that is silent first. Read off the screen rather than from the
|
|
108
|
+
spring, which rests at 1.2s, and including the scroll that carries a second
|
|
109
|
+
message most of its way. `ChatTurnRow` takes it as `answerAfterTravel`;
|
|
110
|
+
`ChatInput` reports it through `onLanded`.
|
|
111
|
+
|
|
112
|
+
### Added
|
|
113
|
+
|
|
114
|
+
- **`ChatTurnRow` takes `entrance`** — `"rise"` or `"fade"`.
|
|
115
|
+
- **A host's own buttons.** A host matched the kit's buttons by hashed class
|
|
116
|
+
name (`[class*='ick-primary-']`), by position (the button in the
|
|
117
|
+
composer's surface is the send) and by `aria-label` (the stop is the one
|
|
118
|
+
labelled "Zaustavi"), so translating a label changed its colour.
|
|
119
|
+
- Every variant is painted from `--ick-btn-<variant>-*` tokens, with
|
|
120
|
+
`--ick-btn-radius` and `--ick-btn-weight`. The defaults are the values
|
|
121
|
+
the variants had: compared in both themes, at rest and on hover, 60
|
|
122
|
+
samples, no difference.
|
|
123
|
+
- Every button the kit draws says what it is for in `data-ick-role` and
|
|
124
|
+
what it is in `data-ick-variant`. `send`, `stop` and `save` are three
|
|
125
|
+
roles, not one button with three labels. A test fails on a `<Button>`
|
|
126
|
+
drawn without a role.
|
|
127
|
+
- `ChatHeaderAction` takes `variant`, so one action can be the host's
|
|
128
|
+
primary.
|
|
129
|
+
- `HostButtons` story; the tokens and the roles are listed in
|
|
130
|
+
`theming.md`.
|
|
131
|
+
|
|
132
|
+
Not a `components={{ Button }}` slot, though that was asked for: the kit's
|
|
133
|
+
buttons carry the composer's morphing glyph and its layout animation, and
|
|
134
|
+
a host component would have to take all of it on to stand in for one.
|
|
135
|
+
- **`OpensWithTheMessage` story**, and `npm run panel-check` in the gate: a
|
|
136
|
+
card's button opens a side panel and sends from it, the answer is ready at
|
|
137
|
+
once. Four failures against 0.59.2, none now — and a long message is
|
|
138
|
+
checked to still be clamped.
|
|
139
|
+
|
|
11
140
|
## 0.59.2 — 2026-09-24
|
|
12
141
|
|
|
13
142
|
### Fixed
|
package/README.md
CHANGED
|
@@ -211,6 +211,8 @@ input that morphs into its own bubble rather than a record of what was typed.
|
|
|
211
211
|
| `placeholder` | `string` | | |
|
|
212
212
|
| `animationConfig` | `InlineAnimConfig` | | Passed to the input |
|
|
213
213
|
| `entranceDelay` | `number` | `0` | Stagger, in seconds |
|
|
214
|
+
| `entrance` | `"rise" \| "fade"` | `"rise"` | How the row arrives — a docked composer fades in place |
|
|
215
|
+
| `answerAfterTravel` | `boolean` | `false` | The answer waits until the sent question has landed — docked, set by `ChatExperience` |
|
|
214
216
|
| `selectionMode` | `"marker" \| "precise"` | `"marker"` | Passed to the highlighter |
|
|
215
217
|
| `questionAlign` | `"end" \| "stretch"` | `"end"` | Where the composer sits — see below |
|
|
216
218
|
| `onDraft` | `(id, value) => void` | | |
|
|
@@ -1393,7 +1395,9 @@ handful of things you can do to the whole thread.
|
|
|
1393
1395
|
| `landmark` | `boolean` | `true` | `false` inside a panel, where `banner` would be a lie |
|
|
1394
1396
|
| `children` | `ReactNode` | | Anything the kit should not manage. Never collapses |
|
|
1395
1397
|
|
|
1396
|
-
Each action is `{ id, label, icon, onClick?, href?, count?, active?, disabled?, pinned? }`.
|
|
1398
|
+
Each action is `{ id, label, icon, onClick?, href?, count?, active?, disabled?, pinned?, variant? }`.
|
|
1399
|
+
`variant` is how one action stands out — `"primary"` for the host's own — and
|
|
1400
|
+
only applies while it is in the header rather than folded into the menu.
|
|
1397
1401
|
`label` is required because an icon has no name of its own, and `count` is
|
|
1398
1402
|
folded into that name — the badge is decorative, so a reader who cannot see it
|
|
1399
1403
|
still hears "Saved highlights, 3".
|
|
@@ -1468,6 +1472,18 @@ existing call sites keep working. Its `s` / `m` / `l` map to `m` / `l` / `xl`.
|
|
|
1468
1472
|
Neither takes a dark-mode prop: the theme is a token swap on an ancestor. See
|
|
1469
1473
|
[theming.md](./theming.md).
|
|
1470
1474
|
|
|
1475
|
+
**Your own button.** `components={{ Button }}` on `ChatExperience` — or
|
|
1476
|
+
`ComponentsProvider` around pieces assembled by hand — draws your button
|
|
1477
|
+
wherever the kit draws one, except the composer's send / stop / save glyph,
|
|
1478
|
+
which morphs inside its button and stays the kit's. The kit keeps the layout
|
|
1479
|
+
(the box, its size from `--ick-control-*`, motion, the 44px touch area) and
|
|
1480
|
+
your button paints. It must forward its `ref`, render a `<button>` and spread
|
|
1481
|
+
the `aria-*` and `data-*` it is given; the props it receives are
|
|
1482
|
+
`KitButtonProps`, and `kitRole` says what each one is for. Set
|
|
1483
|
+
`--ick-btn-radius` to your corner too: the kit's glyph and the composer around
|
|
1484
|
+
it follow it. Tokens first, per-role CSS second, the component third — see
|
|
1485
|
+
"Bring your own button" in [theming.md](./theming.md#bring-your-own-button).
|
|
1486
|
+
|
|
1471
1487
|
## Labels: every word the kit says
|
|
1472
1488
|
|
|
1473
1489
|
Every component takes a `labels` prop, and `ChatExperience` and `ChatTurnRow`
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import { ButtonProps } from './Button';
|
|
3
|
+
import { KitButtonProps, KitButtonRole, KitButtonShape } from '../components/components';
|
|
4
|
+
export interface KitButtonUse extends Omit<ButtonProps, "type"> {
|
|
5
|
+
/** What it is for. Written to `data-ick-role`, and handed to a host's button. */
|
|
6
|
+
kitRole: Exclude<KitButtonRole, "send" | "stop" | "save">;
|
|
7
|
+
/** Worked out from the content when not given: an icon alone is `square`. */
|
|
8
|
+
shape?: KitButtonShape;
|
|
9
|
+
/** The layout box a host's button sits in. The kit's own button ignores it. */
|
|
10
|
+
boxClassName?: string;
|
|
11
|
+
boxStyle?: CSSProperties;
|
|
12
|
+
/** Given to a host's button instead of what the kit's own is given. */
|
|
13
|
+
hostProps?: Partial<Pick<KitButtonProps, "icon" | "iconRight" | "children">>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Every button the kit draws but the composer's morphing glyph.
|
|
17
|
+
*
|
|
18
|
+
* With no host button in `ComponentsProvider` this is the kit's `Button`,
|
|
19
|
+
* given exactly what it was given before the slot existed — the same element,
|
|
20
|
+
* the same attributes, so nothing about the default changes.
|
|
21
|
+
*
|
|
22
|
+
* With one, the host's button is drawn inside a box the kit lays out: the box
|
|
23
|
+
* has the size, takes the place in the row, and carries the 44px hit area on
|
|
24
|
+
* a touch screen; the host's button fills it and paints it. `className` and
|
|
25
|
+
* `style` here are the kit's paint and stay with the kit's button; where they
|
|
26
|
+
* also place it, the call site says so again as `boxClassName` / `boxStyle`.
|
|
27
|
+
*/
|
|
28
|
+
export declare const KitButton: import('react').ForwardRefExoticComponent<KitButtonUse & import('react').RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
/** For tests: forget which roles have been warned about. */
|
|
3
|
+
export declare function resetHostButtonWarnings(): void;
|
|
4
|
+
/**
|
|
5
|
+
* In development, checks a host's button against the contract in
|
|
6
|
+
* `KitButtonProps`, and says so once per role when it falls short:
|
|
7
|
+
*
|
|
8
|
+
* - its ref is not forwarded (`forwardRef`), so the kit cannot focus it;
|
|
9
|
+
* - what it renders is not a `<button>`;
|
|
10
|
+
* - it drops the `aria-*` or `data-ick-*` the kit gave it;
|
|
11
|
+
* - keyboard focus changes nothing about how it looks.
|
|
12
|
+
*
|
|
13
|
+
* `role` is `undefined` for the kit's own button, which is not checked.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useHostButtonChecks(role: string | undefined, box: RefObject<HTMLElement | null>, element: RefObject<HTMLElement | null>, forwarded: RefObject<boolean>, given: Record<string, unknown>): void;
|
|
@@ -8,6 +8,7 @@ import { TranscribeHandler } from '../voice/useVoiceInput';
|
|
|
8
8
|
import { CustomPart, CustomPartContext, TurnPartUpdate } from '../turnParts/turnParts';
|
|
9
9
|
import { ComposerMenuItem } from '../ChatInput/AddCardsOverlay';
|
|
10
10
|
import { ChatLabels } from '../labels/labels';
|
|
11
|
+
import { ChatComponents } from '../components/components';
|
|
11
12
|
import { Answer } from '../QuestionCard/types';
|
|
12
13
|
import { Decision } from '../Approval/Approval';
|
|
13
14
|
/**
|
|
@@ -91,6 +92,15 @@ export interface ChatExperienceProps {
|
|
|
91
92
|
* an inline object costs nothing — it is compared by content.
|
|
92
93
|
*/
|
|
93
94
|
labels?: ChatLabels;
|
|
95
|
+
/**
|
|
96
|
+
* The host's own components, drawn in place of the kit's. `Button` is used
|
|
97
|
+
* for every button the chat draws except the composer's send / stop / save
|
|
98
|
+
* glyph, whose animation lives in the button. The kit keeps the layout —
|
|
99
|
+
* size, place, motion, hit area — and your button paints. It must forward
|
|
100
|
+
* its ref and render a `<button>`; see `KitButtonProps`. Keep it stable:
|
|
101
|
+
* declared outside a render, not inside one.
|
|
102
|
+
*/
|
|
103
|
+
components?: ChatComponents;
|
|
94
104
|
/**
|
|
95
105
|
* The header's built-in actions. `true` (the default) is the theme toggle
|
|
96
106
|
* and Share; `false` is neither; a list keeps only those named. The saved
|
|
@@ -235,4 +245,4 @@ export interface ChatExperienceProps {
|
|
|
235
245
|
onDecideApproval?: (write: PartWriter, turnId: string, partId: string, decision: Decision) => void;
|
|
236
246
|
className?: string;
|
|
237
247
|
}
|
|
238
|
-
export declare function ChatExperience({ onSend, chat: hostChat, renderPart, labels, headerActions: builtInActions, composerMenu, onTranscribe, onThreadReply, title: titleProp, backHref, backLabel, actions, placeholder, empty, contextTotal, contextBase, artifact, openArtifactId: openArtifactProp, onOpenArtifactChange, pane: paneMode, surface, composer, fill: fillMode, theme: themeProp, onThemeChange, cursor, selectionToggle, highlights: marking, bookmarks, anchorOffset, endOffset, animationConfig, foldMotion, feedDelay, onAnswerQuestion, onEditQuestion, onDecideApproval, className, }: ChatExperienceProps): import("react").JSX.Element;
|
|
248
|
+
export declare function ChatExperience({ onSend, chat: hostChat, renderPart, labels, components, headerActions: builtInActions, composerMenu, onTranscribe, onThreadReply, title: titleProp, backHref, backLabel, actions, placeholder, empty, contextTotal, contextBase, artifact, openArtifactId: openArtifactProp, onOpenArtifactChange, pane: paneMode, surface, composer, fill: fillMode, theme: themeProp, onThemeChange, cursor, selectionToggle, highlights: marking, bookmarks, anchorOffset, endOffset, animationConfig, foldMotion, feedDelay, onAnswerQuestion, onEditQuestion, onDecideApproval, className, }: ChatExperienceProps): import("react").JSX.Element;
|