Skip to contentSkip to navigationSkip to topbar
Paste assistant Assistant
Figma
Star

Data Export

The Data Export pattern provides a way for the user to extract data from their account.


Ingredients

Ingredients page anchor

Button

// import all ingredients for the Data export pattern

import {​ Button } from "@twilio-paste/core/button";
import { ExportIcon } from "@twilio-paste/icons/esm/ExportIcon";
import { Menu } from "@twilio-paste/core/menu";
import { Tooltip } from "@twilio-paste/core/tooltip";
import { Anchor } from "@twilio-paste/core/anchor";
import { Toast } from "@twilio-paste/core/toast";

General

General page anchor

The Data export pattern enables customers to extract all or selected data from a data table or graph. Data is usually placed into a CSV, PNG, PDF, or JSON file. In general, data exports are generated by the server in Twilio products (particularly CSVs in Voice & Video, SIP trunking, and Messaging).

Exporting should:

  • Be triggered by a Button (or Button as Anchor) or Menu item. The Button or Menu item should clearly state what type of file will be exported. E.g. “Export CSV”.
  • Tell the customer if there are any limitations to the data that can be exported. Use a Tooltip to communicate this information.
Component preview theme
const ExportButton = () => {
const [submitting, setSubmitting] = React.useState(false);
const handleClick = () => {
setSubmitting(true);
setTimeout(() => {
setSubmitting(false);
}, 2000);
};
return (
<Tooltip text="Export first 10,000 message log lines">
<Button variant="secondary" onClick={handleClick} loading={submitting}>
<ExportIcon decorative />
Export CSV
</Button>
</Tooltip>
);
};
render(
<ExportButton />
)

Using the word “Export” and the ExportIcon are predictable signals to customers that they can extract data from Twilio.

Twilio products generally enable customers to convert files to a range of formats before downloading and saving. However if you can’t provide a format conversion, you should still use the word “Export” and the ExportIcon.

The delayed export is an exception to this copy guideline and uses the word “Download” and the DownloadIcon instead.

An immediate export happens when a customer can download their export on the same page where they clicked the export Button or Menu item.

When using a Button, while an export is in progress, show the Button loading state. When it’s in a loading state, it will disable by default.

Component preview theme
const ExportButton = () => {
const [submitting, setSubmitting] = React.useState(false);
const handleClick = () => {
setSubmitting(true);
setTimeout(() => {
setSubmitting(false);
}, 2000);
};
return (
<Tooltip text="Export first 10,000 message log lines">
<Button variant="secondary" onClick={handleClick} loading={submitting}>
<ExportIcon decorative />
Export CSV
</Button>
</Tooltip>
);
};
const ExportMenu = () => {
const menu = useMenuState();
return (
<>
<MenuButton {...menu} variant="secondary">
<ExportIcon decorative />
Export
<ChevronDownIcon decorative />
</MenuButton>
<Menu {...menu} aria-label="Export options">
<MenuItem
{...menu}
onClick={() => {
alert("Data as CSV");
}}
>
Data as CSV
</MenuItem>
<MenuItem
{...menu}
onClick={() => {
alert("Graph as PNG");
}}
>
Graph as PNG
</MenuItem>
</Menu>
</>
);
};
const ExportImmediate = () => {
return (
<Stack orientation="horizontal" spacing="space60">
<ExportButton />
<ExportMenu />
</Stack>
);
};
render(
<ExportImmediate />
)

Most often, selecting the export Button or Menu item should trigger a “save as” dialog in the browser. Customers will be able to track the export’s download status through their browser.

However in cases where you might offer more customization of the data, you can trigger a Modal first. In the Modal, customers can select what columns to export, additional file formats, etc.

Component preview theme
const ExportOptionsModal = ({ isOpen, closeAction }) => {
const seed = useUIDSeed();
const modalHeadingID = seed("modal-heading");
return (
<Modal
ariaLabelledby={modalHeadingID}
isOpen={isOpen}
onDismiss={closeAction}
size="default"
>
<ModalHeader>
<ModalHeading as="h3" id={modalHeadingID}>
Data export options
</ModalHeading>
</ModalHeader>
<ModalBody>
<CheckboxGroup
name="desktop"
legend="Select the columns you would like to export"
>
<Checkbox id={seed("timestamp")} value="timestamp">
Timestamp
</Checkbox>
<Checkbox id={seed("event")} value="event">
Event
</Checkbox>
<Checkbox id={seed("product")} value="product">
Product
</Checkbox>
<Checkbox id={seed("debug_event_sid")} value="debug_event_sid">
Debug event SID
</Checkbox>
<Checkbox id={seed("service_sid")} value="service_sid">
Service SID
</Checkbox>
<Checkbox id={seed("resource_sid")} value="resource_sid">
Resource SID
</Checkbox>
<Checkbox id={seed("message")} value="message">
Message
</Checkbox>
</CheckboxGroup>
</ModalBody>
<ModalFooter>
<ModalFooterActions>
<Button variant="secondary" onClick={closeAction}>
Cancel
</Button>
<Button variant="primary" onClick={closeAction}>
<ExportIcon decorative /> Export
</Button>
</ModalFooterActions>
</ModalFooter>
</Modal>
);
};
const ExportModal = () => {
const [showExportModal, setShowExportModal] = React.useState(false);
const handleOpen = () => setShowExportModal(true);
const handleClose = () => setShowExportModal(false);
return (
<>
<Tooltip text="Export first 10,000 message log lines">
<Button variant="secondary" onClick={handleOpen}>
<ExportIcon decorative />
Export CSV
</Button>
</Tooltip>
<ExportOptionsModal isOpen={showExportModal} closeAction={handleClose} />
</>
);
};
render(
<ExportModal />
)

A delayed export happens when a customer needs to wait for data to be ready. Use the same components as the immediate export pattern, but make sure to:

  1. Confirm the export was initiated by using a Toast component. Inform the customer that they’ll receive an email notification when it’s ready.
Component preview theme
const ExportDelayed = () => {
const toaster = useToaster();
const handleClick = () => {
toaster.push({
message:
"Successfully initiated data export. You will receive an email when your export is ready to download.",
variant: "success"
});
};
return (
<>
<Button variant="secondary" onClick={handleClick}>
<ExportIcon decorative />
Export CSV
</Button>
<Toaster {...toaster} />
</>
);
};
render(
<ExportDelayed />
)
  1. Send an email notification to the customer when the export is ready, with a link to or attachment of the file(s). In this second step, use the word “Download” (example: “Download CSV”) to trigger the actual file download since the customer already clicked an export action to start the export process.
Component preview theme
const ExportDownloadPage = () => (
<>
<Heading as="h2" variant="heading20">
Active Exports
</Heading>
<Table scrollHorizontally>
<THead>
<Tr>
<Th>Status</Th>
<Th>Export name</Th>
<Th>Actions</Th>
</Tr>
</THead>
<TBody>
<Tr>
<Td>
<Box display="flex" alignItems="center">
<Box
width="sizeSquare40"
height="sizeSquare40"
backgroundColor="colorBackgroundSuccess"
borderRadius="borderRadiusCircle"
/>
<Text as="p" marginLeft="space30">
Ready for download
</Text>
</Box>
<Text as="p" color="colorTextWeak" marginLeft="space60">
Tuesday, June 1, 2021
</Text>
</Td>
<Td>
<strong>Contacts who did not click</strong>
</Td>
<Td>
<Button variant="link">
<DownloadIcon decorative />
Download CSV
</Button>
</Td>
</Tr>
<Tr>
<Td>
<Box display="flex" alignItems="center">
<Box
width="sizeSquare40"
height="sizeSquare40"
backgroundColor="colorBackgroundSuccess"
borderRadius="borderRadiusCircle"
/>
<Text as="p" marginLeft="space30">
Ready for download
</Text>
</Box>
<Text as="p" color="colorTextWeak" marginLeft="space60">
Tuesday, February 2, 2021
</Text>
</Td>
<Td>
<strong>All contacts</strong>
</Td>
<Td>
<Button variant="link">
<DownloadIcon decorative />
Download CSV
</Button>
</Td>
</Tr>
</TBody>
</Table>
</>
);
render(
<ExportDownloadPage />
)

Positioning the export action

Positioning the export action page anchor

Place the export Button above and right-aligned to the data it’s exporting, usually a data table or graph.

Component preview theme
const ExportPlacement = () => (
<>
<Heading as="h2" variant="heading20">
90s Music
</Heading>
<Box display="flex" justifyContent="flex-end" marginBottom="space60">
<Tooltip text="Export first 10,000 message log lines">
<Button variant="secondary" onClick={() => {}}>
<ExportIcon decorative />
Export CSV
</Button>
</Tooltip>
</Box>
<Table>
<THead>
<Tr>
<Th>Artist</Th>
<Th>Title</Th>
<Th>Year</Th>
</Tr>
</THead>
<TBody>
<Tr>
<Td>Blackstreet</Td>
<Td>No Diggity</Td>
<Td>1996</Td>
</Tr>
<Tr>
<Td>Oasis</Td>
<Td>Wonderwall</Td>
<Td>1995</Td>
</Tr>
<Tr>
<Td>Daft Punk</Td>
<Td>Around the World</Td>
<Td>1997</Td>
</Tr>
</TBody>
</Table>
</>
);
render(
<ExportPlacement />
)

It can also be placed in a card component that shows the specific data that will be exported, such as a billing invoice.

Component preview theme
const ExportCard = () => (
<Card>
<Heading as="h3" variant="heading30">
August 2021 usage
</Heading>
<Paragraph>Balance: -$10,512.02</Paragraph>
<Button variant="secondary" onClick={() => {}}>
<ExportIcon decorative />
Export PDF
</Button>
</Card>
);
render(
<ExportCard />
)