@sproutsocial/seeds-react-menu 1.16.16 → 1.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +14 -22
- package/CHANGELOG.md +51 -0
- package/dist/esm/index.js +542 -229
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/v3/index.js +870 -1081
- package/dist/esm/v3/index.js.map +1 -1
- package/dist/v3/index.d.mts +82 -38
- package/dist/v3/index.d.ts +82 -38
- package/dist/v3/index.js +887 -1098
- package/dist/v3/index.js.map +1 -1
- package/dist/v3/menu.css +947 -0
- package/package.json +20 -21
- package/src/ActionMenu/ActionMenu.stories.tsx +1 -1
- package/src/Autocomplete/Autocomplete.stories.tsx +1 -1
- package/src/MenuContent/MenuContent.stories.tsx +1 -1
- package/src/MenuFooter/MenuFooter.stories.tsx +1 -1
- package/src/MenuGroup/MenuGroup.stories.tsx +1 -1
- package/src/MenuHeader/MenuHeader.stories.tsx +1 -1
- package/src/MenuItem/MenuItem.stories.tsx +1 -1
- package/src/MenuToggleButton/MenuToggleButton.stories.tsx +1 -1
- package/src/MultiSelectMenu/MultiSelectMenu.stories.tsx +1 -1
- package/src/NestedMenu/NestedMenu.stories.tsx +1 -1
- package/src/SingleSelectMenu/SingleSelectMenu.stories.tsx +1 -1
- package/src/SubmenuItem/SubmenuItem.stories.tsx +1 -1
- package/src/v3/ActionMenu.stories.tsx +1 -1
- package/src/v3/ActionMenuStyles.tsx +169 -149
- package/src/v3/Common/ComboboxStyles.tsx +396 -511
- package/src/v3/Common/SelectIcons.tsx +17 -8
- package/src/v3/Common/SelectItem.tsx +25 -38
- package/src/v3/Common/SelectStyles.tsx +146 -144
- package/src/v3/Common/cn.ts +38 -0
- package/src/v3/MenuButton.stories.tsx +1 -1
- package/src/v3/MenuButtonStyles.tsx +55 -34
- package/src/v3/ModalStories.stories.tsx +1 -1
- package/src/v3/MultiCombobox.stories.tsx +1 -1
- package/src/v3/MultiCombobox.tsx +7 -0
- package/src/v3/MultiSearchableSelect.stories.tsx +1 -1
- package/src/v3/MultiSearchableSelect.tsx +15 -8
- package/src/v3/MultiSelect.stories.tsx +1 -1
- package/src/v3/MultiSelect.tsx +20 -17
- package/src/v3/SingleCombobox.stories.tsx +1 -1
- package/src/v3/SingleCombobox.tsx +7 -0
- package/src/v3/SingleSearchableSelect.stories.tsx +1 -1
- package/src/v3/SingleSearchableSelect.tsx +7 -0
- package/src/v3/SingleSelect.stories.tsx +1 -1
- package/src/v3/SingleSelect.tsx +22 -14
- package/src/v3/__tests__/ariaLabels.test.tsx +133 -0
- package/src/v3/menu.css +947 -0
- package/tsup.config.ts +0 -1
- package/dist/esm/chunk-ROQATIB7.js +0 -357
- package/dist/esm/chunk-ROQATIB7.js.map +0 -1
- package/dist/esm/v2/index.js +0 -2089
- package/dist/esm/v2/index.js.map +0 -1
- package/dist/v2/index.d.mts +0 -108
- package/dist/v2/index.d.ts +0 -108
- package/dist/v2/index.js +0 -2280
- package/dist/v2/index.js.map +0 -1
- package/src/v2/Autocomplete/Autocomplete.stories.tsx +0 -645
- package/src/v2/Autocomplete/MultiAutocomplete.tsx +0 -487
- package/src/v2/Autocomplete/SingleAutocomplete.tsx +0 -366
- package/src/v2/Autocomplete/index.ts +0 -2
- package/src/v2/Common-V2/ComboboxContent.tsx +0 -457
- package/src/v2/Common-V2/MenuGroup.tsx +0 -60
- package/src/v2/Common-V2/MenuGroupTypes.ts +0 -30
- package/src/v2/Common-V2/MenuHeading.tsx +0 -83
- package/src/v2/Common-V2/MenuItem.tsx +0 -138
- package/src/v2/Common-V2/Popout.tsx +0 -124
- package/src/v2/Common-V2/PopoutTypes.tsx +0 -109
- package/src/v2/Common-V2/SelectToggleButton.tsx +0 -99
- package/src/v2/Common-V2/index.ts +0 -11
- package/src/v2/Common-V2/props.ts +0 -84
- package/src/v2/Common-V2/styles.tsx +0 -41
- package/src/v2/Common-V2/types.ts +0 -16
- package/src/v2/Common-V2/useHighlightedIndex.ts +0 -62
- package/src/v2/Common-V2/utils.ts +0 -238
- package/src/v2/SearchableSelect/AutocompleteContent.tsx +0 -325
- package/src/v2/SearchableSelect/SearchableMultiSelect.tsx +0 -527
- package/src/v2/SearchableSelect/SearchableSelect.tsx +0 -395
- package/src/v2/SearchableSelect/index.ts +0 -12
- package/src/v2/Select/MultiSelect.tsx +0 -417
- package/src/v2/Select/Select.stories.tsx +0 -593
- package/src/v2/Select/SingleSelect.tsx +0 -285
- package/src/v2/Select/index.ts +0 -2
- package/src/v2/index.ts +0 -2
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import styled from "styled-components";
|
|
3
2
|
import { Icon } from "@sproutsocial/seeds-react-icon";
|
|
3
|
+
import { cn } from "./cn";
|
|
4
4
|
|
|
5
|
-
export interface StyledChevronProps {
|
|
5
|
+
export interface StyledChevronProps extends React.ComponentProps<"div"> {
|
|
6
6
|
$isOpen?: boolean;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export const StyledChevron =
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
export const StyledChevron = React.forwardRef<
|
|
10
|
+
HTMLDivElement,
|
|
11
|
+
StyledChevronProps
|
|
12
|
+
>(({ $isOpen, className, ...rest }, ref) => (
|
|
13
|
+
<div
|
|
14
|
+
ref={ref}
|
|
15
|
+
className={cn(
|
|
16
|
+
"seeds-menu-chevron",
|
|
17
|
+
{ "seeds-menu-chevron--open": !!$isOpen },
|
|
18
|
+
className
|
|
19
|
+
)}
|
|
20
|
+
{...rest}
|
|
21
|
+
/>
|
|
22
|
+
));
|
|
23
|
+
StyledChevron.displayName = "StyledChevron";
|
|
15
24
|
|
|
16
25
|
export function ChevronIcon() {
|
|
17
26
|
return <Icon name="chevron-down-outline" fixedWidth aria-hidden />;
|
|
@@ -1,50 +1,37 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Select } from "@base-ui/react/select";
|
|
3
|
-
import styled from "styled-components";
|
|
4
3
|
import Radio from "@sproutsocial/seeds-react-radio";
|
|
5
4
|
import Checkbox from "@sproutsocial/seeds-react-checkbox";
|
|
6
5
|
import { Icon } from "@sproutsocial/seeds-react-icon";
|
|
6
|
+
import { cn, type WithStringClassName } from "./cn";
|
|
7
7
|
|
|
8
|
-
// ───
|
|
8
|
+
// ─── CSS-class components (see menu.css) ────────────────────────────────────
|
|
9
9
|
|
|
10
|
-
export const StyledItem =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
export const StyledItem = React.forwardRef<
|
|
11
|
+
React.ElementRef<typeof Select.Item>,
|
|
12
|
+
WithStringClassName<React.ComponentProps<typeof Select.Item>>
|
|
13
|
+
>(({ className, ...rest }, ref) => (
|
|
14
|
+
<Select.Item
|
|
15
|
+
ref={ref}
|
|
16
|
+
className={cn("seeds-select-item", className)}
|
|
17
|
+
{...rest}
|
|
18
|
+
/>
|
|
19
|
+
));
|
|
20
|
+
StyledItem.displayName = "StyledItem";
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
export const StyledItemIndicator = React.forwardRef<
|
|
23
|
+
React.ElementRef<typeof Select.ItemIndicator>,
|
|
24
|
+
WithStringClassName<React.ComponentProps<typeof Select.ItemIndicator>>
|
|
25
|
+
>(({ className, ...rest }, ref) => (
|
|
26
|
+
<Select.ItemIndicator
|
|
27
|
+
ref={ref}
|
|
28
|
+
className={cn("seeds-select-item-indicator", className)}
|
|
29
|
+
{...rest}
|
|
30
|
+
/>
|
|
31
|
+
));
|
|
32
|
+
StyledItemIndicator.displayName = "StyledItemIndicator";
|
|
24
33
|
|
|
25
|
-
|
|
26
|
-
font-weight: ${({ theme }) => theme.fontWeights.semibold};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
&[data-disabled] {
|
|
30
|
-
opacity: 0.5;
|
|
31
|
-
cursor: not-allowed;
|
|
32
|
-
}
|
|
33
|
-
`;
|
|
34
|
-
|
|
35
|
-
export const StyledItemIndicator = styled(Select.ItemIndicator)`
|
|
36
|
-
display: flex;
|
|
37
|
-
align-items: center;
|
|
38
|
-
width: 16px;
|
|
39
|
-
color: ${({ theme }) => theme.colors.text.body};
|
|
40
|
-
visibility: hidden;
|
|
41
|
-
|
|
42
|
-
&[data-selected] {
|
|
43
|
-
visibility: visible;
|
|
44
|
-
}
|
|
45
|
-
`;
|
|
46
|
-
|
|
47
|
-
export const StyledItemText = styled(Select.ItemText)``;
|
|
34
|
+
export const StyledItemText = Select.ItemText;
|
|
48
35
|
|
|
49
36
|
// ─── Icons ────────────────────────────────────────────────────────────────────
|
|
50
37
|
|
|
@@ -1,146 +1,148 @@
|
|
|
1
|
+
import * as React from "react";
|
|
1
2
|
import { Select } from "@base-ui/react/select";
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
3
|
+
import { cn, type WithStringClassName } from "./cn";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* v3 Select surface, rendered with CSS classes from menu.css (imported via
|
|
7
|
+
* @sproutsocial/seeds-react-menu/base/css) instead of styled-components. Each
|
|
8
|
+
* export keeps its previous name and forwards props/refs to the underlying
|
|
9
|
+
* Base UI component; the transient `$isInvalid` / `$fullWidth` props are
|
|
10
|
+
* translated to modifier classes here so call sites are unchanged.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
type FieldProps = WithStringClassName<React.ComponentProps<"div">> & {
|
|
14
|
+
$fullWidth?: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
|
|
18
|
+
({ $fullWidth, className, ...rest }, ref) => (
|
|
19
|
+
<div
|
|
20
|
+
ref={ref}
|
|
21
|
+
className={cn(
|
|
22
|
+
"seeds-menu-field",
|
|
23
|
+
{ "seeds-menu-field--inline": $fullWidth === false },
|
|
24
|
+
className
|
|
25
|
+
)}
|
|
26
|
+
{...rest}
|
|
27
|
+
/>
|
|
28
|
+
)
|
|
29
|
+
);
|
|
30
|
+
Field.displayName = "Field";
|
|
31
|
+
|
|
32
|
+
export const SelectLabel = React.forwardRef<
|
|
33
|
+
React.ElementRef<typeof Select.Label>,
|
|
34
|
+
WithStringClassName<React.ComponentProps<typeof Select.Label>>
|
|
35
|
+
>(({ className, ...rest }, ref) => (
|
|
36
|
+
<Select.Label
|
|
37
|
+
ref={ref}
|
|
38
|
+
className={cn("seeds-menu-label", className)}
|
|
39
|
+
{...rest}
|
|
40
|
+
/>
|
|
41
|
+
));
|
|
42
|
+
SelectLabel.displayName = "SelectLabel";
|
|
43
|
+
|
|
44
|
+
type SelectTriggerProps = WithStringClassName<
|
|
45
|
+
React.ComponentProps<typeof Select.Trigger>
|
|
46
|
+
> & {
|
|
29
47
|
$isInvalid?: boolean;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
opacity: 1;
|
|
132
|
-
transform: scale(1);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
@keyframes select-popup-out {
|
|
137
|
-
from {
|
|
138
|
-
opacity: 1;
|
|
139
|
-
transform: scale(1);
|
|
140
|
-
}
|
|
141
|
-
to {
|
|
142
|
-
opacity: 0;
|
|
143
|
-
transform: scale(0.95);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
`;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const SelectTrigger = React.forwardRef<
|
|
51
|
+
React.ElementRef<typeof Select.Trigger>,
|
|
52
|
+
SelectTriggerProps
|
|
53
|
+
>(({ $isInvalid, className, ...rest }, ref) => (
|
|
54
|
+
<Select.Trigger
|
|
55
|
+
ref={ref}
|
|
56
|
+
className={cn(
|
|
57
|
+
"seeds-select-trigger",
|
|
58
|
+
{ "seeds-select-trigger--invalid": !!$isInvalid },
|
|
59
|
+
className
|
|
60
|
+
)}
|
|
61
|
+
{...rest}
|
|
62
|
+
/>
|
|
63
|
+
));
|
|
64
|
+
SelectTrigger.displayName = "SelectTrigger";
|
|
65
|
+
|
|
66
|
+
export const SelectValue = React.forwardRef<
|
|
67
|
+
React.ElementRef<typeof Select.Value>,
|
|
68
|
+
WithStringClassName<React.ComponentProps<typeof Select.Value>>
|
|
69
|
+
>(({ className, ...rest }, ref) => (
|
|
70
|
+
<Select.Value
|
|
71
|
+
ref={ref}
|
|
72
|
+
className={cn("seeds-select-value", className)}
|
|
73
|
+
{...rest}
|
|
74
|
+
/>
|
|
75
|
+
));
|
|
76
|
+
SelectValue.displayName = "SelectValue";
|
|
77
|
+
|
|
78
|
+
export const SelectIcon = React.forwardRef<
|
|
79
|
+
React.ElementRef<typeof Select.Icon>,
|
|
80
|
+
WithStringClassName<React.ComponentProps<typeof Select.Icon>>
|
|
81
|
+
>(({ className, ...rest }, ref) => (
|
|
82
|
+
<Select.Icon
|
|
83
|
+
ref={ref}
|
|
84
|
+
className={cn("seeds-select-icon", className)}
|
|
85
|
+
{...rest}
|
|
86
|
+
/>
|
|
87
|
+
));
|
|
88
|
+
SelectIcon.displayName = "SelectIcon";
|
|
89
|
+
|
|
90
|
+
export const SelectGroup = React.forwardRef<
|
|
91
|
+
React.ElementRef<typeof Select.Group>,
|
|
92
|
+
WithStringClassName<React.ComponentProps<typeof Select.Group>>
|
|
93
|
+
>(({ className, ...rest }, ref) => (
|
|
94
|
+
<Select.Group
|
|
95
|
+
ref={ref}
|
|
96
|
+
className={cn("seeds-select-group", className)}
|
|
97
|
+
{...rest}
|
|
98
|
+
/>
|
|
99
|
+
));
|
|
100
|
+
SelectGroup.displayName = "SelectGroup";
|
|
101
|
+
|
|
102
|
+
export const SelectGroupLabel = React.forwardRef<
|
|
103
|
+
React.ElementRef<typeof Select.GroupLabel>,
|
|
104
|
+
WithStringClassName<React.ComponentProps<typeof Select.GroupLabel>>
|
|
105
|
+
>(({ className, ...rest }, ref) => (
|
|
106
|
+
<Select.GroupLabel
|
|
107
|
+
ref={ref}
|
|
108
|
+
className={cn("seeds-select-group-label", className)}
|
|
109
|
+
{...rest}
|
|
110
|
+
/>
|
|
111
|
+
));
|
|
112
|
+
SelectGroupLabel.displayName = "SelectGroupLabel";
|
|
113
|
+
|
|
114
|
+
export const SelectSeparator = React.forwardRef<
|
|
115
|
+
React.ElementRef<typeof Select.Separator>,
|
|
116
|
+
WithStringClassName<React.ComponentProps<typeof Select.Separator>>
|
|
117
|
+
>(({ className, ...rest }, ref) => (
|
|
118
|
+
<Select.Separator
|
|
119
|
+
ref={ref}
|
|
120
|
+
className={cn("seeds-select-separator", className)}
|
|
121
|
+
{...rest}
|
|
122
|
+
/>
|
|
123
|
+
));
|
|
124
|
+
SelectSeparator.displayName = "SelectSeparator";
|
|
125
|
+
|
|
126
|
+
export const SelectPositioner = React.forwardRef<
|
|
127
|
+
React.ElementRef<typeof Select.Positioner>,
|
|
128
|
+
WithStringClassName<React.ComponentProps<typeof Select.Positioner>>
|
|
129
|
+
>(({ className, ...rest }, ref) => (
|
|
130
|
+
<Select.Positioner
|
|
131
|
+
ref={ref}
|
|
132
|
+
className={cn("seeds-select-positioner", className)}
|
|
133
|
+
{...rest}
|
|
134
|
+
/>
|
|
135
|
+
));
|
|
136
|
+
SelectPositioner.displayName = "SelectPositioner";
|
|
137
|
+
|
|
138
|
+
export const SelectPopup = React.forwardRef<
|
|
139
|
+
React.ElementRef<typeof Select.Popup>,
|
|
140
|
+
WithStringClassName<React.ComponentProps<typeof Select.Popup>>
|
|
141
|
+
>(({ className, ...rest }, ref) => (
|
|
142
|
+
<Select.Popup
|
|
143
|
+
ref={ref}
|
|
144
|
+
className={cn("seeds-select-popup", className)}
|
|
145
|
+
{...rest}
|
|
146
|
+
/>
|
|
147
|
+
));
|
|
148
|
+
SelectPopup.displayName = "SelectPopup";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local class-name merge helper for the v3 menu CSS-class components.
|
|
3
|
+
*
|
|
4
|
+
* `cn` is not exported from @sproutsocial/seeds-react-utilities, so — mirroring
|
|
5
|
+
* ButtonTailwind/MessageTailwind — the menu package keeps a local copy. Accepts
|
|
6
|
+
* strings and { className: boolean } records; falsy entries are dropped.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Narrow a Base UI component's props so `className` is a plain string. Base UI
|
|
10
|
+
* types `className` as `string | ((state) => string)`; the v3 CSS-class
|
|
11
|
+
* wrappers only ever forward a string (no consumer uses the function form), and
|
|
12
|
+
* a string is what `cn` accepts.
|
|
13
|
+
*/
|
|
14
|
+
export type WithStringClassName<P> = Omit<P, "className"> & {
|
|
15
|
+
className?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export function cn(
|
|
19
|
+
...inputs: (string | undefined | null | false | Record<string, boolean>)[]
|
|
20
|
+
): string {
|
|
21
|
+
const classes: string[] = [];
|
|
22
|
+
|
|
23
|
+
for (const input of inputs) {
|
|
24
|
+
if (!input) continue;
|
|
25
|
+
|
|
26
|
+
if (typeof input === "string") {
|
|
27
|
+
classes.push(input);
|
|
28
|
+
} else if (typeof input === "object") {
|
|
29
|
+
for (const [key, value] of Object.entries(input)) {
|
|
30
|
+
if (value) {
|
|
31
|
+
classes.push(key);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return classes.join(" ");
|
|
38
|
+
}
|
|
@@ -6,7 +6,7 @@ import { MenuButton } from "./MenuButton";
|
|
|
6
6
|
import { MenuItem } from "./ActionMenu";
|
|
7
7
|
|
|
8
8
|
const meta: Meta<typeof MenuButton> = {
|
|
9
|
-
title: "
|
|
9
|
+
title: "Components/Menus/v3/MenuButton",
|
|
10
10
|
component: MenuButton,
|
|
11
11
|
decorators: [
|
|
12
12
|
(Story) => (
|
|
@@ -1,38 +1,59 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { Button } from "@sproutsocial/seeds-react-button";
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Button, type TypeButtonProps } from "@sproutsocial/seeds-react-button";
|
|
3
|
+
import { cn } from "./Common/cn";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
/**
|
|
6
|
+
* v3 MenuButton (split button) surface, rendered with CSS classes from menu.css
|
|
7
|
+
* (imported via @sproutsocial/seeds-react-menu/base/css) instead of
|
|
8
|
+
* styled-components. Each export keeps its previous name.
|
|
9
|
+
*
|
|
10
|
+
* MainButton / TriggerButton square off the inner corners so the two halves
|
|
11
|
+
* read as one control. The class rules use doubled selectors to reproduce the
|
|
12
|
+
* old `&&` specificity bump; Button forwards `className` and spreads `data-*`
|
|
13
|
+
* (including Base UI's `data-popup-open`) onto its root DOM node, so the chevron
|
|
14
|
+
* rotation selector `.seeds-menu-button-trigger[data-popup-open] .Icon-svg`
|
|
15
|
+
* still resolves.
|
|
16
|
+
*
|
|
17
|
+
* These forward refs and spread all props so Base UI's `Menu.Trigger render`
|
|
18
|
+
* can inject its ref, `data-popup-open`, and event handlers onto the trigger —
|
|
19
|
+
* matching what `styled(Button)` did previously.
|
|
20
|
+
*/
|
|
10
21
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
export const MenuButtonContainer = React.forwardRef<
|
|
23
|
+
HTMLDivElement,
|
|
24
|
+
React.ComponentProps<"div">
|
|
25
|
+
>(({ className, ...rest }, ref) => (
|
|
26
|
+
<div
|
|
27
|
+
ref={ref}
|
|
28
|
+
className={cn("seeds-menu-button-container", className)}
|
|
29
|
+
{...rest}
|
|
30
|
+
/>
|
|
31
|
+
));
|
|
32
|
+
MenuButtonContainer.displayName = "MenuButtonContainer";
|
|
20
33
|
|
|
21
|
-
// Square off the inner (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
transition: transform ${({ theme }) => theme.duration.fast} ease;
|
|
33
|
-
}
|
|
34
|
+
// Square off the inner (right) corners of the main button.
|
|
35
|
+
export const MainButton = React.forwardRef<HTMLButtonElement, TypeButtonProps>(
|
|
36
|
+
({ className, ...rest }, ref) => (
|
|
37
|
+
<Button
|
|
38
|
+
ref={ref}
|
|
39
|
+
className={cn("seeds-menu-button-main", className)}
|
|
40
|
+
{...rest}
|
|
41
|
+
/>
|
|
42
|
+
)
|
|
43
|
+
);
|
|
44
|
+
MainButton.displayName = "MainButton";
|
|
34
45
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
46
|
+
// Square off the inner (left) corners of the chevron trigger button. The
|
|
47
|
+
// chevron rotates 180° while the menu is open: Base UI's Menu.Trigger sets
|
|
48
|
+
// `data-popup-open` on this element (Button spreads it onto its root DOM node).
|
|
49
|
+
export const TriggerButton = React.forwardRef<
|
|
50
|
+
HTMLButtonElement,
|
|
51
|
+
TypeButtonProps
|
|
52
|
+
>(({ className, ...rest }, ref) => (
|
|
53
|
+
<Button
|
|
54
|
+
ref={ref}
|
|
55
|
+
className={cn("seeds-menu-button-trigger", className)}
|
|
56
|
+
{...rest}
|
|
57
|
+
/>
|
|
58
|
+
));
|
|
59
|
+
TriggerButton.displayName = "TriggerButton";
|
|
@@ -138,7 +138,7 @@ function AllComponents() {
|
|
|
138
138
|
// ─── Meta ─────────────────────────────────────────────────────────────────────
|
|
139
139
|
|
|
140
140
|
const meta: Meta = {
|
|
141
|
-
title: "
|
|
141
|
+
title: "Components/Menus/v3/In Modal",
|
|
142
142
|
};
|
|
143
143
|
|
|
144
144
|
export default meta;
|
package/src/v3/MultiCombobox.tsx
CHANGED
|
@@ -74,6 +74,9 @@ interface MultiComboboxBaseProps {
|
|
|
74
74
|
filter?: ((item: unknown, query: string) => boolean) | null;
|
|
75
75
|
inputValue?: string;
|
|
76
76
|
onInputValueChange?: (value: string) => void;
|
|
77
|
+
"aria-label"?: string;
|
|
78
|
+
/** Id of a visible label. Preferred over `aria-label`. */
|
|
79
|
+
"aria-labelledby"?: string;
|
|
77
80
|
"aria-describedby"?: string;
|
|
78
81
|
isInvalid?: boolean;
|
|
79
82
|
required?: boolean;
|
|
@@ -150,6 +153,8 @@ export function MultiCombobox<T extends DataWithId>(
|
|
|
150
153
|
fullWidth = true,
|
|
151
154
|
} = props;
|
|
152
155
|
const ariaDescribedBy = props["aria-describedby"];
|
|
156
|
+
const ariaLabel = props["aria-label"];
|
|
157
|
+
const ariaLabelledBy = props["aria-labelledby"];
|
|
153
158
|
const isInvalid = props.isInvalid;
|
|
154
159
|
|
|
155
160
|
const isChildrenMode = "children" in props && props.children != null;
|
|
@@ -674,6 +679,8 @@ export function MultiCombobox<T extends DataWithId>(
|
|
|
674
679
|
<ComboboxStatus>{isLoading ? loadingText : null}</ComboboxStatus>
|
|
675
680
|
<ComboboxEmpty>{isLoading ? null : emptyText}</ComboboxEmpty>
|
|
676
681
|
<ComboboxList
|
|
682
|
+
aria-label={ariaLabel}
|
|
683
|
+
aria-labelledby={ariaLabelledBy}
|
|
677
684
|
style={
|
|
678
685
|
isVirtualized
|
|
679
686
|
? {
|