@box/blueprint-web 14.31.0 → 14.32.1
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/lib-esm/accordion/accordion-item-header.d.ts +9 -1
- package/dist/lib-esm/accordion/accordion-item-header.js +82 -7
- package/dist/lib-esm/accordion/accordion.js +12 -2
- package/dist/lib-esm/accordion/accordion.module.js +1 -1
- package/dist/lib-esm/accordion/index.d.ts +1 -1
- package/dist/lib-esm/accordion/types.d.ts +68 -4
- package/dist/lib-esm/badge/badge.figma.d.ts +1 -0
- package/dist/lib-esm/index.css +404 -290
- package/dist/lib-esm/search-input/search.module.js +1 -1
- package/package.json +3 -3
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
+
import { type AccordionIconComponent, type StartElementBackgroundVariant } from './types';
|
|
3
|
+
export type { StartElementBackgroundVariant };
|
|
2
4
|
export interface AccordionItemHeaderProps {
|
|
3
5
|
title: string;
|
|
4
6
|
status?: number;
|
|
5
7
|
iconVariant?: 'alert-error' | 'status-pending' | 'status-modified';
|
|
6
8
|
iconAriaLabel?: string;
|
|
7
9
|
error?: string;
|
|
10
|
+
/** @deprecated Prefer `startIcon`. */
|
|
8
11
|
startElement?: ReactNode;
|
|
12
|
+
startIcon?: AccordionIconComponent;
|
|
13
|
+
startElementBackgroundColor?: StartElementBackgroundVariant;
|
|
14
|
+
subtitle?: string;
|
|
15
|
+
subtitleIcon?: ReactNode;
|
|
16
|
+
endText?: string;
|
|
9
17
|
}
|
|
10
|
-
export declare const AccordionItemHeader: ({ title, status, iconVariant, iconAriaLabel, error, startElement, }: AccordionItemHeaderProps) => import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export declare const AccordionItemHeader: ({ title, status, iconVariant, iconAriaLabel, error, startElement, startIcon, startElementBackgroundColor, subtitle, subtitleIcon, endText, }: AccordionItemHeaderProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
19
|
export interface AccordionActionSlotProps {
|
|
12
20
|
action?: ReactNode;
|
|
13
21
|
}
|
|
@@ -2,9 +2,10 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import { ClockBadge, Alert } from '@box/blueprint-web-assets/icons/Fill';
|
|
3
3
|
import { bpSurfaceBadgeSurfaceModified, Orange100, GrayWhite, SurfaceBadgeErrorSurface, SurfaceStatusSurfaceRed, SurfaceStatusSurfaceLightBlue } from '@box/blueprint-web-assets/tokens/tokens';
|
|
4
4
|
import clsx from 'clsx';
|
|
5
|
-
import { createElement } from 'react';
|
|
5
|
+
import { useRef, createElement } from 'react';
|
|
6
6
|
import { Status } from '../status/status.js';
|
|
7
7
|
import { isDefined } from '../utils/isDefined.js';
|
|
8
|
+
import { useFullTextTooltip } from '../utils/useFullTextTooltip.js';
|
|
8
9
|
import styles from './accordion.module.js';
|
|
9
10
|
|
|
10
11
|
const accordionIconVariantToIconProps = {
|
|
@@ -26,13 +27,34 @@ const statusColors = {
|
|
|
26
27
|
error: SurfaceStatusSurfaceRed,
|
|
27
28
|
default: SurfaceStatusSurfaceLightBlue
|
|
28
29
|
};
|
|
30
|
+
const startElementVariantClassNames = {
|
|
31
|
+
default: styles.accordionStartElementFramedDefault,
|
|
32
|
+
box: styles.accordionStartElementFramedBox,
|
|
33
|
+
forms: styles.accordionStartElementFramedForms,
|
|
34
|
+
docgen: styles.accordionStartElementFramedDocgen,
|
|
35
|
+
sign: styles.accordionStartElementFramedSign
|
|
36
|
+
};
|
|
37
|
+
const START_ICON_SIZE = '1.25rem';
|
|
38
|
+
const FRAMED_START_ICON_COLOR_MAP = {
|
|
39
|
+
default: 'var(--bp-gray-100)',
|
|
40
|
+
box: 'var(--bp-box-blue-100)',
|
|
41
|
+
forms: 'var(--bp-green-light-110)',
|
|
42
|
+
docgen: 'var(--bp-grimace-120)',
|
|
43
|
+
sign: 'var(--bp-dark-blue-100)'
|
|
44
|
+
};
|
|
45
|
+
const DEFAULT_START_ICON_COLOR = 'var(--bp-icon-icon-on-light-secondary)';
|
|
29
46
|
const AccordionItemHeader = ({
|
|
30
47
|
title,
|
|
31
48
|
status,
|
|
32
49
|
iconVariant,
|
|
33
50
|
iconAriaLabel,
|
|
34
51
|
error,
|
|
35
|
-
startElement
|
|
52
|
+
startElement,
|
|
53
|
+
startIcon,
|
|
54
|
+
startElementBackgroundColor,
|
|
55
|
+
subtitle,
|
|
56
|
+
subtitleIcon,
|
|
57
|
+
endText
|
|
36
58
|
}) => {
|
|
37
59
|
const iconProps = iconVariant ? accordionIconVariantToIconProps[iconVariant] : undefined;
|
|
38
60
|
const {
|
|
@@ -40,15 +62,62 @@ const AccordionItemHeader = ({
|
|
|
40
62
|
iconColor,
|
|
41
63
|
icon
|
|
42
64
|
} = iconProps ?? {};
|
|
65
|
+
const hasSubtitle = isDefined(subtitle) && subtitle !== '';
|
|
66
|
+
const framedStartElementClassName = startElementBackgroundColor ? startElementVariantClassNames[startElementBackgroundColor] : undefined;
|
|
67
|
+
const startIconColor = startElementBackgroundColor ? FRAMED_START_ICON_COLOR_MAP[startElementBackgroundColor] : DEFAULT_START_ICON_COLOR;
|
|
68
|
+
const renderedStartElement = startIcon ? /*#__PURE__*/createElement(startIcon, {
|
|
69
|
+
width: START_ICON_SIZE,
|
|
70
|
+
height: START_ICON_SIZE,
|
|
71
|
+
color: startIconColor,
|
|
72
|
+
'aria-hidden': true
|
|
73
|
+
}) : startElement;
|
|
74
|
+
// Single-line ellipsis with full-title tooltip on overflow. Tooltip-only
|
|
75
|
+
// (no nested `Focusable`) because the title sits inside the Radix
|
|
76
|
+
// Accordion `<button>` trigger — adding a tabbable wrapper here would
|
|
77
|
+
// create nested interactives. The trigger already owns hover/focus, so
|
|
78
|
+
// pointing/keyboarding the row surfaces the tooltip when the text is cut.
|
|
79
|
+
const titleRef = useRef(null);
|
|
80
|
+
const {
|
|
81
|
+
Wrapper: TitleTooltip,
|
|
82
|
+
wrapperProps: titleTooltipProps
|
|
83
|
+
} = useFullTextTooltip({
|
|
84
|
+
ref: titleRef,
|
|
85
|
+
textValue: title
|
|
86
|
+
});
|
|
43
87
|
return jsxs("h4", {
|
|
44
88
|
className: styles.accordionHeader,
|
|
45
89
|
children: [jsxs("span", {
|
|
46
90
|
className: styles.accordionTitleGroup,
|
|
47
|
-
children: [
|
|
48
|
-
className: styles.accordionStartElement,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
91
|
+
children: [renderedStartElement && jsx("span", {
|
|
92
|
+
className: clsx(styles.accordionStartElement, framedStartElementClassName, {
|
|
93
|
+
[styles.accordionStartElementFramed]: framedStartElementClassName
|
|
94
|
+
}),
|
|
95
|
+
style: framedStartElementClassName ? {
|
|
96
|
+
color: startIconColor
|
|
97
|
+
} : undefined,
|
|
98
|
+
children: renderedStartElement
|
|
99
|
+
}), jsxs("span", {
|
|
100
|
+
className: styles.accordionTitleContent,
|
|
101
|
+
children: [jsx(TitleTooltip, {
|
|
102
|
+
content: title,
|
|
103
|
+
...titleTooltipProps,
|
|
104
|
+
children: jsx("span", {
|
|
105
|
+
ref: titleRef,
|
|
106
|
+
className: styles.accordionTitleText,
|
|
107
|
+
"data-testid": "accordion-item-title",
|
|
108
|
+
children: title
|
|
109
|
+
})
|
|
110
|
+
}), hasSubtitle && jsxs("span", {
|
|
111
|
+
className: styles.accordionSubtitle,
|
|
112
|
+
children: [subtitleIcon && jsx("span", {
|
|
113
|
+
"aria-hidden": "true",
|
|
114
|
+
className: styles.accordionSubtitleIcon,
|
|
115
|
+
children: subtitleIcon
|
|
116
|
+
}), jsx("span", {
|
|
117
|
+
className: styles.accordionSubtitleText,
|
|
118
|
+
children: subtitle
|
|
119
|
+
})]
|
|
120
|
+
})]
|
|
52
121
|
})]
|
|
53
122
|
}), isDefined(status) && jsx("span", {
|
|
54
123
|
className: styles.accordionHeaderInfoSlot,
|
|
@@ -78,6 +147,12 @@ const AccordionItemHeader = ({
|
|
|
78
147
|
width: '0.75rem'
|
|
79
148
|
})
|
|
80
149
|
})
|
|
150
|
+
}), isDefined(endText) && endText !== '' && jsx("span", {
|
|
151
|
+
className: styles.accordionHeaderInfoSlot,
|
|
152
|
+
children: jsx("span", {
|
|
153
|
+
className: styles.accordionEndText,
|
|
154
|
+
children: endText
|
|
155
|
+
})
|
|
81
156
|
})]
|
|
82
157
|
});
|
|
83
158
|
};
|
|
@@ -77,6 +77,11 @@ const Item = props => {
|
|
|
77
77
|
iconAriaLabel,
|
|
78
78
|
title,
|
|
79
79
|
startElement,
|
|
80
|
+
startIcon,
|
|
81
|
+
startElementBackgroundColor,
|
|
82
|
+
subtitle,
|
|
83
|
+
subtitleIcon,
|
|
84
|
+
endText,
|
|
80
85
|
disabled,
|
|
81
86
|
error,
|
|
82
87
|
errorIconAriaLabel,
|
|
@@ -113,12 +118,17 @@ const Item = props => {
|
|
|
113
118
|
}),
|
|
114
119
|
disabled: disabled,
|
|
115
120
|
children: jsx(AccordionItemHeader, {
|
|
121
|
+
endText: endText,
|
|
116
122
|
error: error,
|
|
117
123
|
iconAriaLabel: iconAriaLabel,
|
|
118
124
|
iconVariant: iconVariant,
|
|
125
|
+
startElement: startElement,
|
|
126
|
+
startElementBackgroundColor: startElementBackgroundColor,
|
|
127
|
+
startIcon: startIcon,
|
|
119
128
|
status: status,
|
|
120
|
-
|
|
121
|
-
|
|
129
|
+
subtitle: subtitle,
|
|
130
|
+
subtitleIcon: subtitleIcon,
|
|
131
|
+
title: title
|
|
122
132
|
})
|
|
123
133
|
}), jsx(AccordionActionSlot, {
|
|
124
134
|
action: action
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import '../index.css';
|
|
2
|
-
var styles = {"accordionItem":"bp_accordion_module_accordionItem--
|
|
2
|
+
var styles = {"accordionItem":"bp_accordion_module_accordionItem--c8f78","accordionContent":"bp_accordion_module_accordionContent--c8f78","accordionContentLayout":"bp_accordion_module_accordionContentLayout--c8f78","accordion":"bp_accordion_module_accordion--c8f78","accordionContentWrapper":"bp_accordion_module_accordionContentWrapper--c8f78","accordionInlineErrorWrapper":"bp_accordion_module_accordionInlineErrorWrapper--c8f78","highlighted":"bp_accordion_module_highlighted--c8f78","accordionFixedContent":"bp_accordion_module_accordionFixedContent--c8f78","accordionHeader":"bp_accordion_module_accordionHeader--c8f78","accordionTitleGroup":"bp_accordion_module_accordionTitleGroup--c8f78","accordionStartElement":"bp_accordion_module_accordionStartElement--c8f78","accordionStartElementFramed":"bp_accordion_module_accordionStartElementFramed--c8f78","accordionStartElementFramedDefault":"bp_accordion_module_accordionStartElementFramedDefault--c8f78","accordionStartElementFramedBox":"bp_accordion_module_accordionStartElementFramedBox--c8f78","accordionStartElementFramedForms":"bp_accordion_module_accordionStartElementFramedForms--c8f78","accordionStartElementFramedDocgen":"bp_accordion_module_accordionStartElementFramedDocgen--c8f78","accordionStartElementFramedSign":"bp_accordion_module_accordionStartElementFramedSign--c8f78","accordionTitleContent":"bp_accordion_module_accordionTitleContent--c8f78","accordionTitleText":"bp_accordion_module_accordionTitleText--c8f78","accordionSubtitle":"bp_accordion_module_accordionSubtitle--c8f78","accordionSubtitleIcon":"bp_accordion_module_accordionSubtitleIcon--c8f78","accordionSubtitleText":"bp_accordion_module_accordionSubtitleText--c8f78","accordionEndText":"bp_accordion_module_accordionEndText--c8f78","accordionHeaderInfoSlot":"bp_accordion_module_accordionHeaderInfoSlot--c8f78","accordionSlot":"bp_accordion_module_accordionSlot--c8f78","accordionChevronWrapper":"bp_accordion_module_accordionChevronWrapper--c8f78","accordionTriggerIcon":"bp_accordion_module_accordionTriggerIcon--c8f78","accordionIconWrapper":"bp_accordion_module_accordionIconWrapper--c8f78","bgOnly":"bp_accordion_module_bgOnly--c8f78","withIcon":"bp_accordion_module_withIcon--c8f78","accordionTrigger":"bp_accordion_module_accordionTrigger--c8f78","disabled":"bp_accordion_module_disabled--c8f78","accordionHeaderContainer":"bp_accordion_module_accordionHeaderContainer--c8f78"};
|
|
3
3
|
|
|
4
4
|
export { styles as default };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { Accordion } from './accordion';
|
|
2
|
-
export type { AccordionFixedItem, AccordionItem, AccordionProps, AccordionSectionItem } from './types';
|
|
2
|
+
export type { AccordionFixedItem, AccordionItem, AccordionProps, AccordionSectionItem, StartElementBackgroundVariant, } from './types';
|
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
import { type AccordionMultipleProps, type AccordionSingleProps, type AccordionItemProps as RadixAccordionItemProps } from '@radix-ui/react-accordion';
|
|
2
|
+
import { type FunctionComponent, type PropsWithChildren, type SVGProps } from 'react';
|
|
2
3
|
import { type RequireAllOrNone } from 'type-fest';
|
|
4
|
+
export type AccordionIconComponent = FunctionComponent<PropsWithChildren<SVGProps<SVGSVGElement>>>;
|
|
5
|
+
/** Tint for the optional framed start-of-row icon (modernized items only). */
|
|
6
|
+
export type StartElementBackgroundVariant = 'default' | 'box' | 'forms' | 'docgen' | 'sign';
|
|
7
|
+
/**
|
|
8
|
+
* Mutually-exclusive start-of-row slot. Use either `startIcon` (preferred,
|
|
9
|
+
* icon-component pattern) or `startElement` (legacy `ReactNode`).
|
|
10
|
+
*/
|
|
11
|
+
type StartSlotProps = {
|
|
12
|
+
/**
|
|
13
|
+
* @deprecated Prefer `startIcon`, which renders the icon with
|
|
14
|
+
* consistent size, color, and aria attributes. Still supported for
|
|
15
|
+
* backward compatibility — pass any `ReactNode` to render to the
|
|
16
|
+
* left of the title.
|
|
17
|
+
*/
|
|
18
|
+
startElement?: React.ReactNode;
|
|
19
|
+
startIcon?: never;
|
|
20
|
+
} | {
|
|
21
|
+
startElement?: never;
|
|
22
|
+
/**
|
|
23
|
+
* Icon **component** (e.g. `Search`, `Folder` from
|
|
24
|
+
* `@box/blueprint-web-assets/icons/Medium`) rendered to the left of
|
|
25
|
+
* the title. The Accordion handles sizing (20x20 per the Figma
|
|
26
|
+
* "L. Element=Icon" spec), `currentColor` inheritance, and
|
|
27
|
+
* `aria-hidden`, matching the icon-component pattern used by
|
|
28
|
+
* `BaseButton`, `IconButton`, and `BaseInlineNotice`.
|
|
29
|
+
*
|
|
30
|
+
* When combined with `startElementBackgroundColor`, the icon is
|
|
31
|
+
* placed inside the matching 32x32 framed container.
|
|
32
|
+
*/
|
|
33
|
+
startIcon?: AccordionIconComponent;
|
|
34
|
+
};
|
|
3
35
|
interface Loading {
|
|
4
36
|
/** Loading state of the section. Loading sections are displaying a placeholder. When this is true `loadingAriaLabel` must also be provided. */
|
|
5
37
|
loading: boolean;
|
|
@@ -27,21 +59,30 @@ interface IconProps {
|
|
|
27
59
|
iconAriaLabel: string;
|
|
28
60
|
}
|
|
29
61
|
/**
|
|
30
|
-
* Only one header slot is allowed at a time: `status`, `iconVariant`, or `
|
|
62
|
+
* Only one header slot is allowed at a time: `status`, `iconVariant`, `action`, or `endText`.
|
|
31
63
|
*/
|
|
32
64
|
type HeaderSlotProps = {
|
|
33
65
|
status?: number;
|
|
34
66
|
iconVariant?: never;
|
|
35
67
|
iconAriaLabel?: never;
|
|
36
68
|
action?: never;
|
|
69
|
+
endText?: never;
|
|
37
70
|
} | ({
|
|
38
71
|
status?: never;
|
|
39
72
|
action?: never;
|
|
73
|
+
endText?: never;
|
|
40
74
|
} & RequireAllOrNone<IconProps, keyof IconProps>) | {
|
|
41
75
|
status?: never;
|
|
42
76
|
iconVariant?: never;
|
|
43
77
|
iconAriaLabel?: never;
|
|
44
78
|
action?: React.ReactNode;
|
|
79
|
+
endText?: never;
|
|
80
|
+
} | {
|
|
81
|
+
status?: never;
|
|
82
|
+
iconVariant?: never;
|
|
83
|
+
iconAriaLabel?: never;
|
|
84
|
+
action?: never;
|
|
85
|
+
endText?: string;
|
|
45
86
|
};
|
|
46
87
|
export type AccordionBaseItem = {
|
|
47
88
|
/**
|
|
@@ -65,9 +106,32 @@ export type AccordionSectionItem = AccordionBaseItem & Omit<RadixAccordionItemPr
|
|
|
65
106
|
*/
|
|
66
107
|
disabled?: boolean;
|
|
67
108
|
/**
|
|
68
|
-
*
|
|
109
|
+
* When provided, frames the start-of-row icon in a 32x32 container
|
|
110
|
+
* tinted with the matching Box brand surface color. Each variant
|
|
111
|
+
* pairs a "brand-{variant}-tertiary" tinted background with the
|
|
112
|
+
* corresponding brand foreground glyph:
|
|
113
|
+
*
|
|
114
|
+
* - `default` – `surface-surface-tertiary` (#F5F5F5) background, `gray-100` (#909090) icon
|
|
115
|
+
* - `box` – `brand-box-tertiary` (#E5EFFA) background, `box-blue-100` (#0061D5) icon
|
|
116
|
+
* - `forms` – `brand-forms-tertiary` (#E9F8F2) background, `green-light-110` (#22AF74) icon
|
|
117
|
+
* - `docgen` – `brand-docgen-tertiary` (#ECE9F8) background, `brand-docgen-primary` (purple) icon
|
|
118
|
+
* - `sign` – `brand-sign-tertiary` (#E5EBF2) background, `dark-blue-100` (#003C84) icon
|
|
119
|
+
*
|
|
120
|
+
* Has no effect unless `startIcon` (or the legacy `startElement`) is
|
|
121
|
+
* also provided. Only applies to modernized accordion items.
|
|
69
122
|
*/
|
|
70
|
-
|
|
123
|
+
startElementBackgroundColor?: StartElementBackgroundVariant;
|
|
124
|
+
/**
|
|
125
|
+
* Optional supplemental text displayed below the title in the header.
|
|
126
|
+
* Only applies to modernized accordion items.
|
|
127
|
+
*/
|
|
128
|
+
subtitle?: string;
|
|
129
|
+
/**
|
|
130
|
+
* Optional decorative icon displayed before the subtitle text.
|
|
131
|
+
* Has no effect unless `subtitle` is also provided.
|
|
132
|
+
* Only applies to modernized accordion items.
|
|
133
|
+
*/
|
|
134
|
+
subtitleIcon?: React.ReactNode;
|
|
71
135
|
/**
|
|
72
136
|
* When true, the item renders a colored border and tinted background when
|
|
73
137
|
* expanded to visually indicate it is the active/selected item. The border
|
|
@@ -76,7 +140,7 @@ export type AccordionSectionItem = AccordionBaseItem & Omit<RadixAccordionItemPr
|
|
|
76
140
|
* Only applies to modernized accordion items.
|
|
77
141
|
*/
|
|
78
142
|
highlighted?: boolean;
|
|
79
|
-
} & HeaderSlotProps;
|
|
143
|
+
} & HeaderSlotProps & StartSlotProps;
|
|
80
144
|
export type AccordionItem = AccordionSectionItem | AccordionFixedItem;
|
|
81
145
|
export type AccordionItemProps = AccordionItem & React.ComponentPropsWithRef<'div'>;
|
|
82
146
|
export type AccordionProps = (AccordionSingleProps | AccordionMultipleProps) & React.ComponentPropsWithRef<'div'>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|