Skip to content

Commit

Permalink
Merge pull request #435 from omnifed/433-feat-make-select-recipe
Browse files Browse the repository at this point in the history
433 feat make select recipe
  • Loading branch information
caseybaggz committed Sep 4, 2024
2 parents 83135af + ad62f57 commit 7d49bb9
Show file tree
Hide file tree
Showing 15 changed files with 761 additions and 31 deletions.
2 changes: 1 addition & 1 deletion docs/app/data/categories.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"selection": {
"name": "Selection",
"description": "Components that allow users to select choices.",
"items": ["Toggle", "Radio"]
"items": ["Radio", "Select", "Toggle"]
},
"inputs": {
"name": "Inputs",
Expand Down
28 changes: 28 additions & 0 deletions docs/app/react/select/a11y.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
---

import {
WhenToUseAdmonition
} from '@/app/components/Admonition'
import OverviewList from '@/app/components/OverviewList'

## Use Cases

<OverviewList intro="Users should be able to:" rules={[
'Navigate to and activate a text field with assistive technology',
'Input information into the text field',
'Receive and understand supporting text and error messages',
'Navigate to and select interactive icons',
]} />

## Keyboard Navigation

| Keys | Actions |
| -------- | --------------------------------------------------------------- |
| Tab | Focus lands on (non-disabled) input |

## Labeling Elements

If the UI text is correctly linked, assistive tech (such as a screenreader) will read the UI text followed by the component's role.

The accessibility label for a textfield is typically the same as the label for the textfield.
127 changes: 127 additions & 0 deletions docs/app/react/select/components/input-preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { Search } from '@cerberus-design/icons'
import { Field, FieldMessage, Label, Input } from '@cerberus-design/react'
import { css } from '@cerberus/styled-system/css'
import { vstack } from '@cerberus/styled-system/patterns'

const overrideStyles = css({
w: '1/2',
})

export function InputBasicPreview() {
return (
<div className={overrideStyles}>
<Field>
<Label htmlFor="first_name">First Name</Label>
<Input id="first_name" type="text" />
</Field>
</div>
)
}

export function InputInvalidPreview() {
return (
<div className={overrideStyles}>
<Field required invalid>
<Label htmlFor="preferred">Preferred Name</Label>
<Input
describedBy="help:preferred"
id="preferred"
type="text"
placeholder="i.e. Bobby"
/>
<FieldMessage id="help:preferred">
A preferred name is required to create an account.
</FieldMessage>
</Field>
</div>
)
}

export function InputDisabledPreview() {
return (
<div className={overrideStyles}>
<Field disabled>
<Label htmlFor="preferred">Preferred Name</Label>
<Input
describedBy="help:preferred"
id="preferred"
type="text"
placeholder="i.e. Bobby"
/>
<FieldMessage id="help:preferred">
This will be the name we use to address you.
</FieldMessage>
</Field>
</div>
)
}

export function InputWithIconPreview() {
return (
<div className={overrideStyles}>
<Field>
<Label htmlFor="global_search">Global Search</Label>
<Input
describedBy="help:global_search"
id="global_search"
placeholder="Search the world"
startIcon={<Search />}
type="text"
/>
<FieldMessage id="help:global_search">
Search the world for the best results.
</FieldMessage>
</Field>
</div>
)
}

export function InputSizesPreview() {
return (
<div
className={vstack({
alignItems: 'flex-start',
})}
>
<div>
<Field>
<Label htmlFor="first_name">First Name</Label>
<Input id="first_name" type="text" size="sm" />
</Field>
</div>
<div>
<Field>
<Label htmlFor="last_name">Last Name</Label>
<Input id="last_name" type="text" size="md" />
</Field>
</div>
<div>
<Field>
<Label htmlFor="username">Username</Label>
<Input id="username" type="text" size="lg" />
</Field>
</div>
</div>
)
}

export function InputCustomPreview() {
return (
<div className={overrideStyles}>
<Field required>
<Label htmlFor="global_search">Killa Bees</Label>
<Input
className={css({
border: '2px solid',
borderColor: 'yellow',
bgColor: 'black',
color: 'yellow',
})}
id="global_search"
placeholder="Enter the Wu-Tang Clan here."
type="text"
/>
</Field>
</div>
)
}
57 changes: 57 additions & 0 deletions docs/app/react/select/components/select-preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { ChevronDown, ErrorFilled } from '@cerberus-design/icons'
import { Field, FieldMessage, Label } from '@cerberus-design/react'
import { css, cx } from '@cerberus/styled-system/css'
import { hstack } from '@cerberus/styled-system/patterns'
import { select } from '@cerberus/styled-system/recipes'
import type { OptionHTMLAttributes, SelectHTMLAttributes } from 'react'

const overrideStyles = css({
w: '1/2',
})

function Select(props: SelectHTMLAttributes<HTMLSelectElement>) {
const styles = select()
return (
<div className={styles.root}>
<select {...props} aria-invalid="true" className={styles.input} />
<span
className={cx(
styles.iconStack,
hstack({
gap: '2',
}),
)}
>
<span data-invalid className={styles.stateIcon}>
<ErrorFilled />
</span>
<span>
<ChevronDown />
</span>
</span>
</div>
)
}

function Option(props: OptionHTMLAttributes<HTMLOptionElement>) {
return <option {...props} />
}

export function SelectBasicPreview() {
return (
<div className={overrideStyles}>
<Field>
<Label htmlFor="fruit">Select Fruit</Label>
<Select aria-describedby="help:fruit" id="fruit">
<Option value="">Choose option</Option>
<Option value="one">Option 1</Option>
<Option value="two">Option 2</Option>
<Option value="three">Option 3</Option>
</Select>
<FieldMessage id="help:fruit">
This will be your included in your smoothie.
</FieldMessage>
</Field>
</div>
)
}
Loading

0 comments on commit 7d49bb9

Please sign in to comment.