@sproutsocial/seeds-react-menu 1.17.0 → 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.
Files changed (59) hide show
  1. package/.turbo/turbo-build.log +14 -22
  2. package/CHANGELOG.md +30 -0
  3. package/dist/esm/index.js +542 -229
  4. package/dist/esm/index.js.map +1 -1
  5. package/dist/esm/v3/index.js +793 -1038
  6. package/dist/esm/v3/index.js.map +1 -1
  7. package/dist/v3/index.d.mts +64 -38
  8. package/dist/v3/index.d.ts +64 -38
  9. package/dist/v3/index.js +813 -1058
  10. package/dist/v3/index.js.map +1 -1
  11. package/dist/v3/menu.css +947 -0
  12. package/package.json +20 -21
  13. package/src/v3/ActionMenuStyles.tsx +169 -149
  14. package/src/v3/Common/ComboboxStyles.tsx +396 -511
  15. package/src/v3/Common/SelectIcons.tsx +17 -8
  16. package/src/v3/Common/SelectItem.tsx +25 -38
  17. package/src/v3/Common/SelectStyles.tsx +146 -144
  18. package/src/v3/Common/cn.ts +38 -0
  19. package/src/v3/MenuButtonStyles.tsx +55 -34
  20. package/src/v3/MultiSearchableSelect.tsx +8 -8
  21. package/src/v3/MultiSelect.tsx +11 -16
  22. package/src/v3/SingleSelect.tsx +13 -13
  23. package/src/v3/menu.css +947 -0
  24. package/tsup.config.ts +0 -1
  25. package/dist/esm/chunk-ROQATIB7.js +0 -357
  26. package/dist/esm/chunk-ROQATIB7.js.map +0 -1
  27. package/dist/esm/v2/index.js +0 -2089
  28. package/dist/esm/v2/index.js.map +0 -1
  29. package/dist/v2/index.d.mts +0 -108
  30. package/dist/v2/index.d.ts +0 -108
  31. package/dist/v2/index.js +0 -2280
  32. package/dist/v2/index.js.map +0 -1
  33. package/src/v2/Autocomplete/Autocomplete.stories.tsx +0 -645
  34. package/src/v2/Autocomplete/MultiAutocomplete.tsx +0 -487
  35. package/src/v2/Autocomplete/SingleAutocomplete.tsx +0 -366
  36. package/src/v2/Autocomplete/index.ts +0 -2
  37. package/src/v2/Common-V2/ComboboxContent.tsx +0 -457
  38. package/src/v2/Common-V2/MenuGroup.tsx +0 -60
  39. package/src/v2/Common-V2/MenuGroupTypes.ts +0 -30
  40. package/src/v2/Common-V2/MenuHeading.tsx +0 -83
  41. package/src/v2/Common-V2/MenuItem.tsx +0 -138
  42. package/src/v2/Common-V2/Popout.tsx +0 -124
  43. package/src/v2/Common-V2/PopoutTypes.tsx +0 -109
  44. package/src/v2/Common-V2/SelectToggleButton.tsx +0 -99
  45. package/src/v2/Common-V2/index.ts +0 -11
  46. package/src/v2/Common-V2/props.ts +0 -84
  47. package/src/v2/Common-V2/styles.tsx +0 -41
  48. package/src/v2/Common-V2/types.ts +0 -16
  49. package/src/v2/Common-V2/useHighlightedIndex.ts +0 -62
  50. package/src/v2/Common-V2/utils.ts +0 -238
  51. package/src/v2/SearchableSelect/AutocompleteContent.tsx +0 -325
  52. package/src/v2/SearchableSelect/SearchableMultiSelect.tsx +0 -527
  53. package/src/v2/SearchableSelect/SearchableSelect.tsx +0 -395
  54. package/src/v2/SearchableSelect/index.ts +0 -12
  55. package/src/v2/Select/MultiSelect.tsx +0 -417
  56. package/src/v2/Select/Select.stories.tsx +0 -593
  57. package/src/v2/Select/SingleSelect.tsx +0 -285
  58. package/src/v2/Select/index.ts +0 -2
  59. 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 = styled.div<StyledChevronProps>`
10
- display: flex;
11
- align-items: center;
12
- transition: transform 0.15s;
13
- ${({ $isOpen }) => $isOpen && "transform: rotate(-180deg);"}
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
- // ─── Styled components ────────────────────────────────────────────────────────
8
+ // ─── CSS-class components (see menu.css) ────────────────────────────────────
9
9
 
10
- export const StyledItem = styled(Select.Item)`
11
- display: flex;
12
- align-items: center;
13
- gap: 8px;
14
- padding: 6px 8px;
15
- border-radius: ${({ theme }) => theme.radii[500]};
16
- font-size: 14px;
17
- color: ${({ theme }) => theme.colors.text.body};
18
- cursor: default;
19
- outline: none;
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
- &[data-highlighted] {
22
- background: ${({ theme }) => theme.colors.listItem.background.hover};
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
- &[data-selected] {
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 styled, { css } from "styled-components";
3
- import { focusRing } from "@sproutsocial/seeds-react-mixins";
4
- import { StyledChevron } from "./SelectIcons";
5
-
6
- const invalidStyles = css`
7
- border-color: ${({ theme }) => theme.colors.form.border.error};
8
-
9
- ${StyledChevron} {
10
- color: ${({ theme }) => theme.colors.icon.error};
11
- }
12
- `;
13
-
14
- export const Field = styled.div<{ $fullWidth?: boolean }>`
15
- display: ${({ $fullWidth }) =>
16
- $fullWidth === false ? "inline-flex" : "flex"};
17
- flex-direction: column;
18
- gap: ${({ theme }) => theme.space[200]};
19
- ${({ $fullWidth }) => $fullWidth !== false && "width: 100%;"}
20
- `;
21
-
22
- export const SelectLabel = styled(Select.Label)`
23
- font-size: ${({ theme }) => theme.typography[200].fontSize};
24
- font-weight: ${({ theme }) => theme.fontWeights.semibold};
25
- color: ${({ theme }) => theme.colors.text.body};
26
- `;
27
-
28
- export const SelectTrigger = styled(Select.Trigger)<{
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
- display: flex;
32
- align-items: center;
33
- justify-content: space-between;
34
- gap: ${({ theme }) => theme.space[300]};
35
- padding: ${({ theme }) => `${theme.space[300]}`};
36
- min-width: 160px;
37
- border-radius: ${({ theme }) => theme.radii[500]};
38
- border: 1px solid ${({ theme }) => theme.colors.form.border.base};
39
- background: ${({ theme }) => theme.colors.form.background.base};
40
- font-size: ${({ theme }) => theme.typography[200].fontSize};
41
- color: ${({ theme }) => theme.colors.text.body};
42
- cursor: default;
43
- outline: none;
44
- transition: border-color ${({ theme }) => theme.duration.fast}
45
- ${({ theme }) => theme.easing.ease_in},
46
- box-shadow ${({ theme }) => theme.duration.fast}
47
- ${({ theme }) => theme.easing.ease_in};
48
-
49
- &:focus-visible {
50
- ${focusRing}
51
- }
52
-
53
- &[data-popup-open] {
54
- ${focusRing}
55
- }
56
-
57
- &[data-popup-open] [data-chevron] {
58
- transform: rotate(-180deg);
59
- }
60
-
61
- &[data-disabled] {
62
- opacity: 0.4;
63
- cursor: not-allowed;
64
- }
65
-
66
- ${({ $isInvalid }) => $isInvalid && invalidStyles}
67
- `;
68
-
69
- export const SelectValue = styled(Select.Value)`
70
- min-width: 0;
71
- overflow: hidden;
72
- `;
73
-
74
- export const SelectIcon = styled(Select.Icon)`
75
- display: flex;
76
- align-items: center;
77
- color: ${({ theme }) => theme.colors.icon.base};
78
- flex-shrink: 0;
79
- `;
80
-
81
- export const SelectGroup = styled(Select.Group)`
82
- display: block;
83
- `;
84
-
85
- export const SelectGroupLabel = styled(Select.GroupLabel)`
86
- padding: ${({ theme }) =>
87
- `${theme.space[300]} ${theme.space[300]} ${theme.space[200]}`};
88
- font-size: ${({ theme }) => theme.typography[100].fontSize};
89
- font-weight: ${({ theme }) => theme.fontWeights.semibold};
90
- text-transform: uppercase;
91
- letter-spacing: 0.05em;
92
- color: ${({ theme }) => theme.colors.text.subtext};
93
- `;
94
-
95
- export const SelectSeparator = styled(Select.Separator)`
96
- height: 1px;
97
- margin: ${({ theme }) => `${theme.space[200]} ${theme.space[300]}`};
98
- background: ${({ theme }) => theme.colors.container.border.base};
99
- `;
100
-
101
- export const SelectPositioner = styled(Select.Positioner)`
102
- width: var(--anchor-width);
103
- z-index: 7;
104
- `;
105
-
106
- export const SelectPopup = styled(Select.Popup)`
107
- font-family: ${({ theme }) => theme.fontFamily};
108
- background: ${({ theme }) => theme.colors.container.background.base};
109
- border: 1px solid ${({ theme }) => theme.colors.container.border.base};
110
- border-radius: ${({ theme }) => theme.radii[500]};
111
- box-shadow: ${({ theme }) => theme.shadows.low};
112
- outline: none;
113
- max-height: min(var(--available-height, 400px), 400px);
114
- overflow-y: auto;
115
- padding: ${({ theme }) => theme.space[200]};
116
-
117
- &[data-open] {
118
- animation: select-popup-in 120ms ease-out;
119
- }
120
-
121
- &[data-closed] {
122
- animation: select-popup-out 100ms ease-in;
123
- }
124
-
125
- @keyframes select-popup-in {
126
- from {
127
- opacity: 0;
128
- transform: scale(0.95);
129
- }
130
- to {
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
+ }
@@ -1,38 +1,59 @@
1
- import styled from "styled-components";
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
- // A 1px gap separates the two halves of the split button (fixed pixel value
5
- // per the design, not a theme token).
6
- export const MenuButtonContainer = styled.div`
7
- display: inline-flex;
8
- gap: 1px;
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
- // Square off the inner (right) corners of the main button so it reads as one
12
- // control with the trigger. The `&&` specificity bump beats the base Button
13
- // Container's own `border-radius` (equal-specificity, source-order dependent).
14
- export const MainButton = styled(Button)`
15
- && {
16
- border-top-right-radius: 0;
17
- border-bottom-right-radius: 0;
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 (left) corners of the chevron trigger button. The
22
- // chevron rotates 180° while the menu is open: base-ui's Menu.Trigger sets
23
- // `data-popup-open` on this element (the base Button spreads it onto its root
24
- // DOM node), mirroring the open-state selector convention in ActionMenuStyles.
25
- export const TriggerButton = styled(Button)`
26
- && {
27
- border-top-left-radius: 0;
28
- border-bottom-left-radius: 0;
29
- }
30
-
31
- .Icon-svg {
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
- &[data-popup-open] .Icon-svg {
36
- transform: rotate(180deg);
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";
@@ -32,16 +32,16 @@ import {
32
32
  } from "./Common/ComboboxStyles";
33
33
  import { ClearIcon, StyledChevron, ChevronIcon } from "./Common/SelectIcons";
34
34
  import Icon from "@sproutsocial/seeds-react-icon";
35
- import styled from "styled-components";
35
+ import { cn } from "./Common/cn";
36
36
 
37
- // ─── Styled components ────────────────────────────────────────────────────────
37
+ // ─── CSS-class components (see menu.css) ────────────────────────────────────
38
38
 
39
- const SelectionText = styled.span`
40
- flex: 1;
41
- overflow: hidden;
42
- text-overflow: ellipsis;
43
- white-space: nowrap;
44
- `;
39
+ const SelectionText = ({
40
+ className,
41
+ ...rest
42
+ }: React.ComponentProps<"span">) => (
43
+ <span className={cn("seeds-select-selection-text", className)} {...rest} />
44
+ );
45
45
 
46
46
  // ─── Sentinels ────────────────────────────────────────────────────────────────
47
47
 
@@ -1,6 +1,5 @@
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 { useSeedsPortalContainer } from "./SeedsPortal";
5
4
  import SelectItem from "./Common/SelectItem";
6
5
  import type { DataWithId } from "./Common/types";
@@ -17,25 +16,21 @@ import {
17
16
  SelectPopup,
18
17
  } from "./Common/SelectStyles";
19
18
  import { StyledChevron, ChevronIcon } from "./Common/SelectIcons";
19
+ import { cn } from "./Common/cn";
20
20
 
21
- // ─── Styled components ────────────────────────────────────────────────────────
21
+ // ─── CSS-class components (see menu.css) ────────────────────────────────────
22
22
 
23
- const SelectionText = styled.span`
24
- flex: 1;
25
- overflow: hidden;
26
- text-overflow: ellipsis;
27
- white-space: nowrap;
28
- `;
23
+ const SelectionText = ({
24
+ className,
25
+ ...rest
26
+ }: React.ComponentProps<"span">) => (
27
+ <span className={cn("seeds-select-selection-text", className)} {...rest} />
28
+ );
29
29
 
30
30
  // The styles in here need cleaned up, but in MultiSearchableSelect are correct
31
- const Placeholder = styled.div`
32
- color: ${({ theme }) => theme.colors.text.subtext};
33
- font-size: ${({ theme }) => theme.typography[200].fontSize};
34
- line-height: 16px;
35
- padding-top: 2px;
36
- padding-bottom: 2px;
37
- margin: 2px 8px 0px 0px;
38
- `;
31
+ const Placeholder = ({ className, ...rest }: React.ComponentProps<"div">) => (
32
+ <div className={cn("seeds-select-placeholder", className)} {...rest} />
33
+ );
39
34
 
40
35
  // ─── Props ────────────────────────────────────────────────────────────────────
41
36
 
@@ -1,6 +1,5 @@
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 { useSeedsPortalContainer } from "./SeedsPortal";
5
4
  import SelectItem from "./Common/SelectItem";
6
5
  import type { DataWithId } from "./Common/types";
@@ -16,21 +15,22 @@ import {
16
15
  SelectPopup,
17
16
  } from "./Common/SelectStyles";
18
17
  import { StyledChevron, ChevronIcon } from "./Common/SelectIcons";
18
+ import { cn, type WithStringClassName } from "./Common/cn";
19
19
 
20
20
  // <Listbox(?!\.|B)
21
- // ─── Styled components ────────────────────────────────────────────────────────
21
+ // ─── CSS-class components (see menu.css) ────────────────────────────────────
22
22
 
23
- const StyledValue = styled(Select.Value)`
24
- flex: 1;
25
- text-align: left;
26
- overflow: hidden;
27
- text-overflow: ellipsis;
28
- white-space: nowrap;
29
-
30
- &[data-placeholder] {
31
- color: ${({ theme }) => theme.colors.text.subtext};
32
- }
33
- `;
23
+ const StyledValue = React.forwardRef<
24
+ React.ElementRef<typeof Select.Value>,
25
+ WithStringClassName<React.ComponentProps<typeof Select.Value>>
26
+ >(({ className, ...rest }, ref) => (
27
+ <Select.Value
28
+ ref={ref}
29
+ className={cn("seeds-select-value-text", className)}
30
+ {...rest}
31
+ />
32
+ ));
33
+ StyledValue.displayName = "StyledValue";
34
34
 
35
35
  // ─── Props ────────────────────────────────────────────────────────────────────
36
36