Skip to content

Commit 69dd03f

Browse files
committed
feat(design-system): add autocomplete [AR-38986]
1 parent f36f9f4 commit 69dd03f

File tree

8 files changed

+822
-2
lines changed

8 files changed

+822
-2
lines changed
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
@use '../../styles/shared/dropdown';
2+
@use '../../styles/shared/input';
3+
4+
$autocomplete-input-height: 36px;
5+
$autocomplete-max-visible-items: 4;
6+
$autocomplete-item-height: 38px;
7+
$autocomplete-dropdown-max-height: calc($autocomplete-max-visible-items * $autocomplete-item-height);
8+
$autocomplete-trigger-size: 24px;
9+
$autocomplete-trigger-border-radius: 4px;
10+
$autocomplete-highlight-border-radius: 2px;
11+
$autocomplete-animation-duration: 0.2s;
12+
$autocomplete-animation-translate: -8px;
13+
$autocomplete-outline-width: 2px;
14+
$autocomplete-outline-offset: 2px;
15+
$autocomplete-rotation-open: 180deg;
16+
$autocomplete-opacity-hidden: 0;
17+
$autocomplete-opacity-visible: 1;
18+
19+
.root {
20+
position: relative;
21+
width: 100%;
22+
display: inline-flex;
23+
flex-direction: column;
24+
}
25+
26+
.control {
27+
@include input.base-input-container;
28+
@include input.input-container-states;
29+
display: flex;
30+
align-items: center;
31+
gap: var(--spacing-3xs);
32+
cursor: text;
33+
height: $autocomplete-input-height;
34+
min-height: $autocomplete-input-height;
35+
max-height: $autocomplete-input-height;
36+
37+
&[data-focus] {
38+
border-color: var(--form-control-border-color, var(--color-border-action-primary)) !important;
39+
}
40+
41+
&[data-invalid] {
42+
border-color: var(--color-background-danger-strong);
43+
}
44+
}
45+
46+
.input {
47+
@include input.base-input;
48+
flex: 1;
49+
min-width: 0;
50+
outline: none;
51+
52+
&::placeholder {
53+
color: var(--color-font-placeholder);
54+
}
55+
}
56+
57+
.startAdornment {
58+
display: flex;
59+
align-items: center;
60+
justify-content: center;
61+
color: var(--color-background-action);
62+
flex-shrink: 0;
63+
}
64+
65+
.iconContainer {
66+
display: flex;
67+
align-items: center;
68+
gap: var(--spacing-3xs);
69+
flex-shrink: 0;
70+
}
71+
72+
.clearButton {
73+
@include input.icon-button;
74+
cursor: pointer;
75+
opacity: $autocomplete-opacity-hidden;
76+
visibility: hidden;
77+
transition: opacity $autocomplete-animation-duration ease;
78+
79+
&:hover {
80+
color: var(--color-background-action-hover);
81+
}
82+
}
83+
84+
.control:hover .clearButton,
85+
.control[data-focus] .clearButton {
86+
opacity: $autocomplete-opacity-visible;
87+
visibility: visible;
88+
}
89+
90+
.trigger {
91+
display: flex;
92+
align-items: center;
93+
justify-content: center;
94+
color: var(--color-background-deselected);
95+
transition:
96+
transform $autocomplete-animation-duration ease-in-out,
97+
background-color $autocomplete-animation-duration ease,
98+
color $autocomplete-animation-duration ease;
99+
cursor: pointer;
100+
background: transparent;
101+
border: none;
102+
padding: 0;
103+
border-radius: $autocomplete-trigger-border-radius;
104+
width: $autocomplete-trigger-size;
105+
height: $autocomplete-trigger-size;
106+
107+
&:hover {
108+
color: var(--color-background-deselected-hover);
109+
background: var(--color-background-action-hover-weak);
110+
}
111+
112+
&[data-state='open'] {
113+
transform: rotate($autocomplete-rotation-open);
114+
color: var(--color-background-deselected-hover);
115+
background: var(--color-background-action-hover-weak);
116+
}
117+
118+
&:focus-visible {
119+
outline: $autocomplete-outline-width solid var(--color-focus);
120+
outline-offset: $autocomplete-outline-offset;
121+
}
122+
}
123+
124+
.control[data-focus] .trigger {
125+
color: var(--color-background-deselected-hover);
126+
background: var(--color-background-action-hover-weak);
127+
}
128+
129+
.positioner {
130+
z-index: var(--z-index-dropdown, 9999);
131+
width: var(--reference-width);
132+
}
133+
134+
.content {
135+
@include dropdown.dropdown-content;
136+
overflow: hidden;
137+
animation: expand $autocomplete-animation-duration ease;
138+
width: 100%;
139+
min-width: var(--reference-width);
140+
max-height: $autocomplete-dropdown-max-height;
141+
142+
&[data-state='open'] {
143+
animation: expand $autocomplete-animation-duration ease;
144+
}
145+
146+
&[data-state='closed'] {
147+
animation: collapse $autocomplete-animation-duration ease;
148+
}
149+
}
150+
151+
.itemGroup {
152+
overflow-y: auto;
153+
overflow-x: hidden;
154+
max-height: $autocomplete-dropdown-max-height;
155+
scrollbar-width: thin;
156+
}
157+
158+
.item {
159+
@include dropdown.dropdown-item;
160+
display: flex;
161+
align-items: center;
162+
gap: var(--spacing-xs);
163+
height: $autocomplete-item-height;
164+
min-height: $autocomplete-item-height;
165+
166+
&[data-highlighted] {
167+
background: var(--color-background-secondary-selected-weak);
168+
}
169+
}
170+
171+
.itemIcon {
172+
color: var(--color-background-deselected);
173+
flex-shrink: 0;
174+
display: flex;
175+
align-items: center;
176+
}
177+
178+
.itemText {
179+
flex: 1;
180+
overflow: hidden;
181+
text-overflow: ellipsis;
182+
white-space: nowrap;
183+
184+
mark {
185+
background-color: var(--color-data-yellow);
186+
color: var(--color-font-main);
187+
font-weight: var(--font-weight-medium);
188+
padding: 0;
189+
border-radius: $autocomplete-highlight-border-radius;
190+
}
191+
}
192+
193+
.highlight {
194+
background-color: var(--color-data-yellow);
195+
color: var(--color-font-main);
196+
font-weight: var(--font-weight-medium);
197+
padding: 0;
198+
border-radius: $autocomplete-highlight-border-radius;
199+
}
200+
201+
.noMatches,
202+
.loading {
203+
padding: var(--spacing-xs);
204+
color: var(--color-font-disabled);
205+
text-align: center;
206+
font-size: var(--font-size-sm);
207+
}
208+
209+
.loading {
210+
display: flex;
211+
align-items: center;
212+
justify-content: center;
213+
gap: var(--spacing-xs);
214+
}
215+
216+
.disabled {
217+
.control {
218+
color: var(--color-background-deselected);
219+
background: var(--color-background-secondary);
220+
border-color: var(--color-border-disabled);
221+
cursor: not-allowed;
222+
223+
.input {
224+
color: var(--color-font-disabled);
225+
cursor: not-allowed;
226+
}
227+
228+
.trigger {
229+
color: var(--color-background-disable);
230+
cursor: not-allowed;
231+
background: transparent;
232+
233+
&:hover {
234+
background: transparent;
235+
color: var(--color-background-disable);
236+
}
237+
}
238+
}
239+
}
240+
241+
.invalid {
242+
.control {
243+
border-color: var(--color-background-danger-strong);
244+
245+
&:hover,
246+
&[data-focus] {
247+
border-color: var(--color-background-danger-strong) !important;
248+
}
249+
}
250+
}
251+
252+
@keyframes expand {
253+
0% {
254+
opacity: $autocomplete-opacity-hidden;
255+
transform: translateY($autocomplete-animation-translate);
256+
}
257+
258+
100% {
259+
opacity: $autocomplete-opacity-visible;
260+
transform: translateY(0);
261+
}
262+
}
263+
264+
@keyframes collapse {
265+
0% {
266+
opacity: $autocomplete-opacity-visible;
267+
transform: translateY(0);
268+
}
269+
270+
100% {
271+
opacity: $autocomplete-opacity-hidden;
272+
transform: translateY($autocomplete-animation-translate);
273+
}
274+
}

0 commit comments

Comments
 (0)