Skip to content

Adds a component to support checkbox and radio groups #1657

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 119 commits into from
Jan 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
119 commits
Select commit Hold shift + click to select a range
a23e32d
adds components and stories for basic usage
mperrotti Nov 12, 2021
779e5fe
supports checkbox and radio fields
mperrotti Nov 15, 2021
0ad2715
styles disabled label styles, adds stories, jsdocs props, cleanups
mperrotti Nov 16, 2021
f8668ce
Merge branch 'main' of github.com:primer/react into mp/form-field-com…
mperrotti Nov 16, 2021
e0addd0
adds missing jsdoc comment
mperrotti Nov 16, 2021
0d3ae10
adds components to render groups of radios or checkboxes
mperrotti Nov 17, 2021
a67c80f
supports LeadingVisual for checkbox and radio inputs
mperrotti Nov 17, 2021
fe9696a
animate in field validation message
mperrotti Nov 17, 2021
dd08828
updates validation API
mperrotti Nov 19, 2021
6054f1c
creates text, checkbox, and radio input field components
mperrotti Nov 22, 2021
910ee68
makes InputField validation props smarter
mperrotti Nov 22, 2021
00ecaba
rm ChoiceFieldset from this changeset
mperrotti Nov 22, 2021
115bb4e
Merge branch 'main' of github.com:primer/react into mp/form-field-com…
mperrotti Nov 22, 2021
fc84152
fixes ts errors
mperrotti Nov 22, 2021
f70f8ad
fixes bad imports
mperrotti Nov 22, 2021
793c00d
cleanup
mperrotti Nov 22, 2021
e50bde8
adds VisuallyHidden component
mperrotti Nov 22, 2021
e9bcee9
require label to be passed
mperrotti Nov 23, 2021
4533f20
fixes typo from last commit
mperrotti Nov 23, 2021
ad1c9e8
adds React component docs for TextInputField, RadioInputField, and Ch…
mperrotti Nov 23, 2021
024b5d3
Merge branch 'main' of github.com:primer/react into mp/form-field-com…
mperrotti Nov 23, 2021
006e976
adds tests, fixes check for Label slot
mperrotti Nov 24, 2021
79c2286
warns if id, required, or disabled props are passed directly to the I…
mperrotti Nov 24, 2021
581b4ca
fix issue where the input still had a top margin when the label was h…
mperrotti Nov 24, 2021
54b43a4
marks new internal components as private
mperrotti Nov 24, 2021
7b7c1f8
adds changeset
mperrotti Nov 24, 2021
0a220ad
updates imports
mperrotti Nov 24, 2021
6ea5201
Merge github.com:primer/react into mp/form-field-component
mperrotti Nov 24, 2021
504a9d9
updates stories and docs
mperrotti Nov 24, 2021
d721895
Merge github.com:primer/react into mp/form-field-component
mperrotti Nov 24, 2021
e5a964f
adds React component docs to doc nav, updates docs
mperrotti Nov 24, 2021
15da266
updates CheckboxInputField to use new Checkbox component
mperrotti Nov 24, 2021
cbab1ae
updates snapshots from using checkbox component
mperrotti Nov 24, 2021
9880c53
adds ChoiceFieldset components and stories
mperrotti Nov 24, 2021
ec1312a
Merge branch 'main' into mp/form-field-component
mperrotti Nov 24, 2021
69e99f6
fixes ts error
mperrotti Nov 24, 2021
b092729
Merge github.com:primer/react into mp/form-field-component
mperrotti Nov 30, 2021
6577aa8
Merge branch 'main' into mp/form-field-component
mperrotti Nov 30, 2021
7424440
lightens caption when field is disabled
mperrotti Nov 30, 2021
69334dc
removes unusable export from checkbox and radio input fields
mperrotti Nov 30, 2021
2691adc
Merge branch 'mp/form-field-component' of github.com:primer/react int…
mperrotti Nov 30, 2021
6af2f8c
Merge branch 'mp/form-field-component' of github.com:primer/react int…
mperrotti Nov 30, 2021
3869fff
rename ChoiceField to Item
mperrotti Nov 30, 2021
689ace4
adds a prop to disable the fieldset
mperrotti Nov 30, 2021
f33ff51
exports ChoiceFieldset list item component
mperrotti Nov 30, 2021
14af744
rm ChoiceFieldInput component, improve dev experience for onSelect ha…
mperrotti Dec 1, 2021
2684d58
rm unused imports and exports
mperrotti Dec 1, 2021
06c5f3b
replaced fieldset caption with fieldset description
mperrotti Dec 1, 2021
3c5351a
API improvements and storybook story updates
mperrotti Dec 1, 2021
cfc2e86
adds and updates docs, little fixes and improvments
mperrotti Dec 2, 2021
2f2a998
adds tests
mperrotti Dec 3, 2021
a78625f
adds changeset
mperrotti Dec 3, 2021
d0b19a2
fix lint errors
mperrotti Dec 3, 2021
4b20f1a
Merge branch 'main' of github.com:primer/react into mp/form-field-com…
mperrotti Dec 3, 2021
9c17471
updates docs, adds ChoiceFieldset to docs sidebar
mperrotti Dec 3, 2021
b137a07
updates Checkbox docs to point to CheckboxInputField
mperrotti Dec 3, 2021
72e886d
adds ComponentChecklst to component docs
mperrotti Dec 3, 2021
3c18363
Merge branch 'main' of github.com:primer/react into mp/form-field-com…
mperrotti Dec 6, 2021
4e06ca7
uses new Radio component to render the input
mperrotti Dec 6, 2021
3c312f9
Merge branch 'mp/form-field-component' of github.com:primer/react int…
mperrotti Dec 6, 2021
a0465ee
ensures name prop cannot be undefined when passed to input
mperrotti Dec 6, 2021
18767e1
wraps snapshot renders in SSRProvider
mperrotti Dec 6, 2021
8ef90f2
addresses PR feedback
mperrotti Dec 7, 2021
55aa8e3
rm unused imports
mperrotti Dec 8, 2021
ee2f9bf
Merge branch 'main' of github.com:primer/react into mp/choice-group
mperrotti Dec 8, 2021
a179e92
Merge branch 'main' into mp/form-field-component
mperrotti Dec 8, 2021
ea439d3
wraps snapshot tests in SSRProvider
mperrotti Dec 8, 2021
1aa9277
fixes typo
mperrotti Dec 8, 2021
c33fe78
Merge branch 'mp/form-field-component' of github.com:primer/react int…
mperrotti Dec 8, 2021
73285ba
Merge branch 'main' of github.com:primer/react into mp/form-field-com…
mperrotti Dec 13, 2021
98a67e8
Merge branch 'mp/form-field-component' of github.com:primer/react int…
mperrotti Dec 13, 2021
b6781f4
fixes bad import
mperrotti Dec 13, 2021
8699756
Merge branch 'main' of github.com:primer/react into mp/choice-group
mperrotti Dec 13, 2021
ef2ae4f
Merge branch 'mp/form-field-component' of github.com:primer/react int…
mperrotti Dec 13, 2021
ff79a52
uses new package name
mperrotti Dec 13, 2021
90f40e0
Merge branch 'mp/form-field-component' of github.com:primer/react int…
mperrotti Dec 13, 2021
bfe3b65
uses new package name
mperrotti Dec 13, 2021
f4ff5c8
replaces CheckboxInputField and RadioInputField with 1 component - Ch…
mperrotti Dec 13, 2021
58efa2b
replaces TextInputField component with InputField component
mperrotti Dec 13, 2021
c6c2062
updates documentation formatting
mperrotti Dec 13, 2021
e3f7a6e
Merge branch 'main' of github.com:primer/react into mp/form-field-com…
mperrotti Dec 13, 2021
95dacc4
Merge branch 'mp/form-field-component' of github.com:primer/react int…
mperrotti Dec 13, 2021
3421225
uses ChoiceInputField instead of checkbox and radio field components
mperrotti Dec 14, 2021
1974d98
updates documentation formatting
mperrotti Dec 14, 2021
e283cbe
more docs updates
mperrotti Dec 14, 2021
fc0b75f
merges from InputField branch, updates more docs
mperrotti Dec 14, 2021
c4c6ac3
fixes copy/paste mistake in docs
mperrotti Dec 14, 2021
05f96dd
Merge branch 'main' into mp/form-field-component
mperrotti Dec 14, 2021
c1c4808
Update docs/content/Checkbox.md
mperrotti Dec 15, 2021
ce49a84
addresses PR feedback + misc cleanup
mperrotti Dec 15, 2021
6a7bb75
Merge branch 'main' of github.com:primer/react into mp/form-field-com…
mperrotti Dec 16, 2021
2a77582
Merge branch 'mp/form-field-component' of github.com:primer/react int…
mperrotti Dec 16, 2021
12d8047
TESTING DEPLOYMENT - revert InputField.mdx to last successful build
mperrotti Dec 16, 2021
fd269bf
Merge branch 'main' into mp/form-field-component
mperrotti Dec 16, 2021
73ad10c
attempting to get InputField docs to build
mperrotti Dec 16, 2021
5c56710
attempting to get InputField docs to build
mperrotti Dec 16, 2021
b42dc39
attempting to get InputField docs to build
mperrotti Dec 16, 2021
03156ef
probably fixed deployment
mperrotti Dec 16, 2021
7e1cc93
Merge branch 'mp/form-field-component' of github.com:primer/react int…
mperrotti Dec 16, 2021
00f5ff2
Merge branch 'main' into mp/form-field-component
mperrotti Dec 16, 2021
50a7f81
Merge branch 'main' of github.com:primer/react into mp/form-field-com…
mperrotti Dec 17, 2021
398e541
Merge branch 'mp/form-field-component' of github.com:primer/react int…
mperrotti Dec 17, 2021
d6d3f03
Update docs/content/ChoiceInputField.mdx
mperrotti Dec 17, 2021
c17ec66
addresses more PR feedback
mperrotti Dec 17, 2021
a450bb8
Merge branch 'mp/form-field-component' of github.com:primer/react int…
mperrotti Dec 17, 2021
7e6da8a
Merge branch 'main' of github.com:primer/react into mp/form-field-com…
mperrotti Dec 17, 2021
4d04066
try adding componentchecklist import to fix deployment failure
mperrotti Dec 17, 2021
15bf95c
adds comopnentId to docs frontmatter
mperrotti Dec 17, 2021
d18effc
Merge branch 'mp/form-field-component' of github.com:primer/react int…
mperrotti Dec 17, 2021
709d5a9
Merge branch 'main' of github.com:primer/react into mp/form-field-com…
mperrotti Dec 17, 2021
ad9e954
Merge branch 'main' into mp/form-field-component
mperrotti Dec 17, 2021
2c4f769
Merge branch 'mp/form-field-component' of github.com:primer/react int…
mperrotti Dec 17, 2021
78c12fe
Merge branch 'main' of github.com:primer/react into mp/choice-group
mperrotti Dec 17, 2021
ea2f769
Merge branch 'main' of github.com:primer/react into mp/choice-group
mperrotti Jan 10, 2022
ce577f2
Merge branch 'main' into mp/choice-group
mperrotti Jan 10, 2022
fdb2147
Merge branch 'main' into mp/choice-group
mperrotti Jan 11, 2022
8dbcfed
docs fixes
mperrotti Jan 11, 2022
da725b8
Merge branch 'mp/choice-group' of github.com:primer/react into mp/cho…
mperrotti Jan 11, 2022
42d1bce
Merge branch 'main' into mp/choice-group
mperrotti Jan 11, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/twenty-needles-sit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': minor
---

Adds ChoiceFieldset component
402 changes: 402 additions & 0 deletions docs/content/ChoiceFieldset.mdx

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions docs/content/ChoiceInputField.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,9 @@ If the selectable option would be easier to understand with a visual, the `Choic
hasFigmaComponent: false
}}
/>

## Related components

- [ChoiceFieldset](/ChoiceFieldset)
- [Checkbox](/Checkbox)
- [Radio](/Radio)
2 changes: 2 additions & 0 deletions docs/content/Radio.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Please use a [Checkbox](/Checkbox) if the user needs to select more than one opt

Use the `name` prop to group together related `Radio` components in a list.

If you're not building something custom, you should use the [ChoiceFieldset](/ChoiceFieldset) component to render a group of radio inputs.

```jsx live
<form>
<Box sx={{p: 1, display: 'flex', alignItems: 'center'}}>
Expand Down
2 changes: 2 additions & 0 deletions docs/src/@primer/gatsby-theme-doctocat/nav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
url: /Buttons
- title: Checkbox
url: /Checkbox
- title: ChoiceFieldset
url: /ChoiceFieldset
- title: ChoiceInputField
url: /ChoiceInputField
- title: CircleBadge
Expand Down
19 changes: 13 additions & 6 deletions src/Autocomplete/AutocompleteMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import React, {useContext, useEffect, useMemo, useRef, useState} from 'react'
import {scrollIntoView} from '@primer/behaviors'
import type {ScrollIntoViewOptions} from '@primer/behaviors'
import {ActionList, ItemProps} from '../ActionList'
import {useFocusZone} from '../hooks/useFocusZone'
import {ComponentProps, MandateProps} from '../utils/types'
import {Box, Spinner} from '../'
import {Box, Spinner, useSSRSafeId} from '../'
import {AutocompleteContext} from './AutocompleteContext'
import {PlusIcon} from '@primer/octicons-react'
import VisuallyHidden from '../_VisuallyHidden'
import {uniqueId} from '@primer/behaviors/utils'
import {scrollIntoView} from '@primer/behaviors'
import type {ScrollIntoViewOptions} from '@primer/behaviors'

type OnSelectedChange<T> = (item: T | T[]) => void
type AutocompleteMenuItem = MandateProps<ItemProps, 'id'>
Expand Down Expand Up @@ -146,6 +145,7 @@ function AutocompleteMenu<T extends AutocompleteItemProps>(props: AutocompleteMe
const listContainerRef = useRef<HTMLDivElement>(null)
const [highlightedItem, setHighlightedItem] = useState<T>()
const [sortedItemIds, setSortedItemIds] = useState<Array<number | string>>(items.map(({id: itemId}) => itemId))
const generatedUniqueId = useSSRSafeId(id)

const selectableItems = useMemo(
() =>
Expand Down Expand Up @@ -219,7 +219,7 @@ function AutocompleteMenu<T extends AutocompleteItemProps>(props: AutocompleteMe
leadingVisual: () => <PlusIcon />,
onAction: (item: T) => {
// TODO: make it possible to pass a leadingVisual when using `addNewItem`
addNewItem.handleAddItem({...item, id: item.id || uniqueId(), leadingVisual: undefined})
addNewItem.handleAddItem({...item, id: item.id || generatedUniqueId, leadingVisual: undefined})

if (selectionVariant === 'multiple') {
setInputValue('')
Expand All @@ -230,7 +230,14 @@ function AutocompleteMenu<T extends AutocompleteItemProps>(props: AutocompleteMe
]
: [])
],
[sortedAndFilteredItemsToRender, addNewItem, setAutocompleteSuggestion, selectionVariant, setInputValue]
[
sortedAndFilteredItemsToRender,
addNewItem,
setAutocompleteSuggestion,
selectionVariant,
setInputValue,
generatedUniqueId
]
)

useFocusZone(
Expand Down
6 changes: 6 additions & 0 deletions src/ChoiceFieldset/ChoiceFieldCaption.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from 'react'
import {ChoiceInputField} from '..'

const ChoiceFieldCaption: React.FC = ({children}) => <ChoiceInputField.Caption>{children}</ChoiceInputField.Caption>

export default ChoiceFieldCaption
6 changes: 6 additions & 0 deletions src/ChoiceFieldset/ChoiceFieldLabel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from 'react'
import {ChoiceInputField} from '..'

const ChoiceFieldLabel: React.FC = ({children}) => <ChoiceInputField.Label>{children}</ChoiceInputField.Label>

export default ChoiceFieldLabel
137 changes: 137 additions & 0 deletions src/ChoiceFieldset/ChoiceFieldset.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import React, {ComponentProps} from 'react'
import {Box, useSSRSafeId} from '..'
import createSlots from '../utils/create-slots'
import {FormValidationStatus} from '../utils/types/FormValidationStatus'
import ValidationAnimationContainer from '../_ValidationAnimationContainer'
import InputValidation from '../_InputValidation'
import ChoiceFieldsetListItem from './ChoiceFieldsetListItem'
import ChoiceFieldsetDescription from './ChoiceFieldsetDescription'
import ChoiceFieldsetLegend from './ChoiceFieldsetLegend'
import ChoiceFieldsetList from './ChoiceFieldsetList'
import ChoiceFieldsetValidation from './ChoiceFieldsetValidation'

export interface ChoiceFieldsetProps<T = Record<string, FormValidationStatus>> {
children?: React.ReactNode
/**
* Whether the fieldset is NOT ready for user input
*/
disabled?: boolean
/**
* The unique identifier for this fieldset. Used to associate the validation text with the fieldset
* If an ID is not passed, one will be automatically generated
*/
id?: string
/**
* The unique identifier used to associate radio inputs with eachother
* If a name is not passed and the fieldset renders radio inputs, a name will be automatically generated
*/
name?: string
/**
* The callback that is called when a user toggles a choice on or off
*/
onSelect?: (selectedValues: string[]) => void
/**
* Whether this field must have a value for the user to complete their task
*/
required?: boolean
/**
* The selected values
*/
selected?: string[]
/**
* 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
*/
validationMap?: T
/**
* The key of the validation message to show
*/
validationResult?: keyof T
}

export interface ChoiceFieldsetContext extends ChoiceFieldsetProps {
validationMessageId: string
}

const {Slots, Slot} = createSlots(['Description', 'ChoiceList', 'Legend', 'Validation'])
export {Slot}

const ChoiceFieldset = <T extends Record<string, FormValidationStatus>>({
children,
disabled,
id,
name,
onSelect,
required,
selected,
validationMap,
validationResult
}: ChoiceFieldsetProps<T>) => {
const fieldsetId = useSSRSafeId(id)
const validationChildren: React.ReactElement[] | undefined | null = React.Children.map(children, child =>
React.isValidElement(child) && child.type === ChoiceFieldsetValidation ? child : null
)?.filter(Boolean)
const validationChildToRender = validationChildren?.find(child => child.props.validationKey === validationResult)
const validationMessageId = validationChildToRender ? `${fieldsetId}-validationMsg` : undefined

return (
<Slots
context={{
disabled,
name,
onSelect,
required,
selected,
validationMessageId
}}
>
{slots => {
const isLegendVisible = React.isValidElement(slots.Legend) && slots.Legend.props.isVisible

return (
<div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switch to fragment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I intentionally wrapped this in a div so that everything is grouped in 1 DOM node. This way, if this is in a flex or grid container, the whole component would turn into a flex item or grid cell.

<Box
as="fieldset"
border="none"
margin={0}
padding={0}
aria-describedby={[validationMessageId].filter(Boolean).join(' ')}
>
{React.Children.toArray(children).filter(
child => React.isValidElement(child) && child.type !== ChoiceFieldsetValidation
)}
<Box mb={isLegendVisible ? 3 : undefined}>
{slots.Legend}
{slots.Description}
</Box>
{slots.ChoiceList}
</Box>
{validationChildToRender && (
<Box mt={3}>
{validationMap && validationResult && validationMessageId && (
<ValidationAnimationContainer show>
<InputValidation validationStatus={validationMap[validationResult]} id={validationMessageId}>
{validationChildToRender}
</InputValidation>
</ValidationAnimationContainer>
)}
</Box>
)}
</div>
)
}}
</Slots>
)
}

export type InputFieldComponentProps = ComponentProps<typeof ChoiceFieldset>
export type {ChoiceFieldsetListProps} from './ChoiceFieldsetList'
export type {ChoiceFieldsetLegendProps} from './ChoiceFieldsetLegend'
export type {ChoiceFieldProps} from './ChoiceFieldsetListItem'
export default Object.assign(ChoiceFieldset, {
Description: ChoiceFieldsetDescription,
Item: ChoiceFieldsetListItem,
Legend: ChoiceFieldsetLegend,
List: ChoiceFieldsetList,
Validation: ChoiceFieldsetValidation
})
15 changes: 15 additions & 0 deletions src/ChoiceFieldset/ChoiceFieldsetDescription.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react'
import {Text} from '..'
import {ChoiceFieldsetContext, Slot} from './ChoiceFieldset'

const ChoiceFieldsetDescription: React.FC = ({children}) => (
<Slot name="Description">
{({disabled}: ChoiceFieldsetContext) => (
<Text color={disabled ? 'fg.muted' : 'fg.default'} fontSize={1}>
{children}
</Text>
)}
</Slot>
)

export default ChoiceFieldsetDescription
39 changes: 39 additions & 0 deletions src/ChoiceFieldset/ChoiceFieldsetLegend.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react'
import {Box} from '..'
import VisuallyHidden from '../_VisuallyHidden'
import {ChoiceFieldsetContext, Slot} from './ChoiceFieldset'

export interface ChoiceFieldsetLegendProps {
/**
* Whether to visually hide the fieldset legend
*/
visuallyHidden?: boolean
}

const ChoiceFieldsetLegend: React.FC<ChoiceFieldsetLegendProps> = ({children, visuallyHidden}) => (
<Slot name="Legend">
{({required, disabled}: ChoiceFieldsetContext) => (
<VisuallyHidden
as="legend"
isVisible={!visuallyHidden}
title={required ? 'required field' : undefined}
sx={{
color: disabled ? 'fg.muted' : undefined,
fontSize: 2,
padding: 0
}}
>
{required ? (
<Box display="flex" as="span">
<Box mr={1}>{children}</Box>
<span>*</span>
</Box>
) : (
children
)}
</VisuallyHidden>
)}
</Slot>
)

export default ChoiceFieldsetLegend
80 changes: 80 additions & 0 deletions src/ChoiceFieldset/ChoiceFieldsetList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React from 'react'
import styled from 'styled-components'
import {useSSRSafeId} from '..'
import {get} from '../constants'
import {Slot, ChoiceFieldsetContext} from './ChoiceFieldset'
import ChoiceFieldsetListContext from './ChoiceFieldsetListContext'

export interface ChoiceFieldsetListProps {
/**
* Whether multiple items or a single item can be selected
*/
selectionVariant?: 'single' | 'multiple'
}

const List = styled.ul`
display: flex;
flex-direction: column;
list-style: none;
margin: 0;
padding: 0;

> li + li {
margin-top: ${get('space.2')};
}
`

const getSelectedCheckboxes = (
value: string,
checked: boolean,
selectedValues: string[],
selectionVariant?: ChoiceFieldsetListProps['selectionVariant']
): string[] => {
if (checked) {
return selectionVariant === 'multiple' ? [...selectedValues, value] : [value]
}

return selectedValues.filter(selectedValue => selectedValue !== value)
}

const ChoiceFieldsetList: React.FC<ChoiceFieldsetListProps> = ({selectionVariant, children}) => {
const ssrSafeUniqueName = useSSRSafeId()

return (
<Slot name="ChoiceList">
{({name, onSelect, disabled, selected = []}: ChoiceFieldsetContext) => {
return (
<ChoiceFieldsetListContext.Provider
value={{
disabled,
selected,
name: name || ssrSafeUniqueName,
onChange: e => {
const updatedSelections = getSelectedCheckboxes(
e.currentTarget.value,
e.currentTarget.checked,
selected,
selectionVariant
)
onSelect && onSelect(updatedSelections)
},
selectionVariant
}}
>
<List>
{React.Children.map(children, (child, i) => (
<li key={i}>{child}</li>
))}
</List>
</ChoiceFieldsetListContext.Provider>
)
}}
</Slot>
)
}

ChoiceFieldsetList.defaultProps = {
selectionVariant: 'single'
}

export default ChoiceFieldsetList
11 changes: 11 additions & 0 deletions src/ChoiceFieldset/ChoiceFieldsetListContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {ChangeEventHandler, createContext} from 'react'

const ChoiceFieldsetListContext = createContext<{
disabled?: boolean
name: string
onChange: ChangeEventHandler<HTMLInputElement>
selected?: string[]
selectionVariant?: 'single' | 'multiple'
} | null>(null)

export default ChoiceFieldsetListContext
Loading