Skip to main content

Selectable Tile

A Tile that is selectable. Tiles can contain logos, icons, or text only.

Example

Live Editor
function mySelectableTiles() {
  const items = [
      {
        id: '1',
        name: 'Tiktok',
        badge: {
          iconName: 'Check',
          label: 'Enabled',
          color: 'primary'
        },
        image: {
          url: 'https://upload.wikimedia.org/wikipedia/en/thumb/a/a9/TikTok_logo.svg/1200px-TikTok_logo.svg.png'
        },
        disabled: true
      },
      {
        id: '2',
        name: 'Apple Search Ads',
        iconName: 'PlatformIosFilled',
        badge: {
          iconName: 'Check',
          label: 'Enabled',
          color: 'primary'
        }
      },
       {
        id: '3',
        name: 'Random App',
        iconName: 'AppGrid',
        badge: {
          iconName: 'Check',
          label: 'Enabled',
          color: 'primary'
        },
        tooltipProps: {
          content: 'This is a tooltip',
          position: 'top'
        }
      },
      {
        id: '4',
        name: 'SelectableTile',
        image: {

        },
        badge: {
          iconName: 'Check',
          label: 'Enabled',
          color: 'primary'
        }
      },
       {
        id: '5',
        name: 'No Badge SelectableTile',
        disabled: true
      },
      {
        id: '6',
        name: 'Some App',
        image: {
          url: 'https://www.svgrepo.com/show/19461/url-link.svg',
          altText: 'Sample image',
          style: {
            color: 'blue'
          }
        },
        badge: {
          iconName: 'Cross',
          label: 'Negative',
          color: 'negative'
        }
      },
      {
        id: '7',
        name: 'Google Play App',
        iconName: 'PlatformGooglePlayFilled'
      },
      {
        id: '8',
        name: 'Yahoo Japan Corporation (Zホールディングス) Japan Search Ads',
        image: {
          url: 'https://media.buyee.jp/campaign/shippingfeeoff210324/assets/img/logo_y_shopping.png',
          altText: 'Sample image',
          style: {
            color: 'blue'
          }
        },
        badge: {
          iconName: 'Cross',
          label: 'Negative',
          color: 'negative'
        }
      },
      {
        id: '9',
        name: 'Google Ads',
        image: {
          url: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Google_2015_logo.svg/2560px-Google_2015_logo.svg.png',
          altText: 'Sample image',
          style: {
            color: 'blue'
          }
        }
      }
    ]

  const [selectedTiles, setSelectedTiles] = useState([]);
  const type = 'checkbox';
  
  const onSelect = (id) => {
    const selectedIDs = [...selectedTiles];
    
    if (type === 'radio') {
      setSelectedTiles(id);
      return;
    }
    
    if (!selectedIDs.includes(id)) {
      selectedIDs.push(id); 
    } else {
       selectedIDs.splice(selectedIDs.indexOf(id), 1);
    }
    setSelectedTiles(selectedIDs);
  }

  return (
    <SelectableTile
      items={items}
      selectedItems={selectedTiles}
      spacing={8}
      onChange={onSelect}
      type={type}
      columnSpan={4}
    />
  )
}
Result
Loading...

Variants

App Icons

You can add app icons with appIcon (ReactNode) as an external component (mfe-components). Recommended size is small.

import { AppIcon } from '@adjust/mfe-components';

function mySelectableTiles() {
const items = [
{
id: 'a',
name: 'Tiktok',
badge: {
iconName: 'Check',
label: 'Enabled',
color: 'primary'
},
appIcon: <AppIcon appId="com.adjust-demo.cryptoharvest" appName="Finance - Crypto Harvest" size="small" />
},
{
id: 'b',
name: 'Apple Search Ads',
appIcon: <AppIcon appId="com.adjust-demo.pocketbanking" appName="Finance - Pocket Banking" size="small" />,
badge: {
iconName: 'Check',
label: 'Enabled',
color: 'primary'
}
},
{
id: 'c',
name: 'Random App',
appIcon: <AppIcon appId="com.adjust-demo.amazingmarket" appName="Shopping - Amazing Market" size="small" />,
}
]

const [selectedTiles, setSelectedTiles] = useState([]);

const onSelect = (id) => {
const selectedIDs = [...selectedTiles];
if (!selectedIDs.includes(id)) {
selectedIDs.push(id);
} else {
selectedIDs.splice(selectedIDs.indexOf(id), 1);
}
setSelectedTiles(selectedIDs);
}

return (
<SelectableTile
items={items}
selectedItems={selectedTiles}
spacing={8}
onChange={onSelect}
type="checkbox"
columnSpan={4}
/>
)
}

Multiple instances with the same item ids

By default, a tile's DOM id/name (and its label's htmlFor) are derived directly from the item's id/name. If you render two or more SelectableTile instances on the same page using items with the same ids, clicking a tile in one instance can affect a tile with the same id in another instance, since the ids collide in the DOM.

Set useUniqueId to scope each instance's tiles so they no longer collide.

Live Editor
function mySelectableTiles() {
  const items = [
      {
        id: 'a',
        name: 'Tiktok',
        badge: {
          iconName: 'Check',
          label: 'Enabled',
          color: 'primary'
        },
        image: {
          url: 'https://upload.wikimedia.org/wikipedia/en/thumb/a/a9/TikTok_logo.svg/1200px-TikTok_logo.svg.png'
        }
      },
      {
        id: 'b',
        name: 'Apple Search Ads',
        iconName: 'PlatformIosFilled',
        badge: {
          iconName: 'Check',
          label: 'Enabled',
          color: 'primary'
        }
      },
      {
        id: 'c',
        name: 'Random App',
        iconName: 'AppGrid',
      }
    ]
  const [selectedTiles, setSelectedTiles] = useState([]);
  const [selectedTiles2, setSelectedTiles2] = useState([]);

  const onSelect = (id) => {
    const selectedIDs = [...selectedTiles];
    if (!selectedIDs.includes(id)) {
      selectedIDs.push(id);
    } else {
       selectedIDs.splice(selectedIDs.indexOf(id), 1);
    }
    setSelectedTiles(selectedIDs);
  }
  const onSelect2 = (id) => {
    const selectedIDs = [...selectedTiles2];
    if (!selectedIDs.includes(id)) {
      selectedIDs.push(id);
    } else {
       selectedIDs.splice(selectedIDs.indexOf(id), 1);
    }
    setSelectedTiles2(selectedIDs);
  }

  return (
    <>
      <SelectableTile
        items={items}
        selectedItems={selectedTiles}
        spacing={8}
        onChange={onSelect}
        type="checkbox"
        columnSpan={4}
        useUniqueId
      />
      <SelectableTile
        items={items}
        selectedItems={selectedTiles2}
        spacing={8}
        onChange={onSelect2}
        type="checkbox"
        columnSpan={4}
        useUniqueId
      />
    </>
  )
}
Result
Loading...

Selection Mode

Selectable Tiles allow two different modes: checkbox-like multi selection, and radio-like single selection. There must always be at least 2 tiles to be used within a grid.

  • The component allows radio-like single selection by adding type='checkbox' as following example.
Live Editor
function mySelectableTiles() {
  const items = [
      {
        id: 'a',
        name: 'Tiktok',
        badge: {
          iconName: 'Check',
          label: 'Enabled',
          color: 'primary'
        },
        image: {
          url: 'https://upload.wikimedia.org/wikipedia/en/thumb/a/a9/TikTok_logo.svg/1200px-TikTok_logo.svg.png'
        }
      },
      {
        id: 'b',
        name: 'Apple Search Ads',
        iconName: 'PlatformIosFilled',
        badge: {
          iconName: 'Check',
          label: 'Enabled',
          color: 'primary'
        }
      },
      {
        id: 'c',
        name: 'Random App',
        iconName: 'AppGrid',
      }
    ]

  const [selectedTiles, setSelectedTiles] = useState([]);

  const onSelect = (id) => {
    const selectedIDs = [...selectedTiles];
    if (!selectedIDs.includes(id)) {
      selectedIDs.push(id);
    } else {
       selectedIDs.splice(selectedIDs.indexOf(id), 1);
    }
    setSelectedTiles(selectedIDs);
  }

  return (
    <SelectableTile
      items={items}
      selectedItems={selectedTiles}
      spacing={8}
      onChange={onSelect}
      type="checkbox"
      columnSpan={4}
    />
  )
}
Result
Loading...
  • The component allows radio-like single selection by adding type='radio' as following example.
Live Editor
function mySelectableTiles() {
  const items = [
      {
        id: 'a1',
        name: 'Tiktok',
        badge: {
          iconName: 'Check',
          label: 'Enabled',
          color: 'primary'
        },
        image: {
          url: 'https://upload.wikimedia.org/wikipedia/en/thumb/a/a9/TikTok_logo.svg/1200px-TikTok_logo.svg.png'
        }
      },
      {
        id: 'b1',
        name: 'Apple Search Ads',
        iconName: 'PlatformIosFilled',
        badge: {
          iconName: 'Check',
          label: 'Enabled',
          color: 'primary'
        }
      },
      {
        id: 'c1',
        name: 'Random App',
        iconName: 'AppGrid'
      }
    ]

  const [selectedTile, setSelectedTile] = useState('');

  return (
    <>
      <SelectableTile
        items={items}
        selectedItems={selectedTile}
        spacing={8}
        onChange={setSelectedTile}
        type="radio"
        columnSpan={4}
      />
    </>
  )
}
Result
Loading...

Size

There are two sizes available for selectable tiles: small and medium (default).

info

Small tiles can not show a status badge.

Live Editor
function mySelectableTiles() {
  const getItems = (size) => Array.from({length: 3}, (_, index) => 
    ({
      id: `${size}-${index}`, 
      name: size === 'md' ? 'Medium Tile' : 'Small Tile',
      iconName: index === 1 ? 'PlatformIosFilled' : undefined,
      image: index === 0 ? {
          url: 'https://upload.wikimedia.org/wikipedia/en/thumb/a/a9/TikTok_logo.svg/1200px-TikTok_logo.svg.png'
        } : undefined,
      badge: {
        iconName: 'Check',
        label: 'Enabled',
        color: 'primary'
      }
    })
  )  
  
  const [selectedMdTile, setSelectedMdTile] = useState(getItems('md')[0].id);
  const [selectedSmTile, setSelectedSmTile] = useState(getItems('sm')[1].id);

  return (
    <>
      <SelectableTile
        items={getItems('md')}
        selectedItems={selectedMdTile}
        onChange={setSelectedMdTile}
        spacing={8}
        columnSpan={4}
        type="radio"
      />

      <SelectableTile
        items={getItems('sm')}
        selectedItems={selectedSmTile}
        onChange={setSelectedSmTile}
        spacing={8}
        columnSpan={4}
        size='small'
        type="radio"
      />
    </>
  )
}
Result
Loading...

Tooltip

You can display a tooltip for each SelectableTile item.

To display a tooltip you need to add to your item object tooltipProps property with a content.

The Tooltip position is set to auto by default and can be customized by passing position like below example.

Live Editor
function mySelectableTiles() {
  const items = [
      {
        id: 'a',
        name: 'Tiktok',
        badge: {
          iconName: 'Check',
          label: 'Enabled',
          color: 'primary'
        },
        image: {
          url: 'https://upload.wikimedia.org/wikipedia/en/thumb/a/a9/TikTok_logo.svg/1200px-TikTok_logo.svg.png'
        },
        tooltipProps: {
          content: 'This is a tooltip',
          position: 'top'
        }
      },
      {
        id: 'b',
        name: 'Apple Search Ads',
        iconName: 'PlatformIosFilled',
        badge: {
          iconName: 'Check',
          label: 'Enabled',
          color: 'primary'
        },
        tooltipProps: {
          content: 'This is a tooltip',
          zIndex: -1
        }
      },
       {
        id: 'c',
        name: 'Random App',
        iconName: 'AppGrid',
        badge: {
          iconName: 'Check',
          label: 'Enabled',
          color: 'primary'
        },
        tooltipProps: {
          content: 'This is a tooltip',
          position: 'top'
        }
      }
    ]

  const [selectedTiles, setSelectedTiles] = useState([]);
  const type = 'checkbox';

  const onSelect = (id) => {
    const selectedIDs = [...selectedTiles];

    if (type === 'radio') {
      setSelectedTiles(id);
      return;
    }

    if (!selectedIDs.includes(id)) {
      selectedIDs.push(id);
    } else {
       selectedIDs.splice(selectedIDs.indexOf(id), 1);
    }
    setSelectedTiles(selectedIDs);
  }

  return (
    <SelectableTile
      items={items}
      selectedItems={selectedTiles}
      spacing={8}
      onChange={onSelect}
      type={type}
      columnSpan={4}
    />
  )
}
Result
Loading...

Props

SelectableTile

NameTypeDefault
type *
Type of radio or checkbox
"checkbox" | "radio"
selectedItems *
this support single and multiple selected items
string | string[]
items *
Array of SelectableTileItems
SelectableTileItemProps[]
size
A tile size
"small" | "medium"
"medium"
spacing
A number value to set spacing between tiles
number
8
onChange
Onchange function
((id: string) => void)
columnSpan
equal space between tiles
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
4
useUniqueId
Scopes each tile's input id/name and label htmlFor to this SelectableTile instance, so multiple instances sharing the same item ids can be rendered on the same page. Default false to keep existing DOM output stable.
boolean
false
data-{foo}
Data attributes can be used by testing libraries to retrieve components or assert their existence
string
* - the prop is required.