polymorph-ui-components-mcp 0.4.0 → 0.6.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.
@@ -105,9 +105,9 @@ Override these custom properties to theme the component.
105
105
  | `--button-disabled-cursor` | `not-allowed` | cursor | Cursor shown when the button is disabled. |
106
106
  | `--button-disabled-opacity` | `0.4` | opacity | Opacity when the button is disabled. |
107
107
  | `--button-disabled-text-color` | `-` | color | Text color when the button is disabled. |
108
- | `--button-disabled-font-size` | `-` | font-size | Font size when the button is disabled. |
109
- | `--button-disabled-font-weight` | `-` | font-weight | Font weight when the button is disabled. |
110
- | `--button-disabled-border` | `-` | border | Border when the button is disabled. |
108
+ | `--button-disabled-font-size` | `var(--button-font-size, 14px)` | font-size | Font size when the button is disabled. |
109
+ | `--button-disabled-font-weight` | `var(--button-font-weight, 500)` | font-weight | Font weight when the button is disabled. |
110
+ | `--button-disabled-border` | `var(--button-border, none)` | border | Border when the button is disabled. |
111
111
  | `--button-disabled-text-decoration` | `var(--button-text-decoration, none)` | text-decoration | Text decoration when disabled, e.g. `line-through` for an unavailable option. |
112
112
  | `--button-disabled-background-color` | `-` | background | Background color when the button is disabled. |
113
113
  | `--button-loader-order` | `1` | order | Flex order of the circular loader relative to icon/text. |
@@ -115,7 +115,7 @@ Override these custom properties to theme the component.
115
115
  | `--button-icon-display` | `-` | display | Display property of the icon container. |
116
116
  | `--button-text-order` | `3` | order | Flex order of the text relative to loader/icon. |
117
117
  | `--button-text-display` | `-` | display | Display property of the text container. |
118
- | `--button-hover-color` | inherits `--button-color` | background | Background color on hover. |
118
+ | `--button-hover-color` | inherits `--button-color` | background | Background color on hover. Hover styles never apply to a disabled button. |
119
119
  | `--button-hover-text-color` | inherits `--button-text-color` | color | Text color on hover. |
120
120
  | `--button-hover-border` | inherits `--button-border` | border | Border style on hover. |
121
121
  | `--button-hover-transform` | `-` | transform | CSS transform applied on hover (e.g., `scale(1.05)`). Allows hover scale effects without `:global()`. |
@@ -2,10 +2,14 @@
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.6.2...HEAD)
5
+ ## [Unreleased](https://github.com/sinha-sahil/polymorph-ui-components/compare/0.8.0...HEAD)
6
6
 
7
- - include build:wc in build script so publint finds dist-wc
8
- - add --modal-flex-direction css variable
7
+ - Select: ariaLabel names the combobox, the search input and the open listbox
8
+ - docs: the prop, an accessibility section and the web component attribute
9
+
10
+ ## [0.8.0](https://github.com/sinha-sahil/polymorph-ui-components/compare/0.7.0...0.8.0) - 26 September 2026
11
+
12
+ ## [0.7.0](https://github.com/sinha-sahil/polymorph-ui-components/compare/0.6.2...0.7.0) - 27 August 2026
9
13
 
10
14
  ## [0.6.2](https://github.com/sinha-sahil/polymorph-ui-components/compare/0.6.1...0.6.2) - 11 August 2026
11
15
 
@@ -1,30 +1,60 @@
1
1
  # Carousel
2
2
 
3
- An auto-playing slideshow that renders Svelte components as slides. Supports touch swipe (20px threshold) and mouse drag for navigation. Each slide is a `CarouselView` object containing a Svelte Component reference and optional properties. Shows optional dot indicators below the slides for direct navigation. The carousel width is read from the `--carousel-width` CSS variable at mount time.
3
+ A slideshow for content or announcements. Slides come from a `slide` snippet (called with each index up to `count`) or from `views`, an array of Svelte components. Slides are as wide as the carousel, so any `--carousel-width` works, including percentages. Navigation: optional previous/next arrows, dot indicators, touch swipe and mouse drag (20px threshold). `isScrollableLast` lets navigation wrap from the last slide to the first (rewinding across the slides); `loop` wraps seamlessly instead, sliding forward into the first slide through a hidden copy. Autoplay pauses while the pointer is over the carousel or focus is inside it, and follows changes to `autoplay` and `autoplayInterval`.
4
4
 
5
5
  ## Usage
6
6
 
7
7
  ```svelte
8
8
  <script>
9
9
  import { Carousel } from 'polymorph-ui-components';
10
+
11
+ const messages = ['Free shipping over $50', 'New arrivals every Friday'];
10
12
  </script>
11
13
 
12
14
  <Carousel
13
- views={/* CarouselView[] */}
14
- />
15
+ count={messages.length}
16
+ autoplay
17
+ autoplayInterval={4000}
18
+ loop
19
+ showArrows
20
+ ariaLabel="Announcements"
21
+ >
22
+ {#snippet slide(index)}
23
+ <p>{messages[index]}</p>
24
+ {/snippet}
25
+ </Carousel>
26
+
27
+ <Carousel views={[{ component: SlideOne }, { component: SlideTwo, properties: { tone: 'dark' } }]} showDots />
15
28
  ```
16
29
 
17
30
  ## Props
18
31
 
19
- | Prop | Type | Required | Default | Description |
20
- | ---------------- | ---------------- | -------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
21
- | views | `CarouselView[]` | Yes | `-` | Array of CarouselView objects. Each contains a Svelte Component reference and optional properties to pass to it. |
22
- | autoplay | `boolean` | No | `false` | When true, the carousel automatically advances to the next slide at the autoplayInterval rate. |
23
- | autoplayInterval | `number` | No | `1000` | Time in milliseconds between automatic slide transitions. Only used when autoplay is true. |
24
- | showDots | `boolean` | No | `false` | When true, shows dot indicators below the carousel for direct slide navigation. |
25
- | isScrollableLast | `boolean` | No | `false` | When true, allows scrolling past the last slide (wrapping to the first) and before the first slide (wrapping to the last). |
26
- | testId | `string` | No | `-` | Test selector value applied as `data-pw` on the outermost element. |
27
- | classes | `string` | No | `-` | CSS class string applied to the component's top-level element. Useful for theming — define classes with CSS variable overrides (e.g., `.btn-primary { --button-color: #0070f3; }`) and pass them to create variant styles. |
32
+ | Prop | Type | Required | Default | Description |
33
+ | ---------------- | ---------------- | -------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
34
+ | count | `number` | No | `0` | Number of slides rendered by the `slide` snippet. Ignored without `slide`. |
35
+ | views | `CarouselView[]` | No | `[]` | Slides as Svelte components, each with optional properties passed as a single `properties` prop. Used when there is no `slide` snippet. |
36
+ | autoplay | `boolean` | No | `false` | When true, the carousel advances every `autoplayInterval`. It pauses while hovered or focused, and never runs with fewer than two slides. |
37
+ | autoplayInterval | `number` | No | `1000` | Time in milliseconds between automatic slide transitions. Manual navigation restarts the timer. |
38
+ | showDots | `boolean` | No | `false` | When true, shows dot indicators below the carousel for direct slide navigation. |
39
+ | showArrows | `boolean` | No | `false` | When true (and there are at least two slides), shows previous/next buttons on either side of the slides. |
40
+ | isScrollableLast | `boolean` | No | `false` | When true, next on the last slide goes to the first and previous on the first goes to the last, animating back across the slides. |
41
+ | loop | `boolean` | No | `false` | Like `isScrollableLast`, but seamless: the carousel keeps moving in the same direction through hidden copies of the first and last slides. Those copies mount the slide content a second time. |
42
+ | announce | `boolean` | No | `true` | When true, a slide the user moves to is announced (`aria-live="polite"`) unless autoplay is rotating. Set false when slides contain text that keeps changing, such as a countdown, or every change is read out. |
43
+ | ariaLabel | `string` | No | `'Carousel'` | Accessible name of the carousel region, e.g. `Announcements`. |
44
+ | previousLabel | `string` | No | `'Previous slide'` | Accessible name of the previous button. |
45
+ | nextLabel | `string` | No | `'Next slide'` | Accessible name of the next button. |
46
+ | testId | `string` | No | `-` | Test selector value applied as `data-pw` on the outermost element. |
47
+ | 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. |
48
+
49
+ ## Snippets
50
+
51
+ Svelte 5 Snippet props — pass content blocks to the component.
52
+
53
+ | Snippet | Type | Description |
54
+ | ------------ | ------------------- | ---------------------------------------------------------------------------------------------------- |
55
+ | slide | `Snippet<[number]>` | Renders the slide at the given index. Preferred over `views` for text or markup slides. |
56
+ | previousIcon | `Snippet` | Icon inside the previous button. Falls back to a left chevron. Sized by `--carousel-arrow-size`. |
57
+ | nextIcon | `Snippet` | Icon inside the next button. Falls back to a right chevron. Sized by `--carousel-arrow-size`. |
28
58
 
29
59
  ## Events
30
60
 
@@ -36,18 +66,36 @@ An auto-playing slideshow that renders Svelte components as slides. Supports tou
36
66
 
37
67
  Override these custom properties to theme the component.
38
68
 
39
- | Variable | Default | CSS Property | Description |
40
- | -------------------------- | ------- | ------------- | -------------------------------------------------------------------------------- |
41
- | `--carousel-width` | `300px` | width | Width of the carousel container. Read by JS at mount time for slide positioning. Note: `.carousel-container` uses this variable without a fallback; inner elements fall back to `300px`. |
42
- | `--carousel-height` | `100px` | height | Height of the carousel slides. |
43
- | `--carousel-shadow` | `-` | box-shadow | Box shadow of the carousel container. |
44
- | `--carousel-border-radius` | `0%` | border-radius | Corner rounding of the carousel container. |
45
- | `--carousel-dot-gap` | `10px` | gap | Gap between dot indicators. |
46
- | `--carousel-dot-padding-top` | `10px` | padding-top | Top padding above the dot indicators. |
47
- | `--carousel-dot-width` | `5px` | width | Width of each dot indicator. |
48
- | `--carousel-dot-height` | `5px` | height | Height of each dot indicator. |
49
- | `--carousel-dot-color` | `currentColor` | background | Background color of inactive dot indicators. |
50
- | `--carousel-active-dot-color` | `currentColor` | background | Background color of the active dot indicator. |
69
+ | Variable | Default | CSS Property | Description |
70
+ | ---------------------------------- | -------------- | ------------------- | --------------------------------------------------------------------------------------------------- |
71
+ | `--carousel-width` | `300px` | width, flex-basis | Width of the carousel. Any unit works, including `100%`. `.carousel-container` uses it without a fallback. |
72
+ | `--carousel-height` | `100px` | height | Height of the slides. `fit-content` sizes the carousel to its tallest slide. |
73
+ | `--carousel-shadow` | `-` | box-shadow | Box shadow of the carousel. |
74
+ | `--carousel-border-radius` | `0%` | border-radius | Corner rounding of the carousel. |
75
+ | `--carousel-transition-duration` | `0.5s` | transition-duration | Duration of the slide movement. Zero under `prefers-reduced-motion: reduce`, so slides change without animating (autoplay still advances). |
76
+ | `--carousel-transition-easing` | `ease-in-out` | transition-timing-function | Easing of the slide movement. |
77
+ | `--carousel-arrow-gap` | `8px` | gap | Space between the arrows and the slides. |
78
+ | `--carousel-arrow-size` | `16px` | width, height | Size of the arrow icons. |
79
+ | `--carousel-arrow-padding` | `4px` | padding | Padding inside the arrow buttons. |
80
+ | `--carousel-arrow-background` | `transparent` | background | Background of the arrow buttons. |
81
+ | `--carousel-arrow-hover-background`| `transparent` | background | Background of a hovered arrow button. |
82
+ | `--carousel-arrow-color` | `currentColor` | color | Icon colour of the arrow buttons. |
83
+ | `--carousel-arrow-border` | `none` | border | Border of the arrow buttons. |
84
+ | `--carousel-arrow-border-radius` | `999px` | border-radius | Corner rounding of the arrow buttons. |
85
+ | `--carousel-dot-gap` | `10px` | gap | Gap between dot indicators. |
86
+ | `--carousel-dot-padding-top` | `10px` | padding-top | Top padding above the dot indicators. |
87
+ | `--carousel-dot-width` | `5px` | width | Width of each dot indicator. |
88
+ | `--carousel-dot-height` | `5px` | height | Height of each dot indicator. |
89
+ | `--carousel-dot-color` | `currentColor` | background | Background color of inactive dot indicators. |
90
+ | `--carousel-active-dot-color` | `currentColor` | background | Background color of the active dot indicator. |
91
+
92
+ ## Accessibility
93
+
94
+ - The root is a `role="region"` with `aria-roledescription="carousel"`, named by `ariaLabel`.
95
+ - Each slide is a `role="group"` with `aria-roledescription="slide"` and a label like `2 of 3`. Slides that are off screen are `aria-hidden` and `inert`, so their links and buttons can't be tabbed to; the copies used by `loop` are always hidden.
96
+ - The slide area is `aria-live="polite"` when the user is in control and `off` while autoplay rotates it, so rotation isn't announced every few seconds. `announce={false}` keeps it `off`.
97
+ - Autoplay pauses while the pointer is over the carousel or focus is inside it.
98
+ - Arrows are real buttons named by `previousLabel` and `nextLabel`.
51
99
 
52
100
  ## Type Reference
53
101
 
@@ -62,12 +110,20 @@ type CarouselView = {
62
110
  };
63
111
  ```
64
112
 
113
+ `MandatoryCarouselProperties` (`{ views: CarouselView[] }`) is still exported but deprecated: `views` is optional now.
114
+
115
+ ## Internal Dependencies
116
+
117
+ This component uses the following library components internally:
118
+
119
+ - Button (for the previous and next arrows)
120
+
65
121
  ## Web Component
66
122
 
67
123
  Tag: `<pui-carousel>`
68
124
 
69
125
  ```html
70
- <pui-carousel autoplay show-dots></pui-carousel>
126
+ <pui-carousel autoplay show-dots show-arrows loop aria-label="Featured"></pui-carousel>
71
127
  ```
72
128
 
73
- > **Note:** The `views` prop is an array — set it via JavaScript property.
129
+ > **Note:** The `views` prop is an array — set it via JavaScript property. The `slide`, `previousIcon` and `nextIcon` snippets are Svelte only; custom elements use `views` and the built-in icons.
@@ -34,7 +34,9 @@ A text input field with built-in validation for email, phone (tel), password, an
34
34
  | actionInput | `boolean` | No | `false` | When true, hides the label, error message, and info message, and adjusts border-radius/shadow for seamless integration inside InputButton. |
35
35
  | useTextArea | `boolean` | No | `false` | When true, renders a `<textarea>` instead of an `<input>`. Useful for multi-line text entry. |
36
36
  | autoComplete | `HTMLInputAttributes['autocomplete']` | No | `'on'` | The HTML autocomplete attribute value. Controls browser autofill behavior. Accepts any string for non-standard values (e.g., `'off'`, `'new-password'`). |
37
- | name | `string` | No | `''` | The HTML name attribute for the input. Used for form submission and label association. |
37
+ | name | `string` | No | `''` | The HTML name attribute for the input. Used for form submission. |
38
+ | id | `string` | No | generated | The id of the input or textarea. The label is tied to it with `for`, so clicking the label focuses the field. Generated when omitted. |
39
+ | ariaLabel | `string` | No | `-` | Accessible name for a field without a visible label (e.g. a placeholder-only search or discount field). A visible `label` needs no ariaLabel. |
38
40
  | textTransformers | `TextTransformer[]` | No | `[]` | Array of functions applied to the raw input value before digit extraction (tel mode only). Use for stripping country codes or formatting. |
39
41
  | textViewPresentation | `TextTransformer[]` | No | `[]` | Array of functions applied to the value for display purposes. The underlying value stays clean but the displayed text is transformed (e.g., adding spaces every 4 digits for card numbers). |
40
42
  | testId | `string` | No | `''` | Value for the data-pw attribute, used for end-to-end testing selectors. |
@@ -111,6 +113,12 @@ Override these custom properties to theme the component.
111
113
  | `--input-placeholder-color` | `#a1a1aa` | color | Color of placeholder text. |
112
114
  | `--input-error-border` | `1px solid var(--input-error-msg-text-color, currentColor)` | border | Border of the input when in error state. |
113
115
 
116
+ ## Accessibility
117
+
118
+ - The visible `label` is associated with the field by id, so it names the field and clicking it focuses the field.
119
+ - Use `ariaLabel` when there is no visible label; a placeholder alone is not an accessible name.
120
+ - Validation decides "still typing" by checking focus within the field's own root, so it works inside a shadow root too.
121
+
114
122
  ## Type Reference
115
123
 
116
124
  Custom types used by this component's props and events:
@@ -1,6 +1,6 @@
1
1
  # InputButton
2
2
 
3
- A composite component that combines an Input field with optional left, right, and bottom Button components. The right button is automatically disabled until the input validation state becomes `Valid`, and the bottom button's click handler only fires once validation is `Valid`. Pressing Enter in the input triggers the right button's `onkeyup` handler when validation passes. The input label and error/info messages are rendered outside the input-button group. Internally uses the Input component with `actionInput=true` for seamless visual integration.
3
+ A composite component that combines an Input field with optional left, right, and bottom Button components. The right button is automatically disabled until the input validation state becomes `Valid`, and the bottom button's click handler only fires once validation is `Valid`. Pressing Enter in the input triggers the right button's `onkeyup` handler when validation passes. The input label and error/info messages are rendered outside the input-button group; the label is tied to the input by id, and empty or missing messages render nothing. The input fills its part of the row and stretches to the row's height, so its text lines up with the buttons. Internally uses the Input component with `actionInput=true` for seamless visual integration.
4
4
 
5
5
  ## Usage
6
6
 
@@ -58,7 +58,7 @@ Override these custom properties to theme the component.
58
58
  | Variable | Default | CSS Property | Description |
59
59
  | --------------------------------------- | ---------------------------------------------------- | ------------------------------- | --------------------------------------------------------------------------- |
60
60
  | `--input-button-container-margin` | `-` | margin | Outer margin of the entire InputButton container. |
61
- | `--input-height` | `fit-content` | height | |
61
+ | `--input-height` | `fit-content` | height | Height of the whole control; the input and buttons stretch to fill it. |
62
62
  | `--input-font-size` | `16px` | font-size | |
63
63
  | `--input-button-margin` | `-` | margin | Margin of the inner input-button row. |
64
64
  | `--input-button-radius` | `6px` | border-radius | Corner rounding of the input-button row. |
@@ -1,6 +1,6 @@
1
1
  # Loader
2
2
 
3
- A rotating circular spinner with a gradient foreground that transitions from `--loader-foreground` to `--loader-foreground-end`. The center is cut out using an `::after` pseudo-element with `--loader-background` color, creating a ring/donut shape. Spins continuously with a 1.4s linear animation.
3
+ A rotating circular spinner with a gradient foreground that transitions from `--loader-foreground` to `--loader-foreground-end`. The center is cut out using an `::after` pseudo-element with `--loader-background` color, creating a ring/donut shape. Spins continuously with a linear animation (1.4s per turn by default). Pass `label` to name it for screen readers: the loader then becomes a `role="status"` region with the label as visually hidden text.
4
4
 
5
5
  ## Usage
6
6
 
@@ -10,12 +10,15 @@ A rotating circular spinner with a gradient foreground that transitions from `--
10
10
  </script>
11
11
 
12
12
  <Loader />
13
+
14
+ <Loader label="Updating quantity" />
13
15
  ```
14
16
 
15
17
  ## Props
16
18
 
17
19
  | Prop | Type | Required | Default | Description |
18
20
  | ------- | -------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
21
+ | label | `string` | No | `-` | Visually hidden text for screen readers. When set, the loader gets `role="status"`. Leave it out when surrounding content already says what is loading. |
19
22
  | testId | `string` | No | `-` | Test selector value applied as `data-pw` on the outermost element. |
20
23
  | 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. |
21
24
 
@@ -45,6 +48,12 @@ Override these custom properties to theme the component.
45
48
  | `--loader-after-position` | `absolute` | position | CSS position of the cutout. |
46
49
  | `--loader-after-top` | `50%` | top | Top position of the cutout. |
47
50
  | `--loader-after-left` | `50%` | left | Left position of the cutout. |
51
+ | `--loader-duration` | `1.4s` | animation-duration | Time for one full turn. `0s` stops the spin, e.g. for reduced motion. |
52
+
53
+ ## Accessibility
54
+
55
+ - Without `label` the loader is decorative and has no role.
56
+ - With `label` it is a `role="status"` region whose text is the label, hidden visually but available to screen readers. Screen readers differ on announcing a status region that appears already filled.
48
57
 
49
58
  ## Web Component
50
59
 
@@ -0,0 +1,109 @@
1
+ # NumberStepper
2
+
3
+ A compact − value + control for stepping a number, such as a cart line quantity. `onchange` receives the requested value; the component never changes `value` itself, so the parent stays the source of truth (a server can refuse or cap the change). If `onchange` returns a Promise, a loader replaces the value and further presses are ignored until it settles; the buttons stay focusable, so keyboard focus is never lost. Icon snippets receive the current value, so the decrement icon can become a trash can when the next step removes the item.
4
+
5
+ ## Usage
6
+
7
+ ```svelte
8
+ <script>
9
+ import { NumberStepper } from 'polymorph-ui-components';
10
+
11
+ let quantity = $state(1);
12
+ </script>
13
+
14
+ <NumberStepper value={quantity} min={0} max={10} onchange={(next) => (quantity = next)} />
15
+
16
+ <NumberStepper
17
+ value={line.quantity}
18
+ ariaLabel="Quantity"
19
+ decrementLabel={line.quantity === 1 ? 'Remove item' : 'Decrease quantity'}
20
+ incrementLabel="Increase quantity"
21
+ loadingLabel="Updating quantity"
22
+ onchange={(next) => updateLine(line.id, next)}
23
+ >
24
+ {#snippet decrementIcon(value)}
25
+ {#if value === 1}<TrashIcon />{:else}<MinusIcon />{/if}
26
+ {/snippet}
27
+ </NumberStepper>
28
+ ```
29
+
30
+ ## Props
31
+
32
+ | Prop | Type | Required | Default | Description |
33
+ | -------------- | --------- | -------- | ------------ | ------------------------------------------------------------------------------------------------------------------ |
34
+ | value | `number` | Yes | `-` | The current value. Read only: update it from `onchange`. |
35
+ | min | `number` | No | `0` | Lowest value. Decrement is disabled when `value - step` would fall below it. |
36
+ | max | `number` | No | `Infinity` | Highest value. Increment is disabled when `value + step` would exceed it. |
37
+ | step | `number` | No | `1` | Amount added or removed per press. |
38
+ | disabled | `boolean` | No | `false` | Disables both buttons. |
39
+ | ariaLabel | `string` | No | `'Quantity'` | Accessible name of the control group. |
40
+ | decrementLabel | `string` | No | `'Decrease'` | Accessible name of the decrement button, e.g. `Remove item` when the next step removes it. |
41
+ | incrementLabel | `string` | No | `'Increase'` | Accessible name of the increment button. |
42
+ | loadingLabel | `string` | No | `'Updating'` | Text announced while a Promise returned by `onchange` is pending. |
43
+ | testId | `string` | No | `-` | Value for `data-pw` on the root. The buttons get `{testId}-decrement` and `{testId}-increment`. |
44
+ | 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. |
45
+
46
+ ## Snippets
47
+
48
+ Svelte 5 Snippet props — pass content blocks to the component.
49
+
50
+ | Snippet | Type | Description |
51
+ | ------------- | ------------------- | ---------------------------------------------------------------------------------------- |
52
+ | decrementIcon | `Snippet<[number]>` | Icon inside the decrement button. Receives the current value. Defaults to a minus icon. |
53
+ | incrementIcon | `Snippet<[number]>` | Icon inside the increment button. Receives the current value. Defaults to a plus icon. |
54
+
55
+ ## Events
56
+
57
+ | Event | Type | Description |
58
+ | -------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
59
+ | onchange | `((value: number) => void) \| ((value: number) => Promise<void>)` | Fires with `value ± step` when a button is pressed. Return a Promise to show the loader and ignore further presses until it settles. Handle errors inside it: a rejected Promise ends the pending state and is passed on. |
60
+
61
+ ## CSS Variables
62
+
63
+ Override these custom properties to theme the component.
64
+
65
+ | Variable | Default | CSS Property | Description |
66
+ | ------------------------------------------ | ------------------- | ----------------- | -------------------------------------------------------- |
67
+ | `--number-stepper-gap` | `0` | gap | Space between the buttons and the value. |
68
+ | `--number-stepper-padding` | `0` | padding | Inner padding of the control. |
69
+ | `--number-stepper-border` | `1px solid currentColor` | border | Border around the control. |
70
+ | `--number-stepper-border-radius` | `6px` | border-radius | Corner rounding of the control. |
71
+ | `--number-stepper-background` | `transparent` | background | Background of the control. |
72
+ | `--number-stepper-color` | `currentColor` | color | Text and icon colour. |
73
+ | `--number-stepper-button-background` | `transparent` | background | Background of the buttons. |
74
+ | `--number-stepper-button-color` | `currentColor` | color | Icon colour of the buttons. |
75
+ | `--number-stepper-button-hover-background` | `transparent` | background | Background of a hovered button. |
76
+ | `--number-stepper-button-padding` | `6px` | padding | Padding inside each button. |
77
+ | `--number-stepper-button-border-radius` | `6px` | border-radius | Corner rounding of each button. |
78
+ | `--number-stepper-button-disabled-opacity` | `0.4` | opacity | Opacity of a disabled button, and of both buttons while a change is pending. |
79
+ | `--number-stepper-icon-size` | `14px` | width, height | Size of the button icons. |
80
+ | `--number-stepper-value-min-width` | `24px` | min-width | Minimum width of the value, so the control doesn't jump. |
81
+ | `--number-stepper-value-font-size` | `14px` | font-size | Font size of the value. |
82
+ | `--number-stepper-value-font-weight` | `500` | font-weight | Font weight of the value. |
83
+ | `--number-stepper-value-font-variant-numeric` | `tabular-nums` | font-variant-numeric | Digit style of the value; tabular digits keep its width steady. |
84
+ | `--number-stepper-loader-size` | `14px` | width, height | Size of the loader shown while a change is pending. |
85
+ | `--number-stepper-pending-cursor` | `progress` | cursor | Cursor over the buttons while a change is pending. |
86
+
87
+ ## Accessibility
88
+
89
+ - The control is a `role="group"` named by `ariaLabel`, and each button has its own name, so a screen reader hears "Quantity, group", "Decrease quantity, button", "Increase quantity, button".
90
+ - The value is an `aria-live="polite"` region: the new value is read after each change, and `loadingLabel` while a change is pending.
91
+ - `aria-busy` is set on the group while a change is pending, and presses are ignored so a second press can't race the first. The buttons stay enabled and focusable (dimmed by `--number-stepper-button-disabled-opacity`), so focus stays where it was.
92
+ - At `min` or `max` the matching button is disabled; if it had focus, focus moves to the other button.
93
+
94
+ ## Internal Dependencies
95
+
96
+ This component uses the following library components internally:
97
+
98
+ - Button (for the decrement and increment buttons)
99
+ - Loader (while a change is pending)
100
+
101
+ ## Web Component
102
+
103
+ Tag: `<pui-number-stepper>`
104
+
105
+ ```html
106
+ <pui-number-stepper value="2" min="0" max="10" aria-label="Quantity"></pui-number-stepper>
107
+ ```
108
+
109
+ > **Note:** Set `onchange` via JavaScript property and write the new value back to `value`. The icon snippets are Svelte only; custom elements use the built-in icons.
@@ -56,6 +56,7 @@ Define variant classes in your app's CSS that set Pill CSS variables, then pass
56
56
  | ----------- | --------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
57
57
  | text | `string` | Yes | `-` | The label text displayed inside the pill. Long text is truncated with an ellipsis when it exceeds the maximum width. |
58
58
  | dismissible | `boolean` | No | `false` | When true, shows a small X button after the text that triggers the ondismiss event when clicked. |
59
+ | dismissLabel | `string` | No | `'Dismiss'` | Accessible name of the dismiss button. Name what it removes, e.g. `Remove SAVE10`, so several dismissible pills stay distinguishable to screen readers. |
59
60
  | disabled | `boolean` | No | `false` | When true, the pill appears dimmed (opacity 0.4), shows a not-allowed cursor, and ignores all click and dismiss interactions. |
60
61
  | testId | `string` | No | `-` | Value for the data-pw attribute, used for end-to-end testing selectors. The dismiss button receives `{testId}-dismiss`. |
61
62
  | 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. |
@@ -1,6 +1,6 @@
1
1
  # Progress
2
2
 
3
- A linear progress bar showing task completion or usage. The `value` prop controls the filled portion relative to `max`. When `showLabel` is true, a percentage text is displayed next to the bar. Setting `value` to a negative number activates an indeterminate sliding animation for unknown-duration tasks.
3
+ A linear progress bar showing task completion or usage. The `value` prop controls the filled portion relative to `max`. When `showLabel` is true, a percentage text is displayed next to the bar. Setting `value` to a negative number activates an indeterminate sliding animation for unknown-duration tasks. `milestones` places markers along the track, each at its own value, with optional labels underneath — useful for reward tiers, free-shipping thresholds or checkpoints. A milestone counts as reached once `value` meets it; render your own marker per milestone with the `milestone` snippet.
4
4
 
5
5
  ## Usage
6
6
 
@@ -9,7 +9,23 @@ A linear progress bar showing task completion or usage. The `value` prop control
9
9
  import { Progress } from 'polymorph-ui-components';
10
10
  </script>
11
11
 
12
- <Progress value={60} />
12
+ <Progress value={60} ariaLabel="Upload" />
13
+
14
+ <Progress
15
+ value={2}
16
+ max={3}
17
+ ariaLabel="Rewards"
18
+ valueText="2 of 3 rewards unlocked"
19
+ milestones={[
20
+ { value: 1, label: 'Free shipping' },
21
+ { value: 2, label: '10% off' },
22
+ { value: 3, label: 'Free gift' }
23
+ ]}
24
+ >
25
+ {#snippet milestone(stop, reached)}
26
+ <span class={reached ? 'tier tier-reached' : 'tier'}>{stop.value}</span>
27
+ {/snippet}
28
+ </Progress>
13
29
  ```
14
30
 
15
31
  ## Props
@@ -19,9 +35,20 @@ A linear progress bar showing task completion or usage. The `value` prop control
19
35
  | value | `number` | Yes | `-` | Current progress value (0 to max). Values are clamped to the 0-max range. A negative value activates the indeterminate animation for unknown-duration tasks. |
20
36
  | max | `number` | No | `100` | The maximum value representing 100% completion. The filled percentage is calculated as (value / max) \* 100. |
21
37
  | showLabel | `boolean` | No | `false` | Whether to display the rounded percentage text next to the progress bar. Hidden during indeterminate mode. |
38
+ | ariaLabel | `string` | No | `'Progress'` | Accessible name of the progress bar. |
39
+ | valueText | `string` | No | `-` | Human-readable value announced instead of the number, e.g. `2 of 3 rewards unlocked`. Maps to `aria-valuetext`. |
40
+ | milestones | `ProgressMilestone[]` | No | `[]` | Markers placed along the track at their `value` (clamped to 0–max, sorted). Each marker ends at its value, so one at `max` sits inside the track. Labels, when any milestone has one, render underneath, ending at the same point. |
22
41
  | testId | `string` | No | `-` | Value for the data-pw attribute, used for end-to-end testing selectors. |
23
42
  | 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. |
24
43
 
44
+ ## Snippets
45
+
46
+ Svelte 5 Snippet props — pass content blocks to the component.
47
+
48
+ | Snippet | Type | Description |
49
+ | --------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
50
+ | milestone | `Snippet<[ProgressMilestone, boolean]>` | Renders one milestone marker. Receives the milestone and whether `value` has reached it. Falls back to a round marker when omitted. |
51
+
25
52
  ## CSS Variables
26
53
 
27
54
  Override these custom properties to theme the component.
@@ -43,11 +70,41 @@ Override these custom properties to theme the component.
43
70
  | `--progress-label-color` | `currentColor` | color | Text color of the percentage label. |
44
71
  | `--progress-label-font-family` | `inherit` | font-family | Font family of the percentage label. |
45
72
  | `--progress-label-margin` | `0` | margin | Margin around the percentage label. |
73
+ | `--progress-milestone-size` | `12px` | width, height | Size of the built-in milestone marker. |
74
+ | `--progress-milestone-border` | `2px solid #ffffff` | border | Border of the built-in marker, separating it from the track. |
75
+ | `--progress-milestone-border-radius` | `50%` | border-radius | Corner rounding of the built-in marker. |
76
+ | `--progress-milestone-background` | `#e4e4e7` | background | Built-in marker colour before it is reached. |
77
+ | `--progress-milestone-reached-background` | `currentColor` | background | Built-in marker colour once reached. |
78
+ | `--progress-milestone-label-gap` | `8px` | gap | Space between the track and the milestone labels. |
79
+ | `--progress-milestone-label-font-size` | `12px` | font-size | Font size of the milestone labels. |
80
+ | `--progress-milestone-label-font-weight` | `400` | font-weight | Font weight of the milestone labels. |
81
+ | `--progress-milestone-label-color` | `currentColor` | color | Text colour of the milestone labels. |
82
+ | `--progress-milestone-label-font-family` | `inherit` | font-family | Font family of the milestone labels. |
83
+ | `--progress-milestone-label-text-align` | `end` | text-align | Alignment of a label within its segment; `end` lines it up with its marker. |
84
+
85
+ ## Accessibility
86
+
87
+ - The track has `role="progressbar"` with `aria-valuemin`, `aria-valuemax` and `aria-valuenow` (omitted while indeterminate), named by `ariaLabel`.
88
+ - `valueText` becomes `aria-valuetext`, so screen readers can hear "2 of 3 rewards unlocked" instead of a bare number.
89
+ - Milestone labels sit outside the progress bar, so they stay readable as text.
90
+
91
+ ## Type Reference
92
+
93
+ ### ProgressMilestone
94
+
95
+ ```typescript
96
+ type ProgressMilestone = {
97
+ value: number;
98
+ label?: string;
99
+ };
100
+ ```
46
101
 
47
102
  ## Web Component
48
103
 
49
104
  Tag: `<pui-progress>`
50
105
 
51
106
  ```html
52
- <pui-progress value="60" max="100" show-label></pui-progress>
107
+ <pui-progress value="60" max="100" show-label aria-label="Upload"></pui-progress>
53
108
  ```
109
+
110
+ > **Note:** Set `milestones` via JavaScript property. The `milestone` snippet is Svelte only; custom elements use the built-in marker.
@@ -15,7 +15,7 @@ A dropdown selector that supports single and multi-select modes with optional se
15
15
  ];
16
16
  </script>
17
17
 
18
- <Select {items} placeholder="Pick a fruit" onchange={(val) => console.log(val)} />
18
+ <Select {items} placeholder="Pick a fruit" ariaLabel="Fruit" onchange={(val) => console.log(val)} />
19
19
  ```
20
20
 
21
21
  ### Multi-Select with Search
@@ -34,6 +34,7 @@ A dropdown selector that supports single and multi-select modes with optional se
34
34
  | searchable | `boolean` | No | `false` | Enables a text input in the trigger area for filtering items by label. Works in both single and multi-select modes. |
35
35
  | placeholder | `string` | No | `''` | Text shown when no item is selected (or in the search input when empty). |
36
36
  | disabled | `boolean` | No | `false` | When true, the select is non-interactive, has reduced opacity, and pointer events are disabled. |
37
+ | ariaLabel | `string` | No | - | Accessible name for a select without a visible label, e.g. `"Size"`. Set on the combobox, the search input and the listbox. |
37
38
  | testId | `string` | No | - | Value for the `data-pw` attribute on the container element, used for end-to-end testing selectors. |
38
39
  | 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. |
39
40
 
@@ -137,6 +138,11 @@ These variables style the Pill components shown for selected items in multi-sele
137
138
  | `--select-pill-padding` | `2px 8px` | padding | Padding inside selected item pills. |
138
139
  | `--select-pill-font-size` | `14px` | font-size | Font size of selected item pills. |
139
140
 
141
+ ## Accessibility
142
+
143
+ - The trigger is a `role="combobox"` that controls a `role="listbox"`; the highlighted option is exposed through `aria-activedescendant`.
144
+ - Use `ariaLabel` when there is no visible label; a placeholder alone is not an accessible name.
145
+
140
146
  ## Type Reference
141
147
 
142
148
  Custom types used by this component's props and events:
@@ -161,7 +167,7 @@ This component uses the following library components internally:
161
167
  Tag: `<pui-select>`
162
168
 
163
169
  ```html
164
- <pui-select placeholder="Pick a fruit"></pui-select>
170
+ <pui-select placeholder="Pick a fruit" aria-label="Fruit"></pui-select>
165
171
 
166
172
  <script>
167
173
  const el = document.querySelector('pui-select');
@@ -1,6 +1,6 @@
1
1
  # Sheet
2
2
 
3
- A panel component that slides in from any edge of the screen (left, right, top, or bottom). Designed for navigation menus, settings panels, detail views, or notification trays. Left/right sheets span the full viewport height; top/bottom sheets span the full viewport width. Includes a structured layout with a header (title and close button), scrollable content area, and an optional footer. The `open` prop is bindable for two-way state control. Body scroll is locked while the sheet is open, and focus is trapped within the panel for accessibility.
3
+ A panel component that slides in from any edge of the screen (left, right, top, or bottom). Designed for navigation menus, settings panels, detail views, or notification trays. Left/right sheets span the full viewport height; top/bottom sheets span the full viewport width. Includes a structured layout with a header (title and close button), scrollable content area, and an optional footer. The `open` prop is bindable for two-way state control. The panel slides in by its own full width (or height), so wide sheets never pop in part-way. Page scroll is locked while the sheet is open, focus is trapped within the panel and returns to the element that had it when the sheet closes. Motion is skipped for users who prefer reduced motion.
4
4
 
5
5
  ## Usage
6
6
 
@@ -33,6 +33,7 @@ A panel component that slides in from any edge of the screen (left, right, top,
33
33
  | title | `string` | No | `-` | Text displayed in the sheet header. When provided, a header bar is rendered at the top of the panel with this title. |
34
34
  | showOverlay | `boolean` | No | `true` | When true, shows a dark semi-transparent overlay behind the sheet panel. When false, the overlay is transparent with pointer-events disabled on the backdrop. |
35
35
  | showCloseButton | `boolean` | No | `true` | When true, renders a close button (X) in the sheet header. Clicking it closes the sheet and fires the onclose event. |
36
+ | closeLabel | `string` | No | `'Close'` | Accessible name of the close button, e.g. `Close cart`. |
36
37
  | testId | `string` | No | `-` | Value for data-pw on the overlay container element. The close button gets `{testId}-close` as its data-pw value. Used for Playwright test selectors. |
37
38
  | 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. |
38
39
 
@@ -44,6 +45,7 @@ Svelte 5 Snippet props — pass content blocks to the component.
44
45
  | ------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
45
46
  | content | `Snippet` | Required. The main body content rendered inside the scrollable area of the sheet panel. |
46
47
  | footer | `Snippet` | Optional. Content rendered in a fixed footer area at the bottom of the sheet panel, separated from the content by a border. Useful for action buttons or summary information. |
48
+ | closeIcon | `Snippet` | Optional. Replaces the built-in close icon inside the close button. Sized by `--sheet-close-icon-size`. |
47
49
 
48
50
  ## Events
49
51
 
@@ -68,6 +70,7 @@ Override these custom properties to theme the component.
68
70
  | `--sheet-z-index` | `16` | z-index | Z-index stacking order of the sheet panel itself. |
69
71
  | `--sheet-border` | `none` | border | Border on the edge of the sheet panel facing the page content. Applied as border-left (right side), border-right (left side), border-bottom (top side), or border-top (bottom side). |
70
72
  | `--sheet-header-padding` | `16px 20px` | padding | Inner padding of the header area. |
73
+ | `--sheet-header-gap` | `8px` | gap | Space between the title and the close button. |
71
74
  | `--sheet-header-background` | `inherit` | background-color | Background color of the header area. |
72
75
  | `--sheet-header-border-bottom` | `1px solid #e4e4e7` | border-bottom | Bottom border of the header, visually separating it from the content area. |
73
76
  | `--sheet-title-font-size` | `18px` | font-size | Font size of the title text in the header. |
@@ -75,14 +78,17 @@ Override these custom properties to theme the component.
75
78
  | `--sheet-title-font-family` | `inherit` | font-family | Font family of the title text in the header. |
76
79
  | `--sheet-title-color` | `currentColor` | color | Text color of the title in the header. |
77
80
  | `--sheet-title-line-height` | `1.4` | line-height | Line height of the title text in the header. |
81
+ | `--sheet-title-margin` | `0` | margin | Margin around the title, which is an `h2`. |
78
82
  | `--sheet-close-button-size` | `32px` | width, height | Width and height of the close button in the header. |
79
83
  | `--sheet-close-button-border-radius` | `6px` | border-radius | Border radius of the close button. |
80
84
  | `--sheet-close-button-background` | `transparent` | background-color | Background color of the close button in its default state. |
81
85
  | `--sheet-close-button-color` | `currentColor` | color | Color of the close button icon. |
82
- | `--sheet-close-button-font-size` | `16px` | font-size | Font size of the close button icon. |
86
+ | `--sheet-close-button-font-size` | `16px` | font-size | Font size inside the close button, for icons sized in `em`. |
87
+ | `--sheet-close-icon-size` | `var(--sheet-close-button-font-size, 16px)` | width, height | Width and height of the close icon SVG, built-in or from `closeIcon`. Follows `--sheet-close-button-font-size` when not set. |
83
88
  | `--sheet-close-button-hover-background` | `transparent` | background-color | Background color of the close button when hovered. |
84
89
  | `--sheet-content-overflow-y` | `auto` | overflow-y | Vertical overflow behavior of the scrollable content area. |
85
90
  | `--sheet-content-padding` | `20px` | padding | Inner padding of the content area. |
91
+ | `--sheet-content-overscroll-behavior` | `contain` | overscroll-behavior | Whether scrolling past the end of the content scrolls the page behind. |
86
92
  | `--sheet-scrollbar-width` | `none` | scrollbar-width | Controls the visibility of the scrollbar in the content area. Set to `auto` or `thin` to show scrollbar. |
87
93
  | `--sheet-footer-padding` | `16px 20px` | padding | Inner padding of the footer area. |
88
94
  | `--sheet-footer-background` | `inherit` | background-color | Background color of the footer area. |
@@ -90,11 +96,15 @@ Override these custom properties to theme the component.
90
96
 
91
97
  ## Accessibility
92
98
 
93
- - The sheet panel has `role="dialog"` and `aria-modal="true"` for screen reader support.
94
- - Focus is automatically moved to the sheet panel when it opens.
95
- - Focus is trapped within the sheet panel using Tab/Shift+Tab cycling.
99
+ - The sheet panel has `role="dialog"` and `aria-modal="true"` for screen reader support; the title is an `h2` (it was a `span`; page-wide `h2` rules other than margin, font and colour now reach it).
100
+ - The overlay is `role="presentation"`, so the dialog is never announced as part of a button.
101
+ - Focus is automatically moved to the sheet panel when it opens (also when it is reopened while closing), and returns to the previously focused element when it closes.
102
+ - Focus is trapped within the sheet panel using Tab/Shift+Tab cycling. The trap walks the composed tree, so content passed through slots (`<pui-sheet>`) and open shadow roots take part, and inert or hidden elements are skipped. It works when the sheet itself lives in a shadow root.
103
+ - Escape and Tab still work if focus has fallen out of the panel, for example after the focused element was removed: Escape closes and Tab brings focus back in.
96
104
  - Pressing the Escape key closes the sheet.
97
- - The close button has `aria-label="Close"` for screen reader identification.
105
+ - The close button is named by `closeLabel` (default `Close`).
106
+ - With `prefers-reduced-motion: reduce` the sheet opens and closes without sliding or fading.
107
+ - The page scroll lock is shared with Modal, CommandMenu and Gallery: nested overlays keep the page locked until the last one closes, and the page's own inline `overflow` is restored afterwards.
98
108
 
99
109
  ## Type Reference
100
110
 
@@ -117,7 +127,7 @@ This component uses the following library components internally:
117
127
  Tag: `<pui-sheet>`
118
128
 
119
129
  ```html
120
- <pui-sheet open side="right" title="Settings">
130
+ <pui-sheet open side="right" title="Settings" close-label="Close settings">
121
131
  <p>Sheet body content</p>
122
132
  <div slot="footer">
123
133
  <button>Save</button>
@@ -33,7 +33,7 @@
33
33
  },
34
34
  {
35
35
  "name": "Carousel",
36
- "description": "An auto-playing slideshow that renders Svelte components as slides. Supports touch swipe and mouse drag for navigation. Shows optional dot indicators below the slides for direct navigation."
36
+ "description": "A slideshow whose slides come from a `slide` snippet (with `count`) or from Svelte component `views`. Works at any width, including percentages. Optional previous/next arrows, dot indicators, touch swipe and mouse drag. `isScrollableLast` wraps; `loop` wraps seamlessly. Autoplay pauses on hover and focus; slides change without animating under reduced motion; `announce` controls whether slide changes are read out."
37
37
  },
38
38
  {
39
39
  "name": "Chat",
@@ -141,7 +141,7 @@
141
141
  },
142
142
  {
143
143
  "name": "Loader",
144
- "description": "A rotating circular spinner with a gradient foreground that transitions from `--loader-foreground` to `--loader-foreground-end`. The center is cut out to create a ring/donut shape. Spins continuously with a 1.4s linear animation."
144
+ "description": "A rotating circular spinner with a gradient foreground that transitions from `--loader-foreground` to `--loader-foreground-end`. The center is cut out to create a ring/donut shape. Spins continuously (`--loader-duration`, 1.4s by default). Pass `label` to make it a `role=status` region that announces what is loading."
145
145
  },
146
146
  {
147
147
  "name": "LoadingDots",
@@ -167,6 +167,10 @@
167
167
  "name": "ModalAnimation",
168
168
  "description": "A wrapper that applies fly or fade Svelte transitions to its children based on the modal's `align` prop. For top alignment, content flies in from above; for bottom, from below; for center, a fade transition is used."
169
169
  },
170
+ {
171
+ "name": "NumberStepper",
172
+ "description": "A compact − value + control for stepping a number such as a cart quantity. Controlled: `onchange` receives the requested value and the parent updates `value`. When `onchange` returns a Promise, a loader shows and presses are ignored until it settles, while focus stays on the buttons. Icon snippets receive the value, so decrement can become a trash icon at the last step."
173
+ },
170
174
  {
171
175
  "name": "OverlayAnimation",
172
176
  "description": "A wrapper that applies a fade-out transition (350ms) to its children when they are removed from the DOM. Used internally by Modal to animate the overlay background."
@@ -181,11 +185,11 @@
181
185
  },
182
186
  {
183
187
  "name": "Pill",
184
- "description": "A compact label/tag element for displaying status, categories, or metadata. Supports an optional icon snippet and click interaction with keyboard accessibility (role=button, Enter/Space). Optionally clickable when onclick is provided."
188
+ "description": "A compact label/tag element for displaying status, categories, or metadata. Supports an optional icon snippet and click interaction with keyboard accessibility (role=button, Enter/Space). Optionally clickable when onclick is provided. When dismissible, `dismissLabel` names the dismiss button (e.g. `Remove SAVE10`)."
185
189
  },
186
190
  {
187
191
  "name": "Progress",
188
- "description": "A horizontal progress bar that fills from left to right based on `value` relative to `max`, with an animated width transition. Supports an optional percentage label and an indeterminate sweeping animation when `value` is negative. Styling is configurable via CSS variables."
192
+ "description": "A horizontal progress bar (`role=progressbar`) that fills based on `value` relative to `max`, with an animated width transition. Supports a percentage label, an indeterminate animation when `value` is negative, and `milestones` — markers placed along the track at their own values with optional labels and a `milestone` snippet that knows whether each one is reached."
189
193
  },
190
194
  {
191
195
  "name": "Radio",
@@ -209,7 +213,7 @@
209
213
  },
210
214
  {
211
215
  "name": "Sheet",
212
- "description": "A panel that slides in from any edge of the screen (left, right, top, or bottom). Includes a structured layout with header, scrollable content, and optional footer. Body scroll locks while open, focus is trapped, and Escape key dismisses. The open prop is bindable."
216
+ "description": "A panel that slides in from any edge of the screen by its full size. Includes a header (h2 title and close button with a `closeIcon` snippet and `closeLabel`), scrollable content, and optional footer. Page scroll locks while open; focus is trapped across slots and shadow roots and returned on close; Escape dismisses; motion is skipped for reduced-motion users. The open prop is bindable."
213
217
  },
214
218
  {
215
219
  "name": "Shimmer",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polymorph-ui-components-mcp",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
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
6
  "repository": {