Skip to main content

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:

Live Editor
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' }
      ]}
    />
  );
}
Result
Loading...

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

Live Editor
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>
  );
}
Result
Loading...

Pulse

Live Editor
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>
  );
}
Result
Loading...

Connections

Live Editor
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}
    />
  );
}
Result
Loading...

Account users

Live Editor
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>
  );
}
Result
Loading...

Action center

Live Editor
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>
  );
}
Result
Loading...

Empty State

Live Editor
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>
  );
}
Result
Loading...

Grid examples

Live Editor
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>
  );
}
Result
Loading...

Props

NameTypeDefault
type *
type of accordion
"headline" | "list"
data *
accordion data
AccordionItem[]
bordered
makes accordion headers bordered - for list type only
boolean
disabled
makes all accordion items disabled
boolean
onItemUpdate
callback for getting clicked item id, expand status and type (clicked item is custom checkbox or accordion header)
((id: string | number, isExpanded: boolean, isCustomCheckbox: boolean) => void)
selectable
makes all items selectable
boolean
togglePosition
toggle button position - for list type only
"left" | "right"
backgroundColor
background color of headline
string
data-{foo}
Data attributes can be used by testing libraries to retrieve components or assert their existence
string
* - the prop is required.