SelectableCard
SelectableCard is an interactive variation of Card used for a very limited set of use cases within onboarding flows
![A pointing to the card; B pointing to the title, subtitle, illustration, and tags; C pointing to the description; D pointing to the visible input](/static/a4b1565f9b5a62396def873962abd35b/7f7c4/anatomy.png)
Item | Name | Description |
---|---|---|
A | Container | The <Card /> containing the elements of <SelectableCard /> |
B | <CardHeader /> | The main container for the title, subtitle, illustration, and Tag(s) of <SelectableCard /> |
C | <CardBody /> | The main content area of <SelectableCard /> |
D | <Radio /> <Checkbox /> | The visual representation of <Radio /> or <Checkbox /> to indicate the state of <SelectableCard /> |
import React from 'react'import { Formik } from 'formik'import * as Yup from 'yup'import { Actions, Grid, Tag } from '@gusto/workbench'import {Form,SelectableCard,SelectableCardGroup,SubmitButton,} from '@gusto/workbench-formik'import { Chart, DollarBill, PlusShield } from '@gusto/workbench-illos'export const MultiSelectGroup = () => {return (<FormikinitialValues={{connectApps: [],}}validationSchema={Yup.object().shape({connectApps: Yup.array().min(1, 'At least one add-on is required'),})}onSubmit={values => alert(JSON.stringify(values))}><Form><SelectableCardGroupname="connectApps"legend="Connect apps you love to Gusto"><GridrowGap={6}columnGap={4}maxWidth={660}maxWidthMd="100%"templateColumnsMd="repeat(3, 1fr)"marginBlockEnd={3}>{/* 👇 Remember to add a `value` for Formik to distinguish each input in group */}<SelectableCardtype="checkbox"value="wuckertLLC"illustration={<DollarBill />}title="Wuckert, LLC"body={<div>Wuckert, LLC provides a top of the line payroll platformcombining all the best features.</div>}/>{/* 👇 Remember to add a `value` for Formik to distinguish each input in group */}<SelectableCardtype="checkbox"value="pfannerstillGroup"illustration={<PlusShield />}title="Pfannerstill Group, Inc."body={<div>Pfannerstill Group, Inc. offers a wide range of benefitsincluding 401(k), HSA, and college savings.</div>}tags={<Tag variant="filled" severity="success">New</Tag>}/>{/* 👇 Remember to add a `value` for Formik to distinguish each input in group */}<SelectableCardtype="checkbox"value="prioritySupport"illustration={<Chart />}title="Oberbrunner Accountants, Inc."body={<div>Oberbrunner Accountants, Inc. has integrations for all yourreporting needs. Let Oberbrunner do the accounting for you andspend more time on your business.</div>}/></Grid></SelectableCardGroup><Actions justifyContent="center"><SubmitButton>Submit</SubmitButton></Actions></Form></Formik>)}
import React from 'react'import { Formik } from 'formik'import * as Yup from 'yup'import { Actions, Grid } from '@gusto/workbench'import {Form,SelectableCard,SelectableCardGroup,SubmitButton,} from '@gusto/workbench-formik'import { AddEmployee, Spreadsheet } from '@gusto/workbench-illos'export const SingleSelectGroup = () => {return (<FormikinitialValues={{addEmployees: [],}}validationSchema={Yup.object().shape({addEmployees: Yup.string().required('A selection is required'),})}onSubmit={values => alert(JSON.stringify(values))}><Form><SelectableCardGroupname="addEmployees"legend="How would you like to add your W-2 employees?"><GridrowGap={6}columnGap={4}maxWidth={660}maxWidthMd="100%"templateColumnsMd="repeat(2, 1fr)"marginBlockEnd={3}>{/* 👇 Remember to add a `value` for Formik to distinguish each input in group */}<SelectableCardvalue="oneAtATime"type="radio"illustration={<AddEmployee />}title="One employee at a time"body="Use our form to create each employee’s profile one at a time."/>{/* 👇 Remember to add a `value` for Formik to distinguish each input in group */}<SelectableCardvalue="multipleAtATime"type="radio"illustration={<Spreadsheet />}title="Multiple employees at the same time"body="Use our spreadsheet to add all your employee profiles in one go."/></Grid></SelectableCardGroup><Actions justifyContent="center"><SubmitButton>Submit</SubmitButton></Actions></Form></Formik>)}
Name | Type | Default | Description |
---|---|---|---|
aria-label | string | - | Adds aria-label for the native input |
aria-labelledby | string | - | Adds aria-labelledby for the native input |
body | ReactNode | - | The additional content of the Card; renders SelectableCardBody |
children Required | ReactNode | - | The sub components of the Card; Use this or title |
className | ReactNode | - | Override classes applied to the native input |
illustration | ReactNode | - | Illustration for Card; This should be a small illustration, which is 56 x 56 |
subtitle | ReactNode | - | The subtitle of the Card; renders SelectableCardSubtitle |
tags | ReactNode | - | Tags indicating status information about the Card |
title Required | ReactNode | - | The title of the Card and the accessible name for the native input; renders SelectableCardHeader and SelectableCardTitle ; Use this or children |
type Required | checkbox radio | checkbox | Adds type for the native input |
Name | Type | Default | Description |
---|---|---|---|
children Required | ReactNode | - | The body content of the Card |
Name | Type | Default | Description |
---|---|---|---|
children Required | ReactNode | - | The Card components of the group |
helperText | ReactNode | - | Additional descriptive information below the label |
invalid | boolean | - | Indicates that the input is invalid |
legend Required | string | - | Label text associated with the group. |
name | string | - | Name of the group and will be submitted with the form as part of a name/value pair. This name will be inherited by each Card in the group |
optional | boolean | - | Used to indicate the field is optional |
validationText | ReactNode | - | Validation message associated with the input |
Name | Type | Default | Description |
---|---|---|---|
children Required | ReactNode | - | The sub components of the CardHeader |
illustration | ReactNode | - | Illustration for Card; This should be a small illustration, which is 56 x 56 |
tags | ReactNode | - | Tags indicating status information about the Card |
Name | Type | Default | Description |
---|---|---|---|
children Required | ReactNode | - | The subtitle of the Card |
Name | Type | Default | Description |
---|---|---|---|
children Required | ReactNode | - | The main title of the Card |
- When using
title
, it will be the accessible name of the Card whilebody
,tags
, andillustration
will be its description - When using
children
, all content within the Card will be its accessible name - Only use
aria-label
oraria-labelledby
when the accessible name needs to be different from the default behavior - Do not add interactive elements into a SelectableCard
The following testing snippet(s) offer suggestions for testing the component using React Testing Library with occasional help from Jest.
import React from 'react';import { render, screen } from '@testing-library/react';import { SelectableCard } from '@gusto/workbench';import userEvent from '@testing-library/user-event';it('tests for basic render and functionality', () => {render(<SelectableCardtags={<Tag>Referred</Tag>}title="Candidate"subtitle="Jan 15"body="Send an offer letter to someone you are interested in hiring"type="checkbox"/>);const candidateInput = screen.getByRole('checkbox', { name: 'Candidate'});expect(candidateInput).toBeInTheDocument();expect(candidateInput).toHaveAccessibleDescription('Referred Jan 15 Send an offer letter to someone you are interested in hiring',)expect(candidateInput).not.toBeChecked();userEvent.click(candidateInput);expect(candidateInput).toBeChecked();});