Skip to content

Commit c4267d3

Browse files
authored
Add MultiSelectSearch component (#919)
* Add MultiSelectSearch component TS-1968 * Fixes to PR #919 * Additional fixes to PR #919 * Minor fixes to MultiSelectSearch Add ordering to selected Half-fix onFocus / Tab event interractions Cleanup isNode refs TS-1968
1 parent 06eca41 commit c4267d3

File tree

4 files changed

+405
-0
lines changed

4 files changed

+405
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { StoryFn, Meta } from "@storybook/react";
2+
import React, { useState } from "react";
3+
import { MultiSelectSearch } from "@thunderstore/cyberstorm/src/components/MultiSelectSearch/MultiSelectSearch";
4+
5+
const meta = {
6+
title: "Cyberstorm/Components/MultiSelectSearch",
7+
component: MultiSelectSearch,
8+
} as Meta<typeof MultiSelectSearch>;
9+
10+
const options = [
11+
{ label: "Team 1", value: "Team 1" },
12+
{ label: "Team 2", value: "Team 2" },
13+
{ label: "Team 3", value: "Team 3" },
14+
{ label: "Team 4", value: "Team 4" },
15+
{ label: "Team 5", value: "Team 5" },
16+
{ label: "Team 6", value: "Team 6" },
17+
{ label: "Team 7", value: "Team 7" },
18+
{ label: "Team 8", value: "Team 8" },
19+
{ label: "Team 9", value: "Team 9" },
20+
{ label: "Team 10", value: "Team 10" },
21+
{ label: "Team 11", value: "Team 11" },
22+
{ label: "Team 12", value: "Team 12" },
23+
{ label: "Team 13", value: "Team 13" },
24+
{ label: "Team 14", value: "Team 14" },
25+
];
26+
27+
const defaultArgs = {
28+
placeholder: "Select something",
29+
options: options,
30+
};
31+
32+
const Template: StoryFn<typeof MultiSelectSearch> = (args) => {
33+
const [selected, setSelected] = useState<{ label: string; value: string }[]>(
34+
[]
35+
);
36+
const defaultProps = {
37+
...args,
38+
onChange: (x: { label: string; value: string }[]) => setSelected(x),
39+
value: selected,
40+
};
41+
return (
42+
<div>
43+
<div style={{ color: "white" }}>
44+
Value in state: {selected.map((s) => s.label).join(", ")}
45+
</div>
46+
<MultiSelectSearch {...defaultProps} />
47+
</div>
48+
);
49+
};
50+
51+
const GreenMultiSelectSearch = Template.bind({});
52+
GreenMultiSelectSearch.args = {
53+
...defaultArgs,
54+
color: "green",
55+
};
56+
57+
const RedMultiSelectSearch = Template.bind({});
58+
RedMultiSelectSearch.args = {
59+
...defaultArgs,
60+
color: "red",
61+
};
62+
63+
export { meta as default, GreenMultiSelectSearch, RedMultiSelectSearch };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
.root {
2+
position: relative;
3+
display: flex;
4+
flex-direction: column;
5+
gap: var(--gap--16);
6+
justify-content: flex-end;
7+
width: auto;
8+
min-height: 6rem;
9+
color: var(--color-text--tertiary);
10+
}
11+
12+
.selected {
13+
display: flex;
14+
flex-flow: row wrap;
15+
gap: var(--space--8);
16+
}
17+
18+
.search {
19+
position: relative;
20+
display: flex;
21+
flex-direction: column;
22+
width: auto;
23+
height: 2.75rem;
24+
color: var(--color-text--tertiary);
25+
}
26+
27+
.inputContainer {
28+
display: flex;
29+
flex-direction: row;
30+
align-items: center;
31+
width: 100%;
32+
border: var(--border-width--2) solid var(--border-color);
33+
34+
border-radius: var(--border-radius--8);
35+
background-color: var(--color-surface--4);
36+
37+
--border-color: transparent;
38+
39+
transition: ease-out 300ms;
40+
}
41+
42+
.input {
43+
width: 100%;
44+
margin: var(--space--10) var(--space--14);
45+
font-weight: var(--font-weight-medium);
46+
font-size: var(--font-size--l);
47+
line-height: normal;
48+
background-color: transparent;
49+
}
50+
51+
.inputContainer:hover {
52+
--border-color: var(--color-border--highlight);
53+
}
54+
55+
.inputContainer:focus-within {
56+
color: var(--color-text--default);
57+
background-color: var(--color-black);
58+
59+
--border-color: var(--color-border--highlight);
60+
}
61+
62+
.input::placeholder {
63+
color: var(--color-text--tertiary);
64+
}
65+
66+
.inputContainer[data-color="red"] {
67+
--border-color: var(--color-red--5);
68+
}
69+
70+
.inputContainer[data-color="red"]:hover {
71+
--border-color: var(--color-red--3);
72+
}
73+
74+
.inputContainer[data-color="green"] {
75+
--border-color: var(--color-cyber-green--50);
76+
}
77+
78+
.inputContainer[data-color="green"]:hover {
79+
--border-color: var(--color-cyber-green--80);
80+
}
81+
82+
.clearSearch {
83+
width: 3rem;
84+
height: 100%;
85+
color: #c6c3ff;
86+
background: transparent;
87+
opacity: 0.5;
88+
}
89+
90+
.showMenuButton {
91+
width: 3rem;
92+
height: 100%;
93+
color: #9c9cc4;
94+
background: transparent;
95+
}
96+
97+
.inputButtonDivider {
98+
width: 0.063rem;
99+
height: 1.375rem;
100+
background: #4343a3;
101+
}
102+
103+
.menu {
104+
position: absolute;
105+
top: 3.25rem;
106+
z-index: 9999;
107+
display: flex;
108+
flex-direction: column;
109+
gap: var(--gap--4);
110+
width: 100%;
111+
min-height: 1.5rem;
112+
max-height: 12rem;
113+
padding: var(--space--8) 0;
114+
border: var(--space--px) var(--color-surface--6) solid;
115+
border-radius: var(--border-radius--8);
116+
overflow: hidden;
117+
overflow-y: auto !important;
118+
color: var(--text-color);
119+
background-color: var(--color-surface--2);
120+
box-shadow: var(--box-shadow-default);
121+
visibility: hidden;
122+
123+
--text-color: var(--color-white);
124+
--bg-color: var(--color-surface--4);
125+
}
126+
127+
.menu:where(.visible) {
128+
visibility: visible;
129+
}
130+
131+
.menuLabel {
132+
font-weight: var(--font-weight-medium);
133+
}
134+
135+
.multiSelectItemWrapper {
136+
padding: var(--space--12) var(--space--16);
137+
}
138+
139+
.multiSelectItemWrapper:focus {
140+
background-color: var(--color-surface--6);
141+
}

0 commit comments

Comments
 (0)