@viraui/react 1.0.11 → 1.0.13
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/dist/catalog.json +7 -1
- package/dist/components/accordion/accordion.guide.json +1 -0
- package/dist/components/annotate/annotate.css +1 -1
- package/dist/components/annotate/annotate.d.ts +17 -4
- package/dist/components/annotate/annotate.guide.json +36 -18
- package/dist/components/annotate/annotate.js +13 -5
- package/dist/components/annotate/annotate.module.js +8 -2
- package/dist/components/avatar/avatar.guide.json +1 -0
- package/dist/components/avatar-group/avatar-group.guide.json +1 -0
- package/dist/components/badge/badge.css +1 -0
- package/dist/components/badge/badge.d.ts +39 -0
- package/dist/components/badge/badge.guide.json +55 -0
- package/dist/components/badge/badge.js +50 -0
- package/dist/components/badge/badge.module.js +11 -0
- package/dist/components/badge/index.d.ts +2 -0
- package/dist/components/bleed/bleed.guide.json +1 -0
- package/dist/components/button/button-link.guide.json +1 -0
- package/dist/components/button/button-link.js +1 -1
- package/dist/components/button/button.guide.json +1 -0
- package/dist/components/button/button.js +1 -1
- package/dist/components/checkbox/checkbox.guide.json +1 -0
- package/dist/components/chip/chip.guide.json +1 -0
- package/dist/components/chip/chip.js +1 -1
- package/dist/components/clamp-text/clamp-text.guide.json +1 -0
- package/dist/components/clamp-text/clamp-text.js +1 -1
- package/dist/components/dialog/dialog-sheet.js +1 -1
- package/dist/components/dialog/dialog.guide.json +1 -0
- package/dist/components/elevator/elevator.guide.json +1 -0
- package/dist/components/fieldset/fieldset.guide.json +1 -0
- package/dist/components/fit-text/fit-text.guide.json +1 -0
- package/dist/components/icon-button/icon-button-link.guide.json +1 -0
- package/dist/components/icon-button/icon-button.guide.json +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/linear-progress/linear-progress.guide.json +1 -0
- package/dist/components/masonry/masonry.guide.json +1 -0
- package/dist/components/masonry/masonry.js +1 -1
- package/dist/components/meter/meter.guide.json +1 -0
- package/dist/components/popover/popover-sheet.js +1 -1
- package/dist/components/popover/popover.guide.json +1 -0
- package/dist/components/progressive-blur/progressive-blur.guide.json +1 -0
- package/dist/components/radio/radio.guide.json +1 -0
- package/dist/components/select/select.guide.json +1 -0
- package/dist/components/separator/separator.guide.json +1 -0
- package/dist/components/shimmer/shimmer.guide.json +1 -0
- package/dist/components/skeleton/skeleton.guide.json +1 -0
- package/dist/components/slider/slider.guide.json +1 -0
- package/dist/components/spinner/spinner.guide.json +1 -0
- package/dist/components/stack/stack.css +1 -1
- package/dist/components/stack/stack.guide.json +1 -0
- package/dist/components/static-noise/static-noise.guide.json +1 -0
- package/dist/components/surface/surface.css +1 -1
- package/dist/components/surface/surface.guide.json +1 -0
- package/dist/components/switch/switch.guide.json +1 -0
- package/dist/components/tabs/tabs.guide.json +1 -0
- package/dist/components/text/text.guide.json +1 -0
- package/dist/components/textarea/textarea.guide.json +1 -0
- package/dist/components/textfield/textfield.guide.json +1 -0
- package/dist/components/title/title.css +1 -1
- package/dist/components/title/title.d.ts +4 -4
- package/dist/components/title/title.guide.json +13 -12
- package/dist/components/title/title.js +2 -2
- package/dist/components/toast/toast.guide.json +1 -0
- package/dist/components/toggle-button/toggle-button.guide.json +1 -0
- package/dist/components/toggle-group/toggle-group.guide.json +1 -0
- package/dist/components/tooltip/tooltip.guide.json +1 -0
- package/dist/components/typewriter/typewriter.guide.json +1 -0
- package/dist/index.js +2 -1
- package/package.json +3 -3
package/dist/catalog.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
{
|
|
12
12
|
"id": "annotate",
|
|
13
13
|
"name": "Annotate",
|
|
14
|
-
"summary": "Decorative
|
|
14
|
+
"summary": "Decorative arrow and handwritten label that wraps inline content with optional highlighter mark, positioned via CSS anchor positioning.",
|
|
15
15
|
"guidePath": "./components/annotate/annotate.guide.json"
|
|
16
16
|
},
|
|
17
17
|
{
|
|
@@ -26,6 +26,12 @@
|
|
|
26
26
|
"summary": "Overlapping avatar stack with shared sizing, directional layout, and an optional overflow pill.",
|
|
27
27
|
"guidePath": "./components/avatar-group/avatar-group.guide.json"
|
|
28
28
|
},
|
|
29
|
+
{
|
|
30
|
+
"id": "badge",
|
|
31
|
+
"name": "Badge",
|
|
32
|
+
"summary": "Decorative status-dot overlay that wraps a child, with optional radial mask cutout on the child around the corner dot.",
|
|
33
|
+
"guidePath": "./components/badge/badge.guide.json"
|
|
34
|
+
},
|
|
29
35
|
{
|
|
30
36
|
"id": "bleed",
|
|
31
37
|
"name": "Bleed",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Accordion",
|
|
3
|
+
"structure": "<Accordion>\n <Accordion.Item trigger=\"…\">…</Accordion.Item>\n</Accordion>",
|
|
3
4
|
"summary": "Collapsible sections grouped into open/closed blocks with optional Surface wrapping, shared corner radius, and background on open items.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Progressive disclosure for related content sections in one surface",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-annotate-color{syntax:"<color>";inherits:true;initial-value:#d16500}@property --vui-annotate-arrow-x{syntax:"<length>";inherits:true;initial-value:0}@property --vui-annotate-arrow-y{syntax:"<length>";inherits:true;initial-value:0}@property --vui-annotate-text-x{syntax:"<length>";inherits:true;initial-value:0}@property --vui-annotate-text-y{syntax:"<length>";inherits:true;initial-value:0}@property --vui-annotate-rotate{syntax:"<angle>";inherits:true;initial-value:-4deg}@property --vui-annotate-target-gap{syntax:"<length>";inherits:true;initial-value:0}@property --vui-annotate-label-gap{syntax:"<length>";inherits:true;initial-value:0}@property --vui-annotate-label-max-width{syntax:"<length>";inherits:true;initial-value:150px}.viraui__annotate-module__Annotate_7C36U{--vui-annotate-color:var(--
|
|
1
|
+
@layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-annotate-color{syntax:"<color>";inherits:true;initial-value:#d16500}@property --vui-annotate-arrow-x{syntax:"<length>";inherits:true;initial-value:0}@property --vui-annotate-arrow-y{syntax:"<length>";inherits:true;initial-value:0}@property --vui-annotate-text-x{syntax:"<length>";inherits:true;initial-value:0}@property --vui-annotate-text-y{syntax:"<length>";inherits:true;initial-value:0}@property --vui-annotate-rotate{syntax:"<angle>";inherits:true;initial-value:-4deg}@property --vui-annotate-target-gap{syntax:"<length>";inherits:true;initial-value:0}@property --vui-annotate-label-gap{syntax:"<length>";inherits:true;initial-value:0}@property --vui-annotate-label-max-width{syntax:"<length>";inherits:true;initial-value:150px}@property --vui-annotate-z-index{syntax:"*";inherits:true;initial-value:auto}@property --vui-annotate-text-align{syntax:"*";inherits:true;initial-value:start}.viraui__annotate-module__Annotate_7C36U{--vui-annotate-color:var(--global-foreground);--vui-annotate-target-gap:var(--space-small);--vui-annotate-label-gap:var(--space-x-small);--_annotate-tail-x:23px;--_annotate-tail-y:4px;--_annotate-note-align-x:-50%;--_annotate-note-align-y:calc(-100% - var(--vui-annotate-label-gap));anchor-name:--vui-annotate-target;anchor-scope:--vui-annotate-target,--vui-annotate-arrow;display:inline-block;overflow:visible;border-radius:var(--radius-x-small)}.viraui__annotate-module__Arrow_T4B-6{position:absolute;z-index:var(--vui-annotate-z-index);position-anchor:--vui-annotate-target;anchor-name:--vui-annotate-arrow;width:46px;height:38px;transform:translate(var(--vui-annotate-arrow-x),var(--vui-annotate-arrow-y));transform-origin:50% 50%;mask:var(--_annotate-arrow-mask) center /contain no-repeat;background:var(--vui-annotate-color);pointer-events:none}.viraui__annotate-module__Note_8UW-R{position:absolute;z-index:var(--vui-annotate-z-index);position-anchor:--vui-annotate-arrow;left:calc(anchor(left) + var(--_annotate-tail-x));top:calc(anchor(top) + var(--_annotate-tail-y));width:max-content;max-width:var(--vui-annotate-label-max-width);transform:translate(calc(var(--_annotate-note-align-x) + var(--vui-annotate-text-x)),calc(var(--_annotate-note-align-y) + var(--vui-annotate-text-y))) rotate(var(--vui-annotate-rotate));font-family:Segoe Print,Chalkboard SE,Marker Felt,Dancing Script,sans-serif,system-ui;font-size:.95rem;line-height:1.05;color:var(--vui-annotate-color);text-align:var(--vui-annotate-text-align);white-space:normal;pointer-events:none}.viraui__annotate-module__Annotate_7C36U[data-mark=true]{background:oklab(from var(--vui-annotate-color) l a b/30%);box-shadow:-.3em 0 0 0 oklab(from var(--vui-annotate-color) l a b/30%),.3em 0 0 0 oklab(from var(--vui-annotate-color) l a b/30%)}.viraui__annotate-module__Annotate_7C36U[data-side=top]{--_annotate-tail-x:23px;--_annotate-tail-y:4px;--_annotate-note-align-x:-50%;--_annotate-note-align-y:calc(-100% - var(--vui-annotate-label-gap))}.viraui__annotate-module__Annotate_7C36U[data-side=top] .viraui__annotate-module__Arrow_T4B-6{--_annotate-arrow-mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='46' height='38' viewBox='0 0 46 38'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M23 4c-1 9-1 20 0 31'/%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m17 29 6 7 6-7'/%3E%3C/svg%3E");position-area:block-start;margin-bottom:var(--vui-annotate-target-gap)}.viraui__annotate-module__Annotate_7C36U[data-side=top-start]{--_annotate-tail-x:6px;--_annotate-tail-y:6px;--_annotate-note-align-x:-50%;--_annotate-note-align-y:calc(-100% - var(--vui-annotate-label-gap))}.viraui__annotate-module__Annotate_7C36U[data-side=top-start] .viraui__annotate-module__Arrow_T4B-6{--_annotate-arrow-mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='46' height='38' viewBox='0 0 46 38'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M6 6c10 2 22 14 34 26'/%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m36 22 4 10-10-4'/%3E%3C/svg%3E");position-area:block-start inline-start;margin-bottom:var(--vui-annotate-target-gap)}.viraui__annotate-module__Annotate_7C36U[data-side=top-end]{--_annotate-tail-x:40px;--_annotate-tail-y:6px;--_annotate-note-align-x:-50%;--_annotate-note-align-y:calc(-100% - var(--vui-annotate-label-gap))}.viraui__annotate-module__Annotate_7C36U[data-side=top-end] .viraui__annotate-module__Arrow_T4B-6{--_annotate-arrow-mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='46' height='38' viewBox='0 0 46 38'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M40 6C30 8 18 20 6 32'/%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M10 22 6 32l10-4'/%3E%3C/svg%3E");position-area:block-start inline-end;margin-bottom:var(--vui-annotate-target-gap)}.viraui__annotate-module__Annotate_7C36U[data-side=bottom]{--_annotate-tail-x:23px;--_annotate-tail-y:35px;--_annotate-note-align-x:-50%;--_annotate-note-align-y:var(--vui-annotate-label-gap)}.viraui__annotate-module__Annotate_7C36U[data-side=bottom] .viraui__annotate-module__Arrow_T4B-6{--_annotate-arrow-mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='46' height='38' viewBox='0 0 46 38'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M23 35c-1-9-1-20 0-31'/%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m17 10 6-7 6 7'/%3E%3C/svg%3E");position-area:block-end;margin-top:var(--vui-annotate-target-gap)}.viraui__annotate-module__Annotate_7C36U[data-side=bottom-start]{--_annotate-tail-x:6px;--_annotate-tail-y:32px;--_annotate-note-align-x:-50%;--_annotate-note-align-y:var(--vui-annotate-label-gap)}.viraui__annotate-module__Annotate_7C36U[data-side=bottom-start] .viraui__annotate-module__Arrow_T4B-6{--_annotate-arrow-mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='46' height='38' viewBox='0 0 46 38'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M6 32c10-2 22-14 34-26'/%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m30 10 10-4-4 10'/%3E%3C/svg%3E");position-area:block-end inline-start;margin-top:var(--vui-annotate-target-gap)}.viraui__annotate-module__Annotate_7C36U[data-side=bottom-end]{--_annotate-tail-x:40px;--_annotate-tail-y:32px;--_annotate-note-align-x:-50%;--_annotate-note-align-y:var(--vui-annotate-label-gap)}.viraui__annotate-module__Annotate_7C36U[data-side=bottom-end] .viraui__annotate-module__Arrow_T4B-6{--_annotate-arrow-mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='46' height='38' viewBox='0 0 46 38'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M40 32C30 30 18 18 6 6'/%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M16 10 6 6l4 10'/%3E%3C/svg%3E");position-area:block-end inline-end;margin-top:var(--vui-annotate-target-gap)}.viraui__annotate-module__Annotate_7C36U[data-side=start]{--_annotate-tail-x:4px;--_annotate-tail-y:19px;--_annotate-note-align-x:calc(-100% - var(--vui-annotate-label-gap));--_annotate-note-align-y:-50%}.viraui__annotate-module__Annotate_7C36U[data-side=start] .viraui__annotate-module__Arrow_T4B-6{--_annotate-arrow-mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='46' height='38' viewBox='0 0 46 38'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M4 19c11-1 27-1 39 0'/%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m36 13 7 6-7 6'/%3E%3C/svg%3E");position-area:inline-start;margin-inline-end:var(--vui-annotate-target-gap)}.viraui__annotate-module__Annotate_7C36U[data-side=end]{--_annotate-tail-x:43px;--_annotate-tail-y:19px;--_annotate-note-align-x:var(--vui-annotate-label-gap);--_annotate-note-align-y:-50%}.viraui__annotate-module__Annotate_7C36U[data-side=end] .viraui__annotate-module__Arrow_T4B-6{--_annotate-arrow-mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='46' height='38' viewBox='0 0 46 38'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-width='1.5' d='M43 19c-11-1-28-1-40 0'/%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m10 13-7 6 7 6'/%3E%3C/svg%3E");position-area:inline-end;margin-inline-start:var(--vui-annotate-target-gap)}}
|
|
@@ -11,11 +11,11 @@ export type AnnotateSide = 'top-start' | 'top' | 'top-end' | 'end' | 'bottom-end
|
|
|
11
11
|
*/
|
|
12
12
|
export type AnnotateProps = React.ComponentPropsWithRef<'span'> & {
|
|
13
13
|
/**
|
|
14
|
-
* Decorative label rendered
|
|
14
|
+
* Decorative label rendered in a presentational note span (not announced).
|
|
15
15
|
*
|
|
16
|
-
* Do not put critical information here — assistive tech does not announce the
|
|
16
|
+
* Do not put critical information here — assistive tech does not announce the note.
|
|
17
17
|
*
|
|
18
|
-
* @default No note; arrow and label
|
|
18
|
+
* @default No note; arrow and label stay hidden.
|
|
19
19
|
*/
|
|
20
20
|
note?: string;
|
|
21
21
|
/**
|
|
@@ -27,7 +27,7 @@ export type AnnotateProps = React.ComponentPropsWithRef<'span'> & {
|
|
|
27
27
|
/**
|
|
28
28
|
* Highlight token driving arrow, label, and optional mark color via `--vui-annotate-color`.
|
|
29
29
|
*
|
|
30
|
-
* @default
|
|
30
|
+
* @default `var(--global-foreground)` when omitted
|
|
31
31
|
*/
|
|
32
32
|
color?: ThemeTypes['highlight'];
|
|
33
33
|
/**
|
|
@@ -84,5 +84,18 @@ export type AnnotateProps = React.ComponentPropsWithRef<'span'> & {
|
|
|
84
84
|
* @default `300px`
|
|
85
85
|
*/
|
|
86
86
|
labelMaxWidth?: string;
|
|
87
|
+
/**
|
|
88
|
+
* Stacking order for arrow and note via `--vui-annotate-z-index`.
|
|
89
|
+
* Same value on both parts.
|
|
90
|
+
*
|
|
91
|
+
* @default undefined (`auto`)
|
|
92
|
+
*/
|
|
93
|
+
zIndex?: React.CSSProperties['zIndex'];
|
|
94
|
+
/**
|
|
95
|
+
* Text alignment for the note via `--vui-annotate-text-align`.
|
|
96
|
+
*
|
|
97
|
+
* @default undefined (`start`)
|
|
98
|
+
*/
|
|
99
|
+
textAlign?: React.CSSProperties['textAlign'];
|
|
87
100
|
};
|
|
88
101
|
export declare const Annotate: React.FC<AnnotateProps>;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Annotate",
|
|
3
|
-
"
|
|
3
|
+
"structure": "<Annotate note=\"…\">…<span aria-hidden className={Arrow} /><span aria-hidden className={Note}>{note}</span></Annotate>",
|
|
4
|
+
"summary": "Decorative arrow and handwritten label that wraps inline content with optional highlighter mark, positioned via CSS anchor positioning.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Call out a word or phrase in marketing, docs, or onboarding copy",
|
|
6
|
-
"Add a playful visual annotation without
|
|
7
|
+
"Add a playful visual annotation without interactive chrome",
|
|
7
8
|
"Highlight a target with an optional mark while keeping children as the real content"
|
|
8
9
|
],
|
|
9
10
|
"whenNotToUse": [
|
|
@@ -12,40 +13,41 @@
|
|
|
12
13
|
"Layouts that clip overflow and cannot leave room for the arrow and label"
|
|
13
14
|
],
|
|
14
15
|
"accessibility": [
|
|
15
|
-
"Arrow and
|
|
16
|
+
"Arrow and note are presentational spans with aria-hidden — decorative only and not exposed to assistive tech",
|
|
16
17
|
"Do not put critical information in note; keep real meaning in children or aria-describedby content",
|
|
17
18
|
"Children retain native semantics; Annotate itself is a presentational span wrap"
|
|
18
19
|
],
|
|
19
20
|
"antiPatterns": [
|
|
20
21
|
"Using note as the only source of instructions or status",
|
|
21
22
|
"Nesting Annotate inside overflow-hidden parents without padding for the arrow",
|
|
22
|
-
"Expecting the label to participate in hit-testing or selection"
|
|
23
|
+
"Expecting the label to participate in hit-testing or selection",
|
|
24
|
+
"Adding position:relative on Annotate — it breaks CSS anchor position-area placement"
|
|
23
25
|
],
|
|
24
26
|
"related": ["Text", "Title", "Tooltip", "Chip"],
|
|
25
27
|
"properties": {
|
|
26
28
|
"react": {
|
|
27
29
|
"color": {
|
|
28
|
-
"description": "Highlight token driving arrow, label, and optional mark color via --vui-annotate-color.",
|
|
30
|
+
"description": "Highlight token driving arrow, label, and optional mark color via --vui-annotate-color. When omitted, falls back to var(--global-foreground).",
|
|
29
31
|
"refCss": "color"
|
|
30
32
|
},
|
|
31
33
|
"arrowOffsetX": {
|
|
32
|
-
"description": "Horizontal offset for the arrow
|
|
34
|
+
"description": "Horizontal offset for the arrow part.",
|
|
33
35
|
"refCss": "arrow-x"
|
|
34
36
|
},
|
|
35
37
|
"arrowOffsetY": {
|
|
36
|
-
"description": "Vertical offset for the arrow
|
|
38
|
+
"description": "Vertical offset for the arrow part.",
|
|
37
39
|
"refCss": "arrow-y"
|
|
38
40
|
},
|
|
39
41
|
"textOffsetX": {
|
|
40
|
-
"description": "Horizontal offset for the
|
|
42
|
+
"description": "Horizontal offset for the note part.",
|
|
41
43
|
"refCss": "text-x"
|
|
42
44
|
},
|
|
43
45
|
"textOffsetY": {
|
|
44
|
-
"description": "Vertical offset for the
|
|
46
|
+
"description": "Vertical offset for the note part.",
|
|
45
47
|
"refCss": "text-y"
|
|
46
48
|
},
|
|
47
49
|
"rotate": {
|
|
48
|
-
"description": "Rotation for the
|
|
50
|
+
"description": "Rotation for the note via --vui-annotate-rotate.",
|
|
49
51
|
"refCss": "rotate"
|
|
50
52
|
},
|
|
51
53
|
"targetGap": {
|
|
@@ -53,17 +55,25 @@
|
|
|
53
55
|
"refCss": "target-gap"
|
|
54
56
|
},
|
|
55
57
|
"labelGap": {
|
|
56
|
-
"description": "Gap between arrow and
|
|
58
|
+
"description": "Gap between arrow and note on all sides.",
|
|
57
59
|
"refCss": "label-gap"
|
|
58
60
|
},
|
|
59
61
|
"labelMaxWidth": {
|
|
60
|
-
"description": "Max width for the
|
|
62
|
+
"description": "Max width for the note part.",
|
|
61
63
|
"refCss": "label-max-width"
|
|
64
|
+
},
|
|
65
|
+
"zIndex": {
|
|
66
|
+
"description": "Stacking order for arrow and note via --vui-annotate-z-index. Same value on both. When omitted, auto.",
|
|
67
|
+
"refCss": "z-index"
|
|
68
|
+
},
|
|
69
|
+
"textAlign": {
|
|
70
|
+
"description": "Text alignment for the note via --vui-annotate-text-align. When omitted, start.",
|
|
71
|
+
"refCss": "text-align"
|
|
62
72
|
}
|
|
63
73
|
},
|
|
64
74
|
"css": {
|
|
65
75
|
"color": {
|
|
66
|
-
"description": "Arrow,
|
|
76
|
+
"description": "Arrow, note, and mark accent color. Defaults to var(--global-foreground).",
|
|
67
77
|
"refReact": "color"
|
|
68
78
|
},
|
|
69
79
|
"arrow-x": {
|
|
@@ -75,15 +85,15 @@
|
|
|
75
85
|
"refReact": "arrowOffsetY"
|
|
76
86
|
},
|
|
77
87
|
"text-x": {
|
|
78
|
-
"description": "Horizontal
|
|
88
|
+
"description": "Horizontal note offset.",
|
|
79
89
|
"refReact": "textOffsetX"
|
|
80
90
|
},
|
|
81
91
|
"text-y": {
|
|
82
|
-
"description": "Vertical
|
|
92
|
+
"description": "Vertical note offset.",
|
|
83
93
|
"refReact": "textOffsetY"
|
|
84
94
|
},
|
|
85
95
|
"rotate": {
|
|
86
|
-
"description": "
|
|
96
|
+
"description": "Note rotation angle.",
|
|
87
97
|
"refReact": "rotate"
|
|
88
98
|
},
|
|
89
99
|
"target-gap": {
|
|
@@ -91,12 +101,20 @@
|
|
|
91
101
|
"refReact": "targetGap"
|
|
92
102
|
},
|
|
93
103
|
"label-gap": {
|
|
94
|
-
"description": "Gap between arrow and
|
|
104
|
+
"description": "Gap between arrow and note on all sides.",
|
|
95
105
|
"refReact": "labelGap"
|
|
96
106
|
},
|
|
97
107
|
"label-max-width": {
|
|
98
|
-
"description": "Max width for the
|
|
108
|
+
"description": "Max width for the note part.",
|
|
99
109
|
"refReact": "labelMaxWidth"
|
|
110
|
+
},
|
|
111
|
+
"z-index": {
|
|
112
|
+
"description": "Stacking order for arrow and note. Defaults to auto.",
|
|
113
|
+
"refReact": "zIndex"
|
|
114
|
+
},
|
|
115
|
+
"text-align": {
|
|
116
|
+
"description": "Text alignment for the note. Defaults to start.",
|
|
117
|
+
"refReact": "textAlign"
|
|
100
118
|
}
|
|
101
119
|
}
|
|
102
120
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import './annotate.css';
|
|
2
2
|
import { clsx } from "../../core/clsx.js";
|
|
3
3
|
import annotate_module_default from "./annotate.module.js";
|
|
4
|
-
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/annotate/annotate.tsx
|
|
6
|
-
var Annotate = ({ arrowOffsetX, arrowOffsetY, children, className, color
|
|
6
|
+
var Annotate = ({ arrowOffsetX, arrowOffsetY, children, className, color, labelGap, labelMaxWidth = "300px", mark = false, note, ref, rotate, side = "top", style, targetGap, textAlign, textOffsetX, textOffsetY, zIndex, ...otherProps }) => {
|
|
7
7
|
const dynamicStyle = {
|
|
8
8
|
...color && { "--vui-annotate-color": `var(--highlight-${color})` },
|
|
9
9
|
...arrowOffsetX && { "--vui-annotate-arrow-x": arrowOffsetX },
|
|
@@ -14,17 +14,25 @@ var Annotate = ({ arrowOffsetX, arrowOffsetY, children, className, color = "yell
|
|
|
14
14
|
...targetGap && { "--vui-annotate-target-gap": targetGap },
|
|
15
15
|
...labelGap && { "--vui-annotate-label-gap": labelGap },
|
|
16
16
|
...labelMaxWidth && { "--vui-annotate-label-max-width": labelMaxWidth },
|
|
17
|
+
...zIndex != null && { "--vui-annotate-z-index": zIndex },
|
|
18
|
+
...textAlign && { "--vui-annotate-text-align": textAlign },
|
|
17
19
|
...style
|
|
18
20
|
};
|
|
19
|
-
return /* @__PURE__ */
|
|
21
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
20
22
|
...otherProps,
|
|
21
23
|
ref,
|
|
22
24
|
className: clsx(annotate_module_default.Annotate, className),
|
|
23
25
|
"data-mark": mark ? "true" : void 0,
|
|
24
|
-
"data-note": note,
|
|
25
26
|
"data-side": side,
|
|
26
27
|
style: dynamicStyle,
|
|
27
|
-
children
|
|
28
|
+
children: [children, note && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
29
|
+
"aria-hidden": true,
|
|
30
|
+
className: annotate_module_default.Arrow
|
|
31
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
32
|
+
"aria-hidden": true,
|
|
33
|
+
className: annotate_module_default.Note,
|
|
34
|
+
children: note
|
|
35
|
+
})] })]
|
|
28
36
|
});
|
|
29
37
|
};
|
|
30
38
|
//#endregion
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
//#region src/components/annotate/annotate.module.css
|
|
2
2
|
var Annotate = "viraui__annotate-module__Annotate_7C36U";
|
|
3
|
-
var
|
|
3
|
+
var Arrow = "viraui__annotate-module__Arrow_T4B-6";
|
|
4
|
+
var Note = "viraui__annotate-module__Note_8UW-R";
|
|
5
|
+
var annotate_module_default = {
|
|
6
|
+
Annotate,
|
|
7
|
+
Arrow,
|
|
8
|
+
Note
|
|
9
|
+
};
|
|
4
10
|
//#endregion
|
|
5
|
-
export { Annotate, annotate_module_default as default };
|
|
11
|
+
export { Annotate, Arrow, Note, annotate_module_default as default };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "AvatarGroup",
|
|
3
|
+
"structure": "<AvatarGroup avatars={[{ fallback: \"AB\" }]} />",
|
|
3
4
|
"summary": "Overlapping avatar stack with shared sizing, directional layout, and an optional overflow pill.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Show a compact list of people or entities with consistent avatar sizing",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-badge-size{syntax:"<length>";inherits:true;initial-value:12px}@property --vui-badge-color{syntax:"<color>";inherits:true;initial-value:#292929}@property --_badge-hole-progress{syntax:"<number>";inherits:true;initial-value:0}.viraui__badge-module__Badge_lJqlY{--vui-badge-color:var(--global-primary);--vui-badge-size:0.074rem;--vui-badge-position-x:100%;--vui-badge-position-y:0%;--_badge-gap:calc(var(--vui-badge-size) * 0.25);--_badge-mask-size:calc(var(--vui-badge-size) / 2 + var(--_badge-gap));--_badge-hole-progress:0;position:relative;display:inline-flex;&[data-position=top-end]{--vui-badge-position-x:100%;--vui-badge-position-y:0%}&[data-position=top-start]{--vui-badge-position-x:0%;--vui-badge-position-y:0%}&[data-position=bottom-end]{--vui-badge-position-x:100%;--vui-badge-position-y:100%}&[data-position=bottom-start]{--vui-badge-position-x:0%;--vui-badge-position-y:100%}&>*{outline-offset:-4px}&[data-show=true]{&:after{content:"";width:var(--vui-badge-size);aspect-ratio:1;display:block;border-radius:100000px;background:var(--vui-badge-color);position:absolute;left:calc(var(--vui-badge-position-x) - min(var(--vui-badge-position-x), var(--vui-badge-size)));top:calc(var(--vui-badge-position-y) - min(var(--vui-badge-position-y), var(--vui-badge-size)));pointer-events:none;transform-origin:center}&:not([data-exit]):after{transform:scale(0);animation:viraui__badge-module__badge-dot-in_SKMx8 var(--duration-fast) var(--easing-entrance) 60ms forwards}&[data-exit]:after{transform:scale(1);animation:viraui__badge-module__badge-dot-out_vWhcP var(--duration-fast) var(--easing-entrance) forwards}&>*{mask-image:radial-gradient(circle at calc(var(--vui-badge-position-x) - min(var(--vui-badge-position-x), var(--vui-badge-size)) + (var(--vui-badge-size) / 2)) calc(var(--vui-badge-position-y) - min(var(--vui-badge-position-y), var(--vui-badge-size)) + (var(--vui-badge-size) / 2)),#0000 0 calc(var(--_badge-mask-size) * var(--_badge-hole-progress)),red calc(var(--_badge-mask-size) * var(--_badge-hole-progress) + 1px))}&:not([data-exit])>*{animation:viraui__badge-module__badge-hole-in_71iZP var(--duration-fast) var(--easing-entrance) forwards}&[data-exit]>*{--_badge-hole-progress:1;animation:viraui__badge-module__badge-hole-out_JCHCf var(--duration-fast) var(--easing-entrance) 60ms forwards}@media (prefers-reduced-motion:reduce){&:after{transform:none}&:after,&>*{animation:none}&>*{--_badge-hole-progress:1}&[data-exit]>*{--_badge-hole-progress:0}}}}@keyframes viraui__badge-module__badge-hole-in_71iZP{0%{--_badge-hole-progress:0}to{--_badge-hole-progress:1}}@keyframes viraui__badge-module__badge-hole-out_JCHCf{0%{--_badge-hole-progress:1}to{--_badge-hole-progress:0}}@keyframes viraui__badge-module__badge-dot-in_SKMx8{0%{transform:scale(0)}to{transform:scale(1)}}@keyframes viraui__badge-module__badge-dot-out_vWhcP{0%{transform:scale(1)}to{transform:scale(0)}}}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ThemeTypes } from '@viraui/foundation/vira/types';
|
|
2
|
+
import type * as React from 'react';
|
|
3
|
+
export type BadgePosition = 'top-end' | 'top-start' | 'bottom-end' | 'bottom-start';
|
|
4
|
+
/**
|
|
5
|
+
* Public Badge props.
|
|
6
|
+
*
|
|
7
|
+
* Includes standard `div` attributes such as `children`, `id`, `className`, and event handlers,
|
|
8
|
+
* plus Vira-owned decorative status-dot controls.
|
|
9
|
+
*
|
|
10
|
+
* @default Native div pass-through props keep React defaults.
|
|
11
|
+
*/
|
|
12
|
+
export type BadgeProps = React.ComponentPropsWithRef<'div'> & {
|
|
13
|
+
/**
|
|
14
|
+
* Diameter of the status dot via `--vui-badge-size`.
|
|
15
|
+
*
|
|
16
|
+
* @default '12px'
|
|
17
|
+
*/
|
|
18
|
+
size?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Highlight token driving the status-dot color via `--vui-badge-color`.
|
|
21
|
+
*
|
|
22
|
+
* @default `var(--global-primary)` when omitted
|
|
23
|
+
*/
|
|
24
|
+
color?: ThemeTypes['highlight'];
|
|
25
|
+
/**
|
|
26
|
+
* When true, shows the decorative status dot and applies the radial mask cutout.
|
|
27
|
+
* Enter: hole expands, then the dot scales in. Exit: reverse (dot then hole).
|
|
28
|
+
*
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
show?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Places the status dot on a corner of the wrapped content.
|
|
34
|
+
*
|
|
35
|
+
* @default 'top-end'
|
|
36
|
+
*/
|
|
37
|
+
position?: BadgePosition;
|
|
38
|
+
};
|
|
39
|
+
export declare const Badge: React.FC<BadgeProps>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Badge",
|
|
3
|
+
"structure": "<Badge>{child}</Badge>",
|
|
4
|
+
"summary": "Decorative status-dot overlay that wraps a child, with optional radial mask cutout on the child around the corner dot.",
|
|
5
|
+
"whenToUse": [
|
|
6
|
+
"Show online/offline or presence on an Avatar or icon without changing the child component API",
|
|
7
|
+
"Mark a control as needing attention with a small corner indicator",
|
|
8
|
+
"Keep Chip for labeled text badges; use Badge only for the status-dot overlay"
|
|
9
|
+
],
|
|
10
|
+
"whenNotToUse": [
|
|
11
|
+
"Conveying critical status that assistive tech must announce — put real meaning in the child name or nearby text",
|
|
12
|
+
"Labeled text badges or tags — use Chip",
|
|
13
|
+
"Count or text inside a pill — out of scope for v1"
|
|
14
|
+
],
|
|
15
|
+
"accessibility": [
|
|
16
|
+
"The status dot is a decorative ::after pseudo — not exposed to assistive tech",
|
|
17
|
+
"Do not rely on the dot alone for status; keep real meaning in the child's accessible name or nearby text",
|
|
18
|
+
"Children retain native semantics; Badge itself is a presentational div wrap",
|
|
19
|
+
"Enter/exit motion (hole↔dot, reverse on hide) is suppressed under prefers-reduced-motion"
|
|
20
|
+
],
|
|
21
|
+
"antiPatterns": [
|
|
22
|
+
"Using the visible dot as the only source of status for assistive tech",
|
|
23
|
+
"Wrapping multiple element children when only one should receive the radial mask cutout",
|
|
24
|
+
"Expecting the dot to participate in hit-testing"
|
|
25
|
+
],
|
|
26
|
+
"related": ["Avatar", "AvatarGroup", "Chip", "Annotate"],
|
|
27
|
+
"properties": {
|
|
28
|
+
"react": {
|
|
29
|
+
"size": {
|
|
30
|
+
"description": "Diameter of the status dot via --vui-badge-size. Defaults to 12px.",
|
|
31
|
+
"refCss": "size"
|
|
32
|
+
},
|
|
33
|
+
"color": {
|
|
34
|
+
"description": "Highlight token driving the status-dot color via --vui-badge-color. When omitted, falls back to var(--global-primary).",
|
|
35
|
+
"refCss": "color"
|
|
36
|
+
},
|
|
37
|
+
"show": {
|
|
38
|
+
"description": "When true, shows the decorative status dot and applies the radial mask cutout to the direct child. Enter: hole expands from center, then the dot scales in. Exit: reverse (dot then hole). Defaults to false."
|
|
39
|
+
},
|
|
40
|
+
"position": {
|
|
41
|
+
"description": "Corner placement for the status dot (top-end, top-start, bottom-end, bottom-start). Defaults to top-end."
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"css": {
|
|
45
|
+
"size": {
|
|
46
|
+
"description": "Status-dot diameter. Defaults to 12px.",
|
|
47
|
+
"refReact": "size"
|
|
48
|
+
},
|
|
49
|
+
"color": {
|
|
50
|
+
"description": "Status-dot accent color. Defaults to var(--global-primary).",
|
|
51
|
+
"refReact": "color"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import './badge.css';
|
|
2
|
+
import { clsx } from "../../core/clsx.js";
|
|
3
|
+
import badge_module_default from "./badge.module.js";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { useEffect, useState } from "react";
|
|
6
|
+
//#region src/components/badge/badge.tsx
|
|
7
|
+
var prefersReducedMotion = () => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
8
|
+
var Badge = ({ size = "10px", children, className, color, position = "top-end", ref, show = false, style, ...otherProps }) => {
|
|
9
|
+
const [present, setPresent] = useState(show);
|
|
10
|
+
const [exiting, setExiting] = useState(false);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (show) {
|
|
13
|
+
setPresent(true);
|
|
14
|
+
setExiting(false);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (!present) return;
|
|
18
|
+
if (prefersReducedMotion()) {
|
|
19
|
+
setPresent(false);
|
|
20
|
+
setExiting(false);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
setExiting(true);
|
|
24
|
+
}, [show, present]);
|
|
25
|
+
const handleAnimationEnd = (event) => {
|
|
26
|
+
if (!exiting) return;
|
|
27
|
+
if (!(event.target instanceof HTMLElement) || event.target.parentElement !== event.currentTarget) return;
|
|
28
|
+
if (!event.animationName.includes("badge-hole-out")) return;
|
|
29
|
+
setPresent(false);
|
|
30
|
+
setExiting(false);
|
|
31
|
+
};
|
|
32
|
+
const dynamicStyle = {
|
|
33
|
+
"--vui-badge-size": size,
|
|
34
|
+
...color && { "--vui-badge-color": `var(--highlight-${color})` },
|
|
35
|
+
...style
|
|
36
|
+
};
|
|
37
|
+
return /* @__PURE__ */ jsx("div", {
|
|
38
|
+
...otherProps,
|
|
39
|
+
ref,
|
|
40
|
+
className: clsx(badge_module_default.Badge, className),
|
|
41
|
+
"data-exit": exiting ? "true" : void 0,
|
|
42
|
+
"data-position": position,
|
|
43
|
+
"data-show": present ? "true" : void 0,
|
|
44
|
+
style: dynamicStyle,
|
|
45
|
+
onAnimationEnd: handleAnimationEnd,
|
|
46
|
+
children
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
export { Badge };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/components/badge/badge.module.css
|
|
2
|
+
var Badge = "viraui__badge-module__Badge_lJqlY";
|
|
3
|
+
var badge_module_default = {
|
|
4
|
+
Badge,
|
|
5
|
+
"badge-dot-in": "viraui__badge-module__badge-dot-in_SKMx8",
|
|
6
|
+
"badge-dot-out": "viraui__badge-module__badge-dot-out_vWhcP",
|
|
7
|
+
"badge-hole-in": "viraui__badge-module__badge-hole-in_71iZP",
|
|
8
|
+
"badge-hole-out": "viraui__badge-module__badge-hole-out_JCHCf"
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { Badge, badge_module_default as default };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ButtonLink",
|
|
3
|
+
"structure": "<ButtonLink href=\"#\">Save</ButtonLink>",
|
|
3
4
|
"summary": "Navigation link that shares Button visual chrome (--vui-button-* CSS) and default a root with optional render for framework Link.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Actions that navigate (href or router Link) but should look like Button",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ButtonChromeChildren, getButtonChromeRootAttrs } from "./button-chrome.js";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useRender } from "@base-ui/react/use-render";
|
|
4
3
|
import "react";
|
|
4
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
5
5
|
//#region src/components/button/button-link.tsx
|
|
6
6
|
var ButtonLink = ({ children, className, disabled = false, addon, addonPosition = "start", loading = false, pill = false, size = "medium", variant = "primary", render, ref, onClick, ...otherProps }) => {
|
|
7
7
|
const isDisabled = disabled || loading;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import './button.css';
|
|
2
2
|
import { ButtonChromeChildren, getButtonChromeRootAttrs } from "./button-chrome.js";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import * as React from "react";
|
|
4
5
|
import { Button } from "@base-ui/react/button";
|
|
5
6
|
import { useRender } from "@base-ui/react/use-render";
|
|
6
|
-
import * as React from "react";
|
|
7
7
|
//#region src/components/button/button.tsx
|
|
8
8
|
function usesButtonPrimitiveRender(render) {
|
|
9
9
|
return render === void 0 || React.isValidElement(render) && render.type === "button";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Checkbox",
|
|
3
|
+
"structure": "<Checkbox label=\"…\" />",
|
|
3
4
|
"summary": "Field.Item checkbox option for standalone fields or CheckboxGroup children.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Single boolean fields wrapped in Field.Root with optional label and helper text — no Fieldset required",
|
|
@@ -3,8 +3,8 @@ import { clsx } from "../../core/clsx.js";
|
|
|
3
3
|
import { Stack } from "../stack/stack.js";
|
|
4
4
|
import chip_module_default from "./chip.module.js";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
import { useRender } from "@base-ui/react/use-render";
|
|
7
6
|
import "react";
|
|
7
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
8
8
|
//#region src/components/chip/chip.tsx
|
|
9
9
|
var Chip = ({ addon, addonPosition = "start", children, className, ref, render, variant = "primary", ...otherProps }) => {
|
|
10
10
|
const content = /* @__PURE__ */ jsxs(Stack, {
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import './clamp-text.css';
|
|
3
3
|
import { clsx } from "../../core/clsx.js";
|
|
4
4
|
import clamp_text_module_default from "./clamp-text.module.js";
|
|
5
|
-
import { useRender } from "@base-ui/react/use-render";
|
|
6
5
|
import { useMemo } from "react";
|
|
6
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
7
7
|
//#region src/components/clamp-text/clamp-text.tsx
|
|
8
8
|
var ClampText = ({ className, inline = false, ref, render, rows = 1, style, ...otherProps }) => {
|
|
9
9
|
const dynamicStyle = useMemo(() => ({ "--vui-clamp-text-rows": rows }), [rows]);
|
|
@@ -49,7 +49,7 @@ var DialogSheet = ({ children, description, title, showCloseButton = false, fitC
|
|
|
49
49
|
hPadding: "medium",
|
|
50
50
|
fillChildren: false,
|
|
51
51
|
children: [/* @__PURE__ */ jsx(Drawer.Title, {
|
|
52
|
-
render: /* @__PURE__ */ jsx(Title, {
|
|
52
|
+
render: /* @__PURE__ */ jsx(Title, { size: "4" }),
|
|
53
53
|
children: title
|
|
54
54
|
}), description && /* @__PURE__ */ jsx(Drawer.Description, {
|
|
55
55
|
render: /* @__PURE__ */ jsx(Text, {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Dialog",
|
|
3
|
+
"structure": "<Dialog>\n <Dialog.Trigger />\n <Dialog.Sheet title=\"…\">…</Dialog.Sheet>\n</Dialog>",
|
|
3
4
|
"summary": "Compound drawer sheet with `Dialog.Trigger`, `Dialog.Sheet`, `Dialog.Close`, and Base UI pass-through `Dialog.Provider`, `Dialog.Indent`, and `Dialog.IndentBackground` for app-shell indent effects.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Focused tasks or confirmations that interrupt the current page without navigation",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Fieldset",
|
|
3
|
+
"structure": "<Fieldset label=\"…\">…</Fieldset>",
|
|
3
4
|
"summary": "Semantic field grouping with shared legend and optional group helper copy.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Section legends for multiple related fields — billing details with Textfield, Textarea, or Select children",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "IconButtonLink",
|
|
3
|
+
"structure": "<IconButtonLink href=\"#\" icon={<Plus />} aria-label=\"Add\" />",
|
|
3
4
|
"summary": "Icon-only navigation link that requires an accessible name; wraps ButtonLink.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Compact toolbar or chrome navigation identified only by icon",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "IconButton",
|
|
3
|
+
"structure": "<IconButton icon={<Plus />} aria-label=\"Add\" />",
|
|
3
4
|
"summary": "Icon-only button that requires an accessible name through aria-label or aria-labelledby.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Compact toolbar or chrome actions identified only by icon",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "LinearProgress",
|
|
3
|
+
"structure": "<LinearProgress value={40} />",
|
|
3
4
|
"summary": "Shows determinate or indeterminate progress for a task in a compact horizontal track.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Use for task completion with a known percentage or bounded numeric value.",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Masonry",
|
|
3
|
+
"structure": "<Masonry>\n <Masonry.Item>…</Masonry.Item>\n</Masonry>",
|
|
3
4
|
"summary": "Responsive React-column layout primitive for read-only mixed-height content walls.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Card walls, gallery-like collections, and editorial layouts with uneven item heights",
|
|
@@ -6,8 +6,8 @@ import { Stack } from "../stack/stack.js";
|
|
|
6
6
|
import masonry_module_default from "./masonry.module.js";
|
|
7
7
|
import { MasonryItem } from "./masonry-item.js";
|
|
8
8
|
import { jsx } from "react/jsx-runtime";
|
|
9
|
-
import { useRender } from "@base-ui/react/use-render";
|
|
10
9
|
import { Children, useEffect, useRef, useState } from "react";
|
|
10
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
11
11
|
//#region src/components/masonry/masonry.tsx
|
|
12
12
|
var DEFAULT_BREAKPOINT_COLS = {
|
|
13
13
|
default: 1,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Meter",
|
|
3
|
+
"structure": "<Meter value={40} />",
|
|
3
4
|
"summary": "Shows a determinate metric in a compact horizontal track for static capacity, level, or score values.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Use for storage usage, battery level, capacity, or score within a known range.",
|
|
@@ -48,7 +48,7 @@ var PopoverSheet = ({ unstyled, title, description, children, showCloseButton =
|
|
|
48
48
|
children: [/* @__PURE__ */ jsx(Popover.Title, {
|
|
49
49
|
render: /* @__PURE__ */ jsx(Title, {
|
|
50
50
|
align: headerAlign,
|
|
51
|
-
|
|
51
|
+
size: "6",
|
|
52
52
|
lineHeight: "x-small"
|
|
53
53
|
}),
|
|
54
54
|
children: title
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Popover",
|
|
3
|
+
"structure": "<Popover>\n <Popover.Trigger />\n <Popover.Sheet title=\"…\">…</Popover.Sheet>\n</Popover>",
|
|
3
4
|
"summary": "Compound popover built on Base UI Popover with `Popover.Trigger`, `Popover.Sheet`, `Popover.Close`, `Popover.Title`, `Popover.Description`, and `Popover.createHandle` for detached and multiple triggers; `Sheet` encapsulates Portal + Positioner + Popup + Viewport + Title + Description and animates position, size, and content between triggers; `Sheet` with `unstyled` skips the built-in Surface and header so the consumer composes the popup chrome, including `Popover.Title` and `Popover.Description`.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Anchored quick actions or contextual hints next to a triggering control",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ProgressiveBlur",
|
|
3
|
+
"structure": "<ProgressiveBlur />",
|
|
3
4
|
"summary": "Decorative stacked backdrop-filter overlay that ramps blur from one edge toward the opposite edge.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Edge scrims on cards, sheets, heroes, or scroll regions where content should fade into blur",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Radio",
|
|
3
|
+
"structure": "<RadioGroup>\n <Radio value=\"…\" label=\"…\" />\n</RadioGroup>",
|
|
3
4
|
"summary": "Mutually exclusive choice within a RadioGroup, with optional per-option label and helper text.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Single selection from a small set of related options inside RadioGroup",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Select",
|
|
3
|
+
"structure": "<Select>\n <Select.Option value=\"…\">…</Select.Option>\n <Select.Group label=\"…\">\n <Select.Option value=\"…\">…</Select.Option>\n </Select.Group>\n <Select.Separator />\n</Select>",
|
|
3
4
|
"summary": "Field-wrapped single-select dropdown with grouped options and field copy.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Choose one value from a predefined list with label and helper copy",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-stack-row-gap{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-column-gap{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-h-align{syntax:"*";inherits:false;initial-value:initial}@property --vui-stack-v-align{syntax:"*";inherits:false;initial-value:initial}@property --vui-stack-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-max-width{syntax:"*";inherits:false;initial-value:none}@property --vui-stack-min-width{syntax:"*";inherits:false;initial-value:none}.viraui__stack-module__Stack_NR-Ey{
|
|
1
|
+
@layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-stack-row-gap{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-column-gap{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-h-align{syntax:"*";inherits:false;initial-value:initial}@property --vui-stack-v-align{syntax:"*";inherits:false;initial-value:initial}@property --vui-stack-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-max-width{syntax:"*";inherits:false;initial-value:none}@property --vui-stack-min-width{syntax:"*";inherits:false;initial-value:none}.viraui__stack-module__Stack_NR-Ey{display:flex;gap:var(--vui-stack-row-gap) var(--vui-stack-column-gap);flex-direction:column;align-items:var(--vui-stack-h-align);justify-content:var(--vui-stack-v-align);max-inline-size:var(--vui-stack-max-width);min-inline-size:var(--vui-stack-min-width);&[data-stack-direction=column-reverse]{flex-direction:column-reverse}&[data-stack-direction=row-reverse],&[data-stack-direction=row]{align-items:var(--vui-stack-v-align);justify-content:var(--vui-stack-h-align)}&[data-stack-direction=row]{flex-direction:row}&[data-stack-direction=row-reverse]{flex-direction:row-reverse}&[data-stack-inline=true]{display:inline-flex;flex-grow:0}:where(&[data-stack-wrap=true]){flex-wrap:wrap}:where(&[data-stack-has-padding=true]){padding:var(--vui-stack-padding-block-start) var(--vui-stack-padding-inline-end) var(--vui-stack-padding-block-end) var(--vui-stack-padding-inline-start)}:where(&[data-stack-fill-children=true]>*){flex-grow:var(--vira-flex-grow,1)}}}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Stack",
|
|
3
|
+
"structure": "<Stack>…</Stack>",
|
|
3
4
|
"summary": "Flex layout primitive for arranging children with token spacing, alignment, and padding; root is a named CSS container query context (`stack`).",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Column or row layouts with token gap and alignment",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-surface-background{syntax:"*";inherits:false;initial-value:none}@property --vui-surface-background-hover{syntax:"*";inherits:false;initial-value:none}@property --vui-surface-border-style{syntax:"<custom-ident>";inherits:false;initial-value:solid}@property --vui-surface-overflow{syntax:"<custom-ident>";inherits:false;initial-value:visible}@property --vui-surface-border-radius{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-top-left{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-top-right{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-bottom-right{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-bottom-left{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-surface-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-surface-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-surface-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}.viraui__surface-module__Surface_slEYq{--vui-surface-border-radius-top-left:var(--vui-surface-border-radius);--vui-surface-border-radius-top-right:var(--vui-surface-border-radius);--vui-surface-border-radius-bottom-right:var(--vui-surface-border-radius);--vui-surface-border-radius-bottom-left:var(--vui-surface-border-radius);--vui-surface-background-hover:var(--vui-surface-background);
|
|
1
|
+
@layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-surface-background{syntax:"*";inherits:false;initial-value:none}@property --vui-surface-background-hover{syntax:"*";inherits:false;initial-value:none}@property --vui-surface-border-style{syntax:"<custom-ident>";inherits:false;initial-value:solid}@property --vui-surface-overflow{syntax:"<custom-ident>";inherits:false;initial-value:visible}@property --vui-surface-border-radius{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-top-left{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-top-right{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-bottom-right{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-bottom-left{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-surface-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-surface-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-surface-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}.viraui__surface-module__Surface_slEYq{--vui-surface-border-radius-top-left:var(--vui-surface-border-radius);--vui-surface-border-radius-top-right:var(--vui-surface-border-radius);--vui-surface-border-radius-bottom-right:var(--vui-surface-border-radius);--vui-surface-border-radius-bottom-left:var(--vui-surface-border-radius);--vui-surface-background-hover:var(--vui-surface-background);position:relative;overflow:var(--vui-surface-overflow);box-sizing:border-box;background:var(--vui-surface-background);border-radius:var(--vui-surface-border-radius-top-left) var(--vui-surface-border-radius-top-right) var(--vui-surface-border-radius-bottom-right) var(--vui-surface-border-radius-bottom-left);border:0;@container root not style(--vibrancy-enable: initial){&[data-vibrant]{background:oklab(from var(--vui-surface-background) l a b/80%)}}&[data-surface-radius=auto]{--vui-surface-border-radius-top-left:0;--vui-surface-border-radius-top-right:0;--vui-surface-border-radius-bottom-right:0;--vui-surface-border-radius-bottom-left:0}&[data-surface-has-padding=true]{padding:var(--vui-surface-padding-block-start) var(--vui-surface-padding-inline-end) var(--vui-surface-padding-block-end) var(--vui-surface-padding-inline-start)}&[data-surface-border]{border-style:var(--vui-surface-border-style);border-color:var(--global-contrast)}&[data-surface-border=all]{border-width:1px}&[data-surface-border=top]{border-width:1px 0 0}&[data-surface-border=right]{border-width:0 1px 0 0}&[data-surface-border=bottom]{border-width:0 0 1px}&[data-surface-border=left]{border-width:0 0 0 1px}&[data-surface-border=x]{border-width:0 1px}&[data-surface-border=y]{border-width:1px 0}@media (hover:hover) and (pointer:fine){&[data-surface-has-hover-color=true]:hover{background:var(--vui-surface-background-hover)}}}}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Surface",
|
|
3
|
+
"structure": "<Surface>…</Surface>",
|
|
3
4
|
"summary": "Presentational container with token background, optional border, radius, and padding; nested surfaces use radius=\"auto\" for concentric corners; root is a named CSS container query context (`surface`).",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Group content with base-level background and contrast border",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Tabs",
|
|
3
|
+
"structure": "<Tabs>\n <Tabs.List>\n <Tabs.Tab value=\"a\">…</Tabs.Tab>\n </Tabs.List>\n <Tabs.Viewport>\n <Tabs.Panel value=\"a\">…</Tabs.Panel>\n </Tabs.Viewport>\n</Tabs>",
|
|
3
4
|
"summary": "Compound segmented tab control with Surface list chrome, moving indicator, and animated panels.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Switching between related views in the same surface",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-title-align{syntax:"*";inherits:false;initial-value:start}@property --vui-title-max-width{syntax:"*";inherits:false;initial-value:none}@property --vui-title-literal-color{syntax:"<color>";inherits:false;initial-value:#0000}@property --vui-title-white-space{syntax:"*";inherits:false;initial-value:normal}@property --vui-title-font-weight{syntax:"<number>";inherits:false;initial-value:500}@property --vui-title-font-width{syntax:"<number>";inherits:false;initial-value:100}@property --vui-title-font-opsz{syntax:"<number>";inherits:false;initial-value:16}@property --vui-title-trim{syntax:"*";inherits:false;initial-value:none}@property --vui-title-trim-type{syntax:"*";inherits:false;initial-value:none}@property --vui-title-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-font-size{syntax:"<length>";inherits:false;initial-value:1rem}@property --vui-title-line-height{syntax:"normal | <number> | <length-percentage>";inherits:false;initial-value:normal}@property --vui-title-letter-spacing{syntax:"normal | <length>";inherits:false;initial-value:-.03em}@property --vui-title-font-family{syntax:"*";inherits:false;initial-value:sans-serif}.viraui__title-module__Title_CXMUX{--title-medium:clamp(var(--font-scale-body-medium),calc(var(--font-scale-body-medium) + var(--font-scale-body-x-small) / 12 + 0.24cqi),calc(var(--font-scale-body-medium) + var(--font-scale-body-x-small) / 3));--vui-title-font-size:clamp(var(--font-scale-h2),calc(var(--title-medium) * pow(var(--font-heading-typescale), 5)),var(--font-scale-h1));--vui-title-font-family:var(--font-family-heading);--vui-title-line-height:var(--font-leading-standard);margin:0;max-inline-size:var(--vui-title-max-width);font-family:var(--vui-title-font-family);font-size:var(--vui-title-font-size);line-height:var(--vui-title-line-height);letter-spacing:var(--vui-title-letter-spacing);text-align:var(--vui-title-align);white-space:var(--vui-title-white-space);word-break:break-word;font-weight:var(--vui-title-font-weight);font-stretch:calc(var(--vui-title-font-width) * 1%);font-optical-sizing:auto;font-variation-settings:"wght" var(--vui-title-font-weight),"wdth" var(--vui-title-font-width),"opsz" var(--vui-title-font-opsz);text-box:var(--vui-title-trim) var(--vui-title-trim-type);display:inline-flex;&[data-title-balanced=true]{text-wrap:balance}&[data-title-selection=false]{-webkit-user-select:none;user-select:none}&[data-title-has-padding=true]{padding:var(--vui-title-padding-block-start) var(--vui-title-padding-inline-end) var(--vui-title-padding-block-end) var(--vui-title-padding-inline-start)}&[data-title-
|
|
1
|
+
@layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-title-align{syntax:"*";inherits:false;initial-value:start}@property --vui-title-max-width{syntax:"*";inherits:false;initial-value:none}@property --vui-title-literal-color{syntax:"<color>";inherits:false;initial-value:#0000}@property --vui-title-white-space{syntax:"*";inherits:false;initial-value:normal}@property --vui-title-font-weight{syntax:"<number>";inherits:false;initial-value:500}@property --vui-title-font-width{syntax:"<number>";inherits:false;initial-value:100}@property --vui-title-font-opsz{syntax:"<number>";inherits:false;initial-value:16}@property --vui-title-trim{syntax:"*";inherits:false;initial-value:none}@property --vui-title-trim-type{syntax:"*";inherits:false;initial-value:none}@property --vui-title-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-font-size{syntax:"<length>";inherits:false;initial-value:1rem}@property --vui-title-line-height{syntax:"normal | <number> | <length-percentage>";inherits:false;initial-value:normal}@property --vui-title-letter-spacing{syntax:"normal | <length>";inherits:false;initial-value:-.03em}@property --vui-title-font-family{syntax:"*";inherits:false;initial-value:sans-serif}.viraui__title-module__Title_CXMUX{--title-medium:clamp(var(--font-scale-body-medium),calc(var(--font-scale-body-medium) + var(--font-scale-body-x-small) / 12 + 0.24cqi),calc(var(--font-scale-body-medium) + var(--font-scale-body-x-small) / 3));--vui-title-font-size:clamp(var(--font-scale-h2),calc(var(--title-medium) * pow(var(--font-heading-typescale), 5)),var(--font-scale-h1));--vui-title-font-family:var(--font-family-heading);--vui-title-line-height:var(--font-leading-standard);margin:0;max-inline-size:var(--vui-title-max-width);font-family:var(--vui-title-font-family);font-size:var(--vui-title-font-size);line-height:var(--vui-title-line-height);letter-spacing:var(--vui-title-letter-spacing);text-align:var(--vui-title-align);white-space:var(--vui-title-white-space);word-break:break-word;font-weight:var(--vui-title-font-weight);font-stretch:calc(var(--vui-title-font-width) * 1%);font-optical-sizing:auto;font-variation-settings:"wght" var(--vui-title-font-weight),"wdth" var(--vui-title-font-width),"opsz" var(--vui-title-font-opsz);text-box:var(--vui-title-trim) var(--vui-title-trim-type);display:inline-flex;&[data-title-balanced=true]{text-wrap:balance}&[data-title-selection=false]{-webkit-user-select:none;user-select:none}&[data-title-has-padding=true]{padding:var(--vui-title-padding-block-start) var(--vui-title-padding-inline-end) var(--vui-title-padding-block-end) var(--vui-title-padding-inline-start)}&[data-title-size=display]{--vui-title-font-size:clamp(var(--font-scale-h1),calc(var(--font-scale-h1) + 4.643cqi - 0.9286rem),var(--font-scale-display))}&[data-title-size="1"]{--vui-title-font-size:clamp(var(--font-scale-h2),calc(var(--title-medium) * pow(var(--font-heading-typescale), 5)),var(--font-scale-h1))}&[data-title-size="2"]{--vui-title-font-size:clamp(var(--font-scale-h3),calc(var(--title-medium) * pow(var(--font-heading-typescale), 4)),var(--font-scale-h2))}&[data-title-size="3"]{--vui-title-font-size:clamp(var(--font-scale-h4),calc(var(--title-medium) * pow(var(--font-heading-typescale), 3)),var(--font-scale-h3))}&[data-title-size="4"]{--vui-title-font-size:clamp(var(--font-scale-h5),calc(var(--title-medium) * pow(var(--font-heading-typescale), 2)),var(--font-scale-h4))}&[data-title-size="5"]{--vui-title-font-size:clamp(var(--font-scale-h6),calc(var(--title-medium) * pow(var(--font-heading-typescale), 1)),var(--font-scale-h5));--vui-title-letter-spacing:-0.02em}&[data-title-size="6"]{--vui-title-font-size:clamp(var(--font-scale-body-medium),var(--title-medium),var(--font-scale-h6));--vui-title-letter-spacing:-0.02em}&[data-title-has-literal-color=true]{color:var(--vui-title-literal-color)}&[data-title-line-height=none]{--vui-title-line-height:0}&[data-title-line-height=x-small]{--vui-title-line-height:var(--font-leading-x-small)}&[data-title-line-height=small]{--vui-title-line-height:var(--font-leading-small)}&[data-title-line-height=large]{--vui-title-line-height:var(--font-leading-large)}}}
|
|
@@ -15,7 +15,7 @@ export type TitleProps = React.ComponentPropsWithoutRef<'span'> & {
|
|
|
15
15
|
/**
|
|
16
16
|
* Replaces the default `span` root using Base UI render semantics.
|
|
17
17
|
*
|
|
18
|
-
* Pair this with `
|
|
18
|
+
* Pair this with `size` for most headings so DOM semantics and visual preset stay intentionally aligned.
|
|
19
19
|
*
|
|
20
20
|
* @default The title renders a `span` root.
|
|
21
21
|
*/
|
|
@@ -32,11 +32,11 @@ export type TitleProps = React.ComponentPropsWithoutRef<'span'> & {
|
|
|
32
32
|
* This controls only the visual preset. Semantic heading choice remains owned by `render`,
|
|
33
33
|
* because `Title` keeps a `span` root unless `render` replaces it.
|
|
34
34
|
*
|
|
35
|
-
* @default '
|
|
35
|
+
* @default '1'
|
|
36
36
|
*/
|
|
37
|
-
|
|
37
|
+
size?: 'display' | '1' | '2' | '3' | '4' | '5' | '6';
|
|
38
38
|
/**
|
|
39
|
-
* Overrides the
|
|
39
|
+
* Overrides the size preset weight (`font-weight` + `wght` axis).
|
|
40
40
|
*
|
|
41
41
|
* @default No weight override.
|
|
42
42
|
*/
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Title",
|
|
3
|
+
"structure": "<Title>…</Title>",
|
|
3
4
|
"summary": "Theme-aware heading and display typography primitive.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Headings and display text with title presets",
|
|
6
7
|
"Semantic heading tags chosen explicitly through render",
|
|
7
|
-
"
|
|
8
|
-
"Fluid clamp sizing across title
|
|
8
|
+
"Size and render paired together for most heading use cases",
|
|
9
|
+
"Fluid clamp sizing across title appearance presets"
|
|
9
10
|
],
|
|
10
11
|
"whenNotToUse": ["Body copy — use Text", "Body or mono family typography"],
|
|
11
12
|
"accessibility": [
|
|
12
13
|
"Title renders a span by default, so choose render to match the correct heading level for the page outline",
|
|
13
|
-
"Visual
|
|
14
|
-
"Use
|
|
15
|
-
"Keep heading hierarchy sequential; do not skip levels for styling alone"
|
|
14
|
+
"Visual size presets do not replace picking the right h1–h6 element",
|
|
15
|
+
"Use size for appearance and render for semantics; pair them unless you intentionally need a visual mismatch",
|
|
16
|
+
"Keep heading hierarchy sequential; do not skip outline levels for styling alone"
|
|
16
17
|
],
|
|
17
18
|
"antiPatterns": [
|
|
18
|
-
"Assuming
|
|
19
|
-
"Letting
|
|
19
|
+
"Assuming size changes the HTML tag automatically",
|
|
20
|
+
"Letting size force the HTML tag instead of choosing render explicitly",
|
|
20
21
|
"Using Title for long body paragraphs"
|
|
21
22
|
],
|
|
22
23
|
"related": ["Text", "ClampText"],
|
|
@@ -64,8 +65,8 @@
|
|
|
64
65
|
"vPadding": {
|
|
65
66
|
"description": "Sets block padding using one token or a [start, end] tuple."
|
|
66
67
|
},
|
|
67
|
-
"
|
|
68
|
-
"description": "Selects the visual heading preset; does not change semantic heading level.",
|
|
68
|
+
"size": {
|
|
69
|
+
"description": "Selects the visual heading appearance preset; does not change semantic heading level.",
|
|
69
70
|
"refCss": "font-size"
|
|
70
71
|
},
|
|
71
72
|
"lineHeight": {
|
|
@@ -127,15 +128,15 @@
|
|
|
127
128
|
"refReact": "vPadding"
|
|
128
129
|
},
|
|
129
130
|
"font-size": {
|
|
130
|
-
"description": "Heading font size;
|
|
131
|
-
"refReact": "
|
|
131
|
+
"description": "Heading font size; size prop presets via data attributes.",
|
|
132
|
+
"refReact": "size"
|
|
132
133
|
},
|
|
133
134
|
"line-height": {
|
|
134
135
|
"description": "Line height; lineHeight prop presets via data attributes.",
|
|
135
136
|
"refReact": "lineHeight"
|
|
136
137
|
},
|
|
137
138
|
"letter-spacing": {
|
|
138
|
-
"description": "Heading letter spacing;
|
|
139
|
+
"description": "Heading letter spacing; size presets adjust this."
|
|
139
140
|
},
|
|
140
141
|
"font-family": {
|
|
141
142
|
"description": "Heading font family on the root."
|
|
@@ -4,7 +4,7 @@ import { resolveAxisPadding } from "../../core/styles/resolve-axis-padding.js";
|
|
|
4
4
|
import title_module_default from "./title.module.js";
|
|
5
5
|
import { useRender } from "@base-ui/react/use-render";
|
|
6
6
|
//#region src/components/title/title.tsx
|
|
7
|
-
var Title = ({ align = "start", balanced = false, selection = true, className, color, fontWidth, hPadding,
|
|
7
|
+
var Title = ({ align = "start", balanced = false, selection = true, className, color, fontWidth, hPadding, size = "1", lineHeight = "standard", maxWidth, opticalSize, ref, render, style, trim = "both", trimType = "cap alphabetic", vPadding, weight, whiteSpace = "normal", ...otherProps }) => {
|
|
8
8
|
const hasPadding = Boolean(hPadding || vPadding);
|
|
9
9
|
const dynamicStyle = {
|
|
10
10
|
"--vui-title-align": align,
|
|
@@ -26,7 +26,7 @@ var Title = ({ align = "start", balanced = false, selection = true, className, c
|
|
|
26
26
|
ref,
|
|
27
27
|
props: {
|
|
28
28
|
...otherProps,
|
|
29
|
-
"data-title-
|
|
29
|
+
"data-title-size": size,
|
|
30
30
|
"data-title-weight": weight !== void 0 ? "custom" : "preset",
|
|
31
31
|
"data-title-line-height": lineHeight,
|
|
32
32
|
"data-title-balanced": balanced ? "true" : "false",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Toast",
|
|
3
|
+
"structure": "<Toast.Provider>\n <Toast.Portal>\n <Toast.Viewport>\n <Toast.Banner toast={…}>\n <Toast.Action>…</Toast.Action>\n </Toast.Banner>\n </Toast.Viewport>\n </Toast.Portal>\n</Toast.Provider>",
|
|
3
4
|
"summary": "Transient notification surface with stacked or anchored placement, Banner high-level API, and optional action buttons.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Confirming a completed action such as save or delete",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ToggleButton",
|
|
3
|
+
"structure": "<ToggleButton restingIcon={<Plus />} aria-label=\"Pin\" />",
|
|
3
4
|
"summary": "Icon-only two-state toggle that swaps resting and optional pressed icons on Base UI Toggle state.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Toolbar pin, favorite, or mute toggles identified only by icon",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ToggleGroup",
|
|
3
|
+
"structure": "<ToggleGroup>\n <ToggleButton restingIcon={<Plus />} aria-label=\"List\" value=\"list\" />\n</ToggleGroup>",
|
|
3
4
|
"summary": "Toolbar toggle set with shared selection state and default Stack spacing on Base UI ToggleGroup.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Segmented icon toolbars such as text alignment or formatting controls",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Tooltip",
|
|
3
|
+
"structure": "<Tooltip>\n <Tooltip.Trigger />\n <Tooltip.Content />\n</Tooltip>",
|
|
3
4
|
"summary": "Compound tooltip built on Base UI Tooltip with `Tooltip.Provider`, `Tooltip.Trigger`, `Tooltip.Content`, and `Tooltip.createHandle` for detached and multiple triggers; `Content` encapsulates Portal + Positioner + Popup + Viewport and animates position, size, and content between triggers.",
|
|
4
5
|
"whenToUse": [
|
|
5
6
|
"Short hints on hover or focus for toolbar controls and icon buttons",
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Accordion } from "./components/accordion/accordion.js";
|
|
|
2
2
|
import { Annotate } from "./components/annotate/annotate.js";
|
|
3
3
|
import { Avatar } from "./components/avatar/avatar.js";
|
|
4
4
|
import { AvatarGroup } from "./components/avatar-group/avatar-group.js";
|
|
5
|
+
import { Badge } from "./components/badge/badge.js";
|
|
5
6
|
import { Bleed } from "./components/bleed/bleed.js";
|
|
6
7
|
import { Spinner } from "./components/spinner/spinner.js";
|
|
7
8
|
import { Button } from "./components/button/button.js";
|
|
@@ -51,4 +52,4 @@ import { ToggleGroup } from "./components/toggle-group/toggle-group.js";
|
|
|
51
52
|
import { Typewriter } from "./components/typewriter/typewriter.js";
|
|
52
53
|
import { TooltipContent } from "./components/tooltip/tooltip-content.js";
|
|
53
54
|
import { Tooltip, TooltipProvider, TooltipTrigger } from "./components/tooltip/tooltip.js";
|
|
54
|
-
export { Accordion, Annotate, Avatar, AvatarGroup, Bleed, Button, ButtonLink, Checkbox, CheckboxGroup, Chip, ClampText, Dialog, DialogClose, DialogIndent, DialogIndentBackground, DialogSheet, DialogTrigger, ELEVATION_DEFAULTS, Elevator, Fieldset, FitText, IconButton, IconButtonLink, LinearProgress, Masonry, Meter, Popover, PopoverClose, PopoverDescription, PopoverSheet, PopoverTitle, PopoverTrigger, ProgressiveBlur, Radio, RadioGroup, Select, Separator, Shimmer, Skeleton, Slider, Spinner, Stack, StaticNoise, Surface, Switch, Tabs, Text, Textarea, Textfield, Title, Toast, ToggleButton, ToggleGroup, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Typewriter, getElevationProps };
|
|
55
|
+
export { Accordion, Annotate, Avatar, AvatarGroup, Badge, Bleed, Button, ButtonLink, Checkbox, CheckboxGroup, Chip, ClampText, Dialog, DialogClose, DialogIndent, DialogIndentBackground, DialogSheet, DialogTrigger, ELEVATION_DEFAULTS, Elevator, Fieldset, FitText, IconButton, IconButtonLink, LinearProgress, Masonry, Meter, Popover, PopoverClose, PopoverDescription, PopoverSheet, PopoverTitle, PopoverTrigger, ProgressiveBlur, Radio, RadioGroup, Select, Separator, Shimmer, Skeleton, Slider, Spinner, Stack, StaticNoise, Surface, Switch, Tabs, Text, Textarea, Textfield, Title, Toast, ToggleButton, ToggleGroup, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Typewriter, getElevationProps };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@viraui/react",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"private": false,
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"unplugin-dts": "1.0.3",
|
|
36
36
|
"vite": "8.1.4",
|
|
37
37
|
"vite-plugin-static-copy": "4.1.1",
|
|
38
|
-
"@viraui/foundation": "1.0.11",
|
|
39
38
|
"@viraui/icons": "0.1.7",
|
|
40
39
|
"@viraui/postcss-config": "0.0.18",
|
|
41
|
-
"@viraui/tsconfig": "0.0.17"
|
|
40
|
+
"@viraui/tsconfig": "0.0.17",
|
|
41
|
+
"@viraui/foundation": "1.0.13"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@base-ui/react": ">=1.6.0",
|