Skip to content

Commit 0928a5d

Browse files
fix: multiple UI styles fixes (#1769)
1 parent d62d58b commit 0928a5d

File tree

8 files changed

+169
-48
lines changed

8 files changed

+169
-48
lines changed

.changeset/hot-turkeys-cross.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@strapi/design-system': patch
3+
---
4+
5+
fix: field input padding updated to show correct highlight in autocomplete

.changeset/itchy-rings-listen.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@strapi/design-system': patch
3+
---
4+
5+
fix: ghost button active style border removed

.changeset/soft-zoos-marry.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@strapi/design-system': patch
3+
---
4+
5+
fix: popover default border radius added

docs/stories/04-components/Field.mdx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,11 @@ interface Field {
8282
### With Hint
8383

8484
<Canvas of={FieldStories.Hint} />
85+
86+
### With start action
87+
88+
<Canvas of={FieldStories.WithStartAction} />
89+
90+
### With end action
91+
92+
<Canvas of={FieldStories.WithEndAction} />
Lines changed: 92 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
import { Meta, StoryObj } from '@storybook/react';
22
import { Field } from '@strapi/design-system';
3+
import { Search, Cross } from '@strapi/icons';
34
import { outdent } from 'outdent';
45

5-
interface Props extends Field.Props, Pick<Field.InputProps, 'type' | 'placeholder'> {
6+
interface Props extends Field.Props, Pick<Field.InputProps, 'type' | 'placeholder' | 'startAction' | 'endAction'> {
67
label: string;
78
}
89

910
const meta: Meta<Props> = {
1011
title: 'Components/Field',
11-
render: ({ label, placeholder, type, ...props }) => {
12+
render: ({ label, placeholder, type, startAction, endAction, ...props }) => {
1213
return (
1314
<Field.Root {...props}>
1415
<Field.Label>{label}</Field.Label>
15-
<Field.Input type={type} placeholder={placeholder} />
16+
<Field.Input type={type} placeholder={placeholder} startAction={startAction} endAction={endAction} />
1617
<Field.Error />
1718
<Field.Hint />
1819
</Field.Root>
@@ -29,16 +30,6 @@ const meta: Meta<Props> = {
2930
},
3031
parameters: {
3132
chromatic: { disableSnapshot: false },
32-
docs: {
33-
source: {
34-
code: outdent`
35-
<Field.Root name="firstname">
36-
<Field.Label>First Name</Field.Label>
37-
<Field.Input />
38-
</Field.Root>
39-
`,
40-
},
41-
},
4233
},
4334
};
4435

@@ -48,6 +39,18 @@ type Story = StoryObj<Props>;
4839

4940
export const Base = {
5041
name: 'base',
42+
parameters: {
43+
docs: {
44+
source: {
45+
code: outdent`
46+
<Field.Root>
47+
<Field.Label>First Name</Field.Label>
48+
<Field.Input type="text" placeholder="Ted Lasso" />
49+
</Field.Root>
50+
`,
51+
},
52+
},
53+
},
5154
} satisfies Story;
5255

5356
export const Input = {
@@ -57,18 +60,94 @@ export const Input = {
5760
label: 'New password',
5861
placeholder: 'Enter a new password',
5962
},
63+
parameters: {
64+
docs: {
65+
source: {
66+
code: outdent`
67+
<Field.Root>
68+
<Field.Label>New password</Field.Label>
69+
<Field.Input type="password" placeholder="Enter a new password" />
70+
</Field.Root>
71+
`,
72+
},
73+
},
74+
},
6075
} satisfies Story;
6176

6277
export const Error = {
6378
name: 'error',
6479
args: {
6580
error: 'This field is required',
6681
},
82+
parameters: {
83+
docs: {
84+
source: {
85+
code: outdent`
86+
<Field.Root error="This field is required">
87+
<Field.Label>First Name</Field.Label>
88+
<Field.Input type="text" placeholder="Ted Lasso" />
89+
<Field.Error />
90+
</Field.Root>
91+
`,
92+
},
93+
},
94+
},
6795
} satisfies Story;
6896

6997
export const Hint = {
7098
name: 'hint',
7199
args: {
72100
hint: 'Your full legal name with any middle names',
73101
},
102+
parameters: {
103+
docs: {
104+
source: {
105+
code: outdent`
106+
<Field.Root hint="Your full legal name with any middle names">
107+
<Field.Label>First Name</Field.Label>
108+
<Field.Input type="text" placeholder="Ted Lasso" />
109+
<Field.Hint />
110+
</Field.Root>
111+
`,
112+
},
113+
},
114+
},
115+
} satisfies Story;
116+
117+
export const WithStartAction = {
118+
name: 'with start action',
119+
args: {
120+
startAction: <Search />,
121+
},
122+
parameters: {
123+
docs: {
124+
source: {
125+
code: outdent`
126+
<Field.Root>
127+
<Field.Label>First Name</Field.Label>
128+
<Field.Input type="text" placeholder="Ted Lasso" startAction={<Search />}/>
129+
</Field.Root>
130+
`,
131+
},
132+
},
133+
},
134+
} satisfies Story;
135+
136+
export const WithEndAction = {
137+
name: 'with end action',
138+
args: {
139+
endAction: <Cross />,
140+
},
141+
parameters: {
142+
docs: {
143+
source: {
144+
code: outdent`
145+
<Field.Root>
146+
<Field.Label>First Name</Field.Label>
147+
<Field.Input type="text" placeholder="Ted Lasso" endAction={<Cross />}/>
148+
</Field.Root>
149+
`,
150+
},
151+
},
152+
},
74153
} satisfies Story;

packages/design-system/src/components/Button/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export const getActiveStyle = ({ theme, $variant }: { theme: DefaultTheme; $vari
7777
color: ${theme.colors[`${getVariantColorName($variant)}600`]};
7878
`;
7979
}
80-
if ($variant === TERTIARY) {
80+
if ($variant === TERTIARY || $variant === GHOST) {
8181
return css`
8282
background-color: ${theme.colors.neutral150};
8383
`;

packages/design-system/src/components/Field/Field.tsx

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,27 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
154154
}
155155

156156
const hasError = Boolean(error);
157+
const endActionRef = React.useRef<HTMLDivElement>(null);
158+
const inputElementRef = React.useRef<HTMLInputElement>(null);
159+
const inputRef = useComposedRefs(inputElementRef, ref);
157160

158161
const handleChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
159162
if (!disabled && onChange) {
160163
onChange(e);
161164
}
162165
};
163166

167+
React.useLayoutEffect(() => {
168+
if (endActionRef.current && inputElementRef.current) {
169+
const endActionWidth = endActionRef.current.offsetWidth;
170+
const inputElement = inputElementRef.current;
171+
if (inputElement) {
172+
const inputPadding = endActionWidth + 8 + 16; // adjust padding 8px gap + 16px right padding
173+
inputElement.style.paddingRight = `${inputPadding}px`;
174+
}
175+
}
176+
}, [endAction]);
177+
164178
return (
165179
<InputWrapper
166180
gap={2}
@@ -176,7 +190,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
176190
<InputElement
177191
id={id}
178192
name={name}
179-
ref={ref}
193+
ref={inputRef}
180194
$size={size}
181195
aria-describedby={ariaDescription}
182196
aria-invalid={hasError || hasErrorProp}
@@ -185,15 +199,21 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
185199
data-disabled={disabled ? '' : undefined}
186200
onChange={handleChange}
187201
aria-required={required || requiredProp}
202+
$hasLeftAction={Boolean(startAction)}
203+
$hasRightAction={Boolean(endAction)}
188204
{...props}
189205
/>
190-
{endAction}
206+
{endAction && <EndAction ref={endActionRef}>{endAction}</EndAction>}
191207
</InputWrapper>
192208
);
193209
},
194210
);
195211

196-
const InputElement = styled.input<{ $size: InputProps['size'] }>`
212+
const InputElement = styled.input<{
213+
$size: InputProps['size'];
214+
$hasLeftAction: boolean;
215+
$hasRightAction: boolean;
216+
}>`
197217
border: none;
198218
border-radius: ${({ theme }) => theme.borderRadius};
199219
cursor: ${(props) => (props['aria-disabled'] ? 'not-allowed' : undefined)};
@@ -206,19 +226,6 @@ const InputElement = styled.input<{ $size: InputProps['size'] }>`
206226
width: 100%;
207227
background: inherit;
208228
209-
${(props) => {
210-
switch (props.$size) {
211-
case 'S':
212-
return css`
213-
padding-block: ${props.theme.spaces[1]};
214-
`;
215-
default:
216-
return css`
217-
padding-block: ${props.theme.spaces[2]};
218-
`;
219-
}
220-
}};
221-
222229
::placeholder {
223230
color: ${({ theme }) => theme.colors.neutral500};
224231
opacity: 1;
@@ -233,42 +240,53 @@ const InputElement = styled.input<{ $size: InputProps['size'] }>`
233240
outline: none;
234241
box-shadow: none;
235242
}
236-
`;
237-
238-
const InputWrapper = styled<FlexComponent>(Flex)<{
239-
$disabled?: boolean;
240-
$hasError?: boolean;
241-
$hasLeftAction: boolean;
242-
$hasRightAction: boolean;
243-
$size: InputProps['size'];
244-
}>`
245-
border: 1px solid ${({ theme, $hasError }) => ($hasError ? theme.colors.danger600 : theme.colors.neutral200)};
246-
border-radius: ${({ theme }) => theme.borderRadius};
247-
background: ${({ theme }) => theme.colors.neutral0};
248-
${inputFocusStyle()}
249243
250244
${(props) => {
251245
switch (props.$size) {
252246
case 'S':
253247
return css`
254-
padding-inline-start: ${props.$hasLeftAction ? props.theme.spaces[3] : props.theme.spaces[4]};
255-
padding-inline-end: ${props.$hasRightAction ? props.theme.spaces[3] : props.theme.spaces[4]};
248+
padding-inline-start: ${props.$hasLeftAction ? 0 : props.theme.spaces[4]};
249+
padding-inline-end: ${props.$hasRightAction ? 0 : props.theme.spaces[4]};
250+
padding-block: ${props.theme.spaces[1]};
256251
`;
257252
default:
258253
return css`
259-
padding-inline-start: ${props.$hasLeftAction ? props.theme.spaces[3] : props.theme.spaces[4]};
260-
padding-inline-end: ${props.$hasRightAction ? props.theme.spaces[3] : props.theme.spaces[4]};
254+
padding-inline-start: ${props.$hasLeftAction ? 0 : props.theme.spaces[4]};
255+
padding-inline-end: ${props.$hasRightAction ? 0 : props.theme.spaces[4]};
256+
padding-block: ${props.theme.spaces[2]};
261257
`;
262258
}
263259
}}
260+
`;
261+
262+
const EndAction = styled(Flex)`
263+
position: absolute;
264+
right: ${({ theme }) => theme.spaces[4]};
265+
top: 50%;
266+
transform: translateY(-50%);
267+
`;
264268

269+
const InputWrapper = styled<FlexComponent>(Flex)<{
270+
$disabled?: boolean;
271+
$hasError?: boolean;
272+
$size: InputProps['size'];
273+
$hasLeftAction: boolean;
274+
$hasRightAction: boolean;
275+
}>`
276+
border: 1px solid ${({ theme, $hasError }) => ($hasError ? theme.colors.danger600 : theme.colors.neutral200)};
277+
border-radius: ${({ theme }) => theme.borderRadius};
278+
background: ${({ theme }) => theme.colors.neutral0};
279+
padding-inline-start: ${({ $hasLeftAction, theme }) => ($hasLeftAction ? theme.spaces[4] : 0)};
280+
position: relative;
281+
282+
${inputFocusStyle()}
265283
${({ theme, $disabled }) =>
266284
$disabled
267285
? css`
268286
color: ${theme.colors.neutral600};
269287
background: ${theme.colors.neutral150};
270288
`
271-
: undefined}
289+
: undefined};
272290
`;
273291

274292
/* -------------------------------------------------------------------------------------------------

packages/design-system/src/components/Popover/Popover.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const PopoverContent = styled(Popover.Content)`
5252
z-index: ${({ theme }) => theme.zIndices.popover};
5353
background-color: ${(props) => props.theme.colors.neutral0};
5454
border: 1px solid ${({ theme }) => theme.colors.neutral150};
55+
border-radius: ${({ theme }) => theme.borderRadius};
5556
5657
@media (prefers-reduced-motion: no-preference) {
5758
animation-duration: ${(props) => props.theme.motion.timings['200']};

0 commit comments

Comments
 (0)