Props
Usage guidelines
- When displaying high priority, surface-level information to the user.
- When providing persistent, non-blocking feedback.
- When communicating updates to the state or status of the surface.
- When providing messaging/guidance for specific elements or areas within a surface. Let the team know if this is needed.
- When displaying information that is intended for promotional/marketing purposes. Use Upsell instead.
- When interacting with the Callout is required for the user to proceed with a task or flow. Use Modal instead.
Best practices
Use Callout for messages coming from the product or user interaction. Can be used in both Business and Pinner products.
Place Callout at the top of the page, under the primary navigation or page header when possible.
Use Callouts for marketing new products or features. Use Upsell instead.
Stack Callouts. In the case that banners must be stacked, Callouts should come before Upsells.
Accessibility
Labels
iconAccessibilityLabel
, dismissButton
, primaryAction
and secondaryAction
each require a short, descriptive label for screen readers. These labels should communicate the intent of the icon, such as “Error”, “Info” or “Warning”. They should also be localized.
When using primaryAction
or secondaryAction
, alternative text should be provided through the accessibilityLabel
prop to replace vague text like "Visit" or "Learn more" with more descriptive information, like "Learn more about work from home resources". Avoid using the words "button" or "link" in the label, as this becomes repetitive. If the action text is already descriptive, an empty string can be passed.
For the dismissButton
, the label provided should indicate the intent, like “Dismiss this banner”.
import { Callout, Flex, Box } from 'gestalt'; export default function Example() { return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Box paddingY={8} paddingX={8}> <Callout dismissButton={{ accessibilityLabel: 'Dismiss this banner', onDismiss: () => {}, }} iconAccessibilityLabel="Info" message="Apply to the Verified Merchant Program" primaryAction={{ accessibilityLabel: 'Get started: Verified Merchant Program', href: 'https://pinterest.com', label: 'Get started', target: 'blank', }} secondaryAction={{ accessibilityLabel: 'Learn more: Verified Merchant Program', href: 'https://pinterest.com', label: 'Learn more', target: 'blank', }} title="Your business account was created!" type="info" /> </Box> </Flex> ); }
Localization
Remember to localize all link or button labels, as well as title
and message
.
import { Callout, Flex, Box } from 'gestalt'; export default function Example() { return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Box paddingY={8} paddingX={8}> <Callout dismissButton={{ accessibilityLabel: 'Dismiss this banner', onDismiss: () => {}, }} iconAccessibilityLabel="Info" message="Bewerben Sie sich beim Verified Merchant Program" primaryAction={{ accessibilityLabel: 'Loslegen: Verified Merchant Program', href: 'https://pinterest.com', label: 'Loslegen', target: 'blank', }} secondaryAction={{ accessibilityLabel: 'Erfahren Sie mehr: Verified Merchant Program', href: 'https://pinterest.com', label: 'Erfahren Sie mehr', target: 'blank', }} title="Ihr Geschäftskonto wurde erstellt!" type="info" /> </Box> </Flex> ); }
Variants
Info
Info Callouts communicate helpful messages to users about the product. In most cases, they should provide an action for users to take.
import { Callout, Flex, Box } from 'gestalt'; export default function Example() { return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Box paddingY={8} paddingX={8}> <Callout dismissButton={{ accessibilityLabel: 'Dismiss this banner', onDismiss: () => {}, }} iconAccessibilityLabel="Info" message="Apply to the Verified Merchant Program" primaryAction={{ accessibilityLabel: 'Get started: Verified Merchant Program', href: 'https://pinterest.com', label: 'Get started', target: 'blank', }} secondaryAction={{ accessibilityLabel: 'Learn more: Verified Merchant Program', href: 'https://pinterest.com', label: 'Learn more', target: 'blank', }} title="Your business account was created!" type="info" /> </Box> </Flex> ); }
Recommendation
Recommendation Callouts inform people of quick things they can do to improve their experience.
import { Callout, Flex, Box } from 'gestalt'; export default function Example() { return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Box paddingY={8} paddingX={8}> <Callout dismissButton={{ accessibilityLabel: 'Dismiss this banner', onDismiss: () => {}, }} iconAccessibilityLabel="Recommendation" message="When you run ads on Pinterest, you'll find recommendations to improve them here." primaryAction={{ accessibilityLabel: 'Learn more: Ads on Pinterest', href: 'https://pinterest.com', label: 'Learn more', target: 'blank', }} title="Advertise with confidence!" type="recommendation" /> </Box> </Flex> ); }
Success
Success Callouts communicate confirmation regarding an action within a larger flow.
import { Callout, Flex, Box } from 'gestalt'; export default function Example() { return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Box paddingY={8} paddingX={8}> <Callout dismissButton={{ accessibilityLabel: 'Dismiss this banner', onDismiss: () => {}, }} iconAccessibilityLabel="Success" message="Keep it up by using recommendations to optimize your ad spend." primaryAction={{ accessibilityLabel: 'Get started: Ad recommendations', href: 'https://pinterest.com', label: 'Get started', target: 'blank', }} title="Your ads are doing great!" type="success" /> </Box> </Flex> ); }
Warning
Warning Callouts communicate cautionary messages to users. Action shouldn't be required. The Callout should provide clear guidance on how to correct an issue and/or learn more about it.
import { Callout, Flex, Box } from 'gestalt'; export default function Example() { return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Box paddingY={8} paddingX={8}> <Callout dismissButton={{ accessibilityLabel: 'Dismiss warning', onDismiss: () => {}, }} iconAccessibilityLabel="Warning" message="We have noticed that you have audiences in your advertiser account that have been used in an ad campaign. Pinterest will be deleting any unused audiences on May 30, 2020." primaryAction={{ accessibilityLabel: 'View unused audiences', href: 'https://pinterest.com', label: 'View audiences', target: 'blank', }} title="Unused audiences are going away" type="warning" /> </Box> </Flex> ); }
Error
Error Callouts inform users of problems that require immediate action to correct. Further actions on the page might be blocked if users don't correct the problems. The Callout should also provide clear guidance on how to correct the issue and/or learn more about it.
import { Callout, Flex, Box } from 'gestalt'; export default function Example() { return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Box paddingY={8} paddingX={8}> <Callout iconAccessibilityLabel="Error" message="Your tag has errors, so information may be outdated. Fix your tag for the most accurate metrics." primaryAction={{ accessibilityLabel: 'Fix Pinterest tag', href: 'https://pinterest.com', label: 'Fix tag', target: 'blank', }} title="Pinterest tag needs attention" type="error" /> </Box> </Flex> ); }
Actions
Callouts can have either one primary action, or a primary action and a secondary action. These actions can be Links, by specifying the href
property, or Buttons, when no href
is supplied.
Callout actions with link interaction can be paired with OnLinkNavigationProvider. See OnLinkNavigationProvider to learn more about link navigation.
For example, “Learn more” may link to a separate documentation site, while “Apply now” could be a Button that opens a Modal with an application flow. Be sure to localize the labels of the actions.
If needed, actions can become disabled after clicking by setting disabled: true
in the action data.
import { useState } from 'react'; import { Box, Callout, Layer, Modal, Flex, ButtonGroup, Button, Column, Label, Text, TextField, TextArea, } from 'gestalt'; export default function Example() { const [showModal, setShowModal] = useState(false); const toggleModal = () => { setShowModal((currState) => !currState); }; return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Box paddingY={8} paddingX={8}> <Callout dismissButton={{ accessibilityLabel: 'Dismiss banner', onDismiss: () => {}, }} iconAccessibilityLabel="Info" message="Apply to the Verified Merchant Program" primaryAction={{ accessibilityLabel: 'Apply now: verified merchant program', label: 'Apply now', onClick: toggleModal, }} secondaryAction={{ accessibilityLabel: 'Learn more: Verified Merchant Program', href: 'https://help.pinterest.com/en/business/article/verified-merchant-program', label: 'Learn more', target: 'blank', }} title="Your business account was created!" type="info" /> {showModal && ( <Layer> <Modal accessibilityModalLabel="Apply for the Verified Merchant Program" footer={ <Flex flex="grow" justifyContent="end"> <ButtonGroup> <Button onClick={toggleModal} size="lg" text="Cancel" /> <Button color="red" onClick={toggleModal} size="lg" text="Save" /> </ButtonGroup> </Flex> } heading="Verified Merchant Program Application" onDismiss={toggleModal} size="md" > <Flex> <Column span={12}> <Box paddingY={2} paddingX={8} display="flex"> <Column span={4}> <Label htmlFor="name"> <Text align="start" weight="bold"> Name </Text> </Label> </Column> <Column span={8}> <TextField id="name" onChange={() => {}} /> </Column> </Box> <Box paddingY={2} paddingX={8} display="flex"> <Column span={4}> <Label htmlFor="desc"> <Text align="start" weight="bold"> Business Description </Text> </Label> </Column> <Column span={8}> <TextArea id="desc" onChange={() => {}} /> </Column> </Box> </Column> </Flex> </Modal> </Layer> )} </Box> </Flex> ); }
Dismissible
dismissButton
can be used when Callout doesn't indicate a persistent state. This will most commonly be used in type="info"
Callouts.
Don't use dismiss buttons in the following cases:
- There is a persistent account or page status that the user must address.
- The user must access Callout's information again in order to perform a task.
import { Callout, Flex, Box } from 'gestalt'; export default function Example() { return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Box paddingY={8} paddingX={8}> <Callout dismissButton={{ accessibilityLabel: 'Dismiss this banner', onDismiss: () => {}, }} iconAccessibilityLabel="Info" message="Apply to the Verified Merchant Program" primaryAction={{ accessibilityLabel: 'Get started: Verified Merchant Program', href: 'https://pinterest.com', label: 'Get started', target: 'blank', }} secondaryAction={{ accessibilityLabel: 'Learn more: Verified Merchant Program', href: 'https://pinterest.com', label: 'Learn more', target: 'blank', }} title="Your business account was created!" type="info" /> </Box> </Flex> ); }
Component quality checklist
Quality item | Status | Status description |
---|---|---|
Figma Library | Ready | Component is available in Figma across all platforms. |
Responsive Web | Ready | Component is available in code for web and mobile web. |
iOS | Component is not currently available in code for iOS. | |
Android | Component is not currently available in code for Android. |
Related
Upsell
If marketing new products or features, or encouraging upgrades, use Upsell instead.
Toast
Toast provides feedback on a user interaction, like a confirmation that appears when a Pin has been saved. Unlike Upsell and Callout, Toasts don’t contain actions. They’re also less persistent, and disappear after a certain duration.
ActivationCard
ActivationCards are used in groups to communicate a user’s stage in a series of steps toward an overall action.
OnLinkNavigationProvider
OnLinkNavigationProvider allows external link navigation control across all children components with link behavior.