diff --git a/.changeset/old-schools-happen.md b/.changeset/old-schools-happen.md
new file mode 100644
index 00000000000..41d5ab20f6b
--- /dev/null
+++ b/.changeset/old-schools-happen.md
@@ -0,0 +1,5 @@
+---
+"@primer/react": patch
+---
+
+Add monospace prop to textinput
diff --git a/docs/content/TextInput.mdx b/docs/content/TextInput.mdx
index e74cf6a3006..b3bdfe57be6 100644
--- a/docs/content/TextInput.mdx
+++ b/docs/content/TextInput.mdx
@@ -81,6 +81,18 @@ TextInput is a form component to add default styling to the native text input.
```
+## Monospace text input
+
+```jsx live
+
+```
+
## Props
### TextInput
@@ -103,6 +115,12 @@ TextInput is a form component to add default styling to the native text input.
defaultValue="false"
description="Changes background color to a higher contrast color"
/>
+
} & Pick<
ComponentProps,
- 'block' | 'contrast' | 'disabled' | 'sx' | 'width' | 'maxWidth' | 'minWidth' | 'variant' | 'size'
+ 'block' | 'contrast' | 'disabled' | 'monospace' | 'sx' | 'width' | 'maxWidth' | 'minWidth' | 'variant' | 'size'
>
// 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(
className,
contrast,
disabled,
+ monospace,
validationStatus,
sx: sxProp,
size: sizeProp,
@@ -52,6 +53,7 @@ const TextInput = React.forwardRef(
validationStatus={validationStatus}
contrast={contrast}
disabled={disabled}
+ monospace={monospace}
sx={sxProp}
size={sizeProp}
width={widthProp}
diff --git a/src/_TextInputWrapper.tsx b/src/_TextInputWrapper.tsx
index 5b52ae93496..3b59af94162 100644
--- a/src/_TextInputWrapper.tsx
+++ b/src/_TextInputWrapper.tsx
@@ -45,6 +45,7 @@ export type StyledBaseWrapperProps = {
block?: boolean
contrast?: boolean
disabled?: boolean
+ monospace?: boolean
validationStatus?: FormValidationStatus
} & WidthProps &
MinWidthProps &
@@ -104,6 +105,12 @@ export const TextInputBaseWrapper = styled.span`
background-color: ${get('colors.input.disabledBg')};
border-color: ${get('colors.border.default')};
`}
+
+ ${props =>
+ props.monospace &&
+ css`
+ font-family: ${get('fonts.mono')};
+ `}
${props =>
props.validationStatus === 'error' &&
diff --git a/src/__tests__/TextInput.test.tsx b/src/__tests__/TextInput.test.tsx
index 3e8b071e3c4..ec2b6e05f0c 100644
--- a/src/__tests__/TextInput.test.tsx
+++ b/src/__tests__/TextInput.test.tsx
@@ -46,7 +46,10 @@ describe('TextInput', () => {
})
it('renders contrast', () => {
- expect(render()).toMatchSnapshot()
+ expect(render()).toMatchSnapshot()
+ })
+ it('renders monospace', () => {
+ expect(render()).toMatchSnapshot()
})
it('renders placeholder', () => {
diff --git a/src/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/__tests__/__snapshots__/TextInput.test.tsx.snap
index 23bc8c7cd1c..7791f796b01 100644
--- a/src/__tests__/__snapshots__/TextInput.test.tsx.snap
+++ b/src/__tests__/__snapshots__/TextInput.test.tsx.snap
@@ -351,6 +351,7 @@ exports[`TextInput renders contrast 1`] = `
-ms-flex-align: stretch;
align-items: stretch;
min-height: 32px;
+ background-color: #f6f8fa;
background-repeat: no-repeat;
background-position: right 8px center;
padding-left: 0;
@@ -765,6 +766,111 @@ exports[`TextInput renders leadingVisual 1`] = `
`;
+exports[`TextInput renders monospace 1`] = `
+.c1 {
+ border: 0;
+ font-size: inherit;
+ font-family: inherit;
+ background-color: transparent;
+ -webkit-appearance: none;
+ color: inherit;
+ width: 100%;
+}
+
+.c1:focus {
+ outline: 0;
+}
+
+.c0 {
+ font-size: 14px;
+ line-height: 20px;
+ color: #24292f;
+ vertical-align: middle;
+ background-color: #ffffff;
+ border: 1px solid #d0d7de;
+ border-radius: 6px;
+ outline: none;
+ box-shadow: inset 0 1px 0 rgba(208,215,222,0.2);
+ cursor: text;
+ display: -webkit-inline-box;
+ display: -webkit-inline-flex;
+ display: -ms-inline-flexbox;
+ display: inline-flex;
+ -webkit-align-items: stretch;
+ -webkit-box-align: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch;
+ min-height: 32px;
+ font-family: SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;
+ background-repeat: no-repeat;
+ background-position: right 8px center;
+ padding-left: 0;
+ padding-right: 0;
+}
+
+.c0::-webkit-input-placeholder {
+ color: #6e7781;
+}
+
+.c0::-moz-placeholder {
+ color: #6e7781;
+}
+
+.c0:-ms-input-placeholder {
+ color: #6e7781;
+}
+
+.c0::placeholder {
+ color: #6e7781;
+}
+
+.c0:focus-within {
+ border-color: #0969da;
+ box-shadow: 0 0 0 3px rgba(9,105,218,0.3);
+}
+
+.c0 > textarea {
+ padding: 12px;
+}
+
+.c0 >:not(:last-child) {
+ margin-right: 8px;
+}
+
+.c0 .TextInput-icon {
+ -webkit-align-self: center;
+ -ms-flex-item-align: center;
+ align-self: center;
+ color: #57606a;
+ -webkit-flex-shrink: 0;
+ -ms-flex-negative: 0;
+ flex-shrink: 0;
+}
+
+.c0 > input,
+.c0 > select {
+ padding-left: 12px;
+ padding-right: 12px;
+}
+
+@media (min-width:768px) {
+ .c0 {
+ font-size: 14px;
+ }
+}
+
+
+
+
+`;
+
exports[`TextInput renders placeholder 1`] = `
.c1 {
border: 0;
diff --git a/src/stories/TextInput.stories.tsx b/src/stories/TextInput.stories.tsx
index 02fdd3d92f5..c9a06c451f0 100644
--- a/src/stories/TextInput.stories.tsx
+++ b/src/stories/TextInput.stories.tsx
@@ -39,6 +39,13 @@ export default {
type: 'boolean'
}
},
+ monospace: {
+ name: 'Monospace',
+ defaultValue: false,
+ control: {
+ type: 'boolean'
+ }
+ },
variant: {
name: 'Variants',
options: ['small', 'medium', 'large'],