import { Callout } from "@vitality-ds/components";
Use Callouts to "call out" important messages and notices in a way that attracts the user's attention without interrupting their task.
- When the system requires immediate action by the user.
- When the system needs to communicate actionable information from outside the current context.
<Callout title="Please confirm incorrect amount." severity="warning" description="The invoice total cannot be less than amount already paid ($1,222). Please review the current amounts in this invoice and decide if you wish to confirm this amount or revert to previous amount." actions={{ primary: { label: "Confirm", onClick: () => setIsShown(false), }, secondary: { label: "Revert to Previous", }, }} />
Callouts and notifications serve an essential function in product usability. “Visibility of system status” is number one on the list of the “10 Usability Heuristics for User Interface Design” from the Nielsen Norman Group. The rule states that “the system should always keep users informed about what is going on, through appropriate feedback within a reasonable time.”
Use Vitality's severity color scale to communicate more meaning to the user. This can be set in code via the severity
prop.
Although you should consider the best option for title and icon, each severity type provides a default icon and title.
() => { const description = "The invoice total cannot be less than amount already paid ($1,222). Please review the current amounts in this invoice."; return ( <div style={{ width: "100%" }}> <Stack> <Callout description={description} /> <Callout severity="critical" description={description} /> <Callout severity="success" description={description} /> <Callout severity="warning" description={description} /> <Callout severity="info" description={description} /> </Stack> </div> ); };
In order to support users whose vision may be impaired, it’s a good idea to always complement callout messages with an icon. Each severity variant comes with a default icon:
() => { const description = "The invoice total cannot be less than amount already paid ($1,222). Please review the current amounts in this invoice."; return ( <div style={{ width: "100%" }}> <Stack> <Callout description={description} /> <Callout severity="critical" description={description} /> <Callout severity="success" description={description} /> <Callout severity="warning" description={description} /> <Callout severity="info" description={description} /> </Stack> </div> ); };
Although default icons are provided for each severity type, if a different icon would provide better meaning to the user, you can override it.
<Callout title="ePrescribing not available" description="Due to incorrect credentials, ePrescribing cannot currently be used." severity="warning" icon={Medications} />
The default size of a Callout
is designed to draw the user's attention to it – in order to assist in "calling out" the important information.
For instances where a Callout
is required but needs to take up less visual space, you can add size="compact"
.
<DocsBox css={{ backgroundColor: "$grey1", padding: "$lg" }}> <Stack direction="horizontal" align="center"> <Typography variant="sectionSubtitle">QTE005</Typography> <Callout size="compact" description="Quote voided: Patient no longer needs procedure." severity="warning" /> </Stack> </DocsBox>
A screen reader will read aloud the entire contents of the Callout as one sentence. Since both the title and description will be read as one string, make sure that it makes sense when read aloud together.
All Callout
s require a description. Use the description to provide users with a clear understanding of the reason for the callout appearing. This can be done via the description
prop.
<Callout severity="warning" description="If your bank account details are stored with Medicare your payment will be made by EFT. If not, your Medicare benefit will not be paid. Once you have provided Medicare with your bank account details, your payment will be released." />
- Limit description content to one or two short sentences.
- Help the user by providing an explanation of how to resolve the issue – including any troubleshooting actions or next steps.
- Include links within the notification description that redirects the user to support / knowledgebase articles.
- Use constructive, no-blame language.
- Avoid repeating or paraphrasing the title.
- Avoid technical jargon.
Use a title to provide a quick overview of the Callout’s purpose or prompt users for necessary actions. If the description is lengthy, the title can summarize the reason.
Callouts come with default, generic titles for each severity type (see here). Whilst these can support the user to understand the severity of the callout, aim to customise the title to something meaningful, or choose
hideTitle
<Stack> <Callout title="This action cannot be performed." severity="warning" description={ <> Due to certain limitations in your system preferences, this action cannot be performed. <Link>Learn more here</Link>. </> } /> <Callout title="Please acknowledge before proceeding." description="If your bank account details are stored with Medicare your payment will be made by EFT. If not, your Medicare benefit will not be paid. Once you have provided Medicare with your bank account details, your payment will be released." actions={{ primary: { label: "Acknowledge", }, }} /> </Stack>
- Use titles that deliver a clear, short and descriptive message. It should explain the most important piece of information.
- When coupled with additional action buttons, connect the title with the action button text.
- Don't use a period/full-stop unless the title is a full sentence.
- Redundant, repetitive text in both title and description.
For cases where a callout's content may need to provide additional information, a <Link />
component can be used to link out to some other page. See the Link component documentation for more information.
Note that links should be used for navigation, not for performing actions. If the user is to perform an action, use action buttons.
<Callout title="This action cannot be performed." description={ <> Due to certain limitations in your system preferences, this action cannot be performed. <Link>Learn more here</Link>. </> } />
Some callouts may provide the user with an action to take. This should usually relate to the way in which they can rectify the original reason for a callout being presented. For instance, if a setting or parameter needs to be changed in order to proceed, the user could be provided with a link to the appropriate page, or a button that performs the action needed to change that parameter.
- Keep labels concise and clearly indicate the action the user can take.
- Limit action button labels to one or two words.
<Callout severity="success" title="Your changes have been saved" description="Although you've navigated away, your changes are automatically saved." actions={{ primary: { label: "Got it", onClick: () => {}, }, secondary: { label: "Learn more", onClick: () => {}, }, }} />
Callouts generally do not need to be dismissed or removed – unless there is a specific action they take which results in the callout no longer being relevant. For cases where a system message is temporary, use the Toast
notification pattern.
If the user can perform an action from within the Callout and that action results in the removal of the Callout, you can handle the visibility state in your own implementation.
() => { const [isShown, setIsShown] = React.useState(true); return ( <Stack justify="stretch"> {isShown && ( <Callout actions={{ primary: { label: "Dismiss", onClick: () => setIsShown(false), }, }} severity="success" title="Electronic Prescription successfully sent." /> )} {!isShown && ( <Button onClick={() => setIsShown(true)}> Bring it back <Restore /> </Button> )} </Stack> ); };
For asynchronous actions performed on a Callout
, simply pass the isLoading
prop to the relevant button.
() => { const [isShown, setIsShown] = React.useState(true); const [isLoading, setIsLoading] = React.useState(false); const timer = () => { setIsLoading(true); setTimeout(() => { setIsLoading(false); setIsShown(!isShown); }, 3000); }; return ( <Stack justify="stretch"> {isShown && ( <Callout title="Please confirm claim" description="A claim has been created for this invoice, but you're required to confirm before sending." actions={{ primary: { label: "Confirm & Send", onClick: timer, isLoading: isLoading, }, }} /> )} {!isShown && ( <Button onClick={() => setIsShown(true)} isLoading={isLoading}> Bring it back <Restore /> </Button> )} </Stack> ); };
Description
Configure primary and secondary action button props
Type
Actions
Description
Descriptive text to describe the callout's purpose
Type
ReactNode
Description
Hide the Callout's title.
Type
boolean
Description
Icon to be displayed next to the title when visible. Each severity variant has a default icon.
Type
ElementType<IconType>
Type
Ref<HTMLDivElement>
Description
The severity used to communicate more meaning to the user
Type
("success" | "info" | "warning" | "critical"
Default Value
info
Type
"default" | "compact"
Default Value
default
Description
Descriptive title to display in the callout
Type
string
Default Value
"Information" "Success" "Warning" "Critical"