Selectable Tile
A Tile that is selectable. Tiles can contain logos, icons, or text only.
Example
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} /> ) }
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.
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 /> </> ) }
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.
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} /> ) }
- The component allows radio-like single selection by adding
type='radio'as following example.
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} /> </> ) }
Size
There are two sizes available for selectable tiles: small and medium (default).
Small tiles can not show a status badge.
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" /> </> ) }
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.
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} /> ) }
Props
SelectableTile
| Name | Type | Default |
|---|---|---|
type * Type of radio or checkbox |
| — |
selectedItems * this support single and multiple selected items |
| — |
items * Array of SelectableTileItems |
| — |
size A tile size |
| "medium" |
spacing A number value to set spacing between tiles |
| 8 |
onChange Onchange function |
| — |
columnSpan equal space between tiles |
| 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. |
| false |
data-{foo} Data attributes can be used by testing libraries to retrieve components or assert their existence |
| — |
| * - the prop is required. |