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. |