Skip to content

Commit 2438ebb

Browse files
authored
RI-7817: clear search button spacing (#5274)
* fix(ui): migrate MultiSearch styles to styled-components Migrate MultiSearch component from SCSS modules to styled-components for better theme integration and consistency. References: #RI-7817
1 parent e604286 commit 2438ebb

File tree

3 files changed

+204
-205
lines changed

3 files changed

+204
-205
lines changed
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import { HTMLAttributes } from 'react'
2+
import styled from 'styled-components'
3+
import { Theme } from 'uiSrc/components/base/theme/types'
4+
import { Row } from 'uiSrc/components/base/layout/flex'
5+
import { TextInput } from 'uiSrc/components/base/inputs'
6+
import {
7+
ActionIconButton,
8+
IconButton,
9+
} from 'uiSrc/components/base/forms/buttons'
10+
import GroupBadge from 'uiSrc/components/group-badge'
11+
12+
interface StyledMultiSearchProps extends HTMLAttributes<HTMLDivElement> {
13+
$isFocused: boolean
14+
}
15+
16+
interface StyledSuggestionProps extends HTMLAttributes<HTMLLIElement> {
17+
$isFocused?: boolean
18+
}
19+
20+
export const StyledMultiSearch = styled(Row)<StyledMultiSearchProps>`
21+
border: 1px solid
22+
${({ theme, $isFocused }: { theme: Theme; $isFocused: boolean }) =>
23+
$isFocused
24+
? theme.components.input.states.focused.borderColor
25+
: theme.components.input.states.normal.borderColor};
26+
background-color: ${({ theme }: { theme: Theme }) =>
27+
theme.components.input.states.normal.bgColor};
28+
border-radius: 4px;
29+
30+
position: relative;
31+
flex: 1;
32+
height: 100%;
33+
padding: 5px 6px 5px 0;
34+
background-repeat: no-repeat;
35+
background-size: 0 100%;
36+
transition:
37+
box-shadow 150ms ease-in,
38+
background-image 150ms ease-in,
39+
background-size 150ms ease-in,
40+
background-color 150ms ease-in;
41+
`
42+
/**
43+
* Auto-suggestions dropdown container
44+
* Replaces: .autoSuggestions
45+
*/
46+
export const StyledAutoSuggestions = styled.div<React.HTMLAttributes<HTMLDivElement>>`
47+
background-color: ${({ theme }) => theme.components.select.dropdown.bgColor};
48+
border: 1px solid
49+
${({ theme }) => theme.components.select.states.disabled.borderColor};
50+
position: absolute;
51+
top: calc(100% + ${({ theme }) => theme.core.space.space025});
52+
left: 0;
53+
width: 100%;
54+
min-width: calc(
55+
${({ theme }) => theme.core.space.space550} * 4
56+
); // 176px instead of hardcoded 180px
57+
58+
border-radius: ${({ theme }) => theme.core.space.space050};
59+
z-index: 1001;
60+
padding: ${({ theme }) => theme.core.space.space050} 0 0;
61+
`
62+
63+
export const StyledMultiSearchWrapper = styled(Row)<
64+
React.HTMLAttributes<HTMLDivElement>
65+
>`
66+
flex: 1;
67+
padding-bottom: 0;
68+
height: 100%;
69+
min-height: 36px;
70+
`
71+
72+
export const StyledClearHistory = styled.li<
73+
React.HTMLAttributes<HTMLDivElement>
74+
>`
75+
border-top: 1px solid
76+
${({ theme }: { theme: Theme }) => theme.semantic.color.border.neutral400};
77+
padding: 8px 10px;
78+
text-align: left;
79+
80+
display: flex;
81+
align-items: center;
82+
83+
cursor: pointer;
84+
user-select: none;
85+
86+
&:hover {
87+
background: ${({ theme }) =>
88+
theme.components.select.dropdown.option.states.highlighted.bgColor};
89+
}
90+
`
91+
92+
export const StyledSearchInput = styled(TextInput)`
93+
flex: 1;
94+
background-color: transparent;
95+
max-width: 100%;
96+
border: none;
97+
height: 100%;
98+
padding: 0 6px 0 10px;
99+
background-image: none;
100+
`
101+
102+
/**
103+
* Remove button within suggestion item
104+
* Replaces: .suggestionRemoveBtn
105+
* Note: Defined before StyledSuggestion so it can be referenced in selectors
106+
*/
107+
export const StyledSuggestionRemoveBtn = styled(IconButton)`
108+
flex-shrink: 0;
109+
visibility: hidden;
110+
pointer-events: none;
111+
`
112+
113+
/**
114+
* Individual suggestion item in the dropdown
115+
* Replaces: .suggestion
116+
*/
117+
export const StyledSuggestion = styled.li<StyledSuggestionProps>`
118+
display: flex;
119+
align-items: center;
120+
text-align: left;
121+
padding: ${({ theme }) => theme.core.space.space050}
122+
${({ theme }) => theme.core.space.space100};
123+
cursor: default;
124+
125+
${({ $isFocused, theme }) =>
126+
$isFocused &&
127+
`background: ${theme.components.select.dropdown.option.states.highlighted.bgColor};`}
128+
129+
&:hover {
130+
background: ${({ theme }) =>
131+
theme.components.select.dropdown.option.states.highlighted.bgColor};
132+
}
133+
134+
/* Show remove button on hover or when focused */
135+
&:hover ${StyledSuggestionRemoveBtn} {
136+
visibility: visible;
137+
pointer-events: auto;
138+
}
139+
140+
${({ $isFocused }) =>
141+
$isFocused &&
142+
`& ${StyledSuggestionRemoveBtn} {
143+
visibility: visible;
144+
pointer-events: auto;
145+
}`}
146+
`
147+
148+
/**
149+
* GroupBadge wrapper within suggestion item
150+
* Replaces: .suggestionOption
151+
*/
152+
export const StyledSuggestionOption = styled(GroupBadge)`
153+
margin-right: ${({ theme }) => theme.core.space.space100};
154+
`
155+
156+
/**
157+
* Text content within a suggestion item
158+
* Replaces: .suggestionText
159+
*/
160+
export const StyledSuggestionText = styled.span<
161+
HTMLAttributes<HTMLSpanElement>
162+
>`
163+
text-overflow: ellipsis;
164+
overflow: hidden;
165+
white-space: nowrap;
166+
flex-grow: 1;
167+
line-height: 1.4;
168+
`
169+
/**
170+
* Clear/Reset filters button
171+
* Replaces: .clearButton
172+
*/
173+
export const StyledClearButton = styled(ActionIconButton)`
174+
margin-left: ${({ theme }) => theme.core.space.space050};
175+
`

redisinsight/ui/src/components/multi-search/MultiSearch.tsx

Lines changed: 29 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import React, { useEffect, useRef, useState } from 'react'
2-
import cx from 'classnames'
32

43
import * as keys from 'uiSrc/constants/keys'
5-
import { TextInput } from 'uiSrc/components/base/inputs'
64
import { GroupBadge, RiTooltip } from 'uiSrc/components'
75
import { OutsideClickDetector } from 'uiSrc/components/base/utils'
86
import { Nullable } from 'uiSrc/utils'
@@ -12,49 +10,23 @@ import {
1210
SearchIcon,
1311
SwitchIcon,
1412
} from 'uiSrc/components/base/icons'
15-
import {
16-
ActionIconButton,
17-
IconButton,
18-
} from 'uiSrc/components/base/forms/buttons'
13+
import { IconButton } from 'uiSrc/components/base/forms/buttons'
1914
import { RiIcon } from 'uiSrc/components/base/icons/RiIcon'
2015
import { ProgressBarLoader } from 'uiSrc/components/base/display'
21-
import styles from './styles.module.scss'
22-
import styled from 'styled-components'
23-
import { Theme } from 'uiSrc/components/base/theme/types'
24-
25-
interface StyledMultiSearchProps extends React.HTMLAttributes<HTMLDivElement> {
26-
$isFocused: boolean
27-
}
28-
29-
const StyledMultiSearch = styled.div<StyledMultiSearchProps>`
30-
border: 1px solid
31-
${({ theme, $isFocused }: { theme: Theme; $isFocused: boolean }) =>
32-
$isFocused
33-
? theme.components.input.states.focused.borderColor
34-
: theme.components.input.states.normal.borderColor};
35-
background-color: ${({ theme }: { theme: Theme }) =>
36-
theme.components.input.states.normal.bgColor};
37-
border-radius: 4px;
38-
`
39-
const StyledAutoSuggestions = styled.div<React.HTMLAttributes<HTMLDivElement>>`
40-
background-color: ${({ theme }: { theme: Theme }) =>
41-
theme.components.select.dropdown.bgColor};
42-
border-color: ${({ theme }: { theme: Theme }) =>
43-
theme.components.select.states.disabled.borderColor};
44-
`
45-
const StyledSuggestion = styled.li<React.HTMLAttributes<HTMLLIElement>>`
46-
&:hover {
47-
background: ${({ theme }: { theme: Theme }) =>
48-
theme.components.select.dropdown.option.states.highlighted.bgColor};
49-
}
50-
`
16+
import {
17+
StyledAutoSuggestions,
18+
StyledClearButton,
19+
StyledClearHistory,
20+
StyledMultiSearch,
21+
StyledMultiSearchWrapper,
22+
StyledSearchInput,
23+
StyledSuggestion,
24+
StyledSuggestionOption,
25+
StyledSuggestionRemoveBtn,
26+
StyledSuggestionText,
27+
} from './MultiSearch.styles'
5128

52-
const StyledClearHistory = styled.li<React.HTMLAttributes<HTMLDivElement>>`
53-
&:hover {
54-
background: ${({ theme }: { theme: Theme }) =>
55-
theme.components.select.dropdown.option.states.highlighted.bgColor};
56-
}
57-
`
29+
import { Text } from 'uiSrc/components/base/text'
5830

5931
interface MultiSearchSuggestion {
6032
options: null | Array<{
@@ -201,18 +173,14 @@ const MultiSearch = (props: Props) => {
201173

202174
return (
203175
<OutsideClickDetector onOutsideClick={exitAutoSuggestions}>
204-
<div
205-
className={cx(styles.multiSearchWrapper, className)}
176+
<StyledMultiSearchWrapper
177+
align="center"
178+
className={className}
206179
onKeyDown={handleKeyDown}
207180
role="presentation"
208181
data-testid="multi-search"
209182
>
210-
<StyledMultiSearch
211-
$isFocused={isInputFocus}
212-
className={cx(styles.multiSearch, {
213-
[styles.isFocused]: isInputFocus,
214-
})}
215-
>
183+
<StyledMultiSearch align="center" gap="m" $isFocused={isInputFocus}>
216184
<div>
217185
{options.map((option) => (
218186
<GroupBadge
@@ -223,8 +191,7 @@ const MultiSearch = (props: Props) => {
223191
/>
224192
))}
225193
</div>
226-
<TextInput
227-
className={styles.multiSearchInput}
194+
<StyledSearchInput
228195
placeholder={placeholder}
229196
value={value}
230197
onKeyDown={handleKeyDown}
@@ -237,7 +204,6 @@ const MultiSearch = (props: Props) => {
237204
{showAutoSuggestions && !!suggestionOptions?.length && (
238205
<StyledAutoSuggestions
239206
role="presentation"
240-
className={styles.autoSuggestions}
241207
data-testid="suggestions"
242208
>
243209
{suggestions?.loading && (
@@ -252,28 +218,21 @@ const MultiSearch = (props: Props) => {
252218
value && (
253219
<StyledSuggestion
254220
key={id}
255-
className={cx(styles.suggestion, {
256-
[styles.focused]: focusedItem === index,
257-
})}
221+
$isFocused={focusedItem === index}
258222
onClick={() => handleApplySuggestion(index)}
259223
role="presentation"
260224
data-testid={`suggestion-item-${id}`}
261225
>
262226
{option && (
263-
<GroupBadge
227+
<StyledSuggestionOption
264228
type={option}
265229
compressed={compressed}
266-
className={styles.suggestionOption}
267230
/>
268231
)}
269-
<span
270-
className={styles.suggestionText}
271-
data-testid="suggestion-item-text"
272-
>
232+
<StyledSuggestionText data-testid="suggestion-item-text">
273233
{value}
274-
</span>
275-
<IconButton
276-
className={styles.suggestionRemoveBtn}
234+
</StyledSuggestionText>
235+
<StyledSuggestionRemoveBtn
277236
icon={CancelSlimIcon}
278237
color="primary"
279238
aria-label="Remove History Record"
@@ -289,7 +248,6 @@ const MultiSearch = (props: Props) => {
289248
</ul>
290249
<StyledClearHistory
291250
role="presentation"
292-
className={styles.clearHistory}
293251
onClick={() =>
294252
handleDeleteSuggestion(
295253
suggestionOptions?.map((item) => item.id),
@@ -298,18 +256,19 @@ const MultiSearch = (props: Props) => {
298256
data-testid="clear-history-btn"
299257
>
300258
<RiIcon type="EraserIcon" style={{ marginRight: 6 }} />
301-
<span>Clear history</span>
259+
<Text component="span" size="m">
260+
Clear history
261+
</Text>
302262
</StyledClearHistory>
303263
</StyledAutoSuggestions>
304264
)}
305265
{(value || !!options.length) && (
306266
<RiTooltip content="Reset Filters" position="bottom">
307-
<ActionIconButton
267+
<StyledClearButton
308268
icon={CancelSlimIcon}
309269
size="XS"
310270
aria-label="Reset Filters"
311271
onClick={onClear}
312-
className={styles.clearButton}
313272
data-testid="reset-filter-btn"
314273
variant="secondary"
315274
/>
@@ -336,15 +295,14 @@ const MultiSearch = (props: Props) => {
336295
{disableSubmit && (
337296
<RiTooltip
338297
position="top"
339-
anchorClassName={styles.anchorSubmitBtn}
340298
content="Please choose index in order to preform the search"
341299
>
342300
{SubmitBtn()}
343301
</RiTooltip>
344302
)}
345303
{!disableSubmit && SubmitBtn()}
346304
</StyledMultiSearch>
347-
</div>
305+
</StyledMultiSearchWrapper>
348306
</OutsideClickDetector>
349307
)
350308
}

0 commit comments

Comments
 (0)