Skip to content

Commit 40c93d8

Browse files
pksjcerezrah
andauthored
Add monospace prop to textinput (#1935)
* Add monospace prop to textinput * Add a PAT example Co-authored-by: Rez <rezrah@github.com> * Add check visual to documentation * Create old-schools-happen.md Co-authored-by: Rez <rezrah@github.com>
1 parent e430bd8 commit 40c93d8

File tree

7 files changed

+150
-2
lines changed

7 files changed

+150
-2
lines changed

.changeset/old-schools-happen.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@primer/react": patch
3+
---
4+
5+
Add monospace prop to textinput

docs/content/TextInput.mdx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,18 @@ TextInput is a form component to add default styling to the native text input.
8181
<TextInput contrast aria-label="Zipcode" name="zipcode" placeholder="Find user" autoComplete="postal-code" />
8282
```
8383

84+
## Monospace text input
85+
86+
```jsx live
87+
<TextInput
88+
monospace
89+
aria-label="personal access token"
90+
name="pat"
91+
leadingVisual={CheckIcon}
92+
placeholder="github_pat_abcdefg123456789"
93+
/>
94+
```
95+
8496
## Props
8597

8698
### TextInput
@@ -103,6 +115,12 @@ TextInput is a form component to add default styling to the native text input.
103115
defaultValue="false"
104116
description="Changes background color to a higher contrast color"
105117
/>
118+
<PropsTableRow
119+
name="monospace"
120+
type="boolean"
121+
defaultValue="false"
122+
description="Shows input in monospace font"
123+
/>
106124
<PropsTableRow name='size' type="'small' | 'medium' | 'large'" description="Creates a smaller or larger input than the default." />
107125

108126
<PropsTableRow

src/TextInput.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ type NonPassthroughProps = {
1212
trailingVisual?: string | React.ComponentType<{className?: string}>
1313
} & Pick<
1414
ComponentProps<typeof TextInputWrapper>,
15-
'block' | 'contrast' | 'disabled' | 'sx' | 'width' | 'maxWidth' | 'minWidth' | 'variant' | 'size'
15+
'block' | 'contrast' | 'disabled' | 'monospace' | 'sx' | 'width' | 'maxWidth' | 'minWidth' | 'variant' | 'size'
1616
>
1717

1818
// Note: using ComponentProps instead of ComponentPropsWithoutRef here would cause a type issue where `css` is a required prop.
@@ -29,6 +29,7 @@ const TextInput = React.forwardRef<HTMLInputElement, TextInputInternalProps>(
2929
className,
3030
contrast,
3131
disabled,
32+
monospace,
3233
validationStatus,
3334
sx: sxProp,
3435
size: sizeProp,
@@ -52,6 +53,7 @@ const TextInput = React.forwardRef<HTMLInputElement, TextInputInternalProps>(
5253
validationStatus={validationStatus}
5354
contrast={contrast}
5455
disabled={disabled}
56+
monospace={monospace}
5557
sx={sxProp}
5658
size={sizeProp}
5759
width={widthProp}

src/_TextInputWrapper.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export type StyledBaseWrapperProps = {
4545
block?: boolean
4646
contrast?: boolean
4747
disabled?: boolean
48+
monospace?: boolean
4849
validationStatus?: FormValidationStatus
4950
} & WidthProps &
5051
MinWidthProps &
@@ -104,6 +105,12 @@ export const TextInputBaseWrapper = styled.span<StyledBaseWrapperProps>`
104105
background-color: ${get('colors.input.disabledBg')};
105106
border-color: ${get('colors.border.default')};
106107
`}
108+
109+
${props =>
110+
props.monospace &&
111+
css`
112+
font-family: ${get('fonts.mono')};
113+
`}
107114
108115
${props =>
109116
props.validationStatus === 'error' &&

src/__tests__/TextInput.test.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ describe('TextInput', () => {
4646
})
4747

4848
it('renders contrast', () => {
49-
expect(render(<TextInput name="zipcode" status="contrast" />)).toMatchSnapshot()
49+
expect(render(<TextInput name="zipcode" contrast />)).toMatchSnapshot()
50+
})
51+
it('renders monospace', () => {
52+
expect(render(<TextInput name="zipcode" monospace />)).toMatchSnapshot()
5053
})
5154

5255
it('renders placeholder', () => {

src/__tests__/__snapshots__/TextInput.test.tsx.snap

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ exports[`TextInput renders contrast 1`] = `
351351
-ms-flex-align: stretch;
352352
align-items: stretch;
353353
min-height: 32px;
354+
background-color: #f6f8fa;
354355
background-repeat: no-repeat;
355356
background-position: right 8px center;
356357
padding-left: 0;
@@ -765,6 +766,111 @@ exports[`TextInput renders leadingVisual 1`] = `
765766
</span>
766767
`;
767768

769+
exports[`TextInput renders monospace 1`] = `
770+
.c1 {
771+
border: 0;
772+
font-size: inherit;
773+
font-family: inherit;
774+
background-color: transparent;
775+
-webkit-appearance: none;
776+
color: inherit;
777+
width: 100%;
778+
}
779+
780+
.c1:focus {
781+
outline: 0;
782+
}
783+
784+
.c0 {
785+
font-size: 14px;
786+
line-height: 20px;
787+
color: #24292f;
788+
vertical-align: middle;
789+
background-color: #ffffff;
790+
border: 1px solid #d0d7de;
791+
border-radius: 6px;
792+
outline: none;
793+
box-shadow: inset 0 1px 0 rgba(208,215,222,0.2);
794+
cursor: text;
795+
display: -webkit-inline-box;
796+
display: -webkit-inline-flex;
797+
display: -ms-inline-flexbox;
798+
display: inline-flex;
799+
-webkit-align-items: stretch;
800+
-webkit-box-align: stretch;
801+
-ms-flex-align: stretch;
802+
align-items: stretch;
803+
min-height: 32px;
804+
font-family: SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;
805+
background-repeat: no-repeat;
806+
background-position: right 8px center;
807+
padding-left: 0;
808+
padding-right: 0;
809+
}
810+
811+
.c0::-webkit-input-placeholder {
812+
color: #6e7781;
813+
}
814+
815+
.c0::-moz-placeholder {
816+
color: #6e7781;
817+
}
818+
819+
.c0:-ms-input-placeholder {
820+
color: #6e7781;
821+
}
822+
823+
.c0::placeholder {
824+
color: #6e7781;
825+
}
826+
827+
.c0:focus-within {
828+
border-color: #0969da;
829+
box-shadow: 0 0 0 3px rgba(9,105,218,0.3);
830+
}
831+
832+
.c0 > textarea {
833+
padding: 12px;
834+
}
835+
836+
.c0 >:not(:last-child) {
837+
margin-right: 8px;
838+
}
839+
840+
.c0 .TextInput-icon {
841+
-webkit-align-self: center;
842+
-ms-flex-item-align: center;
843+
align-self: center;
844+
color: #57606a;
845+
-webkit-flex-shrink: 0;
846+
-ms-flex-negative: 0;
847+
flex-shrink: 0;
848+
}
849+
850+
.c0 > input,
851+
.c0 > select {
852+
padding-left: 12px;
853+
padding-right: 12px;
854+
}
855+
856+
@media (min-width:768px) {
857+
.c0 {
858+
font-size: 14px;
859+
}
860+
}
861+
862+
<span
863+
className="c0 TextInput-wrapper"
864+
>
865+
<input
866+
className="c1"
867+
data-component="input"
868+
name="zipcode"
869+
type="text"
870+
/>
871+
</span>
872+
`;
873+
768874
exports[`TextInput renders placeholder 1`] = `
769875
.c1 {
770876
border: 0;

src/stories/TextInput.stories.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ export default {
3939
type: 'boolean'
4040
}
4141
},
42+
monospace: {
43+
name: 'Monospace',
44+
defaultValue: false,
45+
control: {
46+
type: 'boolean'
47+
}
48+
},
4249
variant: {
4350
name: 'Variants',
4451
options: ['small', 'medium', 'large'],

0 commit comments

Comments
 (0)