@viraui/react 0.0.28 → 0.0.29
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/components/button/button-chrome.d.ts +35 -0
- package/dist/components/button/button-chrome.js +44 -0
- package/dist/components/button/button-link.d.ts +64 -0
- package/dist/components/button/button-link.guide.json +17 -0
- package/dist/components/button/button-link.js +47 -0
- package/dist/components/button/button.d.ts +4 -3
- package/dist/components/button/button.guide.json +6 -2
- package/dist/components/button/button.js +22 -37
- package/dist/components/button/index.d.ts +2 -0
- package/dist/components/icon-button/icon-button-link.d.ts +32 -0
- package/dist/components/icon-button/icon-button-link.guide.json +24 -0
- package/dist/components/icon-button/icon-button-link.js +11 -0
- package/dist/components/icon-button/icon-button.guide.json +8 -3
- package/dist/components/icon-button/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/package.json +4 -4
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
export type ButtonSize = 'big' | 'medium' | 'small';
|
|
4
|
+
export type ButtonVariant = 'primary' | 'secondary' | 'flat' | 'destructive';
|
|
5
|
+
export type ButtonAddonPosition = 'start' | 'end';
|
|
6
|
+
export declare const spinnerDimensionsBySize: Record<ButtonSize, 'small' | 'regular'>;
|
|
7
|
+
type ButtonChromeRootAttrsParams = {
|
|
8
|
+
addon?: ReactNode;
|
|
9
|
+
addonPosition: ButtonAddonPosition;
|
|
10
|
+
className?: string;
|
|
11
|
+
isIconOnly: boolean;
|
|
12
|
+
loading: boolean;
|
|
13
|
+
pill: boolean;
|
|
14
|
+
size: ButtonSize;
|
|
15
|
+
variant: ButtonVariant;
|
|
16
|
+
};
|
|
17
|
+
export declare function getButtonChromeRootAttrs({ addon, addonPosition, className, isIconOnly, loading, pill, size, variant, }: ButtonChromeRootAttrsParams): {
|
|
18
|
+
'aria-busy': true | undefined;
|
|
19
|
+
className: string;
|
|
20
|
+
'data-loading': string;
|
|
21
|
+
'data-pill': string | undefined;
|
|
22
|
+
'data-size': ButtonSize;
|
|
23
|
+
'data-icon-only': string | undefined;
|
|
24
|
+
'data-addon-position': ButtonAddonPosition | undefined;
|
|
25
|
+
'data-variant': ButtonVariant;
|
|
26
|
+
};
|
|
27
|
+
type ButtonChromeChildrenProps = {
|
|
28
|
+
addon?: ReactNode;
|
|
29
|
+
children?: ReactNode;
|
|
30
|
+
isIconOnly: boolean;
|
|
31
|
+
loading: boolean;
|
|
32
|
+
size: ButtonSize;
|
|
33
|
+
};
|
|
34
|
+
export declare const ButtonChromeChildren: React.FC<ButtonChromeChildrenProps>;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { clsx } from "../../core/clsx.js";
|
|
2
|
+
import { Spinner } from "../spinner/spinner.js";
|
|
3
|
+
import button_module_default from "./button.module.js";
|
|
4
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import "react";
|
|
6
|
+
//#region src/components/button/button-chrome.tsx
|
|
7
|
+
var spinnerDimensionsBySize = {
|
|
8
|
+
small: "small",
|
|
9
|
+
medium: "small",
|
|
10
|
+
big: "regular"
|
|
11
|
+
};
|
|
12
|
+
function getButtonChromeRootAttrs({ addon, addonPosition, className, isIconOnly, loading, pill, size, variant }) {
|
|
13
|
+
return {
|
|
14
|
+
"aria-busy": loading || void 0,
|
|
15
|
+
className: clsx(button_module_default.Button, className),
|
|
16
|
+
"data-loading": loading ? "true" : "false",
|
|
17
|
+
"data-pill": pill ? "true" : void 0,
|
|
18
|
+
"data-size": size,
|
|
19
|
+
"data-icon-only": isIconOnly ? "true" : void 0,
|
|
20
|
+
"data-addon-position": addon && !isIconOnly ? addonPosition : void 0,
|
|
21
|
+
"data-variant": variant
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
var ButtonChromeChildren = ({ addon, children, isIconOnly, loading, size }) => /* @__PURE__ */ jsxs(Fragment, { children: [isIconOnly ? /* @__PURE__ */ jsx("span", {
|
|
25
|
+
"aria-hidden": "true",
|
|
26
|
+
className: button_module_default.Content,
|
|
27
|
+
"data-loading": loading ? "true" : "false",
|
|
28
|
+
children: addon
|
|
29
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [addon && /* @__PURE__ */ jsx("span", {
|
|
30
|
+
"aria-hidden": "true",
|
|
31
|
+
className: button_module_default.Content,
|
|
32
|
+
"data-loading": loading ? "true" : "false",
|
|
33
|
+
children: addon
|
|
34
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
35
|
+
className: button_module_default.Content,
|
|
36
|
+
"data-loading": loading ? "true" : "false",
|
|
37
|
+
children
|
|
38
|
+
})] }), loading && /* @__PURE__ */ jsx("span", {
|
|
39
|
+
"aria-hidden": "true",
|
|
40
|
+
className: button_module_default.SpinnerOverlay,
|
|
41
|
+
children: /* @__PURE__ */ jsx(Spinner, { size: spinnerDimensionsBySize[size] })
|
|
42
|
+
})] });
|
|
43
|
+
//#endregion
|
|
44
|
+
export { ButtonChromeChildren, getButtonChromeRootAttrs, spinnerDimensionsBySize };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
2
|
+
import { ButtonAddonPosition, ButtonSize, ButtonVariant } from './button-chrome';
|
|
3
|
+
import { IntrinsicViraProps } from '../../core/props/intrinsic-vira-props';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
/**
|
|
7
|
+
* Public ButtonLink props.
|
|
8
|
+
*
|
|
9
|
+
* Native link root with Button visual chrome. Use for navigation; do not use
|
|
10
|
+
* `Button` with `render={<a />}` (Base UI enforces button semantics).
|
|
11
|
+
*
|
|
12
|
+
* @default Renders an `a` root; pass `render` for framework Link composition.
|
|
13
|
+
*/
|
|
14
|
+
export type ButtonLinkProps = Omit<React.ComponentPropsWithRef<'a'>, 'type'> & IntrinsicViraProps & {
|
|
15
|
+
/**
|
|
16
|
+
* Replaces the default `a` root using Base UI render semantics (e.g. Next.js `Link`).
|
|
17
|
+
*
|
|
18
|
+
* @default The link renders an `a` root.
|
|
19
|
+
*/
|
|
20
|
+
render?: useRender.RenderProp;
|
|
21
|
+
/**
|
|
22
|
+
* Controls the visual button size.
|
|
23
|
+
*
|
|
24
|
+
* @default 'medium'
|
|
25
|
+
*/
|
|
26
|
+
size?: ButtonSize;
|
|
27
|
+
/**
|
|
28
|
+
* Selects the visual treatment matching Button.
|
|
29
|
+
*
|
|
30
|
+
* @default 'primary'
|
|
31
|
+
*/
|
|
32
|
+
variant?: ButtonVariant;
|
|
33
|
+
/**
|
|
34
|
+
* Decorative addon rendered alongside the link label.
|
|
35
|
+
*
|
|
36
|
+
* @default No default; omit when the link has no addon.
|
|
37
|
+
*/
|
|
38
|
+
addon?: ReactNode;
|
|
39
|
+
/**
|
|
40
|
+
* Controls whether the addon appears before or after the label.
|
|
41
|
+
*
|
|
42
|
+
* @default 'start'
|
|
43
|
+
*/
|
|
44
|
+
addonPosition?: ButtonAddonPosition;
|
|
45
|
+
/**
|
|
46
|
+
* Shows a centered spinner overlay while preserving the original content width.
|
|
47
|
+
*
|
|
48
|
+
* @default false
|
|
49
|
+
*/
|
|
50
|
+
loading?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Applies a fully rounded pill shape.
|
|
53
|
+
*
|
|
54
|
+
* @default false
|
|
55
|
+
*/
|
|
56
|
+
pill?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Marks the link inert via `aria-disabled` and prevents activation.
|
|
59
|
+
*
|
|
60
|
+
* @default false
|
|
61
|
+
*/
|
|
62
|
+
disabled?: boolean;
|
|
63
|
+
};
|
|
64
|
+
export declare const ButtonLink: React.FC<ButtonLinkProps>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ButtonLink",
|
|
3
|
+
"summary": "Navigation link that shares Button visual chrome (--vui-button-* CSS) and default a root with optional render for framework Link.",
|
|
4
|
+
"whenToUse": [
|
|
5
|
+
"Actions that navigate (href or router Link) but should look like Button",
|
|
6
|
+
"Same size, variant, addon, pill, and loading chrome as Button without button semantics",
|
|
7
|
+
"Compose with Next.js Link or React Router Link via the render prop"
|
|
8
|
+
],
|
|
9
|
+
"whenNotToUse": ["In-page actions that do not navigate — use Button", "Icon-only navigation — use IconButtonLink"],
|
|
10
|
+
"accessibility": [
|
|
11
|
+
"Renders a real link root so assistive tech get link role and keyboard behavior",
|
|
12
|
+
"disabled or loading sets aria-disabled and prevents activation; do not strip href solely for disable styling",
|
|
13
|
+
"Loading sets aria-busy; Spinner stays decorative"
|
|
14
|
+
],
|
|
15
|
+
"antiPatterns": ["Using Button with render={<a />} instead of ButtonLink", "Forcing role=button on a link"],
|
|
16
|
+
"related": ["Button", "IconButtonLink", "Icon", "Spinner", "Chip"]
|
|
17
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
|
|
2
|
+
import { ButtonChromeChildren, getButtonChromeRootAttrs } from "./button-chrome.js";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
5
|
+
import "react";
|
|
6
|
+
//#region src/components/button/button-link.tsx
|
|
7
|
+
var ButtonLink = ({ children, className, disabled = false, addon, addonPosition = "start", loading = false, pill = false, size = "medium", variant = "primary", render, ref, onClick, ...otherProps }) => {
|
|
8
|
+
const isDisabled = disabled || loading;
|
|
9
|
+
const isIconOnly = Boolean(addon) && (children == null || children === "");
|
|
10
|
+
const { componentProps, intrinsicAttributes } = extractIntrinsicViraProps(otherProps);
|
|
11
|
+
return useRender({
|
|
12
|
+
defaultTagName: "a",
|
|
13
|
+
render,
|
|
14
|
+
ref,
|
|
15
|
+
props: {
|
|
16
|
+
...componentProps,
|
|
17
|
+
...intrinsicAttributes,
|
|
18
|
+
...getButtonChromeRootAttrs({
|
|
19
|
+
addon,
|
|
20
|
+
addonPosition,
|
|
21
|
+
className,
|
|
22
|
+
isIconOnly,
|
|
23
|
+
loading,
|
|
24
|
+
pill,
|
|
25
|
+
size,
|
|
26
|
+
variant
|
|
27
|
+
}),
|
|
28
|
+
children: /* @__PURE__ */ jsx(ButtonChromeChildren, {
|
|
29
|
+
addon,
|
|
30
|
+
isIconOnly,
|
|
31
|
+
loading,
|
|
32
|
+
size,
|
|
33
|
+
children
|
|
34
|
+
}),
|
|
35
|
+
onClick: (event) => {
|
|
36
|
+
if (isDisabled) {
|
|
37
|
+
event.preventDefault();
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
onClick?.(event);
|
|
41
|
+
},
|
|
42
|
+
...isDisabled && { "aria-disabled": true }
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
//#endregion
|
|
47
|
+
export { ButtonLink };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Button as PrimitiveButton } from '@base-ui/react/button';
|
|
2
|
+
import { ButtonAddonPosition, ButtonSize, ButtonVariant } from './button-chrome';
|
|
2
3
|
import { IntrinsicViraProps } from '../../core/props/intrinsic-vira-props';
|
|
3
4
|
import { ReactNode } from 'react';
|
|
4
5
|
import * as React from 'react';
|
|
@@ -16,13 +17,13 @@ export type ButtonProps = PrimitiveButton.Props & IntrinsicViraProps & {
|
|
|
16
17
|
*
|
|
17
18
|
* @default 'medium'
|
|
18
19
|
*/
|
|
19
|
-
size?:
|
|
20
|
+
size?: ButtonSize;
|
|
20
21
|
/**
|
|
21
22
|
* Selects the visual treatment for the button.
|
|
22
23
|
*
|
|
23
24
|
* @default 'primary'
|
|
24
25
|
*/
|
|
25
|
-
variant?:
|
|
26
|
+
variant?: ButtonVariant;
|
|
26
27
|
/**
|
|
27
28
|
* Decorative addon rendered alongside the button label.
|
|
28
29
|
* Pass any React element; use `<Icon name="..." />` for icons or `<Chip />` for status chips.
|
|
@@ -35,7 +36,7 @@ export type ButtonProps = PrimitiveButton.Props & IntrinsicViraProps & {
|
|
|
35
36
|
*
|
|
36
37
|
* @default 'start'
|
|
37
38
|
*/
|
|
38
|
-
addonPosition?:
|
|
39
|
+
addonPosition?: ButtonAddonPosition;
|
|
39
40
|
/**
|
|
40
41
|
* Shows a centered spinner overlay while preserving the original content width.
|
|
41
42
|
*
|
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
"Async actions that need a stable width while loading",
|
|
9
9
|
"Primary Chip addons inside a primary Button — set data-theme=\"inverted\" on the Chip so its background contrasts the button fill"
|
|
10
10
|
],
|
|
11
|
-
"whenNotToUse": [
|
|
11
|
+
"whenNotToUse": [
|
|
12
|
+
"Icon-only actions without a visible label — use IconButton",
|
|
13
|
+
"Navigation or non-button semantics — use ButtonLink"
|
|
14
|
+
],
|
|
12
15
|
"accessibility": [
|
|
13
16
|
"Visible button text should name the action; avoid relying on addon alone",
|
|
14
17
|
"Loading sets aria-busy on the control while Spinner stays decorative",
|
|
@@ -16,11 +19,12 @@
|
|
|
16
19
|
],
|
|
17
20
|
"antiPatterns": [
|
|
18
21
|
"Using Button without children as icon-only — prefer IconButton",
|
|
22
|
+
"Using Button with render={<a />} for links — Base UI enforces button semantics; use ButtonLink",
|
|
19
23
|
"Duplicating icon size on every addon slot — Button CSS sizes SVG descendants",
|
|
20
24
|
"Mixing pill with custom border-radius overrides that fight data-pill styling",
|
|
21
25
|
"Primary Chip addon inside a primary Button without data-theme=\"inverted\" — chip background matches the button fill and disappears"
|
|
22
26
|
],
|
|
23
|
-
"related": ["IconButton", "Icon", "Spinner", "Chip"],
|
|
27
|
+
"related": ["ButtonLink", "IconButton", "IconButtonLink", "Icon", "Spinner", "Chip"],
|
|
24
28
|
"properties": {
|
|
25
29
|
"css": {
|
|
26
30
|
"background": {
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
import './button.css';
|
|
2
|
-
import { clsx } from "../../core/clsx.js";
|
|
3
2
|
import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { ButtonChromeChildren, getButtonChromeRootAttrs } from "./button-chrome.js";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
5
|
import { Button } from "@base-ui/react/button";
|
|
8
6
|
import { useRender } from "@base-ui/react/use-render";
|
|
9
7
|
import * as React from "react";
|
|
10
8
|
//#region src/components/button/button.tsx
|
|
11
|
-
var spinnerDimensionsBySize = {
|
|
12
|
-
small: "small",
|
|
13
|
-
medium: "small",
|
|
14
|
-
big: "regular"
|
|
15
|
-
};
|
|
16
9
|
function usesButtonPrimitiveRender(render) {
|
|
17
10
|
return render === void 0 || React.isValidElement(render) && render.type === "button";
|
|
18
11
|
}
|
|
@@ -37,18 +30,22 @@ var ButtonRenderRoot = ({ isDisabled, ref, render, rootProps }) => {
|
|
|
37
30
|
});
|
|
38
31
|
};
|
|
39
32
|
var ButtonRoot = ({ children, className, intrinsicAttributes, isDisabled, isIconOnly, addon, addonPosition, loading, passThroughProps, pill, ref, render, size, variant }) => {
|
|
33
|
+
const chromeAttrs = getButtonChromeRootAttrs({
|
|
34
|
+
addon,
|
|
35
|
+
addonPosition,
|
|
36
|
+
className: typeof className === "string" ? className : void 0,
|
|
37
|
+
isIconOnly,
|
|
38
|
+
loading,
|
|
39
|
+
pill,
|
|
40
|
+
size,
|
|
41
|
+
variant
|
|
42
|
+
});
|
|
40
43
|
const rootProps = {
|
|
41
44
|
...passThroughProps,
|
|
42
45
|
...intrinsicAttributes,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"data-loading": loading ? "true" : "false",
|
|
47
|
-
"data-pill": pill ? "true" : void 0,
|
|
48
|
-
"data-size": size,
|
|
49
|
-
"data-icon-only": isIconOnly ? "true" : void 0,
|
|
50
|
-
"data-addon-position": addon && !isIconOnly ? addonPosition : void 0,
|
|
51
|
-
"data-variant": variant
|
|
46
|
+
...chromeAttrs,
|
|
47
|
+
className: typeof className === "function" ? className : chromeAttrs.className,
|
|
48
|
+
children
|
|
52
49
|
};
|
|
53
50
|
if (usesButtonPrimitiveRender(render)) return /* @__PURE__ */ jsx(Button, {
|
|
54
51
|
...rootProps,
|
|
@@ -69,7 +66,7 @@ var Button$1 = ({ children, className, disabled, addon, addonPosition = "start",
|
|
|
69
66
|
const isIconOnly = Boolean(addon) && (children == null || children === "");
|
|
70
67
|
const { componentProps, intrinsicAttributes } = extractIntrinsicViraProps(otherProps);
|
|
71
68
|
const { render, ref, ...passThroughProps } = componentProps;
|
|
72
|
-
return /* @__PURE__ */
|
|
69
|
+
return /* @__PURE__ */ jsx(ButtonRoot, {
|
|
73
70
|
className,
|
|
74
71
|
intrinsicAttributes,
|
|
75
72
|
isDisabled,
|
|
@@ -83,25 +80,13 @@ var Button$1 = ({ children, className, disabled, addon, addonPosition = "start",
|
|
|
83
80
|
render,
|
|
84
81
|
size,
|
|
85
82
|
variant,
|
|
86
|
-
children:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}) : /* @__PURE__ */ jsxs(Fragment, { children: [addon && /* @__PURE__ */ jsx("span", {
|
|
92
|
-
"aria-hidden": "true",
|
|
93
|
-
className: button_module_default.Content,
|
|
94
|
-
"data-loading": loading ? "true" : "false",
|
|
95
|
-
children: addon
|
|
96
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
97
|
-
className: button_module_default.Content,
|
|
98
|
-
"data-loading": loading ? "true" : "false",
|
|
83
|
+
children: /* @__PURE__ */ jsx(ButtonChromeChildren, {
|
|
84
|
+
addon,
|
|
85
|
+
isIconOnly,
|
|
86
|
+
loading,
|
|
87
|
+
size,
|
|
99
88
|
children
|
|
100
|
-
})
|
|
101
|
-
"aria-hidden": "true",
|
|
102
|
-
className: button_module_default.SpinnerOverlay,
|
|
103
|
-
children: /* @__PURE__ */ jsx(Spinner, { size: spinnerDimensionsBySize[size] })
|
|
104
|
-
}) : null]
|
|
89
|
+
})
|
|
105
90
|
});
|
|
106
91
|
};
|
|
107
92
|
//#endregion
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ButtonLinkProps } from '../button/button-link';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
type AccessibleNameProps = {
|
|
5
|
+
'aria-label': string;
|
|
6
|
+
'aria-labelledby'?: never;
|
|
7
|
+
} | {
|
|
8
|
+
'aria-labelledby': string;
|
|
9
|
+
'aria-label'?: never;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Public IconButtonLink props.
|
|
13
|
+
*
|
|
14
|
+
* Typed wrapper over `ButtonLink` for icon-only navigation. Requires an accessible name
|
|
15
|
+
* via `aria-label` or `aria-labelledby`.
|
|
16
|
+
*/
|
|
17
|
+
export type IconButtonLinkProps = Omit<ButtonLinkProps, 'children' | 'addon' | 'addonPosition' | 'size'> & AccessibleNameProps & {
|
|
18
|
+
/**
|
|
19
|
+
* Controls the visual button size.
|
|
20
|
+
*
|
|
21
|
+
* @default 'medium'
|
|
22
|
+
*/
|
|
23
|
+
size?: ButtonLinkProps['size'];
|
|
24
|
+
/**
|
|
25
|
+
* Icon rendered as the sole visible control content.
|
|
26
|
+
*
|
|
27
|
+
* @default No default; required for every IconButtonLink.
|
|
28
|
+
*/
|
|
29
|
+
icon: ReactNode;
|
|
30
|
+
};
|
|
31
|
+
export declare const IconButtonLink: React.FC<IconButtonLinkProps>;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "IconButtonLink",
|
|
3
|
+
"summary": "Icon-only navigation link that requires an accessible name; wraps ButtonLink.",
|
|
4
|
+
"whenToUse": [
|
|
5
|
+
"Compact toolbar or chrome navigation identified only by icon",
|
|
6
|
+
"Same size, variant, and loading model as IconButton without button semantics",
|
|
7
|
+
"Compose with framework Link via ButtonLink render prop"
|
|
8
|
+
],
|
|
9
|
+
"whenNotToUse": [
|
|
10
|
+
"In-page icon actions that do not navigate — use IconButton",
|
|
11
|
+
"Labeled navigation — use ButtonLink",
|
|
12
|
+
"Missing both aria-label and aria-labelledby"
|
|
13
|
+
],
|
|
14
|
+
"accessibility": [
|
|
15
|
+
"Provide aria-label or aria-labelledby on every IconButtonLink — icon alone is not a name",
|
|
16
|
+
"Renders a real link root so assistive tech get link role",
|
|
17
|
+
"disabled or loading sets aria-disabled and prevents activation"
|
|
18
|
+
],
|
|
19
|
+
"antiPatterns": [
|
|
20
|
+
"Passing children, addon, or addonPosition — not part of the public API",
|
|
21
|
+
"Using IconButton with render={<a />} instead of IconButtonLink"
|
|
22
|
+
],
|
|
23
|
+
"related": ["IconButton", "ButtonLink", "Button", "Icon", "Spinner"]
|
|
24
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ButtonLink } from "../button/button-link.js";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import "react";
|
|
4
|
+
//#region src/components/icon-button/icon-button-link.tsx
|
|
5
|
+
var IconButtonLink = ({ icon, size = "medium", ...otherProps }) => /* @__PURE__ */ jsx(ButtonLink, {
|
|
6
|
+
addon: icon,
|
|
7
|
+
size,
|
|
8
|
+
...otherProps
|
|
9
|
+
});
|
|
10
|
+
//#endregion
|
|
11
|
+
export { IconButtonLink };
|
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
"Same size, variant, and loading model as Button without visible label",
|
|
7
7
|
"Decorative glyph with explicit accessible naming on the root button"
|
|
8
8
|
],
|
|
9
|
-
"whenNotToUse": [
|
|
9
|
+
"whenNotToUse": [
|
|
10
|
+
"Actions that need visible text — use Button",
|
|
11
|
+
"Missing both aria-label and aria-labelledby",
|
|
12
|
+
"Navigation or non-button semantics — use IconButtonLink"
|
|
13
|
+
],
|
|
10
14
|
"accessibility": [
|
|
11
15
|
"Provide aria-label or aria-labelledby on every IconButton — icon alone is not a name",
|
|
12
16
|
"Loading sets aria-busy on the control; Spinner is decorative",
|
|
@@ -14,7 +18,8 @@
|
|
|
14
18
|
],
|
|
15
19
|
"antiPatterns": [
|
|
16
20
|
"Passing children or addonPosition — not part of the public API",
|
|
17
|
-
"Using icon-only Button instead of IconButton"
|
|
21
|
+
"Using icon-only Button instead of IconButton",
|
|
22
|
+
"Using IconButton with render={<a />} for links — use IconButtonLink"
|
|
18
23
|
],
|
|
19
|
-
"related": ["Button", "Icon", "Spinner"]
|
|
24
|
+
"related": ["Button", "ButtonLink", "IconButtonLink", "Icon", "Spinner"]
|
|
20
25
|
}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { AvatarGroup } from "./components/avatar-group/avatar-group.js";
|
|
|
4
4
|
import { Bleed } from "./components/bleed/bleed.js";
|
|
5
5
|
import { Spinner } from "./components/spinner/spinner.js";
|
|
6
6
|
import { Button } from "./components/button/button.js";
|
|
7
|
+
import { ButtonLink } from "./components/button/button-link.js";
|
|
7
8
|
import { Text } from "./components/text/text.js";
|
|
8
9
|
import { Checkbox } from "./components/checkbox/checkbox.js";
|
|
9
10
|
import { CheckboxGroup } from "./components/checkbox/checkbox-group.js";
|
|
@@ -22,6 +23,7 @@ import { Elevator } from "./components/elevator/elevator.js";
|
|
|
22
23
|
import { Fieldset } from "./components/fieldset/fieldset.js";
|
|
23
24
|
import { Icon } from "./components/icon/icon.js";
|
|
24
25
|
import { IconButton } from "./components/icon-button/icon-button.js";
|
|
26
|
+
import { IconButtonLink } from "./components/icon-button/icon-button-link.js";
|
|
25
27
|
import { LinearProgress } from "./components/linear-progress/linear-progress.js";
|
|
26
28
|
import { Masonry } from "./components/masonry/masonry.js";
|
|
27
29
|
import { Meter } from "./components/meter/meter.js";
|
|
@@ -48,4 +50,4 @@ import { ToggleGroup } from "./components/toggle-group/toggle-group.js";
|
|
|
48
50
|
import { Typewriter } from "./components/typewriter/typewriter.js";
|
|
49
51
|
import { TooltipContent } from "./components/tooltip/tooltip-content.js";
|
|
50
52
|
import { Tooltip, TooltipProvider, TooltipTrigger } from "./components/tooltip/tooltip.js";
|
|
51
|
-
export { Accordion, Avatar, AvatarGroup, Bleed, Button, Checkbox, CheckboxGroup, Chip, ClampText, Dialog, DialogClose, DialogIndent, DialogIndentBackground, DialogSheet, DialogTrigger, ELEVATION_DEFAULTS, Elevator, Fieldset, Icon, IconButton, 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 };
|
|
53
|
+
export { Accordion, Avatar, AvatarGroup, Bleed, Button, ButtonLink, Checkbox, CheckboxGroup, Chip, ClampText, Dialog, DialogClose, DialogIndent, DialogIndentBackground, DialogSheet, DialogTrigger, ELEVATION_DEFAULTS, Elevator, Fieldset, Icon, 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": "0.0.
|
|
3
|
+
"version": "0.0.29",
|
|
4
4
|
"private": false,
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"unplugin-dts": "1.0.3",
|
|
43
43
|
"vite": "8.1.4",
|
|
44
44
|
"vite-plugin-static-copy": "4.1.1",
|
|
45
|
+
"@viraui/foundation": "0.0.29",
|
|
45
46
|
"@viraui/icons": "0.0.15",
|
|
46
|
-
"@viraui/
|
|
47
|
-
"@viraui/tsconfig": "0.0.17"
|
|
48
|
-
"@viraui/postcss-config": "0.0.17"
|
|
47
|
+
"@viraui/postcss-config": "0.0.17",
|
|
48
|
+
"@viraui/tsconfig": "0.0.17"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"@base-ui/react": ">=1.6.0",
|