Skip to content

Commit 8d3d491

Browse files
authored
Fix: TextInput styling regression with icon and block prop usage (#1592)
1 parent 2a61b8d commit 8d3d491

File tree

3 files changed

+125
-0
lines changed

3 files changed

+125
-0
lines changed

.changeset/hip-ravens-sell.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@primer/components': patch
3+
---
4+
5+
Fixes a styling bug in TextInput components while using its `icon` and `block` props together

src/_TextInputWrapper.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ const TextInputWrapper = styled.span<StyledWrapperProps>`
9191
display: block;
9292
width: 100%;
9393
`}
94+
95+
${props =>
96+
props.block &&
97+
props.hasIcon &&
98+
css`
99+
display: flex;
100+
`}
94101
95102
// Ensures inputs don't zoom on mobile but are body-font size on desktop
96103
@media (min-width: ${get('breakpoints.1')}) {

src/stories/TextInput.stories.tsx

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import React, {useState, ReactNode} from 'react'
2+
import {Meta} from '@storybook/react'
3+
4+
import {BaseStyles, Box, ThemeProvider, Text} from '..'
5+
import TextInput, {TextInputProps} from '../TextInput'
6+
import {CheckIcon} from '@primer/octicons-react'
7+
8+
export default {
9+
title: 'Forms/Text Input',
10+
component: TextInput,
11+
decorators: [
12+
Story => {
13+
return (
14+
<ThemeProvider>
15+
<BaseStyles>
16+
<Box paddingTop={5}>{Story()}</Box>
17+
</BaseStyles>
18+
</ThemeProvider>
19+
)
20+
}
21+
],
22+
argTypes: {
23+
sx: {
24+
table: {
25+
disable: true
26+
}
27+
},
28+
block: {
29+
name: 'Block',
30+
defaultValue: false,
31+
control: {
32+
type: 'boolean'
33+
}
34+
},
35+
disabled: {
36+
name: 'Disabled',
37+
defaultValue: false,
38+
control: {
39+
type: 'boolean'
40+
}
41+
},
42+
variant: {
43+
name: 'Variants',
44+
options: ['small', 'medium', 'large'],
45+
control: {type: 'radio'}
46+
}
47+
}
48+
} as Meta
49+
50+
const Label = ({htmlFor, children}: {htmlFor: string; children: ReactNode}) => (
51+
<Text as="label" htmlFor={htmlFor} sx={{fontWeight: 600, fontSize: 14}}>
52+
{children}
53+
</Text>
54+
)
55+
56+
export const Default = (args: TextInputProps) => {
57+
const [value, setValue] = useState('')
58+
59+
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
60+
setValue(event.target.value)
61+
}
62+
63+
const inputId = 'basic-text-input'
64+
65+
return (
66+
<form>
67+
<div className="form-group">
68+
<div className="form-group-header">
69+
<Label htmlFor={inputId}>Example label</Label>
70+
</div>
71+
<div className="form-group-body">
72+
<TextInput id={inputId} value={value} onChange={handleChange} {...args} />
73+
</div>
74+
</div>
75+
</form>
76+
)
77+
}
78+
79+
export const WithLeadingIcon = (args: TextInputProps) => {
80+
const [value, setValue] = useState('')
81+
82+
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
83+
setValue(event.target.value)
84+
}
85+
86+
const inputId = 'basic-text-input-with-leading-icon'
87+
88+
return (
89+
<form>
90+
<Label htmlFor={inputId}>Example label</Label>
91+
<br />
92+
<TextInput icon={CheckIcon} id={inputId} value={value} onChange={handleChange} type="password" {...args} />
93+
</form>
94+
)
95+
}
96+
97+
export const Password = (args: TextInputProps) => {
98+
const [value, setValue] = useState('')
99+
100+
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
101+
setValue(event.target.value)
102+
}
103+
104+
const inputId = 'basic-text-input-as-password'
105+
106+
return (
107+
<form>
108+
<Label htmlFor={inputId}>Password</Label>
109+
<br />
110+
<TextInput type="password" id={inputId} value={value} onChange={handleChange} {...args} />
111+
</form>
112+
)
113+
}

0 commit comments

Comments
 (0)