From c9f34f1b7daa625f805f4c19eec9e7005f947b49 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Wed, 2 Mar 2022 10:49:35 -0500 Subject: [PATCH 01/35] adds loading indicator to text inputs --- src/TextInput.tsx | 99 +++++++++++++++++++++---------- src/TextInputWithTokens.tsx | 41 ++++++++----- src/_TextInputInnerVisualSlot.tsx | 45 ++++++++++++++ 3 files changed, 141 insertions(+), 44 deletions(-) create mode 100644 src/_TextInputInnerVisualSlot.tsx diff --git a/src/TextInput.tsx b/src/TextInput.tsx index e647a3ac4dd..7a3ceead366 100644 --- a/src/TextInput.tsx +++ b/src/TextInput.tsx @@ -1,14 +1,31 @@ import classnames from 'classnames' -import React from 'react' +import React, {MouseEventHandler} from 'react' import {ComponentProps, Merge} from './utils/types' import UnstyledTextInput from './_UnstyledTextInput' import TextInputWrapper from './_TextInputWrapper' +import TextInputInnerVisualSlot from './_TextInputInnerVisualSlot' +import {useProvidedRefOrCreate} from './hooks' -type NonPassthroughProps = { +export type TextInputNonPassthroughProps = { className?: string /** @deprecated Use `leadingVisual` or `trailingVisual` prop instead */ icon?: React.ComponentType<{className?: string}> + /** Whether the to show a loading indicator in the input */ + isLoading?: boolean + /** + * Which position to render the loading indicator + * 'auto' (default): at the end of the input, unless a `leadingVisual` is passed. Then, it will render at the beginning + * 'leading': at the beginning of the input + * 'trailing': at the end of the input + **/ + loadingIndicatorPosition?: 'auto' | 'leading' | 'trailing' // TODO: come up with a shorter name + /** + * A visual that renders inside the input before the typing area + */ leadingVisual?: string | React.ComponentType<{className?: string}> + /** + * A visual that renders inside the input after the typing area + */ trailingVisual?: string | React.ComponentType<{className?: string}> } & Pick< ComponentProps, @@ -16,7 +33,10 @@ type NonPassthroughProps = { > // Note: using ComponentProps instead of ComponentPropsWithoutRef here would cause a type issue where `css` is a required prop. -type TextInputInternalProps = Merge, NonPassthroughProps> +type TextInputInternalProps = Merge< + React.ComponentPropsWithoutRef, + TextInputNonPassthroughProps +> // using forwardRef is important so that other components (ex. SelectMenu) can autofocus the input const TextInput = React.forwardRef( @@ -29,6 +49,8 @@ const TextInput = React.forwardRef( className, contrast, disabled, + isLoading, + loadingIndicatorPosition, validationStatus, sx: sxProp, size: sizeProp, @@ -42,44 +64,61 @@ const TextInput = React.forwardRef( }, ref ) => { + const inputRef = useProvidedRefOrCreate(ref as React.RefObject) // this class is necessary to style FilterSearch, plz no touchy! const wrapperClasses = classnames(className, 'TextInput-wrapper') + const showLeadingLoadingIndicator = + isLoading && + (loadingIndicatorPosition === 'leading' || Boolean(LeadingVisual && loadingIndicatorPosition !== 'trailing')) + const showTrailingLoadingIndicator = + isLoading && (loadingIndicatorPosition === 'trailing' || (loadingIndicatorPosition === 'auto' && !LeadingVisual)) + const focusInput: MouseEventHandler = () => { + inputRef.current?.focus() + } return ( - - {IconComponent && } - {LeadingVisual && ( - +
+ + {IconComponent && } + {typeof LeadingVisual === 'function' ? : LeadingVisual} - - )} - - {TrailingVisual && ( - + + + {typeof TrailingVisual === 'function' ? : TrailingVisual} - - )} - + + +
) } ) TextInput.defaultProps = { - type: 'text' + type: 'text', + loadingIndicatorPosition: 'auto' } TextInput.displayName = 'TextInput' diff --git a/src/TextInputWithTokens.tsx b/src/TextInputWithTokens.tsx index d3812497332..bb9497ba19a 100644 --- a/src/TextInputWithTokens.tsx +++ b/src/TextInputWithTokens.tsx @@ -1,6 +1,7 @@ import React, {FocusEventHandler, KeyboardEventHandler, MouseEventHandler, RefObject, useRef, useState} from 'react' import {omit} from '@styled-system/props' import {FocusKeys} from '@primer/behaviors' +import {isFocusable} from '@primer/behaviors/utils' import {useCombinedRefs} from './hooks/useCombinedRefs' import {useFocusZone} from './hooks/useFocusZone' import {ComponentProps} from './utils/types' @@ -12,7 +13,7 @@ import UnstyledTextInput from './_UnstyledTextInput' import TextInputWrapper, {textInputHorizPadding, TextInputSizes} from './_TextInputWrapper' import Box from './Box' import Text from './Text' -import {isFocusable} from '@primer/behaviors/utils' +import TextInputInnerVisualSlot from './_TextInputInnerVisualSlot' // eslint-disable-next-line @typescript-eslint/no-explicit-any type AnyReactComponent = React.ComponentType @@ -68,6 +69,8 @@ function TextInputWithTokensInnerComponent {IconComponent && !LeadingVisual && } - {LeadingVisual && !IconComponent && ( - - {typeof LeadingVisual === 'function' ? : LeadingVisual} - - )} + + {typeof LeadingVisual === 'function' ? : LeadingVisual} + } display="flex" @@ -352,11 +362,13 @@ function TextInputWithTokensInnerComponent ) : null} - {TrailingVisual && ( - - {typeof TrailingVisual === 'function' ? : TrailingVisual} - - )} + + {typeof TrailingVisual === 'function' ? : TrailingVisual} +
) } @@ -367,7 +379,8 @@ TextInputWithTokens.defaultProps = { tokenComponent: Token, size: 'extralarge', hideTokenRemoveButtons: false, - preventTokenWrapping: false + preventTokenWrapping: false, + loadingIndicatorPosition: 'auto' } TextInputWithTokens.displayName = 'TextInputWithTokens' diff --git a/src/_TextInputInnerVisualSlot.tsx b/src/_TextInputInnerVisualSlot.tsx new file mode 100644 index 00000000000..901bba3c134 --- /dev/null +++ b/src/_TextInputInnerVisualSlot.tsx @@ -0,0 +1,45 @@ +import React from 'react' +import {Box, Spinner} from '.' +import {TextInputNonPassthroughProps} from './TextInput' + +const TextInputInnerVisualSlot: React.FC<{ + /** Whether the input is expected to ever show a loading indicator */ + hasLoadingIndicator: boolean + /** Whether the to show the loading indicator */ + showLoadingIndicator: TextInputNonPassthroughProps['isLoading'] + /** Which side of this visual is being rendered */ + visualPosition: 'leading' | 'trailing' +}> = ({children, hasLoadingIndicator, showLoadingIndicator, visualPosition}) => { + if ((!children && !hasLoadingIndicator) || (visualPosition === 'leading' && !children && !showLoadingIndicator)) { + return null + } + + if (!hasLoadingIndicator) { + return {children} + } + + return ( + + + {children && {children}} + + + + ) +} + +export default TextInputInnerVisualSlot From 26976c74b2e088677da1fd1241391d3235bcc476 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Wed, 2 Mar 2022 11:00:51 -0500 Subject: [PATCH 02/35] removes style debugging div --- src/TextInput.tsx | 66 +++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/src/TextInput.tsx b/src/TextInput.tsx index 7a3ceead366..53fe02830b8 100644 --- a/src/TextInput.tsx +++ b/src/TextInput.tsx @@ -77,41 +77,39 @@ const TextInput = React.forwardRef( } return ( -
- + {IconComponent && } + - {IconComponent && } - - {typeof LeadingVisual === 'function' ? : LeadingVisual} - - - - {typeof TrailingVisual === 'function' ? : TrailingVisual} - - -
+ {typeof LeadingVisual === 'function' ? : LeadingVisual} + + + + {typeof TrailingVisual === 'function' ? : TrailingVisual} + + ) } ) From 51570872befe6aa2c5268d5ce3b83c5235b0c218 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Wed, 2 Mar 2022 13:05:10 -0500 Subject: [PATCH 03/35] updates stories and docs --- docs/content/TextInput.mdx | 194 +++++++++++++++++--- docs/content/TextInputWithTokens.mdx | 153 +++++++++++++++ src/stories/TextInput.stories.tsx | 166 +++++++++++++++-- src/stories/TextInputWithTokens.stories.tsx | 70 ++++++- 4 files changed, 534 insertions(+), 49 deletions(-) diff --git a/docs/content/TextInput.mdx b/docs/content/TextInput.mdx index e74cf6a3006..97cdff5c171 100644 --- a/docs/content/TextInput.mdx +++ b/docs/content/TextInput.mdx @@ -47,6 +47,113 @@ TextInput is a form component to add default styling to the native text input. ``` +## Text Input with visuals and loading indicators + +```javascript live noinline +const WithIconAndLoadingIndicator = () => { + const [isLoading, setIsLoading] = React.useState(true) + + const toggleLoadingState = () => { + setIsLoading(!isLoading) + } + + return ( + <> + + + + +

No visual

+ + + + + + + + + + +

Leading visual

+ + + + + + + + + + +

Trailing visual

+ + + + + + + + + + +

Both visuals

+ + + + + + + + + + + ) +} + +render() +``` + ## Text Input with error and warning states ```jsx live @@ -91,11 +198,7 @@ TextInput is a form component to add default styling to the native text input. name="block" type="boolean" defaultValue="false" - description={ - <> - Creates a full width input element - - } + description={<>Creates a full width input element} /> - - -string | React.ComponentType} - description="Visual positioned on the left edge inside the input" -/> -string | React.ComponentType} - description="Visual positioned on the right edge inside the input" -/> - - - - + + + ( + <> +
Which position to render the loading indicator
+
    +
  • + 'auto' (default): at the end of the input, unless a `leadingVisual` is passed. Then, it will render at the + beginning +
  • +
  • 'leading': at the beginning of the input
  • +
  • 'trailing': at the end of the input
  • +
+ + )} + /> + string | React.ComponentType} + description={() => ( + <> +
Which position to render the loading indicator
+
    +
  • + 'auto' (default): at the end of the input, unless a `leadingVisual` is passed. Then, it will render at the + beginning +
  • +
  • 'leading': at the beginning of the input
  • +
  • 'trailing': at the end of the input
  • +
+ + )} + /> + string | React.ComponentType} + description="Visual positioned on the right edge inside the input" + /> + + { render(LeadingVisualExample) ``` +## With visuals and loading indicators + +```javascript live noinline +const WithIconAndLoadingIndicator = () => { + const [dates, setDates] = React.useState([ + {text: '01 Jan', id: 0}, + {text: '01 Feb', id: 1}, + {text: '01 Mar', id: 2} + ]) + const onDateRemove = tokenId => { + setDates(dates.filter(token => token.id !== tokenId)) + } + + const [isLoading, setIsLoading] = React.useState(true) + const toggleLoadingState = () => { + setIsLoading(!isLoading) + } + + return ( + <> + + + + +

No visual

+ + + + + + + + + + +

Leading visual

+ + + + + + + + + + +

Trailing visual

+ + + + + + + + + + +

Both visuals

+ + + + + + + + + + + ) +} + +render() +``` + ## Props diff --git a/src/stories/TextInput.stories.tsx b/src/stories/TextInput.stories.tsx index 02fdd3d92f5..42200e5c7af 100644 --- a/src/stories/TextInput.stories.tsx +++ b/src/stories/TextInput.stories.tsx @@ -1,9 +1,9 @@ import React, {useState, ReactNode} from 'react' import {Meta} from '@storybook/react' -import {BaseStyles, Box, ThemeProvider, Text} from '..' +import {BaseStyles, Box, ThemeProvider, Text, FormControl} from '..' import TextInput, {TextInputProps} from '../TextInput' -import {CheckIcon} from '@primer/octicons-react' +import {CalendarIcon, CheckIcon} from '@primer/octicons-react' export default { title: 'Forms/Text Input', @@ -39,6 +39,21 @@ export default { type: 'boolean' } }, + isLoading: { + name: 'isLoading', + defaultValue: false, + control: { + type: 'boolean' + } + }, + loadingIndicatorPosition: { + name: 'loadingIndicatorPosition', + defaultValue: 'auto', + options: ['auto', 'leading', 'trailing'], + control: { + type: 'radio' + } + }, variant: { name: 'Variants', options: ['small', 'medium', 'large'], @@ -65,29 +80,107 @@ const Label = ({htmlFor, children}: {htmlFor: string; children: ReactNode}) => ( ) -export const Default = (args: TextInputProps) => { - const [value, setValue] = useState('') +export const Default = () => { + const [isLoading, setIsLoading] = useState(false) - const handleChange = (event: React.ChangeEvent) => { - setValue(event.target.value) + const toggleLoadingState = () => { + setIsLoading(!isLoading) } - const inputId = 'basic-text-input' - return ( -
-
-
- -
-
- -
-
-
+ <> + + +

No visual

+ + + + + + + + + + +

Leading visual

+ + + + + + + + + + +

Trailing visual

+ + + + + + + + + + +

Both visuals

+ + + + + + + + } + trailingVisual={() => } + isLoading={isLoading} + loadingIndicatorPosition="trailing" + value="trailing" + /> + + ) } +Default.parameters = {controls: {exclude: ['isLoading', 'loadingIndicatorPosition']}} + export const WithLeadingVisual = (args: TextInputProps) => { const [value, setValue] = useState('') @@ -138,6 +231,43 @@ export const WithTrailingIcon = (args: TextInputProps) => { ) } +export const WithLoadingIndicator = (args: TextInputProps) => { + const [isLoading, setIsLoading] = useState(true) + + const toggleLoadingState = () => { + setIsLoading(!isLoading) + } + + return ( +
+ + + + + + + No visual + + + + + Leading visual + + + + + Both visuals + + + +
+ ) +} + +WithLoadingIndicator.parameters = {controls: {exclude: ['isLoading']}} + export const ContrastTextInput = (args: TextInputProps) => { const [value, setValue] = useState('') diff --git a/src/stories/TextInputWithTokens.stories.tsx b/src/stories/TextInputWithTokens.stories.tsx index 88359ee0d97..32442a61eb6 100644 --- a/src/stories/TextInputWithTokens.stories.tsx +++ b/src/stories/TextInputWithTokens.stories.tsx @@ -2,7 +2,7 @@ import React, {useCallback, useState} from 'react' import {Meta} from '@storybook/react' import {CheckIcon, NumberIcon} from '@primer/octicons-react' -import {BaseStyles, Box, ThemeProvider} from '..' +import {BaseStyles, Box, FormControl, ThemeProvider} from '..' import TextInputWithTokens, {TextInputWithTokensProps} from '../TextInputWithTokens' import IssueLabelToken from '../Token/IssueLabelToken' @@ -47,6 +47,21 @@ export default { type: 'boolean' } }, + isLoading: { + name: 'isLoading', + defaultValue: false, + control: { + type: 'boolean' + } + }, + loadingIndicatorPosition: { + name: 'loadingIndicatorPosition', + defaultValue: 'auto', + options: ['auto', 'leading', 'trailing'], + control: { + type: 'radio' + } + }, size: { name: 'size (token size)', defaultValue: 'extralarge', @@ -121,6 +136,59 @@ export const WithTrailingVisual = (args: TextInputWithTokensProps) => { WithTrailingVisual.parameters = {controls: {exclude: [excludedControls, 'maxHeight']}} +export const WithLoadingIndicator = (args: TextInputWithTokensProps) => { + const [tokens, setTokens] = useState([...mockTokens].slice(0, 3)) + const [isLoading, setIsLoading] = useState(true) + const onTokenRemove: (tokenId: string | number) => void = tokenId => { + setTokens(tokens.filter(token => token.id !== tokenId)) + } + const toggleLoadingState = () => { + setIsLoading(!isLoading) + } + + return ( +
+ + + + + + + No visual + + + + + Leading visual + + + + + Both visuals + + + +
+ ) +} + +WithLoadingIndicator.parameters = {controls: {exclude: [excludedControls, 'maxHeight', 'isLoading']}} + export const UsingIssueLabelTokens = (args: TextInputWithTokensProps) => { const [tokens, setTokens] = useState([ {text: 'enhancement', id: 1, fillColor: '#a2eeef'}, From 258ed6c13fecd41a60af2aa8a78b02b10fb9768c Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Wed, 2 Mar 2022 13:51:25 -0500 Subject: [PATCH 04/35] updates tests --- src/__tests__/TextInput.test.tsx | 60 +- src/__tests__/TextInputWithTokens.test.tsx | 99 + .../__snapshots__/Autocomplete.test.tsx.snap | 7 + .../__snapshots__/TextInput.test.tsx.snap | 12 + .../TextInputWithTokens.test.tsx.snap | 9520 +++++++++++++++++ 5 files changed, 9697 insertions(+), 1 deletion(-) diff --git a/src/__tests__/TextInput.test.tsx b/src/__tests__/TextInput.test.tsx index 3e8b071e3c4..977d9e38440 100644 --- a/src/__tests__/TextInput.test.tsx +++ b/src/__tests__/TextInput.test.tsx @@ -1,7 +1,7 @@ import React from 'react' import {TextInput} from '..' import {render, mount, behavesAsComponent, checkExports} from '../utils/testing' -import {render as HTMLRender, cleanup} from '@testing-library/react' +import {render as HTMLRender, cleanup, fireEvent} from '@testing-library/react' import {axe, toHaveNoViolations} from 'jest-axe' import 'babel-polyfill' import {SearchIcon} from '@primer/octicons-react' @@ -61,6 +61,64 @@ describe('TextInput', () => { expect(render()).toMatchSnapshot() }) + it('focuses the text input if you do not click the input element', () => { + const {container, getByLabelText} = HTMLRender( + <> + {/* eslint-disable-next-line jsx-a11y/label-has-for */} + + + + ) + + const icon = container.querySelector('svg')! + fireEvent.click(icon) + + expect(getByLabelText('Search')).toEqual(document.activeElement) + }) + + // it('renders with a loading indicator', () => { + // expect( + // render( + // <> + // + + // + + // + + // + + // + + // + + // + + // + + // + + // + + // + + // + // + // ) + // ).toMatchSnapshot() + // }) + it('should call onChange prop with input value', () => { const onChangeMock = jest.fn() const component = mount() diff --git a/src/__tests__/TextInputWithTokens.test.tsx b/src/__tests__/TextInputWithTokens.test.tsx index 79cf68a2bad..b8c998f8bc4 100644 --- a/src/__tests__/TextInputWithTokens.test.tsx +++ b/src/__tests__/TextInputWithTokens.test.tsx @@ -109,6 +109,105 @@ describe('TextInputWithTokens', () => { ).toMatchSnapshot() }) + it('renders with a loading indicator', () => { + const onRemoveMock = jest.fn() + expect( + render( + <> + + + + + + + + + + + + + + + + + + + + + + + + + ) + ).toMatchSnapshot() + }) + it('focuses the previous token when keying ArrowLeft', () => { const onRemoveMock = jest.fn() const {getByLabelText, getByText} = HTMLRender( diff --git a/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap b/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap index ed74f706514..f664497098b 100644 --- a/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap +++ b/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap @@ -95,6 +95,7 @@ Array [ `; +exports[`TextInputWithTokens renders with a loading indicator 1`] = ` +Array [ + .c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: -0.25rem; + margin-bottom: -0.25rem; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c1 > * { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + margin-left: 0.25rem; + margin-bottom: 0.25rem; +} + +.c2 { + -webkit-order: 1; + -ms-flex-order: 1; + order: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c7 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c3 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c3: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; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 0; + padding-right: 12px; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); +} + +.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: 0; +} + +.c8 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: visible; +} + +.c6 { + background-color: transparent; + font-family: inherit; + color: currentColor; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-text-decoration: none; + text-decoration: none; + padding: 0; + -webkit-transform: translate(1px,-1px); + -ms-transform: translate(1px,-1px); + transform: translate(1px,-1px); + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; + border: 0; + border-radius: 999px; + margin-left: 8px; + height: 32px; + width: 32px; + position: relative; + z-index: 1; +} + +.c6:hover, +.c6:focus { + background-color: rgba(175,184,193,0.2); +} + +.c6:active { + background-color: rgba(234,238,242,0.5); +} + +.c5 { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + background: transparent; + border: none; + color: inherit; + font: inherit; + margin: 0; + overflow: visible; + padding: 0; + width: auto; + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + -webkit-appearance: none; + line-height: 1; + color: currentColor; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c5:is(a,button,[tabIndex='0']) { + cursor: pointer; +} + +.c5:is(a,button,[tabIndex='0']):after { + content: ''; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.c4 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 999px; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + font-weight: 600; + font-family: inherit; + -webkit-text-decoration: none; + text-decoration: none; + white-space: nowrap; + font-size: 14px; + height: 32px; + line-height: 32px; + padding-left: 16px; + padding-right: 16px; + padding-top: 0; + padding-bottom: 0; + background-color: rgba(234,238,242,0.5); + border-color: rgba(27,31,36,0.15); + border-style: solid; + border-width: 1px; + color: #57606a; + max-width: 100%; + padding-right: 0; + position: relative; +} + +.c4:hover { + background-color: rgba(175,184,193,0.2); + color: #24292f; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + +
+
+ +
+ + + zero + + + + + + one + + + + + + two + + + + + + three + + + + + + four + + + + + + five + + + + + + six + + + + + + seven + + + +
+ +
+ + + + +
+
+
, + .c3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: -0.25rem; + margin-bottom: -0.25rem; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c3 > * { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + margin-left: 0.25rem; + margin-bottom: 0.25rem; +} + +.c4 { + -webkit-order: 1; + -ms-flex-order: 1; + order: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c5 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c5: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; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + padding-right: 0; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); +} + +.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: 0; + padding-right: 12px; +} + +.c2 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: visible; +} + +.c9 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: hidden; +} + +.c8 { + background-color: transparent; + font-family: inherit; + color: currentColor; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-text-decoration: none; + text-decoration: none; + padding: 0; + -webkit-transform: translate(1px,-1px); + -ms-transform: translate(1px,-1px); + transform: translate(1px,-1px); + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; + border: 0; + border-radius: 999px; + margin-left: 8px; + height: 32px; + width: 32px; + position: relative; + z-index: 1; +} + +.c8:hover, +.c8:focus { + background-color: rgba(175,184,193,0.2); +} + +.c8:active { + background-color: rgba(234,238,242,0.5); +} + +.c7 { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + background: transparent; + border: none; + color: inherit; + font: inherit; + margin: 0; + overflow: visible; + padding: 0; + width: auto; + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + -webkit-appearance: none; + line-height: 1; + color: currentColor; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c7:is(a,button,[tabIndex='0']) { + cursor: pointer; +} + +.c7:is(a,button,[tabIndex='0']):after { + content: ''; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.c6 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 999px; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + font-weight: 600; + font-family: inherit; + -webkit-text-decoration: none; + text-decoration: none; + white-space: nowrap; + font-size: 14px; + height: 32px; + line-height: 32px; + padding-left: 16px; + padding-right: 16px; + padding-top: 0; + padding-bottom: 0; + background-color: rgba(234,238,242,0.5); + border-color: rgba(27,31,36,0.15); + border-style: solid; + border-width: 1px; + color: #57606a; + max-width: 100%; + padding-right: 0; + position: relative; +} + +.c6:hover { + background-color: rgba(175,184,193,0.2); + color: #24292f; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+ + + + +
+
+
+
+ +
+ + + zero + + + + + + one + + + + + + two + + + + + + three + + + + + + four + + + + + + five + + + + + + six + + + + + + seven + + + +
+ +
+ + + + +
+
+
, + .c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: -0.25rem; + margin-bottom: -0.25rem; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c1 > * { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + margin-left: 0.25rem; + margin-bottom: 0.25rem; +} + +.c2 { + -webkit-order: 1; + -ms-flex-order: 1; + order: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c7 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c3 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c3: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; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 0; + padding-right: 12px; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); +} + +.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: 0; +} + +.c8 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: visible; +} + +.c6 { + background-color: transparent; + font-family: inherit; + color: currentColor; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-text-decoration: none; + text-decoration: none; + padding: 0; + -webkit-transform: translate(1px,-1px); + -ms-transform: translate(1px,-1px); + transform: translate(1px,-1px); + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; + border: 0; + border-radius: 999px; + margin-left: 8px; + height: 32px; + width: 32px; + position: relative; + z-index: 1; +} + +.c6:hover, +.c6:focus { + background-color: rgba(175,184,193,0.2); +} + +.c6:active { + background-color: rgba(234,238,242,0.5); +} + +.c5 { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + background: transparent; + border: none; + color: inherit; + font: inherit; + margin: 0; + overflow: visible; + padding: 0; + width: auto; + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + -webkit-appearance: none; + line-height: 1; + color: currentColor; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c5:is(a,button,[tabIndex='0']) { + cursor: pointer; +} + +.c5:is(a,button,[tabIndex='0']):after { + content: ''; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.c4 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 999px; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + font-weight: 600; + font-family: inherit; + -webkit-text-decoration: none; + text-decoration: none; + white-space: nowrap; + font-size: 14px; + height: 32px; + line-height: 32px; + padding-left: 16px; + padding-right: 16px; + padding-top: 0; + padding-bottom: 0; + background-color: rgba(234,238,242,0.5); + border-color: rgba(27,31,36,0.15); + border-style: solid; + border-width: 1px; + color: #57606a; + max-width: 100%; + padding-right: 0; + position: relative; +} + +.c4:hover { + background-color: rgba(175,184,193,0.2); + color: #24292f; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + +
+
+ +
+ + + zero + + + + + + one + + + + + + two + + + + + + three + + + + + + four + + + + + + five + + + + + + six + + + + + + seven + + + +
+ +
+ + + + +
+
+
, + .c4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: -0.25rem; + margin-bottom: -0.25rem; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c4 > * { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + margin-left: 0.25rem; + margin-bottom: 0.25rem; +} + +.c5 { + -webkit-order: 1; + -ms-flex-order: 1; + order: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c2 { + visibility: hidden; +} + +.c6 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c6: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; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + padding-right: 0; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); +} + +.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: 0; + padding-right: 12px; +} + +.c10 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: hidden; +} + +.c3 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: visible; + left: 0; +} + +.c9 { + background-color: transparent; + font-family: inherit; + color: currentColor; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-text-decoration: none; + text-decoration: none; + padding: 0; + -webkit-transform: translate(1px,-1px); + -ms-transform: translate(1px,-1px); + transform: translate(1px,-1px); + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; + border: 0; + border-radius: 999px; + margin-left: 8px; + height: 32px; + width: 32px; + position: relative; + z-index: 1; +} + +.c9:hover, +.c9:focus { + background-color: rgba(175,184,193,0.2); +} + +.c9:active { + background-color: rgba(234,238,242,0.5); +} + +.c8 { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + background: transparent; + border: none; + color: inherit; + font: inherit; + margin: 0; + overflow: visible; + padding: 0; + width: auto; + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + -webkit-appearance: none; + line-height: 1; + color: currentColor; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c8:is(a,button,[tabIndex='0']) { + cursor: pointer; +} + +.c8:is(a,button,[tabIndex='0']):after { + content: ''; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.c7 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 999px; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + font-weight: 600; + font-family: inherit; + -webkit-text-decoration: none; + text-decoration: none; + white-space: nowrap; + font-size: 14px; + height: 32px; + line-height: 32px; + padding-left: 16px; + padding-right: 16px; + padding-top: 0; + padding-bottom: 0; + background-color: rgba(234,238,242,0.5); + border-color: rgba(27,31,36,0.15); + border-style: solid; + border-width: 1px; + color: #57606a; + max-width: 100%; + padding-right: 0; + position: relative; +} + +.c7:hover { + background-color: rgba(175,184,193,0.2); + color: #24292f; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+
+
+ + + + +
+
+
+
+ +
+ + + zero + + + + + + one + + + + + + two + + + + + + three + + + + + + four + + + + + + five + + + + + + six + + + + + + seven + + + +
+ +
+ + + + +
+
+
, + .c4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: -0.25rem; + margin-bottom: -0.25rem; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c4 > * { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + margin-left: 0.25rem; + margin-bottom: 0.25rem; +} + +.c5 { + -webkit-order: 1; + -ms-flex-order: 1; + order: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c2 { + visibility: hidden; +} + +.c6 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c6: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; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + padding-right: 0; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); +} + +.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: 0; + padding-right: 12px; +} + +.c10 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: hidden; +} + +.c3 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: visible; + left: 0; +} + +.c9 { + background-color: transparent; + font-family: inherit; + color: currentColor; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-text-decoration: none; + text-decoration: none; + padding: 0; + -webkit-transform: translate(1px,-1px); + -ms-transform: translate(1px,-1px); + transform: translate(1px,-1px); + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; + border: 0; + border-radius: 999px; + margin-left: 8px; + height: 32px; + width: 32px; + position: relative; + z-index: 1; +} + +.c9:hover, +.c9:focus { + background-color: rgba(175,184,193,0.2); +} + +.c9:active { + background-color: rgba(234,238,242,0.5); +} + +.c8 { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + background: transparent; + border: none; + color: inherit; + font: inherit; + margin: 0; + overflow: visible; + padding: 0; + width: auto; + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + -webkit-appearance: none; + line-height: 1; + color: currentColor; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c8:is(a,button,[tabIndex='0']) { + cursor: pointer; +} + +.c8:is(a,button,[tabIndex='0']):after { + content: ''; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.c7 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 999px; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + font-weight: 600; + font-family: inherit; + -webkit-text-decoration: none; + text-decoration: none; + white-space: nowrap; + font-size: 14px; + height: 32px; + line-height: 32px; + padding-left: 16px; + padding-right: 16px; + padding-top: 0; + padding-bottom: 0; + background-color: rgba(234,238,242,0.5); + border-color: rgba(27,31,36,0.15); + border-style: solid; + border-width: 1px; + color: #57606a; + max-width: 100%; + padding-right: 0; + position: relative; +} + +.c7:hover { + background-color: rgba(175,184,193,0.2); + color: #24292f; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+
+
+ + + + +
+
+
+
+ +
+ + + zero + + + + + + one + + + + + + two + + + + + + three + + + + + + four + + + + + + five + + + + + + six + + + + + + seven + + + +
+ +
+ + + + +
+
+
, + .c4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: -0.25rem; + margin-bottom: -0.25rem; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c4 > * { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + margin-left: 0.25rem; + margin-bottom: 0.25rem; +} + +.c5 { + -webkit-order: 1; + -ms-flex-order: 1; + order: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c2 { + visibility: visible; +} + +.c6 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c6: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; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + padding-right: 12px; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); +} + +.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: 0; + padding-right: 0; +} + +.c10 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: visible; +} + +.c3 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: hidden; + left: 0; +} + +.c9 { + background-color: transparent; + font-family: inherit; + color: currentColor; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-text-decoration: none; + text-decoration: none; + padding: 0; + -webkit-transform: translate(1px,-1px); + -ms-transform: translate(1px,-1px); + transform: translate(1px,-1px); + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; + border: 0; + border-radius: 999px; + margin-left: 8px; + height: 32px; + width: 32px; + position: relative; + z-index: 1; +} + +.c9:hover, +.c9:focus { + background-color: rgba(175,184,193,0.2); +} + +.c9:active { + background-color: rgba(234,238,242,0.5); +} + +.c8 { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + background: transparent; + border: none; + color: inherit; + font: inherit; + margin: 0; + overflow: visible; + padding: 0; + width: auto; + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + -webkit-appearance: none; + line-height: 1; + color: currentColor; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c8:is(a,button,[tabIndex='0']) { + cursor: pointer; +} + +.c8:is(a,button,[tabIndex='0']):after { + content: ''; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.c7 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 999px; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + font-weight: 600; + font-family: inherit; + -webkit-text-decoration: none; + text-decoration: none; + white-space: nowrap; + font-size: 14px; + height: 32px; + line-height: 32px; + padding-left: 16px; + padding-right: 16px; + padding-top: 0; + padding-bottom: 0; + background-color: rgba(234,238,242,0.5); + border-color: rgba(27,31,36,0.15); + border-style: solid; + border-width: 1px; + color: #57606a; + max-width: 100%; + padding-right: 0; + position: relative; +} + +.c7:hover { + background-color: rgba(175,184,193,0.2); + color: #24292f; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+
+
+ + + + +
+
+
+
+ +
+ + + zero + + + + + + one + + + + + + two + + + + + + three + + + + + + four + + + + + + five + + + + + + six + + + + + + seven + + + +
+ +
+ + + + +
+
+
, + .c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: -0.25rem; + margin-bottom: -0.25rem; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c1 > * { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + margin-left: 0.25rem; + margin-bottom: 0.25rem; +} + +.c2 { + -webkit-order: 1; + -ms-flex-order: 1; + order: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c7 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c8 { + visibility: hidden; +} + +.c3 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c3: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; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 0; + padding-right: 12px; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); +} + +.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: 0; +} + +.c9 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: visible; + right: 0; +} + +.c6 { + background-color: transparent; + font-family: inherit; + color: currentColor; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-text-decoration: none; + text-decoration: none; + padding: 0; + -webkit-transform: translate(1px,-1px); + -ms-transform: translate(1px,-1px); + transform: translate(1px,-1px); + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; + border: 0; + border-radius: 999px; + margin-left: 8px; + height: 32px; + width: 32px; + position: relative; + z-index: 1; +} + +.c6:hover, +.c6:focus { + background-color: rgba(175,184,193,0.2); +} + +.c6:active { + background-color: rgba(234,238,242,0.5); +} + +.c5 { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + background: transparent; + border: none; + color: inherit; + font: inherit; + margin: 0; + overflow: visible; + padding: 0; + width: auto; + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + -webkit-appearance: none; + line-height: 1; + color: currentColor; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c5:is(a,button,[tabIndex='0']) { + cursor: pointer; +} + +.c5:is(a,button,[tabIndex='0']):after { + content: ''; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.c4 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 999px; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + font-weight: 600; + font-family: inherit; + -webkit-text-decoration: none; + text-decoration: none; + white-space: nowrap; + font-size: 14px; + height: 32px; + line-height: 32px; + padding-left: 16px; + padding-right: 16px; + padding-top: 0; + padding-bottom: 0; + background-color: rgba(234,238,242,0.5); + border-color: rgba(27,31,36,0.15); + border-style: solid; + border-width: 1px; + color: #57606a; + max-width: 100%; + padding-right: 0; + position: relative; +} + +.c4:hover { + background-color: rgba(175,184,193,0.2); + color: #24292f; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + +
+
+ +
+ + + zero + + + + + + one + + + + + + two + + + + + + three + + + + + + four + + + + + + five + + + + + + six + + + + + + seven + + + +
+ +
+
+
+ + + + +
+
+
, + .c3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: -0.25rem; + margin-bottom: -0.25rem; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c3 > * { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + margin-left: 0.25rem; + margin-bottom: 0.25rem; +} + +.c4 { + -webkit-order: 1; + -ms-flex-order: 1; + order: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c9 { + visibility: visible; +} + +.c5 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c5: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; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + padding-right: 12px; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); +} + +.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: 0; + padding-right: 0; +} + +.c2 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: visible; +} + +.c10 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: hidden; + right: 0; +} + +.c8 { + background-color: transparent; + font-family: inherit; + color: currentColor; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-text-decoration: none; + text-decoration: none; + padding: 0; + -webkit-transform: translate(1px,-1px); + -ms-transform: translate(1px,-1px); + transform: translate(1px,-1px); + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; + border: 0; + border-radius: 999px; + margin-left: 8px; + height: 32px; + width: 32px; + position: relative; + z-index: 1; +} + +.c8:hover, +.c8:focus { + background-color: rgba(175,184,193,0.2); +} + +.c8:active { + background-color: rgba(234,238,242,0.5); +} + +.c7 { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + background: transparent; + border: none; + color: inherit; + font: inherit; + margin: 0; + overflow: visible; + padding: 0; + width: auto; + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + -webkit-appearance: none; + line-height: 1; + color: currentColor; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c7:is(a,button,[tabIndex='0']) { + cursor: pointer; +} + +.c7:is(a,button,[tabIndex='0']):after { + content: ''; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.c6 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 999px; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + font-weight: 600; + font-family: inherit; + -webkit-text-decoration: none; + text-decoration: none; + white-space: nowrap; + font-size: 14px; + height: 32px; + line-height: 32px; + padding-left: 16px; + padding-right: 16px; + padding-top: 0; + padding-bottom: 0; + background-color: rgba(234,238,242,0.5); + border-color: rgba(27,31,36,0.15); + border-style: solid; + border-width: 1px; + color: #57606a; + max-width: 100%; + padding-right: 0; + position: relative; +} + +.c6:hover { + background-color: rgba(175,184,193,0.2); + color: #24292f; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+ + + + +
+
+
+
+ +
+ + + zero + + + + + + one + + + + + + two + + + + + + three + + + + + + four + + + + + + five + + + + + + six + + + + + + seven + + + +
+ +
+
+
+ + + + +
+
+
, + .c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: -0.25rem; + margin-bottom: -0.25rem; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c1 > * { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + margin-left: 0.25rem; + margin-bottom: 0.25rem; +} + +.c2 { + -webkit-order: 1; + -ms-flex-order: 1; + order: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c7 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c8 { + visibility: hidden; +} + +.c3 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c3: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; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 0; + padding-right: 12px; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); +} + +.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: 0; +} + +.c9 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: visible; + right: 0; +} + +.c6 { + background-color: transparent; + font-family: inherit; + color: currentColor; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-text-decoration: none; + text-decoration: none; + padding: 0; + -webkit-transform: translate(1px,-1px); + -ms-transform: translate(1px,-1px); + transform: translate(1px,-1px); + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; + border: 0; + border-radius: 999px; + margin-left: 8px; + height: 32px; + width: 32px; + position: relative; + z-index: 1; +} + +.c6:hover, +.c6:focus { + background-color: rgba(175,184,193,0.2); +} + +.c6:active { + background-color: rgba(234,238,242,0.5); +} + +.c5 { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + background: transparent; + border: none; + color: inherit; + font: inherit; + margin: 0; + overflow: visible; + padding: 0; + width: auto; + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + -webkit-appearance: none; + line-height: 1; + color: currentColor; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c5:is(a,button,[tabIndex='0']) { + cursor: pointer; +} + +.c5:is(a,button,[tabIndex='0']):after { + content: ''; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.c4 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 999px; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + font-weight: 600; + font-family: inherit; + -webkit-text-decoration: none; + text-decoration: none; + white-space: nowrap; + font-size: 14px; + height: 32px; + line-height: 32px; + padding-left: 16px; + padding-right: 16px; + padding-top: 0; + padding-bottom: 0; + background-color: rgba(234,238,242,0.5); + border-color: rgba(27,31,36,0.15); + border-style: solid; + border-width: 1px; + color: #57606a; + max-width: 100%; + padding-right: 0; + position: relative; +} + +.c4:hover { + background-color: rgba(175,184,193,0.2); + color: #24292f; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + +
+
+ +
+ + + zero + + + + + + one + + + + + + two + + + + + + three + + + + + + four + + + + + + five + + + + + + six + + + + + + seven + + + +
+ +
+
+
+ + + + +
+
+
, + .c4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: -0.25rem; + margin-bottom: -0.25rem; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c4 > * { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + margin-left: 0.25rem; + margin-bottom: 0.25rem; +} + +.c5 { + -webkit-order: 1; + -ms-flex-order: 1; + order: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c2 { + visibility: hidden; +} + +.c10 { + visibility: visible; +} + +.c6 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c6: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; + min-height: 28px; + padding-left: 8px; + padding-right: 8px; + padding-top: 3px; + padding-bottom: 3px; + font-size: 12px; + line-height: 20px; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + padding-right: 12px; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); +} + +.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: 0; + padding-right: 0; +} + +.c3 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: visible; + left: 0; +} + +.c11 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: hidden; + right: 0; +} + +.c9 { + background-color: transparent; + font-family: inherit; + color: currentColor; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-text-decoration: none; + text-decoration: none; + padding: 0; + -webkit-transform: translate(1px,-1px); + -ms-transform: translate(1px,-1px); + transform: translate(1px,-1px); + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; + border: 0; + border-radius: 999px; + margin-left: 4px; + height: 16px; + width: 16px; + position: relative; + z-index: 1; +} + +.c9:hover, +.c9:focus { + background-color: rgba(175,184,193,0.2); +} + +.c9:active { + background-color: rgba(234,238,242,0.5); +} + +.c8 { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + background: transparent; + border: none; + color: inherit; + font: inherit; + margin: 0; + overflow: visible; + padding: 0; + width: auto; + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + -webkit-appearance: none; + line-height: 1; + color: currentColor; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c8:is(a,button,[tabIndex='0']) { + cursor: pointer; +} + +.c8:is(a,button,[tabIndex='0']):after { + content: ''; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.c7 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 999px; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + font-weight: 600; + font-family: inherit; + -webkit-text-decoration: none; + text-decoration: none; + white-space: nowrap; + font-size: 12px; + height: 16px; + line-height: 16px; + padding-left: 4px; + padding-right: 4px; + padding-top: 0; + padding-bottom: 0; + background-color: rgba(234,238,242,0.5); + border-color: rgba(27,31,36,0.15); + border-style: solid; + border-width: 1px; + color: #57606a; + max-width: 100%; + padding-right: 0; + position: relative; +} + +.c7:hover { + background-color: rgba(175,184,193,0.2); + color: #24292f; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+
+
+ + + + +
+
+
+
+ +
+ + + zero + + + + + + one + + + + + + two + + + + + + three + + + + + + four + + + + + + five + + + + + + six + + + + + + seven + + + +
+ +
+
+
+ + + + +
+
+
, + .c4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: -0.25rem; + margin-bottom: -0.25rem; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c4 > * { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + margin-left: 0.25rem; + margin-bottom: 0.25rem; +} + +.c5 { + -webkit-order: 1; + -ms-flex-order: 1; + order: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c2 { + visibility: hidden; +} + +.c10 { + visibility: visible; +} + +.c6 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c6: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; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + padding-right: 12px; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); +} + +.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: 0; + padding-right: 0; +} + +.c3 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: visible; + left: 0; +} + +.c11 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: hidden; + right: 0; +} + +.c9 { + background-color: transparent; + font-family: inherit; + color: currentColor; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-text-decoration: none; + text-decoration: none; + padding: 0; + -webkit-transform: translate(1px,-1px); + -ms-transform: translate(1px,-1px); + transform: translate(1px,-1px); + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; + border: 0; + border-radius: 999px; + margin-left: 8px; + height: 32px; + width: 32px; + position: relative; + z-index: 1; +} + +.c9:hover, +.c9:focus { + background-color: rgba(175,184,193,0.2); +} + +.c9:active { + background-color: rgba(234,238,242,0.5); +} + +.c8 { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + background: transparent; + border: none; + color: inherit; + font: inherit; + margin: 0; + overflow: visible; + padding: 0; + width: auto; + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + -webkit-appearance: none; + line-height: 1; + color: currentColor; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c8:is(a,button,[tabIndex='0']) { + cursor: pointer; +} + +.c8:is(a,button,[tabIndex='0']):after { + content: ''; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.c7 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 999px; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + font-weight: 600; + font-family: inherit; + -webkit-text-decoration: none; + text-decoration: none; + white-space: nowrap; + font-size: 14px; + height: 32px; + line-height: 32px; + padding-left: 16px; + padding-right: 16px; + padding-top: 0; + padding-bottom: 0; + background-color: rgba(234,238,242,0.5); + border-color: rgba(27,31,36,0.15); + border-style: solid; + border-width: 1px; + color: #57606a; + max-width: 100%; + padding-right: 0; + position: relative; +} + +.c7:hover { + background-color: rgba(175,184,193,0.2); + color: #24292f; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+
+
+ + + + +
+
+
+
+ +
+ + + zero + + + + + + one + + + + + + two + + + + + + three + + + + + + four + + + + + + five + + + + + + six + + + + + + seven + + + +
+ +
+
+
+ + + + +
+
+
, + .c4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: -0.25rem; + margin-bottom: -0.25rem; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c4 > * { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + margin-left: 0.25rem; + margin-bottom: 0.25rem; +} + +.c5 { + -webkit-order: 1; + -ms-flex-order: 1; + order: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c10 { + visibility: hidden; +} + +.c2 { + visibility: visible; +} + +.c6 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c6: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; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + padding-right: 12px; + padding-left: 12px; + padding-top: calc(12px / 2); + padding-bottom: calc(12px / 2); +} + +.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: 0; + padding-right: 0; +} + +.c3 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: hidden; + left: 0; +} + +.c11 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: visible; + right: 0; +} + +.c9 { + background-color: transparent; + font-family: inherit; + color: currentColor; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-text-decoration: none; + text-decoration: none; + padding: 0; + -webkit-transform: translate(1px,-1px); + -ms-transform: translate(1px,-1px); + transform: translate(1px,-1px); + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; + border: 0; + border-radius: 999px; + margin-left: 8px; + height: 24px; + width: 24px; + position: relative; + z-index: 1; +} + +.c9:hover, +.c9:focus { + background-color: rgba(175,184,193,0.2); +} + +.c9:active { + background-color: rgba(234,238,242,0.5); +} + +.c8 { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + background: transparent; + border: none; + color: inherit; + font: inherit; + margin: 0; + overflow: visible; + padding: 0; + width: auto; + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + -webkit-appearance: none; + line-height: 1; + color: currentColor; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c8:is(a,button,[tabIndex='0']) { + cursor: pointer; +} + +.c8:is(a,button,[tabIndex='0']):after { + content: ''; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.c7 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 999px; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + font-weight: 600; + font-family: inherit; + -webkit-text-decoration: none; + text-decoration: none; + white-space: nowrap; + font-size: 12px; + height: 24px; + line-height: 24px; + padding-left: 8px; + padding-right: 8px; + padding-top: 0; + padding-bottom: 0; + background-color: rgba(234,238,242,0.5); + border-color: rgba(27,31,36,0.15); + border-style: solid; + border-width: 1px; + color: #57606a; + max-width: 100%; + padding-right: 0; + position: relative; +} + +.c7:hover { + background-color: rgba(175,184,193,0.2); + color: #24292f; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+
+
+ + + + +
+
+
+
+ +
+ + + zero + + + + + + one + + + + + + two + + + + + + three + + + + + + four + + + + + + five + + + + + + six + + + + + + seven + + + +
+ +
+
+
+ + + + +
+
+
, +] +`; + exports[`TextInputWithTokens renders with tokens 1`] = ` .c1 { display: -webkit-box; From 245b56835491bda52bc9301bb4639a65042550e8 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Wed, 2 Mar 2022 13:53:03 -0500 Subject: [PATCH 05/35] fixes silly test mistakes --- src/__tests__/TextInput.test.tsx | 65 +- .../__snapshots__/TextInput.test.tsx.snap | 2687 +++++++++++++++++ 2 files changed, 2720 insertions(+), 32 deletions(-) diff --git a/src/__tests__/TextInput.test.tsx b/src/__tests__/TextInput.test.tsx index 977d9e38440..faaed2e6c33 100644 --- a/src/__tests__/TextInput.test.tsx +++ b/src/__tests__/TextInput.test.tsx @@ -71,53 +71,54 @@ describe('TextInput', () => { ) const icon = container.querySelector('svg')! - fireEvent.click(icon) + expect(getByLabelText('Search')).not.toEqual(document.activeElement) + fireEvent.click(icon) expect(getByLabelText('Search')).toEqual(document.activeElement) }) - // it('renders with a loading indicator', () => { - // expect( - // render( - // <> - // + it('renders with a loading indicator', () => { + expect( + render( + <> + - // + - // + - // + - // + - // + - // + - // + - // + - // + - // + - // - // - // ) - // ).toMatchSnapshot() - // }) + + + ) + ).toMatchSnapshot() + }) it('should call onChange prop with input value', () => { const onChangeMock = jest.fn() diff --git a/src/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/__tests__/__snapshots__/TextInput.test.tsx.snap index 73520a5a9cb..18373591cc3 100644 --- a/src/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -1228,6 +1228,2693 @@ exports[`TextInput renders warning 1`] = `
`; +exports[`TextInput renders with a loading indicator 1`] = ` +Array [ + .c2 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.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; + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 0; + padding-right: 12px; +} + +.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: 0; +} + +.c3 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: visible; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + + +
+ + + + +
+
+
, + .c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c3 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c3: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; + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + 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: 0; + padding-right: 12px; +} + +.c2 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: visible; +} + +.c4 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: hidden; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+ + + + +
+
+ + +
+ + + + +
+
+
, + .c2 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.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; + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 0; + padding-right: 12px; +} + +.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: 0; +} + +.c3 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: visible; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + + +
+ + + + +
+
+
, + .c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c2 { + visibility: hidden; +} + +.c4 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c4: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; + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + 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: 0; + padding-right: 12px; +} + +.c5 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: hidden; +} + +.c3 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: visible; + left: 0; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+
+
+ + + + +
+
+ + +
+ + + + +
+
+
, + .c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c2 { + visibility: hidden; +} + +.c4 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c4: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; + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + 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: 0; + padding-right: 12px; +} + +.c5 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: hidden; +} + +.c3 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: visible; + left: 0; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+
+
+ + + + +
+
+ + +
+ + + + +
+
+
, + .c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c2 { + visibility: visible; +} + +.c4 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c4: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; + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + padding-right: 12px; +} + +.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: 0; + padding-right: 0; +} + +.c5 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: visible; +} + +.c3 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: hidden; + left: 0; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+
+
+ + + + +
+
+ + +
+ + + + +
+
+
, + .c2 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c3 { + visibility: hidden; +} + +.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; + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 0; + padding-right: 12px; +} + +.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: 0; +} + +.c4 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: visible; + right: 0; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + + +
+
+
+ + + + +
+
+
, + .c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c4 { + visibility: visible; +} + +.c3 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c3: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; + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + padding-right: 12px; +} + +.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: 0; + padding-right: 0; +} + +.c2 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + visibility: visible; +} + +.c5 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: hidden; + right: 0; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+ + + + +
+
+ + +
+
+
+ + + + +
+
+
, + .c2 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c3 { + visibility: hidden; +} + +.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; + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 0; + padding-right: 12px; +} + +.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: 0; +} + +.c4 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: visible; + right: 0; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + + +
+
+
+ + + + +
+
+
, + .c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c2 { + visibility: hidden; +} + +.c5 { + visibility: visible; +} + +.c4 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c4: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; + min-height: 28px; + padding-left: 8px; + padding-right: 8px; + padding-top: 3px; + padding-bottom: 3px; + font-size: 12px; + line-height: 20px; + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + padding-right: 12px; +} + +.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: 0; + padding-right: 0; +} + +.c3 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: visible; + left: 0; +} + +.c6 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: hidden; + right: 0; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+
+
+ + + + +
+
+ + +
+
+
+ + + + +
+
+
, + .c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c2 { + visibility: hidden; +} + +.c5 { + visibility: visible; +} + +.c4 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c4: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; + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + padding-right: 12px; +} + +.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: 0; + padding-right: 0; +} + +.c3 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: visible; + left: 0; +} + +.c6 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: hidden; + right: 0; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+
+
+ + + + +
+
+ + +
+
+
+ + + + +
+
+
, + .c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; +} + +.c5 { + visibility: hidden; +} + +.c2 { + visibility: visible; +} + +.c4 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c4: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; + padding-left: 8px; + padding-right: 8px; + padding-top: 10px; + padding-bottom: 10px; + font-size: 20px; + background-repeat: no-repeat; + background-position: right 8px center; + padding-left: 12px; + padding-right: 12px; +} + +.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: 0; + padding-right: 0; +} + +.c3 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: hidden; + left: 0; +} + +.c6 { + -webkit-animation: rotate-keyframes 1s linear infinite; + animation: rotate-keyframes 1s linear infinite; + position: absolute; + top: 0; + height: 100%; + max-width: 100%; + visibility: visible; + right: 0; +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + +
+
+
+ + + + +
+
+ + +
+
+
+ + + + +
+
+
, +] +`; + exports[`TextInput should render a password input 1`] = ` .c1 { border: 0; From 6c1f3586b8b1d3dbde36bfee6777bce1db727221 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Wed, 2 Mar 2022 13:57:58 -0500 Subject: [PATCH 06/35] revert default textinput story --- src/stories/TextInput.stories.tsx | 110 +++++------------------------- 1 file changed, 16 insertions(+), 94 deletions(-) diff --git a/src/stories/TextInput.stories.tsx b/src/stories/TextInput.stories.tsx index 42200e5c7af..96a73a12d42 100644 --- a/src/stories/TextInput.stories.tsx +++ b/src/stories/TextInput.stories.tsx @@ -80,107 +80,29 @@ const Label = ({htmlFor, children}: {htmlFor: string; children: ReactNode}) => ( ) -export const Default = () => { - const [isLoading, setIsLoading] = useState(false) +export const Default = (args: TextInputProps) => { + const [value, setValue] = useState('') - const toggleLoadingState = () => { - setIsLoading(!isLoading) + const handleChange = (event: React.ChangeEvent) => { + setValue(event.target.value) } - return ( - <> - - -

No visual

- - - - - - - - - - -

Leading visual

- - - - - - - - - - -

Trailing visual

- - - - - - - - - + const inputId = 'basic-text-input' -

Both visuals

- - - - - - - - } - trailingVisual={() => } - isLoading={isLoading} - loadingIndicatorPosition="trailing" - value="trailing" - /> - - + return ( +
+
+
+ +
+
+ +
+
+
) } -Default.parameters = {controls: {exclude: ['isLoading', 'loadingIndicatorPosition']}} - export const WithLeadingVisual = (args: TextInputProps) => { const [value, setValue] = useState('') From 81a1022f8303ecc2bf97bb5774a8c9c2a5a0665d Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Wed, 2 Mar 2022 14:30:40 -0500 Subject: [PATCH 07/35] adds changeset --- .changeset/smooth-lemons-brake.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/smooth-lemons-brake.md diff --git a/.changeset/smooth-lemons-brake.md b/.changeset/smooth-lemons-brake.md new file mode 100644 index 00000000000..4a68284bebf --- /dev/null +++ b/.changeset/smooth-lemons-brake.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +Adds a loadings state to our text input components From 5388500f21073cb4a2852eef14b2dbcfae1035fe Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Tue, 8 Mar 2022 11:42:08 -0500 Subject: [PATCH 08/35] Update src/TextInput.tsx Co-authored-by: Pavithra Kodmad --- src/TextInput.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TextInput.tsx b/src/TextInput.tsx index 53fe02830b8..64fce470d63 100644 --- a/src/TextInput.tsx +++ b/src/TextInput.tsx @@ -71,7 +71,7 @@ const TextInput = React.forwardRef( isLoading && (loadingIndicatorPosition === 'leading' || Boolean(LeadingVisual && loadingIndicatorPosition !== 'trailing')) const showTrailingLoadingIndicator = - isLoading && (loadingIndicatorPosition === 'trailing' || (loadingIndicatorPosition === 'auto' && !LeadingVisual)) + isLoading && (loadingIndicatorPosition === 'trailing' || Boolean(loadingIndicatorPosition === 'auto' && !LeadingVisual)) const focusInput: MouseEventHandler = () => { inputRef.current?.focus() } From 070612fe8d94c39f1464b23dd3c03a930ec02a5d Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Tue, 8 Mar 2022 11:45:10 -0500 Subject: [PATCH 09/35] updates component API --- docs/content/TextInput.mdx | 38 +++++---------------- docs/content/TextInputWithTokens.mdx | 16 ++++----- src/TextInput.tsx | 11 +++--- src/TextInputWithTokens.tsx | 9 +++-- src/__tests__/TextInput.test.tsx | 21 +++++------- src/__tests__/TextInputWithTokens.test.tsx | 26 +++++--------- src/stories/TextInput.stories.tsx | 4 +-- src/stories/TextInputWithTokens.stories.tsx | 4 +-- 8 files changed, 46 insertions(+), 83 deletions(-) diff --git a/docs/content/TextInput.mdx b/docs/content/TextInput.mdx index 97cdff5c171..e4f6852b18c 100644 --- a/docs/content/TextInput.mdx +++ b/docs/content/TextInput.mdx @@ -70,10 +70,10 @@ const WithIconAndLoadingIndicator = () => { - + - +

Leading visual

@@ -81,20 +81,10 @@ const WithIconAndLoadingIndicator = () => { - + - +

Trailing visual

@@ -102,20 +92,10 @@ const WithIconAndLoadingIndicator = () => { - + - +

Both visuals

@@ -133,7 +113,7 @@ const WithIconAndLoadingIndicator = () => { leadingVisual={SearchIcon} trailingVisual={SearchIcon} isLoading={isLoading} - loadingIndicatorPosition="leading" + loaderPosition="leading" value="leading" /> @@ -143,7 +123,7 @@ const WithIconAndLoadingIndicator = () => { leadingVisual={SearchIcon} trailingVisual={SearchIcon} isLoading={isLoading} - loadingIndicatorPosition="trailing" + loaderPosition="trailing" value="trailing" /> @@ -213,7 +193,7 @@ render() /> ( <> diff --git a/docs/content/TextInputWithTokens.mdx b/docs/content/TextInputWithTokens.mdx index 22c43c5cafc..e119f218502 100644 --- a/docs/content/TextInputWithTokens.mdx +++ b/docs/content/TextInputWithTokens.mdx @@ -275,7 +275,7 @@ const WithIconAndLoadingIndicator = () => { onTokenRemove={onDateRemove} value="leading" isLoading={isLoading} - loadingIndicatorPosition="leading" + loaderPosition="leading" /> @@ -284,7 +284,7 @@ const WithIconAndLoadingIndicator = () => { onTokenRemove={onDateRemove} value="trailing" isLoading={isLoading} - loadingIndicatorPosition="trailing" + loaderPosition="trailing" /> @@ -304,7 +304,7 @@ const WithIconAndLoadingIndicator = () => { onTokenRemove={onDateRemove} leadingVisual={CalendarIcon} isLoading={isLoading} - loadingIndicatorPosition="leading" + loaderPosition="leading" value="leading" /> @@ -314,7 +314,7 @@ const WithIconAndLoadingIndicator = () => { onTokenRemove={onDateRemove} leadingVisual={CalendarIcon} isLoading={isLoading} - loadingIndicatorPosition="trailing" + loaderPosition="trailing" value="trailing" /> @@ -335,7 +335,7 @@ const WithIconAndLoadingIndicator = () => { onTokenRemove={onDateRemove} trailingVisual={CalendarIcon} isLoading={isLoading} - loadingIndicatorPosition="leading" + loaderPosition="leading" value="leading" /> @@ -345,7 +345,7 @@ const WithIconAndLoadingIndicator = () => { onTokenRemove={onDateRemove} trailingVisual={CalendarIcon} isLoading={isLoading} - loadingIndicatorPosition="trailing" + loaderPosition="trailing" value="trailing" /> @@ -369,7 +369,7 @@ const WithIconAndLoadingIndicator = () => { leadingVisual={CalendarIcon} trailingVisual={CalendarIcon} isLoading={isLoading} - loadingIndicatorPosition="leading" + loaderPosition="leading" value="leading" /> @@ -381,7 +381,7 @@ const WithIconAndLoadingIndicator = () => { leadingVisual={CalendarIcon} trailingVisual={CalendarIcon} isLoading={isLoading} - loadingIndicatorPosition="trailing" + loaderPosition="trailing" value="trailing" /> diff --git a/src/TextInput.tsx b/src/TextInput.tsx index 64fce470d63..5863a205f08 100644 --- a/src/TextInput.tsx +++ b/src/TextInput.tsx @@ -18,7 +18,7 @@ export type TextInputNonPassthroughProps = { * 'leading': at the beginning of the input * 'trailing': at the end of the input **/ - loadingIndicatorPosition?: 'auto' | 'leading' | 'trailing' // TODO: come up with a shorter name + loaderPosition?: 'auto' | 'leading' | 'trailing' /** * A visual that renders inside the input before the typing area */ @@ -50,7 +50,7 @@ const TextInput = React.forwardRef( contrast, disabled, isLoading, - loadingIndicatorPosition, + loaderPosition, validationStatus, sx: sxProp, size: sizeProp, @@ -68,10 +68,9 @@ const TextInput = React.forwardRef( // this class is necessary to style FilterSearch, plz no touchy! const wrapperClasses = classnames(className, 'TextInput-wrapper') const showLeadingLoadingIndicator = - isLoading && - (loadingIndicatorPosition === 'leading' || Boolean(LeadingVisual && loadingIndicatorPosition !== 'trailing')) + isLoading && (loaderPosition === 'leading' || Boolean(LeadingVisual && loaderPosition !== 'trailing')) const showTrailingLoadingIndicator = - isLoading && (loadingIndicatorPosition === 'trailing' || Boolean(loadingIndicatorPosition === 'auto' && !LeadingVisual)) + isLoading && (loaderPosition === 'trailing' || Boolean(loaderPosition === 'auto' && !LeadingVisual)) const focusInput: MouseEventHandler = () => { inputRef.current?.focus() } @@ -116,7 +115,7 @@ const TextInput = React.forwardRef( TextInput.defaultProps = { type: 'text', - loadingIndicatorPosition: 'auto' + loaderPosition: 'auto' } TextInput.displayName = 'TextInput' diff --git a/src/TextInputWithTokens.tsx b/src/TextInputWithTokens.tsx index bb9497ba19a..f5f68b9dfde 100644 --- a/src/TextInputWithTokens.tsx +++ b/src/TextInputWithTokens.tsx @@ -70,7 +70,7 @@ function TextInputWithTokensInnerComponent { <> - + - + - + - + - + - + - + ) diff --git a/src/__tests__/TextInputWithTokens.test.tsx b/src/__tests__/TextInputWithTokens.test.tsx index b8c998f8bc4..0cb9f0c43f3 100644 --- a/src/__tests__/TextInputWithTokens.test.tsx +++ b/src/__tests__/TextInputWithTokens.test.tsx @@ -116,19 +116,9 @@ describe('TextInputWithTokens', () => { <> - + - + { onTokenRemove={onRemoveMock} isLoading leadingVisual={MarkGithubIcon} - loadingIndicatorPosition="leading" + loaderPosition="leading" /> { onTokenRemove={onRemoveMock} isLoading leadingVisual={MarkGithubIcon} - loadingIndicatorPosition="trailing" + loaderPosition="trailing" /> { onTokenRemove={onRemoveMock} isLoading trailingVisual={MarkGithubIcon} - loadingIndicatorPosition="leading" + loaderPosition="leading" /> { onTokenRemove={onRemoveMock} isLoading trailingVisual={MarkGithubIcon} - loadingIndicatorPosition="trailing" + loaderPosition="trailing" /> { isLoading leadingVisual={MarkGithubIcon} trailingVisual={MarkGithubIcon} - loadingIndicatorPosition="leading" + loaderPosition="leading" /> { size="large" leadingVisual={MarkGithubIcon} trailingVisual={MarkGithubIcon} - loadingIndicatorPosition="trailing" + loaderPosition="trailing" /> ) diff --git a/src/stories/TextInput.stories.tsx b/src/stories/TextInput.stories.tsx index 96a73a12d42..c4066b5b4c5 100644 --- a/src/stories/TextInput.stories.tsx +++ b/src/stories/TextInput.stories.tsx @@ -46,8 +46,8 @@ export default { type: 'boolean' } }, - loadingIndicatorPosition: { - name: 'loadingIndicatorPosition', + loaderPosition: { + name: 'loaderPosition', defaultValue: 'auto', options: ['auto', 'leading', 'trailing'], control: { diff --git a/src/stories/TextInputWithTokens.stories.tsx b/src/stories/TextInputWithTokens.stories.tsx index 32442a61eb6..5642565c2e0 100644 --- a/src/stories/TextInputWithTokens.stories.tsx +++ b/src/stories/TextInputWithTokens.stories.tsx @@ -54,8 +54,8 @@ export default { type: 'boolean' } }, - loadingIndicatorPosition: { - name: 'loadingIndicatorPosition', + loaderPosition: { + name: 'loaderPosition', defaultValue: 'auto', options: ['auto', 'leading', 'trailing'], control: { From 097e8fb0e535cfeb433d726002ce270277b5e94c Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Tue, 8 Mar 2022 16:24:43 -0500 Subject: [PATCH 10/35] adds trailing action to text input, tweaks formcontrol --- docs/content/TextInput.mdx | 57 ++ src/FormControl/FormControl.tsx | 4 +- src/TextInput.tsx | 43 +- src/_InputLabel.tsx | 1 + src/_TextInputInnerAction.tsx | 68 +++ src/_TextInputWrapper.tsx | 76 ++- src/__tests__/TextInput.test.tsx | 26 + .../__snapshots__/Autocomplete.test.tsx.snap | 21 +- .../ChoiceFieldset.test.tsx.snap | 18 + .../__snapshots__/TextInput.test.tsx.snap | 527 +++++++++++++++++- .../TextInputWithTokens.test.tsx.snap | 75 ++- src/stories/TextInput.stories.tsx | 167 +++--- 12 files changed, 940 insertions(+), 143 deletions(-) create mode 100644 src/_TextInputInnerAction.tsx diff --git a/docs/content/TextInput.mdx b/docs/content/TextInput.mdx index e4f6852b18c..e207c0f852b 100644 --- a/docs/content/TextInput.mdx +++ b/docs/content/TextInput.mdx @@ -134,6 +134,58 @@ const WithIconAndLoadingIndicator = () => { render() ``` +## Text input with trailing action + +```jsx live + + + Icon action + { + alert('clear input') + }} + icon={XIcon} + iconLabel="Clear input" + sx={{color: 'fg.subtle'}} + /> + } + /> + + + Icon action with tooltip + { + alert('clear input') + }} + icon={XIcon} + iconLabel="Clear input" + tooltipMessage="Clear" + sx={{color: 'fg.subtle'}} + /> + } + /> + + + Text action + { + alert('clear input') + }} + > + Clear + + } + /> + + +``` + ## Text Input with error and warning states ```jsx live @@ -226,6 +278,11 @@ render() )} /> + string | React.ComponentType} diff --git a/src/FormControl/FormControl.tsx b/src/FormControl/FormControl.tsx index c1ac5ea74f8..a70b0ea717e 100644 --- a/src/FormControl/FormControl.tsx +++ b/src/FormControl/FormControl.tsx @@ -180,7 +180,6 @@ const FormControl = ({children, disabled: disabledProp, id: idProp, required, sx *:not(label) + *': {marginTop: 2}} : {'> * + *': {marginTop: 2}}), ...sx}} > {React.Children.toArray(children).filter( @@ -195,7 +194,8 @@ const FormControl = ({children, disabled: disabledProp, id: idProp, required, sx required, disabled, validationStatus, - ['aria-describedby']: [validationMessageId, captionId].filter(Boolean).join(' ') + ['aria-describedby']: [validationMessageId, captionId].filter(Boolean).join(' '), + ...InputComponent.props })} {validationChild && {slots.Validation}} {slots.Caption} diff --git a/src/TextInput.tsx b/src/TextInput.tsx index 5863a205f08..10b19011395 100644 --- a/src/TextInput.tsx +++ b/src/TextInput.tsx @@ -1,10 +1,11 @@ import classnames from 'classnames' -import React, {MouseEventHandler} from 'react' +import React, {HTMLProps, MouseEventHandler, useState, useCallback} from 'react' import {ComponentProps, Merge} from './utils/types' import UnstyledTextInput from './_UnstyledTextInput' import TextInputWrapper from './_TextInputWrapper' import TextInputInnerVisualSlot from './_TextInputInnerVisualSlot' import {useProvidedRefOrCreate} from './hooks' +import TextInputAction from './_TextInputInnerAction' export type TextInputNonPassthroughProps = { className?: string @@ -27,6 +28,11 @@ export type TextInputNonPassthroughProps = { * A visual that renders inside the input after the typing area */ trailingVisual?: string | React.ComponentType<{className?: string}> + /** + * A visual that renders inside the input after the typing area + */ + trailingAction?: React.ReactElement> + // trailingAction?: React.ComponentType<{className?: string; onClick: MouseEventHandler}> } & Pick< ComponentProps, 'block' | 'contrast' | 'disabled' | 'sx' | 'width' | 'maxWidth' | 'minWidth' | 'variant' | 'size' @@ -45,6 +51,7 @@ const TextInput = React.forwardRef( icon: IconComponent, leadingVisual: LeadingVisual, trailingVisual: TrailingVisual, + trailingAction, block, className, contrast, @@ -54,6 +61,8 @@ const TextInput = React.forwardRef( validationStatus, sx: sxProp, size: sizeProp, + onFocus, + onBlur, // start deprecated props width: widthProp, minWidth: minWidthProp, @@ -64,6 +73,7 @@ const TextInput = React.forwardRef( }, ref ) => { + const [isInputFocused, setIsInputFocused] = useState(false) const inputRef = useProvidedRefOrCreate(ref as React.RefObject) // this class is necessary to style FilterSearch, plz no touchy! const wrapperClasses = classnames(className, 'TextInput-wrapper') @@ -74,6 +84,20 @@ const TextInput = React.forwardRef( const focusInput: MouseEventHandler = () => { inputRef.current?.focus() } + const handleInputFocus = useCallback( + e => { + setIsInputFocused(true) + onFocus && onFocus(e) + }, + [onFocus] + ) + const handleInputBlur = useCallback( + e => { + setIsInputFocused(false) + onBlur && onBlur(e) + }, + [onBlur] + ) return ( ( variant={variantProp} hasLeadingVisual={Boolean(LeadingVisual || showLeadingLoadingIndicator)} hasTrailingVisual={Boolean(TrailingVisual || showTrailingLoadingIndicator)} + hasActions={Boolean(trailingAction)} + isInputFocused={isInputFocused} onClick={focusInput} > {IconComponent && } @@ -100,7 +126,14 @@ const TextInput = React.forwardRef( > {typeof LeadingVisual === 'function' ? : LeadingVisual} - + ( > {typeof TrailingVisual === 'function' ? : TrailingVisual} + {trailingAction} ) } @@ -121,4 +155,7 @@ TextInput.defaultProps = { TextInput.displayName = 'TextInput' export type TextInputProps = ComponentProps -export default TextInput + +export default Object.assign(TextInput, { + Action: TextInputAction +}) diff --git a/src/_InputLabel.tsx b/src/_InputLabel.tsx index 6118c7c9633..2b6a51554bf 100644 --- a/src/_InputLabel.tsx +++ b/src/_InputLabel.tsx @@ -21,6 +21,7 @@ const InputLabel: React.FC = ({children, disabled, required, vis display: 'block', color: disabled ? 'fg.muted' : 'fg.default', cursor: disabled ? 'default' : 'pointer', + alignSelf: 'flex-start', ...sx }} > diff --git a/src/_TextInputInnerAction.tsx b/src/_TextInputInnerAction.tsx new file mode 100644 index 00000000000..fd985ba875a --- /dev/null +++ b/src/_TextInputInnerAction.tsx @@ -0,0 +1,68 @@ +import {IconProps} from '@primer/octicons-react' +import React, {forwardRef, MouseEventHandler} from 'react' +import {Box, Tooltip} from '.' +import {Button, ButtonProps, IconButton} from './Button2' +import {SxProp} from './sx' + +type TextInputActionProps = Omit, 'onClick' | 'children' | 'size'> & { + children?: React.ReactNode + onClick: MouseEventHandler + icon?: React.FunctionComponent + iconLabel?: string + tooltipMessage?: string + variant?: ButtonProps['variant'] +} & SxProp + +const buttonStyleOverrides = { + color: 'fg.default' +} + +// TODO: modify this to _just_ render out a tooltip. No need for `wrapper` +const ConditionalWrapper: React.FC<{ + condition: boolean + wrapper: (children: React.ReactNode) => React.ReactNode +}> = ({condition, wrapper, children}) => <>{condition ? wrapper(children) : children} + +const TextInputAction = forwardRef( + ({children, icon, iconLabel, sx: sxProp, tooltipMessage, variant, ...rest}, forwardedRef) => { + const sx = { + ...buttonStyleOverrides, + ...sxProp + } + + if (icon && !iconLabel) { + console.warn('Use the `iconLabel` prop to provide an accessible label for assistive technology') + } + + return ( + + {tooltipLabel}} + > + {icon && iconLabel ? ( + + ) : ( + + )} + + + ) + } +) + +TextInputAction.defaultProps = { + variant: 'invisible' +} + +export default TextInputAction diff --git a/src/_TextInputWrapper.tsx b/src/_TextInputWrapper.tsx index 5b52ae93496..d5be147408e 100644 --- a/src/_TextInputWrapper.tsx +++ b/src/_TextInputWrapper.tsx @@ -1,4 +1,4 @@ -import styled, {css} from 'styled-components' +import styled, {css, DefaultTheme, FlattenInterpolation, ThemedCssFunction, ThemeProps} from 'styled-components' import {maxWidth, MaxWidthProps, minWidth, MinWidthProps, variant, width, WidthProps} from 'styled-system' import {get} from './constants' import sx, {SxProp} from './sx' @@ -45,6 +45,8 @@ export type StyledBaseWrapperProps = { block?: boolean contrast?: boolean disabled?: boolean + hasActions?: boolean + isInputFocused?: boolean validationStatus?: FormValidationStatus } & WidthProps & MinWidthProps & @@ -62,6 +64,26 @@ export type StyledWrapperProps = { const textInputBasePadding = '12px' export const textInputHorizPadding = textInputBasePadding +const renderFocusStyles = ( + hasActions: boolean, + isInputFocused: boolean, + focusStyles: FlattenInterpolation>> +) => { + if (hasActions) { + return ( + isInputFocused && + css` + ${focusStyles} + ` + ) + } + return css` + &:focus-within { + ${focusStyles} + } + ` +} + export const TextInputBaseWrapper = styled.span` font-size: ${get('fontSizes.1')}; line-height: 20px; @@ -81,10 +103,15 @@ export const TextInputBaseWrapper = styled.span` color: ${get('colors.fg.subtle')}; } - &:focus-within { - border-color: ${get('colors.accent.emphasis')}; - box-shadow: ${get('shadows.primer.shadow.focus')}; - } + ${props => + renderFocusStyles( + Boolean(props.hasActions), + Boolean(props.isInputFocused), + css` + border-color: ${get('colors.accent.emphasis')}; + box-shadow: ${get('shadows.primer.shadow.focus')}; + ` + )} > textarea { padding: ${textInputBasePadding}; @@ -109,10 +136,14 @@ export const TextInputBaseWrapper = styled.span` props.validationStatus === 'error' && css` border-color: ${get('colors.danger.emphasis')}; - &:focus-within { - border-color: ${get('colors.danger.emphasis')}; - box-shadow: ${get('shadows.btn.danger.focusShadow')}; - } + ${renderFocusStyles( + Boolean(props.hasActions), + Boolean(props.isInputFocused), + css` + border-color: ${get('colors.danger.emphasis')}; + box-shadow: ${get('shadows.btn.danger.focusShadow')}; + ` + )} `} @@ -120,10 +151,14 @@ export const TextInputBaseWrapper = styled.span` props.validationStatus === 'success' && css` border-color: ${get('colors.success.emphasis')}; - &:focus-within { - border-color: ${get('colors.success.emphasis')}; - box-shadow: 0 0 0 3px ${get('colors.success.muted')}; - } + ${renderFocusStyles( + Boolean(props.hasActions), + Boolean(props.isInputFocused), + css` + border-color: ${get('colors.success.emphasis')}; + box-shadow: 0 0 0 3px ${get('colors.success.muted')}; + ` + )} `} ${props => @@ -154,7 +189,8 @@ const TextInputWrapper = styled(TextInputBaseWrapper)` margin-right: ${get('space.2')}; } - .TextInput-icon { + .TextInput-icon, + .TextInput-action { align-self: center; color: ${get('colors.fg.muted')}; flex-shrink: 0; @@ -176,10 +212,14 @@ const TextInputWrapper = styled(TextInputBaseWrapper)` props.validationStatus === 'warning' && css` border-color: ${get('colors.attention.emphasis')}; - &:focus-within { - border-color: ${get('colors.attention.emphasis')}; - box-shadow: 0 0 0 3px ${get('colors.attention.muted')}; - } + ${renderFocusStyles( + Boolean(props.hasActions), + Boolean(props.isInputFocused), + css` + border-color: ${get('colors.attention.emphasis')}; + box-shadow: 0 0 0 3px ${get('colors.attention.muted')}; + ` + )} `} ${sx}; diff --git a/src/__tests__/TextInput.test.tsx b/src/__tests__/TextInput.test.tsx index e4496d59c98..6b4f1d44c4c 100644 --- a/src/__tests__/TextInput.test.tsx +++ b/src/__tests__/TextInput.test.tsx @@ -61,6 +61,32 @@ describe('TextInput', () => { expect(render()).toMatchSnapshot() }) + it('renders trailingAction text button', () => { + const handleAction = jest.fn() + expect( + render( + Clear} + /> + ) + ).toMatchSnapshot() + }) + + it('renders trailingAction icon button', () => { + const handleAction = jest.fn() + expect( + render( + } + /> + ) + ).toMatchSnapshot() + }) + it('focuses the text input if you do not click the input element', () => { const {container, getByLabelText} = HTMLRender( <> diff --git a/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap b/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap index f664497098b..3af30737c1d 100644 --- a/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap +++ b/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap @@ -71,7 +71,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -218,7 +219,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -400,7 +402,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -1345,7 +1348,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -2200,7 +2204,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -3066,7 +3071,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -4062,7 +4068,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; diff --git a/src/__tests__/__snapshots__/ChoiceFieldset.test.tsx.snap b/src/__tests__/__snapshots__/ChoiceFieldset.test.tsx.snap index 293456083ea..f5e38f8d3ef 100644 --- a/src/__tests__/__snapshots__/ChoiceFieldset.test.tsx.snap +++ b/src/__tests__/__snapshots__/ChoiceFieldset.test.tsx.snap @@ -46,6 +46,9 @@ exports[`ChoiceFieldset renders a disabled list 1`] = ` display: block; color: #57606a; cursor: default; + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; } .c6 { @@ -209,6 +212,9 @@ exports[`ChoiceFieldset renders a fieldset with a description 1`] = ` display: block; color: #24292f; cursor: pointer; + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; } .c7 { @@ -396,6 +402,9 @@ exports[`ChoiceFieldset renders a list of items with leading visuals and caption display: block; color: #24292f; cursor: pointer; + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; } .c6 { @@ -699,6 +708,9 @@ exports[`ChoiceFieldset renders with a hidden legend 1`] = ` display: block; color: #24292f; cursor: pointer; + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; } .c1 { @@ -894,6 +906,9 @@ exports[`ChoiceFieldset renders with a success validation message 1`] = ` display: block; color: fg.default; cursor: pointer; + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; } .c6 { @@ -1137,6 +1152,9 @@ exports[`ChoiceFieldset renders with an error validation message 1`] = ` display: block; color: fg.default; cursor: pointer; + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; } .c6 { diff --git a/src/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/__tests__/__snapshots__/TextInput.test.tsx.snap index 18373591cc3..561dca5d814 100644 --- a/src/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -70,7 +70,8 @@ exports[`TextInput renders 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -100,6 +101,8 @@ exports[`TextInput renders 1`] = ` className="c1" data-component="input" name="zipcode" + onBlur={[Function]} + onFocus={[Function]} type="text" />
@@ -180,7 +183,8 @@ exports[`TextInput renders block 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -210,6 +214,8 @@ exports[`TextInput renders block 1`] = ` className="c1" data-component="input" name="zipcode" + onBlur={[Function]} + onFocus={[Function]} type="text" /> @@ -285,7 +291,8 @@ exports[`TextInput renders consistently 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -314,6 +321,8 @@ exports[`TextInput renders consistently 1`] = ` @@ -389,7 +398,8 @@ exports[`TextInput renders contrast 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -419,6 +429,8 @@ exports[`TextInput renders contrast 1`] = ` className="c1" data-component="input" name="zipcode" + onBlur={[Function]} + onFocus={[Function]} type="text" /> @@ -494,7 +506,8 @@ exports[`TextInput renders error 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -524,6 +537,8 @@ exports[`TextInput renders error 1`] = ` className="c1" data-component="input" name="zipcode" + onBlur={[Function]} + onFocus={[Function]} type="text" /> @@ -604,7 +619,8 @@ exports[`TextInput renders large 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -635,6 +651,8 @@ exports[`TextInput renders large 1`] = ` className="c1" data-component="input" name="zipcode" + onBlur={[Function]} + onFocus={[Function]} type="text" /> @@ -710,7 +728,8 @@ exports[`TextInput renders leadingVisual 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -766,6 +785,8 @@ exports[`TextInput renders leadingVisual 1`] = ` className="c1" data-component="input" name="search" + onBlur={[Function]} + onFocus={[Function]} placeholder="Search" type="text" /> @@ -842,7 +863,8 @@ exports[`TextInput renders placeholder 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -872,6 +894,8 @@ exports[`TextInput renders placeholder 1`] = ` className="c1" data-component="input" name="zipcode" + onBlur={[Function]} + onFocus={[Function]} placeholder="560076" type="text" /> @@ -955,7 +979,8 @@ exports[`TextInput renders small 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -986,11 +1011,420 @@ exports[`TextInput renders small 1`] = ` className="c1" data-component="input" name="zipcode" + onBlur={[Function]} + onFocus={[Function]} type="text" /> `; +exports[`TextInput renders trailingAction icon button 1`] = ` +.c3 { + display: inline-block; +} + +.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; + 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 > textarea { + padding: 12px; +} + +.c0 >:not(:last-child) { + margin-right: 8px; +} + +.c0 .TextInput-icon, +.c0 .TextInput-action { + -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; +} + +.c2 { + border-radius: 6px; + border: 0; + border-color: rgba(27,31,36,0.15); + font-family: inherit; + font-weight: 600; + line-height: 20px; + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-text-decoration: none; + text-decoration: none; + text-align: center; + padding-top: 6px; + padding-bottom: 6px; + padding-left: 8px; + padding-right: 8px; + font-size: 14px; + color: #24292f; + background-color: transparent; + box-shadow: none; +} + +.c2:focus { + outline: none; +} + +.c2:disabled { + cursor: default; + color: #8c959f; +} + +.c2:disabled svg { + opacity: 0.6; +} + +.c2 [data-component="ButtonCounter"] { + font-size: 14px; +} + +.c2:hover:not([disabled]) { + background-color: #f3f4f6; +} + +.c2:focus:not([disabled]) { + box-shadow: 0 0 0 3px rgba(9,105,218,0.3); +} + +.c2:active:not([disabled]) { + background-color: hsla(220,14%,94%,1); +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + + + + + +`; + +exports[`TextInput renders trailingAction text button 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; + 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 > textarea { + padding: 12px; +} + +.c0 >:not(:last-child) { + margin-right: 8px; +} + +.c0 .TextInput-icon, +.c0 .TextInput-action { + -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; +} + +.c2 { + border-radius: 6px; + border: 0; + border-color: rgba(27,31,36,0.15); + font-family: inherit; + font-weight: 600; + line-height: 20px; + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-text-decoration: none; + text-decoration: none; + text-align: center; + display: grid; + grid-template-areas: "leadingIcon text trailingIcon"; + padding-top: 4px; + padding-bottom: 4px; + padding-left: 12px; + padding-right: 12px; + font-size: 12px; + color: #24292f; + background-color: transparent; + box-shadow: none; +} + +.c2:focus { + outline: none; +} + +.c2:disabled { + cursor: default; + color: #8c959f; +} + +.c2:disabled svg { + opacity: 0.6; +} + +.c2 > :not(:last-child) { + margin-right: 8px; +} + +.c2 [data-component="leadingIcon"] { + grid-area: leadingIcon; +} + +.c2 [data-component="text"] { + grid-area: text; +} + +.c2 [data-component="trailingIcon"] { + grid-area: trailingIcon; +} + +.c2 [data-component="ButtonCounter"] { + font-size: 12px; +} + +.c2:hover:not([disabled]) { + background-color: #f3f4f6; +} + +.c2:focus:not([disabled]) { + box-shadow: 0 0 0 3px rgba(9,105,218,0.3); +} + +.c2:active:not([disabled]) { + background-color: hsla(220,14%,94%,1); +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + + + + + +`; + exports[`TextInput renders trailingVisual 1`] = ` .c1 { border: 0; @@ -1061,7 +1495,8 @@ exports[`TextInput renders trailingVisual 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -1091,6 +1526,8 @@ exports[`TextInput renders trailingVisual 1`] = ` className="c1" data-component="input" name="search" + onBlur={[Function]} + onFocus={[Function]} placeholder="Search" type="text" /> @@ -1193,7 +1630,8 @@ exports[`TextInput renders warning 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -1223,6 +1661,8 @@ exports[`TextInput renders warning 1`] = ` className="c1" data-component="input" name="zipcode" + onBlur={[Function]} + onFocus={[Function]} type="text" /> @@ -1307,7 +1747,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -1342,6 +1783,8 @@ Array [ diff --git a/src/__tests__/__snapshots__/TextInputWithTokens.test.tsx.snap b/src/__tests__/__snapshots__/TextInputWithTokens.test.tsx.snap index f2fb6bb996c..eecae5adbba 100644 --- a/src/__tests__/__snapshots__/TextInputWithTokens.test.tsx.snap +++ b/src/__tests__/__snapshots__/TextInputWithTokens.test.tsx.snap @@ -115,7 +115,8 @@ exports[`TextInputWithTokens renders a leadingVisual and trailingVisual 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -841,7 +842,8 @@ exports[`TextInputWithTokens renders a truncated set of tokens 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -1255,7 +1257,8 @@ exports[`TextInputWithTokens renders as block layout 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -1421,7 +1424,8 @@ exports[`TextInputWithTokens renders at a maximum height when specified 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -2102,7 +2106,8 @@ exports[`TextInputWithTokens renders tokens at the specified sizes 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -2783,7 +2788,8 @@ exports[`TextInputWithTokens renders tokens at the specified sizes 2`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -3457,7 +3463,8 @@ exports[`TextInputWithTokens renders tokens at the specified sizes 3`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -4131,7 +4138,8 @@ exports[`TextInputWithTokens renders tokens at the specified sizes 4`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -4807,7 +4815,8 @@ exports[`TextInputWithTokens renders tokens on a single line when specified 1`] margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -5481,7 +5490,8 @@ exports[`TextInputWithTokens renders tokens without a remove button when specifi margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -5872,7 +5882,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -6595,7 +6606,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -7362,7 +7374,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -8089,7 +8102,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -8896,7 +8910,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -9703,7 +9718,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -10510,7 +10526,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -11273,7 +11290,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -12080,7 +12098,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -12854,7 +12873,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -13701,7 +13721,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -14548,7 +14569,8 @@ Array [ margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -15383,7 +15405,8 @@ exports[`TextInputWithTokens renders with tokens 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -16057,7 +16080,8 @@ exports[`TextInputWithTokens renders with tokens using a custom token component margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -16736,7 +16760,8 @@ exports[`TextInputWithTokens renders without tokens 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; diff --git a/src/stories/TextInput.stories.tsx b/src/stories/TextInput.stories.tsx index c4066b5b4c5..6ed58c9c4fe 100644 --- a/src/stories/TextInput.stories.tsx +++ b/src/stories/TextInput.stories.tsx @@ -1,9 +1,9 @@ -import React, {useState, ReactNode} from 'react' +import React, {useState} from 'react' import {Meta} from '@storybook/react' -import {BaseStyles, Box, ThemeProvider, Text, FormControl} from '..' +import {BaseStyles, Box, ThemeProvider, FormControl} from '..' import TextInput, {TextInputProps} from '../TextInput' -import {CalendarIcon, CheckIcon} from '@primer/octicons-react' +import {CalendarIcon, CheckIcon, XCircleFillIcon} from '@primer/octicons-react' export default { title: 'Forms/Text Input', @@ -74,12 +74,6 @@ export default { } } as Meta -const Label = ({htmlFor, children}: {htmlFor: string; children: ReactNode}) => ( - - {children} - -) - export const Default = (args: TextInputProps) => { const [value, setValue] = useState('') @@ -87,18 +81,12 @@ export const Default = (args: TextInputProps) => { setValue(event.target.value) } - const inputId = 'basic-text-input' - return (
-
-
- -
-
- -
-
+ + Example label + +
) } @@ -110,16 +98,16 @@ export const WithLeadingVisual = (args: TextInputProps) => { setValue(event.target.value) } - const iconInputId = 'text-input-with-leading-icon' - const leadingTextId = 'text-input-with-leading-text' - return (
- - -
- - + + Example label + + + + Enter monies + + ) } @@ -131,24 +119,85 @@ export const WithTrailingIcon = (args: TextInputProps) => { setValue(event.target.value) } - const iconInputId = 'text-input-with-trailing-icon' - const trailingTextInputId = 'text-input-with-trailing-text' + return ( +
+ + Example label + + + + Enter monies + + +
+ ) +} + +export const WithTrailingAction = (args: TextInputProps) => { + const [value, setValue] = useState('') + + const handleChange = (event: React.ChangeEvent) => { + setValue(event.target.value) + } return (
- - -
- - + + + Icon action + { + setValue('') + }} + icon={XCircleFillIcon} + iconLabel="Clear input" + sx={{color: 'fg.subtle'}} + /> + } + value={value} + onChange={handleChange} + {...args} + /> + + + Icon action with tooltip + { + setValue('') + }} + icon={XCircleFillIcon} + iconLabel="Clear input" + tooltipMessage="Clear" + sx={{color: 'fg.subtle'}} + /> + } + value={value} + onChange={handleChange} + {...args} + /> + + + Text action + { + setValue('') + }} + > + Clear + + } + value={value} + onChange={handleChange} + {...args} + /> + + ) } @@ -197,13 +246,12 @@ export const ContrastTextInput = (args: TextInputProps) => { setValue(event.target.value) } - const inputId = 'contrast-text-input' - return (
- -
- + + Example label + + ) } @@ -215,13 +263,12 @@ export const Password = (args: TextInputProps) => { setValue(event.target.value) } - const inputId = 'basic-text-input-as-password' - return (
- -
- + + Password + + ) } @@ -233,20 +280,12 @@ export const TextInputInWarningState = (args: TextInputProps) => { setValue(event.target.value) } - const inputId = 'text-input-with-warning' - return (
- -
- + + Password + + ) } From 79fbe769d17f40adb966a60d2e9a537da66ace0e Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Thu, 10 Mar 2022 12:08:52 -0500 Subject: [PATCH 11/35] addresses PR feedback --- docs/content/TextInput.mdx | 81 +++++++++++------------------ src/stories/TextInput.stories.tsx | 86 ++++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 72 deletions(-) diff --git a/docs/content/TextInput.mdx b/docs/content/TextInput.mdx index e4f6852b18c..7935ece0380 100644 --- a/docs/content/TextInput.mdx +++ b/docs/content/TextInput.mdx @@ -59,72 +59,49 @@ const WithIconAndLoadingIndicator = () => { return ( <> - + -

No visual

- - - - - - - - + + No visual + + + -

Leading visual

- - - - - - - - + + Leading visual + + + -

Trailing visual

- - - - - - - - + + Trailing visual + + + -

Both visuals

- - + + Both visuals + + + - - - - + + + Both visuals, position overriden + + @@ -195,7 +172,7 @@ render() ( + description={ <>
Which position to render the loading indicator
    @@ -207,7 +184,7 @@ render()
  • 'trailing': at the end of the input
- )} + } /> { ) } -export const WithLoadingIndicator = (args: TextInputProps) => { - const [isLoading, setIsLoading] = useState(true) +export const WithLoadingIndicator = () => { + const [isLoading, setIsLoading] = React.useState(true) const toggleLoadingState = () => { setIsLoading(!isLoading) } return ( -
- + <> + - - - No visual - - - - - Leading visual - - - - - Both visuals - - +

No visual

+ + - + + + + + + + +

Leading visual

+ + + + + + + + + + +

Trailing visual

+ + + + + + + + + + +

Both visuals

+ + + + + + + + + + ) } From 4a4fcc09907505f54d9040f8b5b47a07911ea91f Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Thu, 10 Mar 2022 12:12:41 -0500 Subject: [PATCH 12/35] fixes linting error --- src/stories/TextInput.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stories/TextInput.stories.tsx b/src/stories/TextInput.stories.tsx index f06dbc64c18..c8bf8c00a77 100644 --- a/src/stories/TextInput.stories.tsx +++ b/src/stories/TextInput.stories.tsx @@ -1,7 +1,7 @@ import React, {useState, ReactNode} from 'react' import {Meta} from '@storybook/react' -import {BaseStyles, Box, ThemeProvider, Text, FormControl} from '..' +import {BaseStyles, Box, ThemeProvider, Text} from '..' import TextInput, {TextInputProps} from '../TextInput' import {CalendarIcon, CheckIcon} from '@primer/octicons-react' From 1bdf6d1f60816f807edfc4f1ac68a25d070aac2a Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Thu, 10 Mar 2022 12:44:31 -0500 Subject: [PATCH 13/35] indicate a busy status to assistive technology --- src/TextInput.tsx | 2 ++ src/__tests__/TextInput.test.tsx | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/TextInput.tsx b/src/TextInput.tsx index 5863a205f08..4778208300f 100644 --- a/src/TextInput.tsx +++ b/src/TextInput.tsx @@ -91,6 +91,8 @@ const TextInput = React.forwardRef( hasLeadingVisual={Boolean(LeadingVisual || showLeadingLoadingIndicator)} hasTrailingVisual={Boolean(TrailingVisual || showTrailingLoadingIndicator)} onClick={focusInput} + aria-live="polite" + aria-busy={isLoading} > {IconComponent && } { ).toMatchSnapshot() }) + it('indicates a busy status to assistive technology', () => { + const {container} = HTMLRender( + <> + {/* eslint-disable-next-line jsx-a11y/label-has-for */} + + + + ) + + expect(container.querySelector('span[aria-busy=true]')).not.toBeNull() + }) + it('should call onChange prop with input value', () => { const onChangeMock = jest.fn() const component = mount() From 3464982b167ef8262550eb24e17a6466960b6e87 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Fri, 11 Mar 2022 10:59:09 -0500 Subject: [PATCH 14/35] updates snaps --- src/TextInput.tsx | 2 +- .../__snapshots__/Autocomplete.test.tsx.snap | 14 +++++ .../__snapshots__/TextInput.test.tsx.snap | 51 +++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/TextInput.tsx b/src/TextInput.tsx index f16f5c95108..6ebabbe971f 100644 --- a/src/TextInput.tsx +++ b/src/TextInput.tsx @@ -94,7 +94,7 @@ const TextInput = React.forwardRef( hasTrailingVisual={Boolean(TrailingVisual || showTrailingLoadingIndicator)} onClick={focusInput} aria-live="polite" - aria-busy={isLoading} + aria-busy={Boolean(isLoading)} > {IconComponent && } @@ -241,6 +243,8 @@ Array [ } @@ -423,6 +427,8 @@ Array [ } @@ -1368,6 +1374,8 @@ Array [ } @@ -2223,6 +2231,8 @@ Array [ } @@ -3089,6 +3099,8 @@ Array [ } @@ -4085,6 +4097,8 @@ Array [ } diff --git a/src/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/__tests__/__snapshots__/TextInput.test.tsx.snap index e83cff71fff..e8dbdc959dd 100644 --- a/src/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -93,6 +93,8 @@ exports[`TextInput renders 1`] = ` } @@ -203,6 +205,8 @@ exports[`TextInput renders block 1`] = ` } @@ -308,6 +312,8 @@ exports[`TextInput renders consistently 1`] = ` } @@ -413,6 +419,8 @@ exports[`TextInput renders contrast 1`] = ` } @@ -518,6 +526,8 @@ exports[`TextInput renders error 1`] = ` } @@ -628,6 +638,8 @@ exports[`TextInput renders large 1`] = ` } @@ -867,7 +881,10 @@ exports[`TextInput renders monospace 1`] = ` } @@ -1084,6 +1103,8 @@ exports[`TextInput renders small 1`] = ` } @@ -1322,6 +1345,8 @@ exports[`TextInput renders warning 1`] = ` } @@ -1442,6 +1467,8 @@ Array [ } @@ -1601,6 +1628,8 @@ Array [ } @@ -1792,6 +1821,8 @@ Array [ } @@ -1960,6 +1991,8 @@ Array [ } @@ -2197,6 +2230,8 @@ Array [ } @@ -2434,6 +2469,8 @@ Array [ } @@ -2665,6 +2702,8 @@ Array [ } @@ -2864,6 +2903,8 @@ Array [ } @@ -3095,6 +3136,8 @@ Array [ } @@ -3310,6 +3353,8 @@ Array [ } @@ -3870,6 +3917,8 @@ Array [ } From d586a80e9af65ee652fe283eedf598c287c9b313 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Tue, 15 Mar 2022 13:12:28 -0400 Subject: [PATCH 15/35] renames 'isLoading' prop to 'loading' --- docs/content/TextInput.mdx | 31 +++++++++--------- docs/content/TextInputWithTokens.mdx | 30 ++++++++--------- src/TextInput.tsx | 14 ++++---- src/TextInputWithTokens.tsx | 10 +++--- src/_TextInputInnerVisualSlot.tsx | 2 +- src/__tests__/TextInput.test.tsx | 26 +++++++-------- src/__tests__/TextInputWithTokens.test.tsx | 24 +++++++------- src/stories/TextInput.stories.tsx | 36 ++++++++++----------- src/stories/TextInputWithTokens.stories.tsx | 18 +++++------ 9 files changed, 96 insertions(+), 95 deletions(-) diff --git a/docs/content/TextInput.mdx b/docs/content/TextInput.mdx index 23f6f1f2a77..2781cfae43f 100644 --- a/docs/content/TextInput.mdx +++ b/docs/content/TextInput.mdx @@ -51,17 +51,17 @@ TextInput is a form component to add default styling to the native text input. ```javascript live noinline const WithIconAndLoadingIndicator = () => { - const [isLoading, setIsLoading] = React.useState(true) + const [loading, setLoading] = React.useState(true) const toggleLoadingState = () => { - setIsLoading(!isLoading) + setLoading(!loading) } return ( <> @@ -69,40 +69,35 @@ const WithIconAndLoadingIndicator = () => { No visual - + Leading visual - + Trailing visual - + Both visuals - + Both visuals, position overriden - + ) @@ -178,7 +173,8 @@ render() {' '} - + + ) type="'error' | 'success' | 'warning'" description="Style the input to match the status" /> - + { setDates(dates.filter(token => token.id !== tokenId)) } - const [isLoading, setIsLoading] = React.useState(true) + const [loading, setLoading] = React.useState(true) const toggleLoadingState = () => { - setIsLoading(!isLoading) + setLoading(!loading) } return ( <>

No visual

- + @@ -281,7 +281,7 @@ const WithIconAndLoadingIndicator = () => { tokens={dates} onTokenRemove={onDateRemove} value="trailing" - isLoading={isLoading} + loading={loading} loaderPosition="trailing" />
@@ -292,7 +292,7 @@ const WithIconAndLoadingIndicator = () => { tokens={dates} onTokenRemove={onDateRemove} leadingVisual={CalendarIcon} - isLoading={isLoading} + loading={loading} value="auto" />
@@ -301,7 +301,7 @@ const WithIconAndLoadingIndicator = () => { tokens={dates} onTokenRemove={onDateRemove} leadingVisual={CalendarIcon} - isLoading={isLoading} + loading={loading} loaderPosition="leading" value="leading" /> @@ -311,7 +311,7 @@ const WithIconAndLoadingIndicator = () => { tokens={dates} onTokenRemove={onDateRemove} leadingVisual={CalendarIcon} - isLoading={isLoading} + loading={loading} loaderPosition="trailing" value="trailing" /> @@ -323,7 +323,7 @@ const WithIconAndLoadingIndicator = () => { tokens={dates} onTokenRemove={onDateRemove} trailingVisual={CalendarIcon} - isLoading={isLoading} + loading={loading} value="auto" />
@@ -332,7 +332,7 @@ const WithIconAndLoadingIndicator = () => { tokens={dates} onTokenRemove={onDateRemove} trailingVisual={CalendarIcon} - isLoading={isLoading} + loading={loading} loaderPosition="leading" value="leading" /> @@ -342,7 +342,7 @@ const WithIconAndLoadingIndicator = () => { tokens={dates} onTokenRemove={onDateRemove} trailingVisual={CalendarIcon} - isLoading={isLoading} + loading={loading} loaderPosition="trailing" value="trailing" /> @@ -356,7 +356,7 @@ const WithIconAndLoadingIndicator = () => { size="small" leadingVisual={CalendarIcon} trailingVisual={CalendarIcon} - isLoading={isLoading} + loading={loading} value="auto" />
@@ -366,7 +366,7 @@ const WithIconAndLoadingIndicator = () => { onTokenRemove={onDateRemove} leadingVisual={CalendarIcon} trailingVisual={CalendarIcon} - isLoading={isLoading} + loading={loading} loaderPosition="leading" value="leading" /> @@ -378,7 +378,7 @@ const WithIconAndLoadingIndicator = () => { size="large" leadingVisual={CalendarIcon} trailingVisual={CalendarIcon} - isLoading={isLoading} + loading={loading} loaderPosition="trailing" value="trailing" /> diff --git a/src/TextInput.tsx b/src/TextInput.tsx index 6ebabbe971f..6143cf0b28c 100644 --- a/src/TextInput.tsx +++ b/src/TextInput.tsx @@ -11,7 +11,7 @@ export type TextInputNonPassthroughProps = { /** @deprecated Use `leadingVisual` or `trailingVisual` prop instead */ icon?: React.ComponentType<{className?: string}> /** Whether the to show a loading indicator in the input */ - isLoading?: boolean + loading?: boolean /** * Which position to render the loading indicator * 'auto' (default): at the end of the input, unless a `leadingVisual` is passed. Then, it will render at the beginning @@ -49,7 +49,7 @@ const TextInput = React.forwardRef( className, contrast, disabled, - isLoading, + loading, loaderPosition, monospace, validationStatus, @@ -69,9 +69,9 @@ const TextInput = React.forwardRef( // this class is necessary to style FilterSearch, plz no touchy! const wrapperClasses = classnames(className, 'TextInput-wrapper') const showLeadingLoadingIndicator = - isLoading && (loaderPosition === 'leading' || Boolean(LeadingVisual && loaderPosition !== 'trailing')) + loading && (loaderPosition === 'leading' || Boolean(LeadingVisual && loaderPosition !== 'trailing')) const showTrailingLoadingIndicator = - isLoading && (loaderPosition === 'trailing' || Boolean(loaderPosition === 'auto' && !LeadingVisual)) + loading && (loaderPosition === 'trailing' || Boolean(loaderPosition === 'auto' && !LeadingVisual)) const focusInput: MouseEventHandler = () => { inputRef.current?.focus() } @@ -94,13 +94,13 @@ const TextInput = React.forwardRef( hasTrailingVisual={Boolean(TrailingVisual || showTrailingLoadingIndicator)} onClick={focusInput} aria-live="polite" - aria-busy={Boolean(isLoading)} + aria-busy={Boolean(loading)} > {IconComponent && } {typeof LeadingVisual === 'function' ? : LeadingVisual} @@ -108,7 +108,7 @@ const TextInput = React.forwardRef( {typeof TrailingVisual === 'function' ? : TrailingVisual} diff --git a/src/TextInputWithTokens.tsx b/src/TextInputWithTokens.tsx index f5f68b9dfde..ca4828cccce 100644 --- a/src/TextInputWithTokens.tsx +++ b/src/TextInputWithTokens.tsx @@ -69,7 +69,7 @@ function TextInputWithTokensInnerComponent {IconComponent && !LeadingVisual && } @@ -362,7 +362,7 @@ function TextInputWithTokensInnerComponent diff --git a/src/_TextInputInnerVisualSlot.tsx b/src/_TextInputInnerVisualSlot.tsx index 901bba3c134..aac487b11e8 100644 --- a/src/_TextInputInnerVisualSlot.tsx +++ b/src/_TextInputInnerVisualSlot.tsx @@ -6,7 +6,7 @@ const TextInputInnerVisualSlot: React.FC<{ /** Whether the input is expected to ever show a loading indicator */ hasLoadingIndicator: boolean /** Whether the to show the loading indicator */ - showLoadingIndicator: TextInputNonPassthroughProps['isLoading'] + showLoadingIndicator: TextInputNonPassthroughProps['loading'] /** Which side of this visual is being rendered */ visualPosition: 'leading' | 'trailing' }> = ({children, hasLoadingIndicator, showLoadingIndicator, visualPosition}) => { diff --git a/src/__tests__/TextInput.test.tsx b/src/__tests__/TextInput.test.tsx index 79b591b2a63..9a55083cd97 100644 --- a/src/__tests__/TextInput.test.tsx +++ b/src/__tests__/TextInput.test.tsx @@ -84,30 +84,30 @@ describe('TextInput', () => { expect( render( <> - + - + - + - + - + - + - + - + - + - + - + { <> {/* eslint-disable-next-line jsx-a11y/label-has-for */} - + ) diff --git a/src/__tests__/TextInputWithTokens.test.tsx b/src/__tests__/TextInputWithTokens.test.tsx index 0cb9f0c43f3..51cbfd28fc7 100644 --- a/src/__tests__/TextInputWithTokens.test.tsx +++ b/src/__tests__/TextInputWithTokens.test.tsx @@ -114,23 +114,23 @@ describe('TextInputWithTokens', () => { expect( render( <> - + - + - + @@ -138,7 +138,7 @@ describe('TextInputWithTokens', () => { @@ -146,14 +146,14 @@ describe('TextInputWithTokens', () => { @@ -161,7 +161,7 @@ describe('TextInputWithTokens', () => { @@ -169,7 +169,7 @@ describe('TextInputWithTokens', () => { { { { } export const WithLoadingIndicator = () => { - const [isLoading, setIsLoading] = React.useState(true) + const [loading, setLoading] = React.useState(true) const toggleLoadingState = () => { - setIsLoading(!isLoading) + setLoading(!loading) } return ( <>

No visual

- + - + - +

Leading visual

- + - + - +

Trailing visual

- + - + - +

Both visuals

@@ -214,7 +214,7 @@ export const WithLoadingIndicator = () => { size="small" leadingVisual={CalendarIcon} trailingVisual={CalendarIcon} - isLoading={isLoading} + loading={loading} value="auto" />
@@ -222,7 +222,7 @@ export const WithLoadingIndicator = () => { @@ -232,7 +232,7 @@ export const WithLoadingIndicator = () => { size="large" leadingVisual={CalendarIcon} trailingVisual={CalendarIcon} - isLoading={isLoading} + loading={loading} loaderPosition="trailing" value="trailing" /> @@ -241,7 +241,7 @@ export const WithLoadingIndicator = () => { ) } -WithLoadingIndicator.parameters = {controls: {exclude: ['isLoading']}} +WithLoadingIndicator.parameters = {controls: {exclude: ['loading']}} export const ContrastTextInput = (args: TextInputProps) => { const [value, setValue] = useState('') diff --git a/src/stories/TextInputWithTokens.stories.tsx b/src/stories/TextInputWithTokens.stories.tsx index 5642565c2e0..5a5ac418f5f 100644 --- a/src/stories/TextInputWithTokens.stories.tsx +++ b/src/stories/TextInputWithTokens.stories.tsx @@ -47,8 +47,8 @@ export default { type: 'boolean' } }, - isLoading: { - name: 'isLoading', + loading: { + name: 'loading', defaultValue: false, control: { type: 'boolean' @@ -138,26 +138,26 @@ WithTrailingVisual.parameters = {controls: {exclude: [excludedControls, 'maxHeig export const WithLoadingIndicator = (args: TextInputWithTokensProps) => { const [tokens, setTokens] = useState([...mockTokens].slice(0, 3)) - const [isLoading, setIsLoading] = useState(true) + const [loading, setLoading] = useState(true) const onTokenRemove: (tokenId: string | number) => void = tokenId => { setTokens(tokens.filter(token => token.id !== tokenId)) } const toggleLoadingState = () => { - setIsLoading(!isLoading) + setLoading(!loading) } return (
No visual - + @@ -165,7 +165,7 @@ export const WithLoadingIndicator = (args: TextInputWithTokensProps) => { @@ -176,7 +176,7 @@ export const WithLoadingIndicator = (args: TextInputWithTokensProps) => { { ) } -WithLoadingIndicator.parameters = {controls: {exclude: [excludedControls, 'maxHeight', 'isLoading']}} +WithLoadingIndicator.parameters = {controls: {exclude: [excludedControls, 'maxHeight', 'loading']}} export const UsingIssueLabelTokens = (args: TextInputWithTokensProps) => { const [tokens, setTokens] = useState([ From 8bc639e5311a0c4bcebc5e0977af264c2002f0c9 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Mon, 21 Mar 2022 14:21:17 -0400 Subject: [PATCH 16/35] Update docs/content/TextInput.mdx Co-authored-by: Cole Bemis --- docs/content/TextInput.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/TextInput.mdx b/docs/content/TextInput.mdx index 2781cfae43f..1ff90b33cf8 100644 --- a/docs/content/TextInput.mdx +++ b/docs/content/TextInput.mdx @@ -162,7 +162,7 @@ render() name="block" type="boolean" defaultValue="false" - description={<>Creates a full width input element} + description="Creates a full-width input element" /> Date: Mon, 21 Mar 2022 14:21:27 -0400 Subject: [PATCH 17/35] Update docs/content/TextInput.mdx Co-authored-by: Cole Bemis --- docs/content/TextInput.mdx | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/content/TextInput.mdx b/docs/content/TextInput.mdx index 1ff90b33cf8..6d9676d49dd 100644 --- a/docs/content/TextInput.mdx +++ b/docs/content/TextInput.mdx @@ -172,8 +172,6 @@ render() /> -{' '} - Date: Mon, 21 Mar 2022 14:21:39 -0400 Subject: [PATCH 18/35] Update docs/content/TextInput.mdx Co-authored-by: Cole Bemis --- docs/content/TextInput.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/TextInput.mdx b/docs/content/TextInput.mdx index 6d9676d49dd..8a13b4120df 100644 --- a/docs/content/TextInput.mdx +++ b/docs/content/TextInput.mdx @@ -172,7 +172,7 @@ render() /> - + Date: Mon, 21 Mar 2022 14:22:54 -0400 Subject: [PATCH 19/35] Update docs/content/TextInput.mdx Co-authored-by: Cole Bemis --- docs/content/TextInput.mdx | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/docs/content/TextInput.mdx b/docs/content/TextInput.mdx index 8a13b4120df..d87040431f6 100644 --- a/docs/content/TextInput.mdx +++ b/docs/content/TextInput.mdx @@ -193,19 +193,7 @@ render() string | React.ComponentType} - description={() => ( - <> -
Which position to render the loading indicator
-
    -
  • - 'auto' (default): at the end of the input, unless a `leadingVisual` is passed. Then, it will render at the - beginning -
  • -
  • 'leading': at the beginning of the input
  • -
  • 'trailing': at the end of the input
  • -
- - )} + description="Visual positioned on the left edge inside the input" /> Date: Mon, 21 Mar 2022 14:23:01 -0400 Subject: [PATCH 20/35] Update docs/content/TextInput.mdx Co-authored-by: Cole Bemis --- docs/content/TextInput.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/TextInput.mdx b/docs/content/TextInput.mdx index d87040431f6..a99088752c7 100644 --- a/docs/content/TextInput.mdx +++ b/docs/content/TextInput.mdx @@ -175,7 +175,7 @@ render()
Which position to render the loading indicator
From 8bf281de7de6c9507c28065d7d5168b7ae41e79c Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Mon, 21 Mar 2022 14:31:48 -0400 Subject: [PATCH 21/35] updates snapshots --- .../__snapshots__/TextInput.test.tsx.snap | 336 ++++++++-------- .../TextInputWithTokens.test.tsx.snap | 380 +++++++++--------- 2 files changed, 358 insertions(+), 358 deletions(-) diff --git a/src/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/__tests__/__snapshots__/TextInput.test.tsx.snap index 428f988f6b8..9b90d3ef97f 100644 --- a/src/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -1381,20 +1381,6 @@ Array [ position: relative; } -.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; @@ -1466,6 +1452,20 @@ Array [ padding-right: 0; } +.c1 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c1:focus { + outline: 0; +} + .c3 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -1536,20 +1536,6 @@ Array [ position: relative; } -.c3 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; -} - -.c3:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -1621,6 +1607,20 @@ Array [ padding-right: 12px; } +.c3 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c3:focus { + outline: 0; +} + .c2 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -1735,20 +1735,6 @@ Array [ position: relative; } -.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; @@ -1820,6 +1806,20 @@ Array [ padding-right: 0; } +.c1 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c1:focus { + outline: 0; +} + .c3 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -1894,20 +1894,6 @@ Array [ visibility: hidden; } -.c4 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; -} - -.c4:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -1979,6 +1965,20 @@ Array [ padding-right: 12px; } +.c4 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c4:focus { + outline: 0; +} + .c5 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -2133,20 +2133,6 @@ Array [ visibility: hidden; } -.c4 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; -} - -.c4:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -2218,6 +2204,20 @@ Array [ padding-right: 12px; } +.c4 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c4:focus { + outline: 0; +} + .c5 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -2372,20 +2372,6 @@ Array [ visibility: visible; } -.c4 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; -} - -.c4:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -2457,6 +2443,20 @@ Array [ padding-right: 0; } +.c4 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c4:focus { + outline: 0; +} + .c5 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -2611,20 +2611,6 @@ Array [ visibility: hidden; } -.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; @@ -2696,6 +2682,20 @@ Array [ padding-right: 0; } +.c1 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c1:focus { + outline: 0; +} + .c4 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -2806,20 +2806,6 @@ Array [ visibility: visible; } -.c3 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; -} - -.c3:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -2891,6 +2877,20 @@ Array [ padding-right: 0; } +.c3 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c3:focus { + outline: 0; +} + .c2 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -3045,20 +3045,6 @@ Array [ visibility: hidden; } -.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; @@ -3130,6 +3116,20 @@ Array [ padding-right: 0; } +.c1 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c1:focus { + outline: 0; +} + .c4 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -3244,20 +3244,6 @@ Array [ visibility: visible; } -.c4 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; -} - -.c4:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -3336,6 +3322,20 @@ Array [ padding-right: 0; } +.c4 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c4:focus { + outline: 0; +} + .c3 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -3531,20 +3531,6 @@ Array [ visibility: visible; } -.c4 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; -} - -.c4:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -3616,6 +3602,20 @@ Array [ padding-right: 0; } +.c4 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c4:focus { + outline: 0; +} + .c3 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -3810,20 +3810,6 @@ Array [ visibility: visible; } -.c4 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; -} - -.c4:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -3900,6 +3886,20 @@ Array [ padding-right: 0; } +.c4 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c4:focus { + outline: 0; +} + .c3 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; diff --git a/src/__tests__/__snapshots__/TextInputWithTokens.test.tsx.snap b/src/__tests__/__snapshots__/TextInputWithTokens.test.tsx.snap index db91a0b7eb0..c4f02a602bc 100644 --- a/src/__tests__/__snapshots__/TextInputWithTokens.test.tsx.snap +++ b/src/__tests__/__snapshots__/TextInputWithTokens.test.tsx.snap @@ -5796,21 +5796,6 @@ Array [ position: relative; } -.c3 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; - height: 100%; -} - -.c3:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -5837,7 +5822,7 @@ Array [ background-repeat: no-repeat; background-position: right 8px center; padding-left: 0; - padding-right: 12px; + padding-right: 0; padding-left: 12px; padding-top: calc(12px / 2); padding-bottom: calc(12px / 2); @@ -5885,7 +5870,22 @@ Array [ .c0 > input, .c0 > select { padding-left: 12px; - padding-right: 0; + padding-right: 12px; +} + +.c3 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c3:focus { + outline: 0; } .c8 { @@ -6519,21 +6519,6 @@ Array [ position: relative; } -.c5 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; - height: 100%; -} - -.c5:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -6559,7 +6544,7 @@ Array [ padding-bottom: calc(12px / 2); background-repeat: no-repeat; background-position: right 8px center; - padding-left: 12px; + padding-left: 0; padding-right: 0; padding-left: 12px; padding-top: calc(12px / 2); @@ -6607,10 +6592,25 @@ Array [ .c0 > input, .c0 > select { - padding-left: 0; + padding-left: 12px; padding-right: 12px; } +.c5 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c5:focus { + outline: 0; +} + .c2 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -7286,21 +7286,6 @@ Array [ position: relative; } -.c3 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; - height: 100%; -} - -.c3:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -7327,7 +7312,7 @@ Array [ background-repeat: no-repeat; background-position: right 8px center; padding-left: 0; - padding-right: 12px; + padding-right: 0; padding-left: 12px; padding-top: calc(12px / 2); padding-bottom: calc(12px / 2); @@ -7375,7 +7360,22 @@ Array [ .c0 > input, .c0 > select { padding-left: 12px; - padding-right: 0; + padding-right: 12px; +} + +.c3 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c3:focus { + outline: 0; } .c8 { @@ -8013,21 +8013,6 @@ Array [ visibility: hidden; } -.c6 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; - height: 100%; -} - -.c6:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -8105,6 +8090,21 @@ Array [ padding-right: 12px; } +.c6 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c6:focus { + outline: 0; +} + .c10 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -8820,21 +8820,6 @@ Array [ visibility: hidden; } -.c6 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; - height: 100%; -} - -.c6:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -8912,6 +8897,21 @@ Array [ padding-right: 12px; } +.c6 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c6:focus { + outline: 0; +} + .c10 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -9627,21 +9627,6 @@ Array [ visibility: visible; } -.c6 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; - height: 100%; -} - -.c6:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -9668,7 +9653,7 @@ Array [ background-repeat: no-repeat; background-position: right 8px center; padding-left: 12px; - padding-right: 12px; + padding-right: 0; padding-left: 12px; padding-top: calc(12px / 2); padding-bottom: calc(12px / 2); @@ -9716,7 +9701,22 @@ Array [ .c0 > input, .c0 > select { padding-left: 0; - padding-right: 0; + padding-right: 12px; +} + +.c6 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c6:focus { + outline: 0; } .c10 { @@ -10434,21 +10434,6 @@ Array [ visibility: hidden; } -.c3 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; - height: 100%; -} - -.c3:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -10526,6 +10511,21 @@ Array [ padding-right: 0; } +.c3 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c3:focus { + outline: 0; +} + .c9 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -11197,21 +11197,6 @@ Array [ visibility: visible; } -.c5 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; - height: 100%; -} - -.c5:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -11237,7 +11222,7 @@ Array [ padding-bottom: calc(12px / 2); background-repeat: no-repeat; background-position: right 8px center; - padding-left: 12px; + padding-left: 0; padding-right: 12px; padding-left: 12px; padding-top: calc(12px / 2); @@ -11285,10 +11270,25 @@ Array [ .c0 > input, .c0 > select { - padding-left: 0; + padding-left: 12px; padding-right: 0; } +.c5 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c5:focus { + outline: 0; +} + .c2 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -12004,21 +12004,6 @@ Array [ visibility: hidden; } -.c3 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; - height: 100%; -} - -.c3:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -12096,6 +12081,21 @@ Array [ padding-right: 0; } +.c3 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c3:focus { + outline: 0; +} + .c9 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -12771,21 +12771,6 @@ Array [ visibility: visible; } -.c6 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; - height: 100%; -} - -.c6:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -12870,6 +12855,21 @@ Array [ padding-right: 0; } +.c6 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c6:focus { + outline: 0; +} + .c3 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -13625,21 +13625,6 @@ Array [ visibility: visible; } -.c6 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; - height: 100%; -} - -.c6:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -13717,6 +13702,21 @@ Array [ padding-right: 0; } +.c6 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c6:focus { + outline: 0; +} + .c3 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; @@ -14472,21 +14472,6 @@ Array [ visibility: visible; } -.c6 { - border: 0; - font-size: inherit; - font-family: inherit; - background-color: transparent; - -webkit-appearance: none; - color: inherit; - width: 100%; - height: 100%; -} - -.c6:focus { - outline: 0; -} - .c0 { font-size: 14px; line-height: 20px; @@ -14564,6 +14549,21 @@ Array [ padding-right: 0; } +.c6 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; + height: 100%; +} + +.c6:focus { + outline: 0; +} + .c3 { -webkit-animation: rotate-keyframes 1s linear infinite; animation: rotate-keyframes 1s linear infinite; From e785ccdd926cf5e123df82e7e6ec21912b764660 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Mon, 21 Mar 2022 14:34:12 -0400 Subject: [PATCH 22/35] nests examples under an 'Examples' heading --- docs/content/TextInput.mdx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/content/TextInput.mdx b/docs/content/TextInput.mdx index a99088752c7..bb98bb7113c 100644 --- a/docs/content/TextInput.mdx +++ b/docs/content/TextInput.mdx @@ -9,13 +9,15 @@ TextInput is a form component to add default styling to the native text input. **Note:** Don't forget to set `aria-label` to make the TextInput accessible to screen reader users. -## Default example +## Examples + +### Basic ```jsx live ``` -## Text Input with icons +### With icons ```jsx live <> @@ -37,7 +39,7 @@ TextInput is a form component to add default styling to the native text input. ``` -## Text Input with text visuals +### With text visuals ```jsx live <> @@ -47,7 +49,7 @@ TextInput is a form component to add default styling to the native text input. ``` -## Text Input with visuals and loading indicators +### With visuals and loading indicators ```javascript live noinline const WithIconAndLoadingIndicator = () => { @@ -106,7 +108,7 @@ const WithIconAndLoadingIndicator = () => { render() ``` -## Text Input with error and warning states +### With error and warning states ```jsx live <> @@ -128,19 +130,19 @@ render() ``` -## Block text input +### Block text input ```jsx live ``` -## Contrast text input +### Contrast text input ```jsx live ``` -## Monospace text input +### Monospace text input ```jsx live Date: Mon, 21 Mar 2022 14:39:33 -0400 Subject: [PATCH 23/35] export TextInput non-pass-through props --- src/TextInput.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TextInput.tsx b/src/TextInput.tsx index 671fcc9097f..212a7e65499 100644 --- a/src/TextInput.tsx +++ b/src/TextInput.tsx @@ -8,7 +8,7 @@ import {Merge} from './utils/types' import TextInputWrapper, {StyledWrapperProps} from './_TextInputWrapper' import UnstyledTextInput from './_UnstyledTextInput' -type NonPassthroughProps = { +export type TextInputNonPassthroughProps = { /** @deprecated Use `leadingVisual` or `trailingVisual` prop instead */ icon?: React.ComponentType<{className?: string}> /** Whether the to show a loading indicator in the input */ From fffa7641349a427ec40a5a67b74e8ef3eb866216 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Mon, 21 Mar 2022 14:42:44 -0400 Subject: [PATCH 24/35] fix undefined type usage --- src/TextInput.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TextInput.tsx b/src/TextInput.tsx index 212a7e65499..08f59f3ea89 100644 --- a/src/TextInput.tsx +++ b/src/TextInput.tsx @@ -43,7 +43,7 @@ export type TextInputNonPassthroughProps = { | 'validationStatus' > -export type TextInputProps = Merge, NonPassthroughProps> +export type TextInputProps = Merge, TextInputNonPassthroughProps> // using forwardRef is important so that other components (ex. SelectMenu) can autofocus the input const TextInput = React.forwardRef( From f9ad318d202b2d81fc0ebc5ca231838000527699 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Mon, 21 Mar 2022 15:12:02 -0400 Subject: [PATCH 25/35] fixes story types --- src/stories/TextInputWithTokens.stories.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/stories/TextInputWithTokens.stories.tsx b/src/stories/TextInputWithTokens.stories.tsx index 7285d8b0d1a..084d3179f90 100644 --- a/src/stories/TextInputWithTokens.stories.tsx +++ b/src/stories/TextInputWithTokens.stories.tsx @@ -157,29 +157,29 @@ export const WithLoadingIndicator = (args: TextInputWithTokensProps) => { No visual - + Leading visual Both visuals From 3f6b35ec25a5bd85dbb8d0337cd9000ca9cd449b Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Mon, 21 Mar 2022 15:31:31 -0400 Subject: [PATCH 26/35] rm unnecessary width style from formcontrol, fix formcontrol import --- src/FormControl/FormControl.tsx | 1 - src/_TextInputInnerAction.tsx | 2 +- .../__snapshots__/TextInput.test.tsx.snap | 304 ++++++++++-------- 3 files changed, 167 insertions(+), 140 deletions(-) diff --git a/src/FormControl/FormControl.tsx b/src/FormControl/FormControl.tsx index d437fb80e98..79eaf428456 100644 --- a/src/FormControl/FormControl.tsx +++ b/src/FormControl/FormControl.tsx @@ -174,7 +174,6 @@ const FormControl = React.forwardRef( ref={ref} display="flex" flexDirection="column" - width="100%" sx={{...(isLabelHidden ? {'> *:not(label) + *': {marginTop: 1}} : {'> * + *': {marginTop: 1}}), ...sx}} > {slots.Label} diff --git a/src/_TextInputInnerAction.tsx b/src/_TextInputInnerAction.tsx index fd985ba875a..543ae28c3e4 100644 --- a/src/_TextInputInnerAction.tsx +++ b/src/_TextInputInnerAction.tsx @@ -1,7 +1,7 @@ import {IconProps} from '@primer/octicons-react' import React, {forwardRef, MouseEventHandler} from 'react' import {Box, Tooltip} from '.' -import {Button, ButtonProps, IconButton} from './Button2' +import {Button, ButtonProps, IconButton} from './Button' import {SxProp} from './sx' type TextInputActionProps = Omit, 'onClick' | 'children' | 'size'> & { diff --git a/src/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/__tests__/__snapshots__/TextInput.test.tsx.snap index c8affcbc459..e579e7cee68 100644 --- a/src/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -871,7 +871,8 @@ exports[`TextInput renders monospace 1`] = ` margin-right: 8px; } -.c0 .TextInput-icon { +.c0 .TextInput-icon, +.c0 .TextInput-action { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; @@ -917,6 +918,8 @@ exports[`TextInput renders monospace 1`] = ` className="c1" data-component="input" name="zipcode" + onBlur={[Function]} + onFocus={[Function]} type="text" /> @@ -1156,18 +1159,71 @@ exports[`TextInput renders trailingAction icon button 1`] = ` display: inline-block; } -.c1 { +.c2 { + border-radius: 6px; border: 0; - font-size: inherit; + border-color: rgba(27,31,36,0.15); font-family: inherit; - background-color: transparent; + font-weight: 600; + line-height: 20px; + white-space: nowrap; + vertical-align: middle; + cursor: pointer; -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-text-decoration: none; + text-decoration: none; + text-align: center; + padding-top: 6px; + padding-bottom: 6px; + padding-left: 8px; + padding-right: 8px; + font-size: 14px; + color: #24292f; + background-color: transparent; + box-shadow: none; +} + +.c2:focus { + outline: none; +} + +.c2:disabled { + cursor: default; + color: #8c959f; +} + +.c2:disabled [data-component=ButtonCounter] { color: inherit; - width: 100%; } -.c1:focus { - outline: 0; +.c2:disabled svg { + opacity: 0.6; +} + +.c2 [data-component=ButtonCounter] { + font-size: 14px; +} + +.c2:hover:not([disabled]) { + background-color: #f3f4f6; +} + +.c2:focus:not([disabled]) { + box-shadow: 0 0 0 3px rgba(9,105,218,0.3); +} + +.c2:active:not([disabled]) { + background-color: hsla(220,14%,94%,1); +} + +.c2[aria-expanded=true] { + background-color: hsla(220,14%,94%,1); } .c0 { @@ -1237,63 +1293,24 @@ exports[`TextInput renders trailingAction icon button 1`] = ` padding-right: 12px; } -.c2 { - border-radius: 6px; +.c1 { border: 0; - border-color: rgba(27,31,36,0.15); + font-size: inherit; font-family: inherit; - font-weight: 600; - line-height: 20px; - white-space: nowrap; - vertical-align: middle; - cursor: pointer; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-text-decoration: none; - text-decoration: none; - text-align: center; - padding-top: 6px; - padding-bottom: 6px; - padding-left: 8px; - padding-right: 8px; - font-size: 14px; - color: #24292f; background-color: transparent; - box-shadow: none; -} - -.c2:focus { - outline: none; -} - -.c2:disabled { - cursor: default; - color: #8c959f; -} - -.c2:disabled svg { - opacity: 0.6; -} - -.c2 [data-component="ButtonCounter"] { - font-size: 14px; -} - -.c2:hover:not([disabled]) { - background-color: #f3f4f6; + -webkit-appearance: none; + color: inherit; + width: 100%; } -.c2:focus:not([disabled]) { - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); +.c1:focus { + outline: 0; } -.c2:active:not([disabled]) { - background-color: hsla(220,14%,94%,1); +@media (forced-colors:active) { + .c2:focus { + outline: solid 1px transparent; + } } @media (min-width:768px) { @@ -1303,6 +1320,8 @@ exports[`TextInput renders trailingAction icon button 1`] = ` } @@ -1319,17 +1338,10 @@ exports[`TextInput renders trailingAction icon button 1`] = ` className="TextInput-action" > - )} - + + )}
) } diff --git a/src/__tests__/TextInput.test.tsx b/src/__tests__/TextInput.test.tsx index 7a761f8d1af..1516917ca2b 100644 --- a/src/__tests__/TextInput.test.tsx +++ b/src/__tests__/TextInput.test.tsx @@ -77,6 +77,23 @@ describe('TextInput', () => { ).toMatchSnapshot() }) + it('renders trailingAction text button with a tooltip', () => { + const handleAction = jest.fn() + expect( + render( + + Clear + + } + /> + ) + ).toMatchSnapshot() + }) + it('renders trailingAction icon button', () => { const handleAction = jest.fn() expect( @@ -84,7 +101,7 @@ describe('TextInput', () => { } + trailingAction={} /> ) ).toMatchSnapshot() diff --git a/src/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/__tests__/__snapshots__/TextInput.test.tsx.snap index e579e7cee68..62381879a6d 100644 --- a/src/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -1155,11 +1155,11 @@ exports[`TextInput renders small 1`] = ` `; exports[`TextInput renders trailingAction icon button 1`] = ` -.c3 { +.c4 { display: inline-block; } -.c2 { +.c3 { border-radius: 6px; border: 0; border-color: rgba(27,31,36,0.15); @@ -1189,40 +1189,40 @@ exports[`TextInput renders trailingAction icon button 1`] = ` box-shadow: none; } -.c2:focus { +.c3:focus { outline: none; } -.c2:disabled { +.c3:disabled { cursor: default; color: #8c959f; } -.c2:disabled [data-component=ButtonCounter] { +.c3:disabled [data-component=ButtonCounter] { color: inherit; } -.c2:disabled svg { +.c3:disabled svg { opacity: 0.6; } -.c2 [data-component=ButtonCounter] { +.c3 [data-component=ButtonCounter] { font-size: 14px; } -.c2:hover:not([disabled]) { +.c3:hover:not([disabled]) { background-color: #f3f4f6; } -.c2:focus:not([disabled]) { +.c3:focus:not([disabled]) { box-shadow: 0 0 0 3px rgba(9,105,218,0.3); } -.c2:active:not([disabled]) { +.c3:active:not([disabled]) { background-color: hsla(220,14%,94%,1); } -.c2[aria-expanded=true] { +.c3[aria-expanded=true] { background-color: hsla(220,14%,94%,1); } @@ -1307,8 +1307,227 @@ exports[`TextInput renders trailingAction icon button 1`] = ` outline: 0; } +.c2 { + position: relative; +} + +.c2::before { + position: absolute; + z-index: 1000001; + display: none; + width: 0px; + height: 0px; + color: #24292f; + pointer-events: none; + content: ''; + border: 6px solid transparent; + opacity: 0; +} + +.c2::after { + position: absolute; + z-index: 1000000; + display: none; + padding: 0.5em 0.75em; + font: normal normal 11px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"; + -webkit-font-smoothing: subpixel-antialiased; + color: #ffffff; + text-align: center; + -webkit-text-decoration: none; + text-decoration: none; + text-shadow: none; + text-transform: none; + -webkit-letter-spacing: normal; + -moz-letter-spacing: normal; + -ms-letter-spacing: normal; + letter-spacing: normal; + word-wrap: break-word; + white-space: pre; + pointer-events: none; + content: attr(aria-label); + background: #24292f; + border-radius: 3px; + opacity: 0; +} + +.c2:hover::before, +.c2:active::before, +.c2:focus::before, +.c2:hover::after, +.c2:active::after, +.c2:focus::after { + display: inline-block; + -webkit-text-decoration: none; + text-decoration: none; + -webkit-animation-name: tooltip-appear; + animation-name: tooltip-appear; + -webkit-animation-duration: 0.1s; + animation-duration: 0.1s; + -webkit-animation-fill-mode: forwards; + animation-fill-mode: forwards; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + -webkit-animation-delay: 0.4s; + animation-delay: 0.4s; +} + +.c2.tooltipped-no-delay:hover::before, +.c2.tooltipped-no-delay:active::before, +.c2.tooltipped-no-delay:focus::before, +.c2.tooltipped-no-delay:hover::after, +.c2.tooltipped-no-delay:active::after, +.c2.tooltipped-no-delay:focus::after { + -webkit-animation-delay: 0s; + animation-delay: 0s; +} + +.c2.tooltipped-multiline:hover::after, +.c2.tooltipped-multiline:active::after, +.c2.tooltipped-multiline:focus::after { + display: table-cell; +} + +.c2.tooltipped-s::after, +.c2.tooltipped-se::after, +.c2.tooltipped-sw::after { + top: 100%; + right: 50%; + margin-top: 6px; +} + +.c2.tooltipped-s::before, +.c2.tooltipped-se::before, +.c2.tooltipped-sw::before { + top: auto; + right: 50%; + bottom: -7px; + margin-right: -6px; + border-bottom-color: #24292f; +} + +.c2.tooltipped-se::after { + right: auto; + left: 50%; + margin-left: -16px; +} + +.c2.tooltipped-sw::after { + margin-right: -16px; +} + +.c2.tooltipped-n::after, +.c2.tooltipped-ne::after, +.c2.tooltipped-nw::after { + right: 50%; + bottom: 100%; + margin-bottom: 6px; +} + +.c2.tooltipped-n::before, +.c2.tooltipped-ne::before, +.c2.tooltipped-nw::before { + top: -7px; + right: 50%; + bottom: auto; + margin-right: -6px; + border-top-color: #24292f; +} + +.c2.tooltipped-ne::after { + right: auto; + left: 50%; + margin-left: -16px; +} + +.c2.tooltipped-nw::after { + margin-right: -16px; +} + +.c2.tooltipped-s::after, +.c2.tooltipped-n::after { + -webkit-transform: translateX(50%); + -ms-transform: translateX(50%); + transform: translateX(50%); +} + +.c2.tooltipped-w::after { + right: 100%; + bottom: 50%; + margin-right: 6px; + -webkit-transform: translateY(50%); + -ms-transform: translateY(50%); + transform: translateY(50%); +} + +.c2.tooltipped-w::before { + top: 50%; + bottom: 50%; + left: -7px; + margin-top: -6px; + border-left-color: #24292f; +} + +.c2.tooltipped-e::after { + bottom: 50%; + left: 100%; + margin-left: 6px; + -webkit-transform: translateY(50%); + -ms-transform: translateY(50%); + transform: translateY(50%); +} + +.c2.tooltipped-e::before { + top: 50%; + right: -7px; + bottom: 50%; + margin-top: -6px; + border-right-color: #24292f; +} + +.c2.tooltipped-multiline::after { + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; + max-width: 250px; + word-wrap: break-word; + white-space: pre-line; + border-collapse: separate; +} + +.c2.tooltipped-multiline.tooltipped-s::after, +.c2.tooltipped-multiline.tooltipped-n::after { + right: auto; + left: 50%; + -webkit-transform: translateX(-50%); + -ms-transform: translateX(-50%); + transform: translateX(-50%); +} + +.c2.tooltipped-multiline.tooltipped-w::after, +.c2.tooltipped-multiline.tooltipped-e::after { + right: 100%; +} + +.c2.tooltipped-align-right-2::after { + right: 0; + margin-right: 0; +} + +.c2.tooltipped-align-right-2::before { + right: 15px; +} + +.c2.tooltipped-align-left-2::after { + left: 0; + margin-left: 0; +} + +.c2.tooltipped-align-left-2::before { + left: 10px; +} + @media (forced-colors:active) { - .c2:focus { + .c3:focus { outline: solid 1px transparent; } } @@ -1337,38 +1556,45 @@ exports[`TextInput renders trailingAction icon button 1`] = ` - + viewBox="0 0 16 16" + width={16} + /> + + + `; @@ -1586,6 +1812,445 @@ exports[`TextInput renders trailingAction text button 1`] = ` `; +exports[`TextInput renders trailingAction text button with a tooltip 1`] = ` +.c3 { + border-radius: 6px; + border: 0; + border-color: rgba(27,31,36,0.15); + font-family: inherit; + font-weight: 600; + line-height: 20px; + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-text-decoration: none; + text-decoration: none; + text-align: center; + display: grid; + grid-template-areas: "leadingIcon text trailingIcon"; + padding-top: 4px; + padding-bottom: 4px; + padding-left: 12px; + padding-right: 12px; + font-size: 12px; + color: #24292f; + background-color: transparent; + box-shadow: none; +} + +.c3:focus { + outline: none; +} + +.c3:disabled { + cursor: default; + color: #8c959f; +} + +.c3:disabled [data-component=ButtonCounter] { + color: inherit; +} + +.c3:disabled svg { + opacity: 0.6; +} + +.c3 > :not(:last-child) { + margin-right: 8px; +} + +.c3 [data-component="leadingIcon"] { + grid-area: leadingIcon; +} + +.c3 [data-component="text"] { + grid-area: text; +} + +.c3 [data-component="trailingIcon"] { + grid-area: trailingIcon; +} + +.c3 [data-component=ButtonCounter] { + font-size: 12px; +} + +.c3:hover:not([disabled]) { + background-color: #f3f4f6; +} + +.c3:focus:not([disabled]) { + box-shadow: 0 0 0 3px rgba(9,105,218,0.3); +} + +.c3:active:not([disabled]) { + background-color: hsla(220,14%,94%,1); +} + +.c3[aria-expanded=true] { + background-color: hsla(220,14%,94%,1); +} + +.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; + 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 > textarea { + padding: 12px; +} + +.c0 >:not(:last-child) { + margin-right: 8px; +} + +.c0 .TextInput-icon, +.c0 .TextInput-action { + -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; +} + +.c1 { + border: 0; + font-size: inherit; + font-family: inherit; + background-color: transparent; + -webkit-appearance: none; + color: inherit; + width: 100%; +} + +.c1:focus { + outline: 0; +} + +.c2 { + position: relative; + display: inline-block; +} + +.c2::before { + position: absolute; + z-index: 1000001; + display: none; + width: 0px; + height: 0px; + color: #24292f; + pointer-events: none; + content: ''; + border: 6px solid transparent; + opacity: 0; +} + +.c2::after { + position: absolute; + z-index: 1000000; + display: none; + padding: 0.5em 0.75em; + font: normal normal 11px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"; + -webkit-font-smoothing: subpixel-antialiased; + color: #ffffff; + text-align: center; + -webkit-text-decoration: none; + text-decoration: none; + text-shadow: none; + text-transform: none; + -webkit-letter-spacing: normal; + -moz-letter-spacing: normal; + -ms-letter-spacing: normal; + letter-spacing: normal; + word-wrap: break-word; + white-space: pre; + pointer-events: none; + content: attr(aria-label); + background: #24292f; + border-radius: 3px; + opacity: 0; +} + +.c2:hover::before, +.c2:active::before, +.c2:focus::before, +.c2:hover::after, +.c2:active::after, +.c2:focus::after { + display: inline-block; + -webkit-text-decoration: none; + text-decoration: none; + -webkit-animation-name: tooltip-appear; + animation-name: tooltip-appear; + -webkit-animation-duration: 0.1s; + animation-duration: 0.1s; + -webkit-animation-fill-mode: forwards; + animation-fill-mode: forwards; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + -webkit-animation-delay: 0.4s; + animation-delay: 0.4s; +} + +.c2.tooltipped-no-delay:hover::before, +.c2.tooltipped-no-delay:active::before, +.c2.tooltipped-no-delay:focus::before, +.c2.tooltipped-no-delay:hover::after, +.c2.tooltipped-no-delay:active::after, +.c2.tooltipped-no-delay:focus::after { + -webkit-animation-delay: 0s; + animation-delay: 0s; +} + +.c2.tooltipped-multiline:hover::after, +.c2.tooltipped-multiline:active::after, +.c2.tooltipped-multiline:focus::after { + display: table-cell; +} + +.c2.tooltipped-s::after, +.c2.tooltipped-se::after, +.c2.tooltipped-sw::after { + top: 100%; + right: 50%; + margin-top: 6px; +} + +.c2.tooltipped-s::before, +.c2.tooltipped-se::before, +.c2.tooltipped-sw::before { + top: auto; + right: 50%; + bottom: -7px; + margin-right: -6px; + border-bottom-color: #24292f; +} + +.c2.tooltipped-se::after { + right: auto; + left: 50%; + margin-left: -16px; +} + +.c2.tooltipped-sw::after { + margin-right: -16px; +} + +.c2.tooltipped-n::after, +.c2.tooltipped-ne::after, +.c2.tooltipped-nw::after { + right: 50%; + bottom: 100%; + margin-bottom: 6px; +} + +.c2.tooltipped-n::before, +.c2.tooltipped-ne::before, +.c2.tooltipped-nw::before { + top: -7px; + right: 50%; + bottom: auto; + margin-right: -6px; + border-top-color: #24292f; +} + +.c2.tooltipped-ne::after { + right: auto; + left: 50%; + margin-left: -16px; +} + +.c2.tooltipped-nw::after { + margin-right: -16px; +} + +.c2.tooltipped-s::after, +.c2.tooltipped-n::after { + -webkit-transform: translateX(50%); + -ms-transform: translateX(50%); + transform: translateX(50%); +} + +.c2.tooltipped-w::after { + right: 100%; + bottom: 50%; + margin-right: 6px; + -webkit-transform: translateY(50%); + -ms-transform: translateY(50%); + transform: translateY(50%); +} + +.c2.tooltipped-w::before { + top: 50%; + bottom: 50%; + left: -7px; + margin-top: -6px; + border-left-color: #24292f; +} + +.c2.tooltipped-e::after { + bottom: 50%; + left: 100%; + margin-left: 6px; + -webkit-transform: translateY(50%); + -ms-transform: translateY(50%); + transform: translateY(50%); +} + +.c2.tooltipped-e::before { + top: 50%; + right: -7px; + bottom: 50%; + margin-top: -6px; + border-right-color: #24292f; +} + +.c2.tooltipped-multiline::after { + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; + max-width: 250px; + word-wrap: break-word; + white-space: pre-line; + border-collapse: separate; +} + +.c2.tooltipped-multiline.tooltipped-s::after, +.c2.tooltipped-multiline.tooltipped-n::after { + right: auto; + left: 50%; + -webkit-transform: translateX(-50%); + -ms-transform: translateX(-50%); + transform: translateX(-50%); +} + +.c2.tooltipped-multiline.tooltipped-w::after, +.c2.tooltipped-multiline.tooltipped-e::after { + right: 100%; +} + +.c2.tooltipped-align-right-2::after { + right: 0; + margin-right: 0; +} + +.c2.tooltipped-align-right-2::before { + right: 15px; +} + +.c2.tooltipped-align-left-2::after { + left: 0; + margin-left: 0; +} + +.c2.tooltipped-align-left-2::before { + left: 10px; +} + +@media (forced-colors:active) { + .c3:focus { + outline: solid 1px transparent; + } +} + +@media (min-width:768px) { + .c0 { + font-size: 14px; + } +} + + + + + + + + + +`; + exports[`TextInput renders trailingVisual 1`] = ` .c0 { font-size: 14px; diff --git a/src/stories/TextInput.stories.tsx b/src/stories/TextInput.stories.tsx index 2db439fa8fb..d316402ca90 100644 --- a/src/stories/TextInput.stories.tsx +++ b/src/stories/TextInput.stories.tsx @@ -159,7 +159,7 @@ export const WithTrailingAction = (args: TextInputProps) => { setValue('') }} icon={XCircleFillIcon} - iconLabel="Clear input" + aria-label="Clear input" sx={{color: 'fg.subtle'}} /> } @@ -177,8 +177,7 @@ export const WithTrailingAction = (args: TextInputProps) => { setValue('') }} icon={XCircleFillIcon} - iconLabel="Clear input" - tooltipMessage="Clear" + aria-label="Clear input" sx={{color: 'fg.subtle'}} /> } From 0dabb66475a5e0c3a2c17857019ec9c22e102d77 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Thu, 24 Mar 2022 12:53:31 -0400 Subject: [PATCH 31/35] rms redundant stories --- docs/content/TextInput.mdx | 16 ---------------- src/stories/TextInput.stories.tsx | 18 ------------------ 2 files changed, 34 deletions(-) diff --git a/docs/content/TextInput.mdx b/docs/content/TextInput.mdx index 140b2da7435..37340720351 100644 --- a/docs/content/TextInput.mdx +++ b/docs/content/TextInput.mdx @@ -127,22 +127,6 @@ render() } /> - - Icon action with tooltip - { - alert('clear input') - }} - icon={XIcon} - iconLabel="Clear input" - tooltipMessage="Clear" - sx={{color: 'fg.subtle'}} - /> - } - /> - Text action { {...args} /> - - Icon action with tooltip - { - setValue('') - }} - icon={XCircleFillIcon} - aria-label="Clear input" - sx={{color: 'fg.subtle'}} - /> - } - value={value} - onChange={handleChange} - {...args} - /> - Text action Date: Thu, 24 Mar 2022 13:09:57 -0400 Subject: [PATCH 32/35] removes excess right padding when we pass 'trailingAction' and 'loading' --- src/TextInput.tsx | 2 +- src/_TextInputWrapper.tsx | 18 +++++++++--------- .../__snapshots__/TextInput.test.tsx.snap | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/TextInput.tsx b/src/TextInput.tsx index befdde9a559..af50cade0f3 100644 --- a/src/TextInput.tsx +++ b/src/TextInput.tsx @@ -122,7 +122,7 @@ const TextInput = React.forwardRef( variant={variantProp} hasLeadingVisual={Boolean(LeadingVisual || showLeadingLoadingIndicator)} hasTrailingVisual={Boolean(TrailingVisual || showTrailingLoadingIndicator)} - hasActions={Boolean(trailingAction)} + hasTrailingAction={Boolean(trailingAction)} isInputFocused={isInputFocused} onClick={focusInput} aria-live="polite" diff --git a/src/_TextInputWrapper.tsx b/src/_TextInputWrapper.tsx index 5087f3f1c13..29962499ee6 100644 --- a/src/_TextInputWrapper.tsx +++ b/src/_TextInputWrapper.tsx @@ -45,7 +45,7 @@ export type StyledBaseWrapperProps = { block?: boolean contrast?: boolean disabled?: boolean - hasActions?: boolean + hasTrailingAction?: boolean isInputFocused?: boolean monospace?: boolean validationStatus?: FormValidationStatus @@ -67,8 +67,8 @@ export const textInputHorizPadding = textInputBasePadding // TODO: figure out how to type a themed CSS function (e.g.: css`color: blue;`) // eslint-disable-next-line @typescript-eslint/no-explicit-any -const renderFocusStyles = (hasActions: boolean, isInputFocused: boolean, focusStyles: any) => { - if (hasActions) { +const renderFocusStyles = (hasTrailingAction: boolean, isInputFocused: boolean, focusStyles: any) => { + if (hasTrailingAction) { return ( isInputFocused && css` @@ -104,7 +104,7 @@ export const TextInputBaseWrapper = styled.span` ${props => renderFocusStyles( - Boolean(props.hasActions), + Boolean(props.hasTrailingAction), Boolean(props.isInputFocused), css` border-color: ${get('colors.accent.emphasis')}; @@ -142,7 +142,7 @@ export const TextInputBaseWrapper = styled.span` css` border-color: ${get('colors.danger.emphasis')}; ${renderFocusStyles( - Boolean(props.hasActions), + Boolean(props.hasTrailingAction), Boolean(props.isInputFocused), css` border-color: ${get('colors.danger.emphasis')}; @@ -157,7 +157,7 @@ export const TextInputBaseWrapper = styled.span` css` border-color: ${get('colors.success.emphasis')}; ${renderFocusStyles( - Boolean(props.hasActions), + Boolean(props.hasTrailingAction), Boolean(props.isInputFocused), css` border-color: ${get('colors.success.emphasis')}; @@ -204,12 +204,12 @@ const TextInputWrapper = styled(TextInputBaseWrapper)` ${props => css` padding-left: ${props.hasLeadingVisual ? textInputHorizPadding : 0}; - padding-right: ${props.hasTrailingVisual ? textInputHorizPadding : 0}; + padding-right: ${props.hasTrailingVisual && !props.hasTrailingAction ? textInputHorizPadding : 0}; > input, > select { padding-left: ${!props.hasLeadingVisual ? textInputHorizPadding : 0}; - padding-right: ${!props.hasTrailingVisual ? textInputHorizPadding : 0}; + padding-right: ${!props.hasTrailingVisual && !props.hasTrailingAction ? textInputHorizPadding : 0}; } `} @@ -218,7 +218,7 @@ const TextInputWrapper = styled(TextInputBaseWrapper)` css` border-color: ${get('colors.attention.emphasis')}; ${renderFocusStyles( - Boolean(props.hasActions), + Boolean(props.hasTrailingAction), Boolean(props.isInputFocused), css` border-color: ${get('colors.attention.emphasis')}; diff --git a/src/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/__tests__/__snapshots__/TextInput.test.tsx.snap index 62381879a6d..6c82e7e7ba0 100644 --- a/src/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -1290,7 +1290,7 @@ exports[`TextInput renders trailingAction icon button 1`] = ` .c0 > input, .c0 > select { padding-left: 12px; - padding-right: 12px; + padding-right: 0; } .c1 { @@ -1749,7 +1749,7 @@ exports[`TextInput renders trailingAction text button 1`] = ` .c0 > input, .c0 > select { padding-left: 12px; - padding-right: 12px; + padding-right: 0; } .c1 { @@ -1962,7 +1962,7 @@ exports[`TextInput renders trailingAction text button with a tooltip 1`] = ` .c0 > input, .c0 > select { padding-left: 12px; - padding-right: 12px; + padding-right: 0; } .c1 { From b26b765b30990249b41f52dc4e7ec1258bce8f9c Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Fri, 25 Mar 2022 12:46:17 -0400 Subject: [PATCH 33/35] change iconLabel to aria-label in docs example --- docs/content/TextInput.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/TextInput.mdx b/docs/content/TextInput.mdx index 37340720351..4ec34745bc8 100644 --- a/docs/content/TextInput.mdx +++ b/docs/content/TextInput.mdx @@ -121,7 +121,7 @@ render() alert('clear input') }} icon={XIcon} - iconLabel="Clear input" + aria-label="Clear input" sx={{color: 'fg.subtle'}} /> } From 6d1e442c2dce67cb95b4fbdaa4b813d3aaad802a Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Fri, 25 Mar 2022 14:17:01 -0400 Subject: [PATCH 34/35] empy commit to make CI run From b1d60a22f8fdb245ef0068af0f61ce3f1055d9f1 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Tue, 29 Mar 2022 11:24:04 -0400 Subject: [PATCH 35/35] disable html-addon to prevent Storybook from timing out Chromatic --- .storybook/main.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.storybook/main.js b/.storybook/main.js index 6afe7693ed5..245375840ce 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -5,6 +5,8 @@ module.exports = { '@storybook/addon-links', '@storybook/addon-essentials', 'storybook-addon-performance/register', - ...(process.env.NODE_ENV === 'production' ? ['@whitespace/storybook-addon-html'] : []) + ...(process.env.NODE_ENV === 'production' && process.env.GITHUB_JOB !== 'chromatic' + ? ['@whitespace/storybook-addon-html'] + : []) ] }