polymorph-ui-components-mcp 0.3.0 → 0.3.2

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.
@@ -100,12 +100,15 @@ Override these custom properties to theme the component.
100
100
  | `--button-content-gap` | `16px` | gap | Gap between icon and text inside the button. |
101
101
  | `--button-visibility` | `visible` | visibility | Controls button visibility (visible/hidden). |
102
102
  | `--button-box-shadow` | `none` | box-shadow | Box shadow of the button. |
103
+ | `--button-text-decoration` | `none` | text-decoration | Text decoration of the label, e.g. `underline` for a link-styled button. |
104
+ | `--button-line-height` | `normal` | line-height | Line height of the label. Useful when a link-styled button must sit on a text baseline. |
103
105
  | `--button-disabled-cursor` | `not-allowed` | cursor | Cursor shown when the button is disabled. |
104
106
  | `--button-disabled-opacity` | `0.4` | opacity | Opacity when the button is disabled. |
105
107
  | `--button-disabled-text-color` | `-` | color | Text color when the button is disabled. |
106
108
  | `--button-disabled-font-size` | `-` | font-size | Font size when the button is disabled. |
107
109
  | `--button-disabled-font-weight` | `-` | font-weight | Font weight when the button is disabled. |
108
110
  | `--button-disabled-border` | `-` | border | Border when the button is disabled. |
111
+ | `--button-disabled-text-decoration` | `var(--button-text-decoration, none)` | text-decoration | Text decoration when disabled, e.g. `line-through` for an unavailable option. |
109
112
  | `--button-disabled-background-color` | `-` | background | Background color when the button is disabled. |
110
113
  | `--button-loader-order` | `1` | order | Flex order of the circular loader relative to icon/text. |
111
114
  | `--button-icon-order` | `2` | order | Flex order of the icon relative to loader/text. |
@@ -116,6 +119,7 @@ Override these custom properties to theme the component.
116
119
  | `--button-hover-text-color` | inherits `--button-text-color` | color | Text color on hover. |
117
120
  | `--button-hover-border` | inherits `--button-border` | border | Border style on hover. |
118
121
  | `--button-hover-transform` | `-` | transform | CSS transform applied on hover (e.g., `scale(1.05)`). Allows hover scale effects without `:global()`. |
122
+ | `--button-hover-opacity` | `var(--button-opacity, 1)` | opacity | Opacity on hover, for a fade effect without overriding the background colour. |
119
123
  | `--button-active-transform` | `-` | transform | CSS transform applied on active/pressed state (e.g., `scale(0.95)`). Allows press-down effects without `:global()`. |
120
124
  | `--button-progress-loader-background-color` | `#00000030` | background | Background color of the progress bar overlay. |
121
125
  | `--button-progress-loader-duration` | `8s` | animation-duration | Duration of the progress bar fill animation. |
@@ -2,12 +2,16 @@
2
2
  based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to
3
3
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
4
 
5
- ## [Unreleased](https://github.com/sinha-sahil/polymorph-ui-components/compare/0.4.0...HEAD)
5
+ ## [Unreleased](https://github.com/sinha-sahil/polymorph-ui-components/compare/0.6.1...HEAD)
6
6
 
7
- - added gallery component for list, grid view + fullscreen views
8
- - updated icon, img for supporting new props and css styling
9
- - added get element ref in button component
10
- - updated docs, assets
7
+ - passing attachments to ChatMessageList and ChatMessage components
8
+ - updated documentation
9
+
10
+ ## [0.6.1](https://github.com/sinha-sahil/polymorph-ui-components/compare/0.6.0...0.6.1) - 5 August 2026
11
+
12
+ ## [0.6.0](https://github.com/sinha-sahil/polymorph-ui-components/compare/0.5.0...0.6.0) - 5 August 2026
13
+
14
+ ## [0.5.0](https://github.com/sinha-sahil/polymorph-ui-components/compare/0.4.0...0.5.0) - 5 July 2026
11
15
 
12
16
  ## [0.4.0](https://github.com/sinha-sahil/polymorph-ui-components/compare/0.3.0...0.4.0) - 1 July 2026
13
17
 
@@ -77,6 +77,24 @@ Markdown is intentionally not bundled: pass pre-sanitized HTML on a message's `h
77
77
 
78
78
  **Roles.** Messages use the two-party primitive `role` — `sender` / `responder` (see `ChatMessage`). The controller emits those, and `partyOf(role)` resolves any role (including the `user`/`assistant`/`system` extensions) to its party. Map the primitive to your provider's roles inside the transport, where the API-specific terms belong: `history.map((m) => ({ role: partyOf(m.role) === 'sender' ? 'user' : 'assistant', content: m.content }))`.
79
79
 
80
+ ## Your own UI inside a message
81
+
82
+ Two snippets, and the difference matters. `message` replaces the whole message — you own the bubble, alignment, streaming indicator, and you lose the built-in copy / retry / feedback wiring. `messageAttachments` renders **below** the bubble and keeps all of that, so reach for it first.
83
+
84
+ It receives the whole `ChatMessageData`, so render on whatever field you like — a custom field of your own, or `attachments`, which `ChatController` fills from a transport's `handlers.onAttachment(...)`:
85
+
86
+ ```svelte
87
+ <Chat {messages} bind:value allowCopy onretry={() => chat.retry()} {onsend}>
88
+ {#snippet messageAttachments(msg)}
89
+ {#each msg.attachments ?? [] as item, index (index)}
90
+ <YourComponent data={item} />
91
+ {/each}
92
+ {/snippet}
93
+ </Chat>
94
+ ```
95
+
96
+ The snippet is invoked for every message, so branch inside it to target specific ones. Rendering nothing costs no layout — the container collapses when empty.
97
+
80
98
  ## Layout — fullscreen & floating
81
99
 
82
100
  `Chat` is position- and size-agnostic: its root fills its container (`--chat-height` / `--chat-width` default to `100%`), with the message list on `flex: 1` and the composer pinned to the bottom. The only requirement is a **bounded-height parent** — the flexing list needs something to fill. Positioning (fixed, floating, modal) is the consumer's job; the component never assumes a layout context.
@@ -163,7 +181,8 @@ The fixed-height `.chat-panel` gives `Chat` its bounds; add a slide/scale transi
163
181
  | headerAvatar | `Snippet` | No | `-` | Brand/avatar mark in the header (takes precedence over `image`). |
164
182
  | headerActions | `Snippet` | No | `-` | Extra inline header actions. |
165
183
  | headerContent | `Snippet` | No | `-` | Extra content as a full-width second row in the header (toolbar, status…). |
166
- | message | `Snippet<[ChatMessageData]>` | No | `-` | Custom per-message rendering. |
184
+ | message | `Snippet<[ChatMessageData]>` | No | `-` | Custom per-message rendering. Replaces the default bubble entirely. |
185
+ | messageAttachments | `Snippet<[ChatMessageData]>` | No | `-` | Your own UI rendered below each bubble, keeping the default bubble and its actions. |
167
186
  | empty | `Snippet` | No | `-` | Empty-state content. |
168
187
  | composerLeading | `Snippet` | No | `-` | Content before the composer input. |
169
188
  | sendIcon / stopIcon / voiceIcon / attachIcon | `Snippet` | No | `-` | Custom composer icons; each falls back to a built-in asset. |
@@ -29,7 +29,7 @@ A single chat bubble. The primitive is the **party** — every message is from o
29
29
  | status | `'sending' \| 'sent' \| 'error'` | No | `-` | `error` tints the bubble with the error color. |
30
30
  | avatar | `Snippet` | No | `-` | Avatar shown beside the bubble. |
31
31
  | header | `Snippet` | No | `-` | Header row above the bubble (author name, timestamp, etc.). |
32
- | attachments | `Snippet` | No | `-` | Content rendered below the bubble. |
32
+ | attachments | `Snippet \| null` | No | `-` | Content rendered below the bubble. Collapses to no layout when it renders nothing. |
33
33
  | allowCopy | `boolean` | No | `false` | Show a built-in copy button in the hover actions row. |
34
34
  | actions | `Snippet` | No | `-` | Extra custom actions appended to the actions row. |
35
35
  | copyLabel / retryLabel / feedbackUpLabel / feedbackDownLabel | `string` | No | `…` | Aria-labels for the action buttons. |
@@ -1,6 +1,6 @@
1
1
  # ChatMessageList
2
2
 
3
- A scrollable, auto-scrolling container for a conversation. It renders each message with `ChatMessage` by default, or a fully custom `message` snippet (use this to add avatars, attachments, or timestamps). When there are no messages, the `empty` snippet is shown. **Smart auto-scroll** keeps the latest content in view only while you're already near the bottom — if you scroll up to read history it won't yank you down, and a **jump-to-latest** button appears instead. Opt-in message actions (`allowCopy`, `onretry`, `onfeedback`) are applied to the default-rendered messages: copy and feedback on assistant messages, retry on the most recent assistant message. Implemented with a Svelte action (no effects), respecting `prefers-reduced-motion`.
3
+ A scrollable, auto-scrolling container for a conversation. It renders each message with `ChatMessage` by default. To add your own UI below a bubble, pass `messageAttachments` — it receives each `ChatMessageData` and keeps the default bubble along with its copy/retry/feedback actions. Use the `message` snippet only when you want to replace a message entirely, which forgoes that default rendering. When there are no messages, the `empty` snippet is shown. **Smart auto-scroll** keeps the latest content in view only while you're already near the bottom — if you scroll up to read history it won't yank you down, and a **jump-to-latest** button appears instead. Opt-in message actions (`allowCopy`, `onretry`, `onfeedback`) are applied to the default-rendered messages: copy and feedback on assistant messages, retry on the most recent assistant message. Implemented with a Svelte action (no effects), respecting `prefers-reduced-motion`.
4
4
 
5
5
  ## Usage
6
6
 
@@ -24,6 +24,7 @@ A scrollable, auto-scrolling container for a conversation. It renders each messa
24
24
  | messages | `ChatMessageData[]` | Yes | `-` | Messages to render. |
25
25
  | autoscroll | `boolean` | No | `true` | Auto-scroll to the latest message as content changes. |
26
26
  | message | `Snippet<[ChatMessageData]>` | No | `-` | Custom per-message rendering; overrides the default bubble. |
27
+ | messageAttachments | `Snippet<[ChatMessageData]>` | No | `-` | Own UI below each bubble; keeps the default bubble and actions. |
27
28
  | empty | `Snippet` | No | `-` | Shown when there are no messages. |
28
29
  | jumpLabel | `string` | No | `'Jump to latest'` | Aria-label for the jump-to-latest button. |
29
30
  | jumpIcon | `Snippet` | No | `-` | Custom jump-to-latest icon. Falls back to a built-in asset. |
@@ -21,6 +21,7 @@ A large-target selection card used for prominent single or multi-choice selectio
21
21
  | selected | `boolean` | No | `false` | The current selection state of the choicebox. Bindable. |
22
22
  | mode | `'radio' \| 'checkbox'` | No | `'radio'` | Sets the element's ARIA role and selection behavior. In `radio` mode a selected card cannot be deselected by clicking it again; `checkbox` mode toggles freely. |
23
23
  | disabled | `boolean` | No | `false` | When true, the choicebox is non-interactive and visually dimmed. |
24
+ | showIndicator | `boolean` | No | `false` | Draw the radio dot / checkbox tick inside the card. Off by default so cards that supply their own selected affordance are unaffected. |
24
25
  | testId | `string` | No | `undefined` | Value for the `data-pw` attribute used in Playwright test selectors. |
25
26
  | classes | `string` | No | `-` | CSS class string applied to the component's top-level element. Useful for theming — define classes with CSS variable overrides and pass them to create variant styles. |
26
27
 
@@ -69,3 +70,36 @@ Tag: `<pui-choicebox>`
69
70
  <span>Option A</span>
70
71
  </pui-choicebox>
71
72
  ```
73
+
74
+ ### Indicator
75
+
76
+ Set `showIndicator` to render a selection mark inside the card — a dot in `radio` mode, a tick in
77
+ `checkbox` mode. The mark is decorative: the card itself carries `role` and `aria-checked`, so the
78
+ indicator is `aria-hidden` and assistive tech reports one control, not two.
79
+
80
+ The slot content is wrapped in a growing element, so the indicator always sits at the card's
81
+ trailing edge whatever the slot contains. The wrapper's alignment and gap fall through to the
82
+ card's own values, so theming the card is enough — you only set these to make the inside of the
83
+ card differ from the card itself.
84
+
85
+ | Variable | Default | Description |
86
+ | ------------------------------ | -------------------------------- | --------------------------------------------------------------- |
87
+ | `--choicebox-body-flex` | `1` | Flex of the slot wrapper. `1` makes it fill, pushing the mark out. |
88
+ | `--choicebox-body-min-width` | `0` | Allows long slot content to ellipsis rather than overflow. |
89
+ | `--choicebox-body-display` | `flex` | Layout of the slot wrapper. |
90
+ | `--choicebox-body-align-items` | `var(--choicebox-align-items)` | Cross-axis alignment inside the wrapper. |
91
+ | `--choicebox-body-gap` | `var(--choicebox-gap)` | Gap between slot children. |
92
+
93
+ | Variable | Default | Description |
94
+ | ------------------------------------------- | -------------------- | ---------------------------------------------------- |
95
+ | `--choicebox-indicator-size` | `20px` | Width and height of the indicator. |
96
+ | `--choicebox-indicator-border` | `2px solid #757575` | Border when unselected. |
97
+ | `--choicebox-indicator-background` | `transparent` | Fill when unselected. |
98
+ | `--choicebox-indicator-selected-border` | `2px solid #2196f3` | Border when selected. |
99
+ | `--choicebox-indicator-selected-background` | `#2196f3` | Fill when selected. |
100
+ | `--choicebox-indicator-border-radius` | `var(--radius, 4px)` | Corner rounding in `checkbox` mode. |
101
+ | `--choicebox-indicator-dot-inset` | `4px` | Ring thickness that forms the dot in `radio` mode. |
102
+ | `--choicebox-indicator-dot-color` | `#ffffff` | Colour of the ring that punches out the dot. Set this to the card's real background when the choicebox itself is transparent. |
103
+ | `--choicebox-indicator-icon-size` | `14px` | Size of the tick in `checkbox` mode. |
104
+ | `--choicebox-indicator-icon-color` | `#ffffff` | Colour of the tick. |
105
+ | `--choicebox-indicator-transition` | `background 0.2s, border-color 0.2s` | Transition for selection changes. |
@@ -18,6 +18,8 @@ A dialog overlay component that renders on top of the page with configurable siz
18
18
  | ------------------------ | --------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
19
19
  | size | `ModalSize = 'large' \| 'medium' \| 'small' \| 'fit-content'` | No | `'fit-content'` | Controls the height of the modal content panel. 'small'=20vh, 'medium'=50vh, 'large'=80vh, 'fit-content'=auto with 80vh max. |
20
20
  | align | `ModalAlign = 'top' \| 'center' \| 'bottom'` | No | `'center'` | Vertical alignment of the modal within the viewport. 'top' aligns to the top (flex-start), 'center' centers vertically, 'bottom' aligns to the bottom (flex-end). |
21
+ | lockScroll | `boolean` | No | `true` | Whether the modal takes the page scroll lock. Set false when another element already owns it — otherwise this modal releases that lock when it unmounts. |
22
+ | autoDismissAfter | `number \| null` | No | `null` | Milliseconds after which the modal fires `onclose` itself. Null keeps it open until dismissed. The timer is cleared on unmount. |
21
23
  | showOverlay | `boolean` | No | `true` | When true, shows a dark semi-transparent overlay behind the modal. When false, the overlay is transparent with pointer-events disabled. |
22
24
  | supportHardwareBackPress | `boolean` | No | `false` | When true, pushes a history state on mount so that pressing the device back button triggers onclose instead of navigating away. Cleans up on destroy. |
23
25
  | enableTransition | `boolean` | No | `true` | When true, the modal content animates in/out using fly or fade transitions via ModalAnimation. |
@@ -58,6 +60,7 @@ Override these custom properties to theme the component.
58
60
  | -------------------------------------------------------- | ------------------ | ------------------------------- | ------------------------------------------------------------------ |
59
61
  | `--modal-width` | `100vw` | width | Width of the modal overlay container. |
60
62
  | `--modal-height` | `100vh` | height | Height of the modal overlay container. |
63
+ | `--modal-position` | `fixed` | position | Positioning of the overlay layer. Set `absolute` to scope the modal to a positioned ancestor — a drawer, sheet or embedded widget — instead of the viewport. Pair it with `--modal-width` / `--modal-height` (`auto` lets the insets size it). |
61
64
  | `--modal-z-index` | `15` | z-index | Z-index stacking order of the modal overlay. |
62
65
  | `--modal-margin` | `-` | margin | Outer margin of the modal overlay. |
63
66
  | `--modal-overlay-background-color` | `#00000066` | background-color | Background color of the semi-transparent overlay behind the modal. |
@@ -37,7 +37,7 @@
37
37
  },
38
38
  {
39
39
  "name": "Chat",
40
- "description": "A full chat surface composing ChatHeader, ChatMessageList, ChatSuggestions, ChatToolStatus, and ChatComposer. Fully controlled (pass `messages`, handle `onsend`) with no baked-in transport. Opt-in features: header image, stop-generation, voice mic, file attachments, prompt suggestions, smart autoscroll, and per-message copy/retry/feedback. Pair with the decoupled `ChatController` runes class — message state, streaming, typewriter reveal, retry, and session threading — which delegates the network call to a pluggable `ChatTransport` (adapt SSE, WebSocket, or polling). Markdown is not bundled — pass pre-sanitized HTML on a message's `html` field."
40
+ "description": "A full chat surface composing ChatHeader, ChatMessageList, ChatSuggestions, ChatToolStatus, and ChatComposer. Fully controlled (pass `messages`, handle `onsend`) with no baked-in transport. Opt-in features: header image, stop-generation, voice mic, file attachments, prompt suggestions, smart autoscroll, and per-message copy/retry/feedback. Render your own UI below any bubble with the `messageAttachments` snippet. Pair with the decoupled `ChatController` runes class — message state, streaming, typewriter reveal, retry, and session threading — which delegates the network call to a pluggable `ChatTransport` (adapt SSE, WebSocket, or polling). Markdown is not bundled — pass pre-sanitized HTML on a message's `html` field."
41
41
  },
42
42
  {
43
43
  "name": "ChatBubble",
@@ -57,7 +57,7 @@
57
57
  },
58
58
  {
59
59
  "name": "ChatMessageList",
60
- "description": "A scrollable conversation container with smart auto-scroll: it sticks to the bottom only while you're already near it, and shows a jump-to-latest button when you've scrolled up. Renders each message with ChatMessage by default or a custom `message` snippet, shows an `empty` snippet when there are no messages, and forwards opt-in message actions (allowCopy, onretry, onfeedback). Uses a Svelte action (no effects), respecting reduced-motion."
60
+ "description": "A scrollable conversation container with smart auto-scroll: it sticks to the bottom only while you're already near it, and shows a jump-to-latest button when you've scrolled up. Renders each message with ChatMessage by default, adds your own UI below any bubble via the per-message `messageAttachments` snippet, or replaces a message entirely with the `message` snippet, shows an `empty` snippet when there are no messages, and forwards opt-in message actions (allowCopy, onretry, onfeedback). Uses a Svelte action (no effects), respecting reduced-motion."
61
61
  },
62
62
  {
63
63
  "name": "ChatSuggestions",
package/package.json CHANGED
@@ -1,8 +1,18 @@
1
1
  {
2
2
  "name": "polymorph-ui-components-mcp",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "MCP server for polymorph-ui-components - provides structured access to component props, CSS variables, and usage patterns",
5
5
  "type": "module",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/sinha-sahil/polymorph-ui-components.git",
9
+ "directory": "mcp"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/sinha-sahil/polymorph-ui-components/issues"
13
+ },
14
+ "homepage": "https://github.com/sinha-sahil/polymorph-ui-components/tree/release/mcp#readme",
15
+ "author": "Sahil Sinha",
6
16
  "main": "build/index.js",
7
17
  "bin": {
8
18
  "polymorph-ui-components-mcp": "./build/index.js"