Widget
Widget component
A widget is a quick summary view of data from the product. It gives users quick access to a product area and the most recent content in use there, as well as key actions. Widgets are mainly used on the Home page.
Example:
function WidgetExpample() { const [value, setValue] = useState('allreports'); const options = [ { value: 'allreports', label: 'All reports' }, { value: 'myreports', label: 'My reports' } ]; const Filters = () => { return ( <SegmentedButton items={options} value={value} onChange={(event) => setValue(event.target.value)} /> ); }; const cta = { label: 'New Report', iconName: 'Plus', onClick: () => console.log(''), id: 'widget-secondary-action-data-testid' }; const footerAction = { label: 'Go to reports', onClick: () => console.log('secondary action click'), id: 'widget-secondary-action-data-testid' }; // WIDGET CONTENT const columns = [ { Header: 'Name', accessor: 'name' }, { Header: 'Last modified', accessor: 'lastModified', minWidth: 115, width: 115, align: 'right' } ]; const data = [ { name: 'omatest', lastModified: '01/18/2024' }, { name: 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.', lastModified: '12/19/2023' }, { name: 'Aydin Hinton', lastModified: '12/19/2023' }, { name: 'Raegan Hickman', lastModified: '12/19/2023' }, { name: 'Ashley Page', lastModified: '12/19/2023' } ]; const rowOnClickHandler = (rowData) => { console.log(rowData); }; return ( <Widget title="Reports" cta={cta} secondaryAction={footerAction} filters={<Filters />} data={data} columns={columns} isHoverable rowOnClickHandler={rowOnClickHandler} actionMenu={[ { label: 'Edit', onClick: () => {}, iconName: 'Edit' }, { label: 'Delete', onClick: () => {}, iconName: 'Cross' } ]} /> ); }
Header
The header part accepts a title, primary action button, and filters.
Title:
You can provide title value with the title prop. It accepts a string value.
Cta:
You can provide the call-to-action button using a cta prop. This part uses the Atlas Button component with the primary button kind.
You can use the following props from the Button in cta prop object:
label, id (used for providing the custom data-testid), iconName,
onClick, onMouseEnter, onMouseLeave, onFocus, onBlur, onKeyDown, and disabled
Filters:
You can provide a filter set using the filters prop. This part uses the type of ReactNode that accepts Atlas components like Combobox, SegmentedButton etc.
Content
The content part of the Widget uses Atlas Table with limited features. resizing, header actions, header groups, header menu, nested table, editable, sticky, and dnd features are disabled here.
You can use the data and columns props as its used in Atlas Table.
Action Menu:
The Action Menu adds the menu for all the rows to the table as a last column item. You can use the actionMenu prop to provide the action menu for the table, as in the examples.
EmptyState:
You can provide an EmptyState instead of the table within the "emptyState" prop used in the example.
Secondary Action
You can provide the secondary-call-to-action button to footer part of the Widget using a secondaryAction prop. This part uses the Atlas Button component with the secondary button kind.
Examples:
Apps
function WidgetExpample() { const cta = { label: 'New App', iconName: 'Plus', onClick: () => console.log(''), id: 'widget-secondary-action-data-testid' }; const footerAction = { label: 'Go to Apps', onClick: () => console.log('secondary action click'), id: 'widget-secondary-action-data-testid' }; // WIDGET CONTENT const columns = [ { Header: 'Apps', accessor: 'apps', width: 175, minWidth: 100, Cell: () => ( <div style={{ display: 'flex', alignItems: 'center' }}> <div style={{marginLeft: Spacing10}}><Icon name="PlatformIosFilled" /> <Icon name="PlatformAndroidFilled" /> <Icon name="PlatformWindowsFilled" /></div> </div> ) }, { Header: 'Name', accessor: 'name', width: 165 } ]; const data = [ { name: 'Pettaculars', lastModified: 'Pettaculars' }, { name: 'Get out', lastModified: '12/19/2023' }, { name: 'Bottle up', lastModified: '12/19/2023' }, { name: 'Bee Garden', lastModified: '12/19/2023' }, { name: 'Fly me up', lastModified: '12/19/2023' } ]; const rowOnClickHandler = (rowData) => { console.log(rowData); }; return ( <Container> <Row> <Column xs={12} lg={12}> <Widget title="Apps" cta={cta} secondaryAction={footerAction} data={data} columns={columns} isHoverable rowOnClickHandler={rowOnClickHandler} actionMenu={[ { label: 'Edit', onClick: () => {}, iconName: 'Edit' }, { label: 'Delete', onClick: () => {}, iconName: 'Cross' } ]} /> </Column> </Row> </Container> ); }
Pulse
function WidgetExpample() { const cta = { label: 'New Pulse', iconName: 'Plus', onClick: () => console.log(''), id: 'widget-secondary-action-data-testid' }; const footerAction = { label: 'Go to Pulse', onClick: () => console.log('secondary action click'), id: 'widget-secondary-action-data-testid' }; // WIDGET CONTENT const columns = [ { Header: 'Name', accessor: 'name' }, { Header: 'Type', accessor: 'type', minWidth: 64, width: 64, Cell: ({ value }) => <Badge color="positive" iconName="Key" /> }, { Header: 'Frequency', accessor: 'frequency' } ]; const data = [ { name: 'Pettaculars', lastModified: 'Pettaculars', frequency: 'Weekly - Wednesday, 06:00 UTC' }, { name: 'Get out', lastModified: '12/19/2023', frequency: 'Weekly - Wednesday, 06:00 UTC' }, { name: 'Bottle up', lastModified: '12/19/2023', frequency: 'Weekly - Wednesday, 06:00 UTC' }, { name: 'Bee Garden', lastModified: '12/19/2023', frequency: 'Weekly - Wednesday, 06:00 UTC' }, { name: 'Fly me up', lastModified: '12/19/2023', frequency: 'Weekly - Wednesday, 06:00 UTC' } ]; const rowOnClickHandler = (rowData) => { console.log(rowData); }; return ( <Container> <Row> <Column xs={12} lg={12}> <Widget title="Pulse" cta={cta} secondaryAction={footerAction} data={data} columns={columns} isHoverable rowOnClickHandler={rowOnClickHandler} actionMenu={[ { label: 'Edit', onClick: () => {}, iconName: 'Edit' }, { label: 'Delete', onClick: () => {}, iconName: 'Cross' } ]} /> </Column> </Row> </Container> ); }
Connections
function WidgetExpample() { const cta = { label: 'New Connection', iconName: 'Plus', onClick: () => console.log(''), id: 'widget-secondary-action-data-testid' }; const footerAction = { label: 'Go to connections', onClick: () => console.log('secondary action click'), id: 'widget-secondary-action-data-testid' }; // WIDGET CONTENT const columns = [ { Header: 'Partner', accessor: 'name' }, { Header: 'Status', accessor: 'type', minWidth: 64, width: 64, Cell: ({ value }) => <Badge color="positive" iconName="Check" /> }, { Header: 'Accounts', accessor: 'accounts' } ]; const data = [ { name: 'Facebook', accounts: '3' }, { name: 'Twitter', accounts: '3' }, { name: 'Apple / Apple Ads', accounts: '3' }, { name: 'Google / Google Ads', accounts: '3' }, { name: 'Snapchat', accounts: '3' } ]; const rowOnClickHandler = (rowData) => { console.log(rowData); }; return ( <Widget title="Connections" cta={cta} secondaryAction={footerAction} data={data} columns={columns} isHoverable rowOnClickHandler={rowOnClickHandler} /> ); }
Account users
function WidgetExpample() { const cta = { label: 'New user', iconName: 'Plus', onClick: () => console.log(''), id: 'widget-secondary-action-data-testid' }; const footerAction = { label: 'Go to account users', onClick: () => console.log('secondary action click'), id: 'widget-secondary-action-data-testid' }; // WIDGET CONTENT const columns = [ { Header: 'User', accessor: 'name', maxWidth: 200 }, { Header: 'Role', accessor: 'role', minWidth: 98, width: 98, Cell: ({ value }) => ( <Badge color={value === 'Admin' ? 'negative' : 'primary'} label={value} /> ) } ]; const data = [ { name: 'John Doe', role: 'Admin' }, { name: 'Peter Brown', role: 'Admin' }, { name: 'Raegan Hickman', role: 'Admin' }, { name: 'Mark Spencer', role: 'Admin' }, { name: 'Aydin Hinton', role: 'Editor' } ]; const rowOnClickHandler = (rowData) => { console.log(rowData); }; return ( <Container> <Row> <Column xs={12} lg={12}> <Widget title="Account users" cta={cta} secondaryAction={footerAction} data={data} columns={columns} isHoverable rowOnClickHandler={rowOnClickHandler} actionMenu={[ { label: 'Edit', onClick: () => {}, iconName: 'Edit' }, { label: 'Delete', onClick: () => {}, iconName: 'Cross' } ]} /> </Column> </Row> </Container> ); }
Action center
function WidgetExpample() { const options = [ { value: 'last30days', label: 'Last 30 days' }, { value: 'lastMonth', label: 'Last Month' } ]; const footerAction = { label: 'Go to account users', onClick: () => console.log('secondary action click'), id: 'widget-secondary-action-data-testid' }; // WIDGET CONTENT const columns = [ { Header: 'Action created', accessor: 'date', width: 250 }, { Header: 'Status', accessor: 'status', maxWidth: 170, Cell: ({ value }) => <Badge color="warning" label={value} size="small" /> }, { Header: '', accessor: 'actions', maxWidth: 120, align: 'right', Cell: ({ value }) => ( <> <IconButton iconName="Check" kind="light" aria-label="Approve" /> <IconButton iconName="Cross" kind="light" aria-label="Cancel" css={{ marginLeft: '8px' }} /> </> ) } ]; const data = [ { date: '01/18/2024', status: 'Pending' }, { date: '01/18/2024', status: 'Pending' }, { date: '01/18/2024', status: 'Pending' }, { date: '01/18/2024', status: 'Pending' }, { date: '01/18/2024', status: 'Pending' } ]; const items = [ { label: 'Pending', value: 'pending' }, { label: 'Approved', value: 'approved' } ]; const initialSelectedItems = [ { label: 'Pending', value: 'pending' } ]; const [selectedItems, setSelectedItems] = useState(initialSelectedItems); const rowOnClickHandler = (rowData) => { console.log(rowData); }; return ( <Container> <Row> <Column xs={12} lg={12}> <Widget title="Action center" subTitle="24 pending changes" secondaryAction={footerAction} data={data} columns={columns} isHoverable rowOnClickHandler={rowOnClickHandler} filters={ <div style={{ display: 'flex', flexDirection: 'row' }}> <ComboBox options={options} placeholder="Last 30 days" css={{ marginRight: '16px' }} /> <FilterButton name="Status" items={items} selectedItems={selectedItems} onApply={setSelectedItems} /> </div> } /> </Column> </Row> </Container> ); }
Empty State
function WidgetExpample() { const cta = { label: 'New App', iconName: 'Plus', onClick: () => console.log(''), id: 'widget-secondary-action-data-testid' }; const footerAction = { label: 'Go to Apps', onClick: () => console.log('secondary action click'), id: 'widget-secondary-action-data-testid' }; // WIDGET CONTENT const columns = [ { Header: 'Apps', accessor: 'apps', width: 175 }, { Header: 'Name', accessor: 'name', width: 165 } ]; const data = [ { name: 'Pettaculars', lastModified: 'Pettaculars' }, { name: 'Get out', lastModified: '12/19/2023' }, { name: 'Bottle up', lastModified: '12/19/2023' }, { name: 'Bee Garden', lastModified: '12/19/2023' }, { name: 'Fly me up', lastModified: '12/19/2023' } ]; const emptyStateProps = { headLine: 'No apps yet', bodyText: 'When apps are added, you’ll see them here.', background: 'apps', iconKey: 'noData' }; const emptyStatePropsAdmin = { headLine: 'Add your first app', bodyText: 'Connect a platform, add some events, and integrate the Adjust SDK.', background: 'apps', iconKey: 'noData' }; return ( <Container> <Row> <Column xs={12} lg={6}> <Widget title="Apps" cta={cta} secondaryAction={footerAction} data={[]} columns={[]} emptyState={emptyStatePropsAdmin} /> </Column> <Column xs={12} lg={6}> <Widget title="Apps" secondaryAction={footerAction} emptyState={emptyStateProps} /> </Column> </Row> </Container> ); }
Grid examples
function WidgetExpample() { const options = [ { value: 'last30days', label: 'Last 30 days' }, { value: 'lastMonth', label: 'Last Month' } ]; const footerAction = { label: 'Go to account users', onClick: () => console.log('secondary action click'), id: 'widget-secondary-action-data-testid' }; // WIDGET CONTENT const columns = [ { Header: 'Action created', accessor: 'date' }, { Header: 'Status', accessor: 'status', Cell: ({ value }) => <Badge color="warning" label={value} size="small" /> }, { Header: '', accessor: 'actions', align: 'right', Cell: ({ value }) => ( <> <IconButton iconName="Check" kind="light" aria-label="Approve" /> <IconButton iconName="Cross" kind="light" aria-label="Cancel" /> </> ) } ]; const data = [ { date: '01/18/2024', status: 'Pending' }, { date: '01/18/2024', status: 'Pending' }, { date: '01/18/2024', status: 'Pending' }, { date: '01/18/2024', status: 'Pending' }, { date: '01/18/2024', status: 'Pending' } ]; const items = [ { label: 'Pending', value: 'pending' }, { label: 'Approved', value: 'approved' } ]; const initialSelectedItems = [ { label: 'Pending', value: 'pending' } ]; const [selectedItems, setSelectedItems] = useState(initialSelectedItems); const [value, setValue] = useState('allreports'); const optionsReports = [ { value: 'allreports', label: 'All reports' }, { value: 'myreports', label: 'My reports' } ]; const Filters = () => { return ( <SegmentedButton items={optionsReports} value={value} onChange={(event) => setValue(event.target.value)} /> ); }; const ctaReports = { label: 'New Report', iconName: 'Plus', onClick: () => console.log(''), id: 'widget-secondary-action-data-testid' }; const footerActionReports = { label: 'Go to reports', onClick: () => console.log('secondary action click'), id: 'widget-secondary-action-data-testid' }; const columnsReports = [ { Header: 'Name', accessor: 'name' }, { Header: 'Last modified', accessor: 'lastModified', minWidth: 115, width: 115, align: 'right' } ]; const dataReports = [ { name: 'omatest', lastModified: '01/18/2024' }, { name: 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.', lastModified: '12/19/2023' }, { name: 'Aydin Hinton', lastModified: '12/19/2023' }, { name: 'Raegan Hickman', lastModified: '12/19/2023' }, { name: 'Ashley Page', lastModified: '12/19/2023' } ]; const ctaPulse = { label: 'New Pulse', iconName: 'Plus', onClick: () => console.log(''), id: 'widget-secondary-action-data-testid' }; const footerActionPulse = { label: 'Go to Pulse', onClick: () => console.log('secondary action click'), id: 'widget-secondary-action-data-testid' }; const rowOnClickHandler = (rowData) => { console.log(rowData); }; // WIDGET CONTENT const columnsPulse = [ { Header: 'Name', accessor: 'name' }, { Header: 'Type', accessor: 'type', minWidth: 64, width: 64, Cell: ({ value }) => <Badge color="positive" iconName="Key" /> }, { Header: 'Frequency', accessor: 'frequency' } ]; const dataPulse = [ { name: 'Pettaculars', lastModified: 'Pettaculars', frequency: 'Weekly - Wednesday, 06:00 UTC' }, { name: 'Get out', lastModified: '12/19/2023', frequency: 'Weekly - Wednesday, 06:00 UTC' }, { name: 'Bottle up', lastModified: '12/19/2023', frequency: 'Weekly - Wednesday, 06:00 UTC' }, { name: 'Bee Garden', lastModified: '12/19/2023', frequency: 'Weekly - Wednesday, 06:00 UTC' }, { name: 'Fly me up', lastModified: '12/19/2023', frequency: 'Weekly - Wednesday, 06:00 UTC' } ]; const ctaAccount = { label: 'New user', iconName: 'Plus', onClick: () => console.log(''), id: 'widget-secondary-action-data-testid' }; const footerActionAccount = { label: 'Go to account users', onClick: () => console.log('secondary action click'), id: 'widget-secondary-action-data-testid' }; // WIDGET CONTENT const columnsAccount = [ { Header: 'User', accessor: 'name', maxWidth: 200 }, { Header: 'Role', accessor: 'role', minWidth: 98, width: 98, Cell: ({ value }) => ( <Badge color={value === 'Admin' ? 'negative' : 'primary'} iconName="Key" label={value} /> ) } ]; const dataAccount = [ { name: 'John Doe', role: 'Admin' }, { name: 'Peter Brown', role: 'Admin' }, { name: 'Raegan Hickman', role: 'Admin' }, { name: 'Mark Spencer', role: 'Admin' }, { name: 'Aydin Hinton', role: 'Editor' } ]; return ( <Container> <Row> <Column xs={12} lg={6}> <Widget title="Reports" cta={ctaReports} secondaryAction={footerActionReports} filters={<Filters />} data={dataReports} columns={columnsReports} isHoverable rowOnClickHandler={rowOnClickHandler} actionMenu={[ { label: 'Edit', onClick: () => {}, iconName: 'Edit' }, { label: 'Delete', onClick: () => {}, iconName: 'Cross' } ]} /> </Column> <Column xs={12} lg={6}> <Widget title="Action center" subTitle="24 pending changes" secondaryAction={footerAction} data={data} columns={columns} isHoverable rowOnClickHandler={rowOnClickHandler} filters={ <div style={{ display: 'flex', flexDirection: 'row' }}> <ComboBox options={options} placeholder="Last 30 days" css={{ marginRight: '16px' }} /> <FilterButton name="Status" items={items} selectedItems={selectedItems} onApply={setSelectedItems} /> </div> } /> </Column> </Row> <Row> <Column xs={12} lg={12}> <Widget title="Action center" subTitle="24 pending changes" secondaryAction={footerAction} data={data} columns={columns} isHoverable rowOnClickHandler={rowOnClickHandler} filters={ <div style={{ display: 'flex', flexDirection: 'row' }}> <ComboBox options={options} placeholder="Last 30 days" css={{ marginRight: '16px' }} /> <FilterButton name="Status" items={items} selectedItems={selectedItems} onApply={setSelectedItems} /> </div> } /> </Column> </Row> <Row> <Column xs={12} lg={6}> <Widget title="Account users" cta={ctaAccount} secondaryAction={footerActionAccount} data={dataAccount} columns={columnsAccount} isHoverable rowOnClickHandler={rowOnClickHandler} actionMenu={[ { label: 'Edit', onClick: () => {}, iconName: 'Edit' }, { label: 'Delete', onClick: () => {}, iconName: 'Cross' } ]} /> </Column> <Column xs={12} lg={6}> <Widget title="Pulse" cta={ctaPulse} secondaryAction={footerActionPulse} data={dataPulse} columns={columnsPulse} isHoverable rowOnClickHandler={rowOnClickHandler} actionMenu={[ { label: 'Edit', onClick: () => {}, iconName: 'Edit' }, { label: 'Delete', onClick: () => {}, iconName: 'Cross' } ]} /> </Column> </Row> </Container> ); }
Props
| Name | Type | Default |
|---|---|---|
type * type of accordion |
| — |
data * accordion data |
| — |
bordered makes accordion headers bordered - for list type only |
| — |
disabled makes all accordion items disabled |
| — |
onItemUpdate callback for getting clicked item id, expand status and type (clicked item is custom checkbox or accordion header) |
| — |
selectable makes all items selectable |
| — |
togglePosition toggle button position - for list type only |
| — |
backgroundColor background color of headline |
| — |
data-{foo} Data attributes can be used by testing libraries to retrieve components or assert their existence |
| — |
| * - the prop is required. |