Skip to content
SiteEmail

List

The List component displays structured content as a vertical stack of items. It supports unordered and ordered formats, automatic nesting, and configurable bullets. Each item also exposes an inline Icon slot so you can override the bullet/icon for that specific item.

It’s ideal for UI elements like settings menus, objectives, inventories, or any structured group of interactive or static content.

To use List, wrap List.Item components inside the List. You can optionally specify the list type (unordered or ordered) and set the bullet style for the list with the bullet-type prop, or override it per item by placing List.Icon inside that item.

import List from '@components/Layout/List/List';
import starIcon from '@assets/starIcon.svg'
const App = () => {
return (
<List bullet-type="disc">
<List.Item>Step one</List.Item>
<List.Item>
Step two
<List bullet-type={starIcon}>
<List.Item>Step 2.1</List.Item>
<List.Item>Step 2.2</List.Item>
</List>
</List.Item>
<List.Item>
Special step
<List.Icon class="custom-icon" />
</List.Item>
</List>
);
};
export default App;
Prop NameTypeDefaultDescription
refHTMLDivElementundefinedRetrieves the component’s DOM element and assigns it to a variable.
type'ordered' | 'unordered''unordered'Controls whether the list is ordered (numbered) or unordered (bulleted). Automatically set to 'ordered' when bullet-type is "number".
bullet-type'disc' | 'circle' | 'square' | 'number' | 'none' | string | ImageMetadata'disc' (unordered) / 'number' (ordered)Sets the bullet style for all items in the list. Can be a predefined style, or an image.
bullet-classstring""Additional CSS classes to apply to all bullet elements.
styleJSX.CSSProperties{}Inline styles to apply to the root element.
classstring""Additional CSS classes to apply to the root element.
childrenJSX.Element""List items to render. It renders only List.Item components.
onActionRecord<string, (scope?: string, ...args: any[]) => void>undefinedAllows you to add custom navigation action handlers to the component. See the Navigation component documentation for details.
anchorstring | HTMLElementundefinedLinks navigation to another element. When the anchor element is focused, this component’s actions will execute. Can be a CSS selector or HTMLElement.

Use List.Item to define an item in the list. Items can contain any valid JSX content, including nested List components.

Prop NameTypeDefaultDescription
styleJSX.CSSProperties{}Inline styles for the individual list item.
classstring""Additional CSS classes for the item.
childrenJSX.Element""Content of the list item. Supports nested List components and any other valid JSX content.
onActionRecord<string, (scope?: string, ...args: any[]) => void>undefinedAllows you to add custom navigation action handlers to the component. See the Navigation component documentation for details.
anchorstring | HTMLElementundefinedLinks navigation to another element. When the anchor element is focused, this component’s actions will execute. Can be a CSS selector or HTMLElement.
import List from '@components/Layout/List/List';
const App = () => {
return (
<List>
<List.Item>Start the game</List.Item>
<List.Item>
<div>Adjust settings</div>
<List>
<List.Item>Graphics</List.Item>
<List.Item>Sound</List.Item>
</List>
</List.Item>
<List.Item>Exit</List.Item>
</List>
);
};

The List.Icon slot lets you override the bullet for one specific item.
It does not affect other items in the list.

  • bullet-type and bullet-class (props on List) set the default bullet for all items.
  • If you add class or style directly to List.Icon, those styles override the defaults for that item only.
  • If you provide children inside List.Icon, they replace the bullet entirely for that item (text, SVG, custom JSX, etc.).
import List from '@components/Layout/List/List';
import SwordIcon from '@assets/icons/sword.svg?component-solid';
const App = () => {
return (
<List bullet-type="disc">
<List.Item>
Default bullet
</List.Item>
<List.Item>
Custom styled bullet
<List.Icon class="highlighted" style={{ 'background-color': 'red' }} />
</List.Item>
<List.Item>
Fully custom icon
<List.Icon>
<SwordIcon style={{width: '100%', height: '100%'}} />
</List.Icon>
</List.Item>
</List>
);
};
Prop NameTypeDefaultDescription
refHTMLDivElementundefinedRetrieves the component’s DOM element and assigns it to a variable.
classstring""Additional CSS classes for this icon only. Overrides bullet-class from List for this item.
styleJSX.CSSProperties{}Inline styles for this icon only. Overrides styles from List for this item.
childrenJSX.Element""Custom content to replace the bullet entirely for this item. If set, bullet-type and bullet-class are ignored.

The List component supports automatic styling for nested items. When you nest one List inside a List.Item, indentation adjust accordingly.

import List from '@components/Layout/List/List';
const App = () => {
return (
<List>
<List.Item>Main Quest</List.Item>
<List.Item>
Side Quests
<List type="ordered" list-class="bolded-icons">
<List.Item>Rescue the merchant</List.Item>
<List.Item>Find the lost ring</List.Item>
</List>
</List.Item>
</List>
);
};

To dynamically render list items in the List component, you can use an array and map over it:

import List from '@components/Layout/List/List';
const items = [
{ id: 1, text: 'Start mission' },
{ id: 2, text: 'Collect 5 herbs' },
{ id: 3, text: 'Return to base' }
];
const App = () => {
return (
<List>
{items.map((item) => (
<List.Item >
{item.text}
</List.Item>
))}
</List>
);
};

Alternatively, you can use the SolidJS <For> component:

import List from '@components/Layout/List/List';
import { For } from 'solid-js';
const items = [
{ id: 1, text: 'Start mission' },
{ id: 2, text: 'Collect 5 herbs' },
{ id: 3, text: 'Return to base' }
];
const App = () => {
return (
<List>
<For each={items}>
{(item) => (
<List.Item>
{item.text}
</List.Item>
)}
</For>
</List>
);
};

To change all bullets of the List with a custom image, import the image and pass it to the bullet-type prop:

import List from '@components/Layout/List/List';
import QuestArrow from 'assets@/quest-arrow.svg';
import 'index.css'
const App = () => {
return (
<List bullet-type={QuestArrow} bullet-class="custom-bullet-icon">
<List.Item>Capture 3 fish</List.Item>
<List.Item>Cook fish</List.Item>
<List.Item>Eat fish</List.Item>
</List>
);
};

To apply additional styles to all bullets at once, use the bullet-class prop and define your styles in CSS:

index.css
.custom-bullet-icon {
background-color: yellow;
}

Additionally, if you wish to change one of the icons in a list item, just provide it as a child in the List.icon slot.

import List from '@components/Layout/List/List';
import QuestArrow from 'assets@/quest-arrow.svg';
import QuestArrow2 from 'assets@/quest-arrow2.svg?component-svg';
import 'index.css'
const App = () => {
return (
<List bullet-type={QuestArrow} bullet-class="custom-bullet-icon">
<List.Item>Capture 3 fish</List.Item>
<List.Item>Cook fish</List.Item>
<List.Item>
<List.Icon>
<QuestArrow2 style={{width: '100%', height: '100%'}} />
</List.Icon>
</List.Item>
</List>
);
};

To access the HTML DOM element of the List component.

  1. Declare a variable to hold the ref but don’t initialize it with a value
  2. The declared value should have a type of HTMLDivElement.
  3. Set the declared variable as the value of the ref prop of the List component
import List from '@components/Layout/List/List';
const App = () => {
let listRef!: HTMLDivElement
return (
<List ref={listRef}>
<List.Item>Main Quest</List.Item>
<List.Item>Side Quest</List.Item>
</List>
);
};

Now you can access the HTML element of List with listRef and make modifications to it if needed.

To make the List component navigable via keyboard or gamepad, you can use the Navigation component. There are two ways to achieve this.

You can manually register the list items using the registerArea method.

  1. Wrap the List (or a parent) with the Navigation component.
  2. Use the ref callback to access the Navigation API immediately.
  3. Register the specific class name of your list items using registerArea.
import List from '@components/Layout/List/List';
import Navigation, {NavigationRef} from '@components/Utility/Navigation/Navigation';
import { For } from 'solid-js';
const App = () => {
// 1. Use a callback to register the area immediately when Navigation initializes
const handleNavRef = (api: NavigationRef) => {
// Note the dot (.) prefix for the class selector
api.registerArea('list-items', ['.test'], true);
};
return (
<Navigation ref={handleNavRef} >
<List >
<For each={items}>
{(item) => (
// 2. Add the matching class name to your items
<List.Item class='test'>
{item.text}
</List.Item>
)}
</For>
</List>
</Navigation>
);
}

Approach 2: The Wrapper Component (Declarative)

Section titled “Approach 2: The Wrapper Component (Declarative)”

Alternatively, you can wrap the List in a Navigation.Area component.

In this case, you must provide the selector prop to tell the area which inner elements are focusable.

import List from '@components/Layout/List/List';
import Navigation from '@components/Utility/Navigation/Navigation';
import For from 'solid-js';
const App = () => {
return (
<Navigation >
<Navigation.Area selector="test" name="list-items" focused >
<List >
<For each={items}>
{(item) => (
// Add the matching class name to your items
<List.Item class='test'>
{item.text}
</List.Item>
)}
</For>
</List>
</Navigation.Area>
</Navigation>
);
}