Skip to content

Commit

Permalink
Select input component (#1736)
Browse files Browse the repository at this point in the history
* adds Select component and stories

* adds tests

* styling fix for Firefox

* adds docs

* adds changeset

* appease the linter

* Update src/Select.tsx

Co-authored-by: Rez <rezrah@github.com>

* addresses PR feedback

* addresses more PR feedback

* adds props table to select

* fix deployment failure

* fixes docs build

* change ternary to AND operator

* adds comopnentId to docs frontmatter

* adds Select as a possible InputField child

* updates package-lock.json

Co-authored-by: Rez <rezrah@github.com>
  • Loading branch information
mperrotti and rezrah committed Jan 11, 2022
1 parent a205ce9 commit 82961d4
Show file tree
Hide file tree
Showing 15 changed files with 630 additions and 37,271 deletions.
5 changes: 5 additions & 0 deletions .changeset/cool-parrots-double.md
@@ -0,0 +1,5 @@
---
'@primer/react': minor
---

Adds a component for a native select input
75 changes: 56 additions & 19 deletions docs/content/InputField.mdx
Expand Up @@ -7,9 +7,7 @@ source: https://github.com/primer/react/blob/main/src/InputField/InputField.tsx
storybook: '/react/storybook?path=/story/forms-inputfield--text-input-field'
---

import {InputField, TextInputWithTokens} from '@primer/react'
import {PropsTable} from '../src/props-table'
import {ComponentChecklist} from '../src/component-checklist'
import {InputField, TextInputWithTokens, Autocomplete, Select} from '@primer/react'

## Examples

Expand Down Expand Up @@ -40,7 +38,7 @@ import {ComponentChecklist} from '../src/component-checklist'
</InputField>
```

### Using a TextInputWithTokens input
### Using different input components

```javascript live noinline
const TextInputWithTokensExample = () => {
Expand All @@ -54,10 +52,49 @@ const TextInputWithTokensExample = () => {
}

return (
<InputField>
<InputField.Label>Name</InputField.Label>
<TextInputWithTokens onTokenRemove={onTokenRemove} tokens={tokens} />
</InputField>
<Box
display="flex"
flexDirection="column"
sx={{
'> * + *': {
marginTop: 4
}
}}
>
<InputField>
<InputField.Label>TextInputWithTokens</InputField.Label>
<TextInputWithTokens onTokenRemove={onTokenRemove} tokens={tokens} />
</InputField>
<InputField>
<InputField.Label>Autocomplete</InputField.Label>
<Autocomplete>
<Autocomplete.Input block />
<Autocomplete.Overlay>
<Autocomplete.Menu
items={[
{text: 'css', id: 0},
{text: 'css-in-js', id: 1},
{text: 'styled-system', id: 2},
{text: 'javascript', id: 3},
{text: 'typescript', id: 4},
{text: 'react', id: 5},
{text: 'design-systems', id: 6}
]}
selectedItemIds={[]}
/>
</Autocomplete.Overlay>
</Autocomplete>
</InputField>
<InputField>
<InputField.Label>Select</InputField.Label>
<Select>
<Select.Option value="figma">Figma</Select.Option>
<Select.Option value="css">Primer CSS</Select.Option>
<Select.Option value="prc">Primer React components</Select.Option>
<Select.Option value="pvc">Primer ViewComponents</Select.Option>
</Select>
</InputField>
</Box>
)
}

Expand Down Expand Up @@ -137,43 +174,43 @@ render(ValidationExample)
The container that handles the layout and passes the relevant IDs and ARIA attributes it's children.

<PropsTable>
<PropsTable.Row
<PropsTableRow
name="children"
type="InputField.Label | InputField.Caption | InputField.Validation | Autocomplete | TextInput | TextInputWithTokens"
type="InputField.Label | InputField.Caption | InputField.Validation | Autocomplete | TextInput | TextInputWithTokens | Select"
required
/>
<PropsTable.Row
<PropsTableRow
name="disabled"
type="boolean"
defaultValue="false"
description="Whether the field is ready for user input"
/>
<PropsTable.Row
<PropsTableRow
name="id"
type="string"
defaultValue="a generated string"
description="The unique identifier for this field. Used to associate the label, validation text, and caption text"
/>
<PropsTable.Row
<PropsTableRow
name="required"
type="boolean"
defaultValue="false"
description="Whether the field is ready for user input"
/>
<PropsTable.Row
<PropsTableRow
name="validationMap"
type="Record<string, 'error'|'sucess'>"
description="A map of validation statuses and their associated validation keys. When one of the validation keys is passed to the `validationResult` prop, the associated validation message will be rendered in the correct style"
/>
<PropsTable.Row name="validationResult" type="string" description="The key of the validation message to show " />
<PropsTableRow name="validationResult" type="string" description="The key of the validation message to show " />
</PropsTable>

### InputField.Label

A `InputField.Label` must be passed for the field to be accessible to assistive technology, but it may be visually hidden.

<PropsTable>
<PropsTable.Row
<PropsTableRow
name="boolean"
type="InputField.Label | InputField.Caption | InputField.Validation | Autocomplete | TextInput | TextInputWithTokens"
defaultValue="false"
Expand All @@ -186,7 +223,7 @@ A `InputField.Label` must be passed for the field to be accessible to assistive
`InputField.Caption` may be used to render hint text for fields that require additional context.

<PropsTable>
<PropsTable.Row
<PropsTableRow
name="children"
type="React.ReactNode"
description="The content (usually just text) that is rendered to give contextual info about the field"
Expand All @@ -198,12 +235,12 @@ A `InputField.Label` must be passed for the field to be accessible to assistive
`InputField.Validation` may be used to render contextual validation information if the field was flagged during validation.

<PropsTable>
<PropsTable.Row
<PropsTableRow
name="children"
type="React.ReactNode"
description="The content (usually just text) that is rendered to give contextual info about the validation result for the field"
/>
<PropsTable.Row
<PropsTableRow
name="validationKey"
type="string"
description="The key of the property from `InputField` that corresponds to this validation message. When `InputField`'s `validationResult` prop matches `InputField.Validation`'s `validationKey` prop, this message is shown."
Expand Down
125 changes: 125 additions & 0 deletions docs/content/Select.mdx
@@ -0,0 +1,125 @@
---
componentId: select
title: Select
description: Use a select input when a user needs to select one option from a long list
status: Alpha
source: https://github.com/primer/react/blob/main/src/Select.tsx
storybook: '/react/storybook?path=/story/forms-select--default'
---

import {Select, Text} from '@primer/react'

## Examples

### Basic

```jsx live
<>
<Text fontWeight="bold" fontSize={1} as="label" display="block" htmlFor="basic">
Preferred Primer component interface
</Text>
<Select id="basic">
<Select.Option value="figma">Figma</Select.Option>
<Select.Option value="css">Primer CSS</Select.Option>
<Select.Option value="prc">Primer React components</Select.Option>
<Select.Option value="pvc">Primer ViewComponents</Select.Option>
</Select>
</>
```

### With grouped options

```jsx live
<>
<Text fontWeight="bold" fontSize={1} as="label" display="block" htmlFor="grouped">
Preferred Primer component interface
</Text>
<Select id="grouped">
<Select.OptGroup label="GUI">
<Select.Option value="figma">Figma</Select.Option>
</Select.OptGroup>
<Select.OptGroup label="Code">
<Select.Option value="css">Primer CSS</Select.Option>
<Select.Option value="prc">Primer React components</Select.Option>
<Select.Option value="pvc">Primer ViewComponents</Select.Option>
</Select.OptGroup>
</Select>
</>
```

### With a placeholder

```jsx live
<>
<Text fontWeight="bold" fontSize={1} as="label" display="block" htmlFor="withPlaceholder">
Preferred Primer component interface
</Text>
<Select id="withPlaceholder" placeholder="Pick an interface">
<Select.Option value="figma">Figma</Select.Option>
<Select.Option value="css">Primer CSS</Select.Option>
<Select.Option value="prc">Primer React components</Select.Option>
<Select.Option value="pvc">Primer ViewComponents</Select.Option>
</Select>
</>
```

## Props

### Select

<PropsTable>
<PropsTableRow
name="block"
type="boolean"
defaultValue="false"
description={<>Creates a full width input element</>}
/>
<PropsTableRow
name="contrast"
type="boolean"
defaultValue="false"
description="Changes background color to a higher contrast color"
/>
<PropsTableRow
name="size"
type="'small' | 'medium' | 'large'"
description="Creates a smaller or larger input than the default."
/>
<PropsTableRow name="validationStatus" type="'warning' | 'error'" description="Style the input to match the status" />
<PropsTablePassthroughPropsRow
elementName="select"
passthroughPropsLink={
<Link href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#attributes">MDN</Link>
}
/>

</PropsTable>

### Select.OptGroup

The `Select.OptGroup` component accepts the same props as a native HTML [`<optgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup).

### Select.Option

The `Select.Option` component accepts the same props as a native HTML [`<option>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option).

## Status

<ComponentChecklist
items={{
propsDocumented: true,
noUnnecessaryDeps: true,
adaptsToThemes: true,
adaptsToScreenSizes: true,
fullTestCoverage: true,
usedInProduction: false,
usageExamplesDocumented: true,
hasStorybookStories: true,
designReviewed: false,
a11yReviewed: false,
stableApi: false,
addressedApiFeedback: false,
hasDesignGuidelines: false,
hasFigmaComponent: false
}}
/>
2 changes: 2 additions & 0 deletions docs/src/@primer/gatsby-theme-doctocat/nav.yml
Expand Up @@ -99,6 +99,8 @@
url: /ProgressBar
- title: Radio
url: /Radio
- title: Select
url: /Select
- title: SelectPanel
url: /SelectPanel
- title: SideNav
Expand Down

0 comments on commit 82961d4

Please sign in to comment.