Skip to content

SelectableCard

SelectableCard is an interactive variation of Card used for a very limited set of use cases within onboarding flows
Figma logo
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
SelectableCard and its sub-components
Explaining the pieces that make up a SelectableCard
ItemNameDescription
AContainerThe <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 />
Connect apps you love to Gusto

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 (
<Formik
initialValues={{
connectApps: [],
}}
validationSchema={Yup.object().shape({
connectApps: Yup.array().min(1, 'At least one add-on is required'),
})}
onSubmit={values => alert(JSON.stringify(values))}
>
<Form>
<SelectableCardGroup
name="connectApps"
legend="Connect apps you love to Gusto"
>
<Grid
rowGap={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 */}
<SelectableCard
type="checkbox"
value="wuckertLLC"
illustration={<DollarBill />}
title="Wuckert, LLC"
body={
<div>
Wuckert, LLC provides a top of the line payroll platform
combining all the best features.
</div>
}
/>
{/* 👇 Remember to add a `value` for Formik to distinguish each input in group */}
<SelectableCard
type="checkbox"
value="pfannerstillGroup"
illustration={<PlusShield />}
title="Pfannerstill Group, Inc."
body={
<div>
Pfannerstill Group, Inc. offers a wide range of benefits
including 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 */}
<SelectableCard
type="checkbox"
value="prioritySupport"
illustration={<Chart />}
title="Oberbrunner Accountants, Inc."
body={
<div>
Oberbrunner Accountants, Inc. has integrations for all your
reporting needs. Let Oberbrunner do the accounting for you and
spend more time on your business.
</div>
}
/>
</Grid>
</SelectableCardGroup>
<Actions justifyContent="center">
<SubmitButton>Submit</SubmitButton>
</Actions>
</Form>
</Formik>
)
}
How would you like to add your W-2 employees?

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 (
<Formik
initialValues={{
addEmployees: [],
}}
validationSchema={Yup.object().shape({
addEmployees: Yup.string().required('A selection is required'),
})}
onSubmit={values => alert(JSON.stringify(values))}
>
<Form>
<SelectableCardGroup
name="addEmployees"
legend="How would you like to add your W-2 employees?"
>
<Grid
rowGap={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 */}
<SelectableCard
value="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 */}
<SelectableCard
value="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>
)
}
React props
NameTypeDefaultDescription
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
checkboxradio
checkboxAdds type for the native input
React props
NameTypeDefaultDescription
children  Required
ReactNode
-The body content of the Card
React props
NameTypeDefaultDescription
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
React props
NameTypeDefaultDescription
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
React props
NameTypeDefaultDescription
children  Required
ReactNode
-The subtitle of the Card
React props
NameTypeDefaultDescription
children  Required
ReactNode
-The main title of the Card
  • When using title, it will be the accessible name of the Card while body, tags, and illustration will be its description
  • When using children, all content within the Card will be its accessible name
  • Only use aria-label or aria-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 LibraryExternal link with occasional help from JestExternal link.

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(
<SelectableCard
tags={<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();
});