List

The de-facto user interface in Raycast. Ideal to present similar data such as to-dos or files.

Our List component provides great user experience out of the box:

  • Use built-in filtering for best performance.

  • Group-related items in sections with titles and subtitles.

  • Show loading indicator for longer operations.

  • Use the search query for typeahead experiences, optionally throttled.

The search bar allows users to interact quickly with list items. By default, List.Items are displayed if the user's input can be (fuzzy) matched to the item's title or keywords.

Custom filtering

Sometimes, you may not want to rely on Raycast's filtering, but use/implement your own. If that's the case, you can set the List's filtering prop to false, and the items displayed will be independent of the search bar's text. Note that filtering is also implicitly set to false if an onSearchTextChange listener is specified. If you want to specify a change listener and still take advantage of Raycast's built-in filtering, you can explicitly set filtering to true.

import { useEffect, useState } from "react";
import { Action, ActionPanel, List } from "@raycast/api";

const items = ["Augustiner Helles", "Camden Hells", "Leffe Blonde", "Sierra Nevada IPA"];

export default function Command() {
  const [searchText, setSearchText] = useState("");
  const [filteredList, filterList] = useState(items);

  useEffect(() => {
    filterList(items.filter((item) => item.includes(searchText)));
  }, [searchText]);

  return (
    <List
      filtering={false}
      onSearchTextChange={setSearchText}
      navigationTitle="Search Beers"
      searchBarPlaceholder="Search your favorite beer"
    >
      {filteredList.map((item) => (
        <List.Item
          key={item}
          title={item}
          actions={
            <ActionPanel>
              <Action title="Select" onAction={() => console.log(`${item} selected`)} />
            </ActionPanel>
          }
        />
      ))}
    </List>
  );
}

Other times, you may want the content of the search bar to be updated by the extension, for example, you may store a list of the user's previous searches and, on the next visit, allow them to "continue" where they left off.

To do so, you can use the searchText prop.

import { useEffect, useState } from "react";
import { Action, ActionPanel, List } from "@raycast/api";

const items = ["Augustiner Helles", "Camden Hells", "Leffe Blonde", "Sierra Nevada IPA"];

export default function Command() {
  const [searchText, setSearchText] = useState("");

  return (
    <List
      searchText={searchText}
      onSearchTextChange={setSearchText}
      navigationTitle="Search Beers"
      searchBarPlaceholder="Search your favorite beer"
    >
      {items.map((item) => (
        <List.Item
          key={item}
          title={item}
          actions={
            <ActionPanel>
              <Action title="Select" onAction={() => setSearchText(item)} />
            </ActionPanel>
          }
        />
      ))}
    </List>
  );
}

Some extensions may benefit from giving users a second filtering dimension. A todo extension may allow users to use different groups, a newspaper-reading extension may want to allow quickly switching categories, etc.

This is where the searchBarAccessory prop is useful. Pass it a List.Dropdown component, and it will be displayed on the right-side of the search bar. Invoke it either by using the global shortcut P or by clicking on it.

Pagination

Pagination requires version 1.69.0 or higher of the @raycast/api package.

Lists have built-in support for pagination. To opt in to pagination, you need to pass it a pagination prop, which is an object providing 3 pieces of information:

  • onLoadMore - will be called by Raycast when the user reaches the end of the list, either using the keyboard or the mouse. When it gets called, the extension is expected to perform an async operation which eventually can result in items being appended to the end of the list.

  • hasMore - indicates to Raycast whether it should call onLoadMore when the user reaches the end of the list.

  • pageSize - indicates how many placeholder items Raycast should add to the end of the list when it calls onLoadMore. Once onLoadMore finishes executing, the placeholder items will be replaced by the newly-added list items.

Note that extensions have access to a limited amount of memory. As your extension paginates, its memory usage will increase. Paginating extensively could lead to the extension eventually running out of memory and crashing. To protect against the extension crashing due to memory exhaustion, Raycast monitors the extension's memory usage and employs heuristics to determine whether it's safe to paginate further. If it's deemed unsafe to continue paginating, onLoadMore will not be triggered when the user scrolls to the bottom, regardless of the hasMore value. Additionally, during development, a warning will be printed in the terminal.

For convenience, most of the hooks that we provide have built-in pagination support. Here's an example of how to add pagination support to a simple command using usePromise, and one "from scratch".

import { setTimeout } from "node:timers/promises";
import { useState } from "react";
import { List } from "@raycast/api";
import { usePromise } from "@raycast/utils";

export default function Command() {
  const [searchText, setSearchText] = useState("");

  const { isLoading, data, pagination } = usePromise(
    (searchText: string) => async (options: { page: number }) => {
      await setTimeout(200);
      const newData = Array.from({ length: 25 }, (_v, index) => ({
        index,
        page: options.page,
        text: searchText,
      }));
      return { data: newData, hasMore: options.page < 10 };
    },
    [searchText]
  );

  return (
    <List isLoading={isLoading} onSearchTextChange={setSearchText} pagination={pagination}>
      {data?.map((item) => (
        <List.Item
          key={`${item.page} ${item.index} ${item.text}`}
          title={`Page ${item.page} Item ${item.index}`}
          subtitle={item.text}
        />
      ))}
    </List>
  );
}

Examples

import { List } from "@raycast/api";

export default function Command() {
  return (
    <List>
      <List.Item title="Item 1" />
      <List.Item title="Item 2" subtitle="Optional subtitle" />
    </List>
  );
}

API Reference

List

Displays List.Section or List.Item.

The list uses built-in filtering by indexing the title of list items and additionally keywords.

Example

import { List } from "@raycast/api";

export default function Command() {
  return (
    <List navigationTitle="Search Beers" searchBarPlaceholder="Search your favorite beer">
      <List.Item title="Augustiner Helles" />
      <List.Item title="Camden Hells" />
      <List.Item title="Leffe Blonde" />
      <List.Item title="Sierra Nevada IPA" />
    </List>
  );
}

Props

PropDescriptionTypeDefault

actions

A reference to an ActionPanel. It will only be shown when there aren't any children.

React.ReactNode

-

children

List sections or items. If List.Item elements are specified, a default section is automatically created.

React.ReactNode

-

filtering

Toggles Raycast filtering. When true, Raycast will use the query in the search bar to filter the items. When false, the extension needs to take care of the filtering.

boolean or { keepSectionOrder: boolean }

false when onSearchTextChange is specified, true otherwise.

isLoading

Indicates whether a loading bar should be shown or hidden below the search bar

boolean

false

isShowingDetail

Whether the List should have an area on the right side of the items to show additional details about the selected item.

boolean

-

navigationTitle

The main title for that view displayed in Raycast

string

Command title

pagination

Configuration for pagination

{ hasMore: boolean; pageSize: number; onLoadMore: (page: number) => void }

-

searchBarAccessory

List.Dropdown that will be shown in the right-hand-side of the search bar.

ReactElement<List.Dropdown.Props, string>

-

searchBarPlaceholder

Placeholder text that will be shown in the search bar.

string

"Search…"

searchText

The text that will be displayed in the search bar.

string

-

selectedItemId

Selects the item with the specified id.

string

-

throttle

Defines whether the onSearchTextChange handler will be triggered on every keyboard press or with a delay for throttling the events. Recommended to set to true when using custom filtering logic with asynchronous operations (e.g. network requests).

boolean

false

onSearchTextChange

Callback triggered when the search bar text changes.

(text: string) => void

-

onSelectionChange

Callback triggered when the item selection in the list changes.

(id: string) => void

-

List.Dropdown

A dropdown menu that will be shown in the right-hand-side of the search bar.

Example

import { List } from "@raycast/api";

type DrinkType = { id: string; name: string };

function DrinkDropdown(props: { drinkTypes: DrinkType[]; onDrinkTypeChange: (newValue: string) => void }) {
  const { drinkTypes, onDrinkTypeChange } = props;
  return (
    <List.Dropdown
      tooltip="Select Drink Type"
      storeValue={true}
      onChange={(newValue) => {
        onDrinkTypeChange(newValue);
      }}
    >
      <List.Dropdown.Section title="Alcoholic Beverages">
        {drinkTypes.map((drinkType) => (
          <List.Dropdown.Item key={drinkType.id} title={drinkType.name} value={drinkType.id} />
        ))}
      </List.Dropdown.Section>
    </List.Dropdown>
  );
}

export default function Command() {
  const drinkTypes: DrinkType[] = [
    { id: "1", name: "Beer" },
    { id: "2", name: "Wine" },
  ];
  const onDrinkTypeChange = (newValue: string) => {
    console.log(newValue);
  };
  return (
    <List
      navigationTitle="Search Beers"
      searchBarPlaceholder="Search your favorite drink"
      searchBarAccessory={<DrinkDropdown drinkTypes={drinkTypes} onDrinkTypeChange={onDrinkTypeChange} />}
    >
      <List.Item title="Augustiner Helles" />
      <List.Item title="Camden Hells" />
      <List.Item title="Leffe Blonde" />
      <List.Item title="Sierra Nevada IPA" />
    </List>
  );
}

Props

PropDescriptionTypeDefault

tooltip*

Tooltip displayed when hovering the dropdown.

string

-

children

Dropdown sections or items. If Dropdown.Item elements are specified, a default section is automatically created.

React.ReactNode

-

defaultValue

The default value of the dropdown. Keep in mind that defaultValue will be configured once per component lifecycle. This means that if a user changes the value, defaultValue won't be configured on re-rendering.

string

-

filtering

Toggles Raycast filtering. When true, Raycast will use the query in the search bar to filter the items. When false, the extension needs to take care of the filtering.

boolean or { keepSectionOrder: boolean }

false when onSearchTextChange is specified, true otherwise.

id

ID of the dropdown.

string

-

isLoading

Indicates whether a loading indicator should be shown or hidden next to the search bar

boolean

false

placeholder

Placeholder text that will be shown in the dropdown search field.

string

"Search…"

storeValue

Indicates whether the value of the dropdown should be persisted after selection, and restored next time the dropdown is rendered.

boolean

-

throttle

Defines whether the onSearchTextChange handler will be triggered on every keyboard press or with a delay for throttling the events. Recommended to set to true when using custom filtering logic with asynchronous operations (e.g. network requests).

boolean

false

value

The currently value of the dropdown.

string

-

onChange

Callback triggered when the dropdown selection changes.

(newValue: string) => void

-

onSearchTextChange

Callback triggered when the search bar text changes.

(text: string) => void

-

List.Dropdown.Item

A dropdown item in a List.Dropdown

Example

import { List } from "@raycast/api";

export default function Command() {
  return (
    <List
      searchBarAccessory={
        <List.Dropdown tooltip="Dropdown With Items">
          <List.Dropdown.Item title="One" value="one" />
          <List.Dropdown.Item title="Two" value="two" />
          <List.Dropdown.Item title="Three" value="three" />
        </List.Dropdown>
      }
    >
      <List.Item title="Item in the Main List" />
    </List>
  );
}

Props

PropDescriptionTypeDefault

title*

The title displayed for the item.

string

-

value*

Value of the dropdown item. Make sure to assign each unique value for each item.

string

-

icon

An optional icon displayed for the item.

-

keywords

An optional property used for providing additional indexable strings for search. When filtering the items in Raycast, the keywords will be searched in addition to the title.

string[]

The title of its section if any

List.Dropdown.Section

Visually separated group of dropdown items.

Use sections to group related menu items together.

Example

import { List } from "@raycast/api";

export default function Command() {
  return (
    <List
      searchBarAccessory={
        <List.Dropdown tooltip="Dropdown With Sections">
          <List.Dropdown.Section title="First Section">
            <List.Dropdown.Item title="One" value="one" />
          </List.Dropdown.Section>
          <List.Dropdown.Section title="Second Section">
            <List.Dropdown.Item title="Two" value="two" />
          </List.Dropdown.Section>
        </List.Dropdown>
      }
    >
      <List.Item title="Item in the Main List" />
    </List>
  );
}

Props

PropDescriptionTypeDefault

children

The item elements of the section.

React.ReactNode

-

title

Title displayed above the section

string

-

List.EmptyView

A view to display when there aren't any items available. Use to greet users with a friendly message if the extension requires user input before it can show any list items e.g. when searching for a package, an article etc.

Raycast provides a default EmptyView that will be displayed if the List component either has no children, or if it has children, but none of them match the query in the search bar. This too can be overridden by passing an empty view alongside the other List.Items.

Note that the EmptyView is never displayed if the List's isLoading property is true and the search bar is empty.

Example

import { useEffect, useState } from "react";
import { List } from "@raycast/api";

export default function CommandWithCustomEmptyView() {
  const [state, setState] = useState({ searchText: "", items: [] });

  useEffect(() => {
    // perform an API call that eventually populates `items`.
  }, [state.searchText]);

  return (
    <List onSearchTextChange={(newValue) => setState((previous) => ({ ...previous, searchText: newValue }))}>
      {state.searchText === "" && state.items.length === 0 ? (
        <List.EmptyView icon={{ source: "https://placekitten.com/500/500" }} title="Type something to get started" />
      ) : (
        state.items.map((item) => <List.Item key={item} title={item} />)
      )}
    </List>
  );
}

Props

PropDescriptionTypeDefault

actions

A reference to an ActionPanel.

React.ReactNode

-

description

An optional description for why the empty view is shown.

string

-

icon

An icon displayed in the center of the EmptyView.

-

title

The main title displayed for the Empty View.

string

-

List.Item

A item in the List.

This is one of the foundational UI components of Raycast. A list item represents a single entity. It can be a GitHub pull request, a file, or anything else. You most likely want to perform actions on this item, so make it clear to the user what this list item is about.

Example

import { Icon, List } from "@raycast/api";

export default function Command() {
  return (
    <List>
      <List.Item icon={Icon.Star} title="Augustiner Helles" subtitle="0,5 Liter" accessories={[{ text: "Germany" }]} />
    </List>
  );
}

Props

PropDescriptionTypeDefault

title*

The main title displayed for that item, optionally with a tooltip.

string or { tooltip?: string; value: string }

-

accessories

An optional array of List.Item.Accessory items displayed on the right side in a List.Item.

-

actions

An ActionPanel that will be updated for the selected list item.

React.ReactNode

-

detail

The List.Item.Detail to be rendered in the right side area when the parent List is showing details and the item is selected.

React.ReactNode

-

icon

An optional icon displayed for the list item.

Image.ImageLike or { tooltip: string; value: Image.ImageLike }

-

id

ID of the item. This string is passed to the onSelectionChange handler of the List when the item is selected. Make sure to assign each item a unique ID or a UUID will be auto generated.

string

-

keywords

An optional property used for providing additional indexable strings for search. When filtering the list in Raycast through the search bar, the keywords will be searched in addition to the title.

string[]

-

quickLook

Optional information to preview files with Quick Look. Toggle the preview with Action.ToggleQuickLook.

{ name?: string; path: string }

-

subtitle

An optional subtitle displayed next to the main title, optionally with a tooltip.

string or { tooltip?: string; value?: string }

-

List.Item.Detail

A Detail view that will be shown in the right-hand-side of the List.

When shown, it is recommended not to show any accessories on the List.Item and instead bring those additional information in the List.Item.Detail view.

Example

import { List } from "@raycast/api";

export default function Command() {
  return (
    <List isShowingDetail>
      <List.Item
        title="Pikachu"
        subtitle="Electric"
        detail={
          <List.Item.Detail markdown="![Illustration](https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/25.png)" />
        }
      />
    </List>
  );
}

Props

PropDescriptionTypeDefault

isLoading

Indicates whether a loading bar should be shown or hidden above the detail

boolean

false

markdown

The CommonMark string to be rendered in the right side area when the parent List is showing details and the item is selected.

string

-

metadata

The List.Item.Detail.Metadata to be rendered in the bottom side of the List.Item.Detail

React.ReactNode

-

List.Item.Detail.Metadata

A Metadata view that will be shown in the bottom side of the List.Item.Detail.

Use it to display additional structured data about the content of the List.Item.

Example

import { List } from "@raycast/api";

export default function Metadata() {
  const markdown = `
![Illustration](https://assets.pokemon.com/assets/cms2/img/pokedex/full/001.png)
There is a plant seed on its back right from the day this Pokémon is born. The seed slowly grows larger.
`;
  return (
    <List isShowingDetail>
      <List.Item
        title="Bulbasaur"
        detail={
          <List.Item.Detail
            markdown={markdown}
            metadata={
              <List.Item.Detail.Metadata>
                <List.Item.Detail.Metadata.Label title="Types" />
                <List.Item.Detail.Metadata.Label title="Grass" icon="pokemon_types/grass.svg" />
                <List.Item.Detail.Metadata.Separator />
                <List.Item.Detail.Metadata.Label title="Poison" icon="pokemon_types/poison.svg" />
                <List.Item.Detail.Metadata.Separator />
                <List.Item.Detail.Metadata.Label title="Chracteristics" />
                <List.Item.Detail.Metadata.Label title="Height" text="70cm" />
                <List.Item.Detail.Metadata.Separator />
                <List.Item.Detail.Metadata.Label title="Weight" text="6.9 kg" />
                <List.Item.Detail.Metadata.Separator />
                <List.Item.Detail.Metadata.Label title="Abilities" />
                <List.Item.Detail.Metadata.Label title="Chlorophyll" text="Main Series" />
                <List.Item.Detail.Metadata.Separator />
                <List.Item.Detail.Metadata.Label title="Overgrow" text="Main Series" />
                <List.Item.Detail.Metadata.Separator />
              </List.Item.Detail.Metadata>
            }
          />
        }
      />
    </List>
  );
}

Props

PropDescriptionTypeDefault

children*

The elements of the Metadata view.

React.ReactNode

-

List.Item.Detail.Metadata.Label

A title with, optionally, an icon and/or text to its right.

Example

import { List } from "@raycast/api";

export default function Metadata() {
  return (
    <List isShowingDetail>
      <List.Item
        title="Bulbasaur"
        detail={
          <List.Item.Detail
            metadata={
              <List.Item.Detail.Metadata>
                <List.Item.Detail.Metadata.Label title="Type" icon="pokemon_types/grass.svg" text="Grass" />
              </List.Item.Detail.Metadata>
            }
          />
        }
      />
    </List>
  );
}

Props

PropDescriptionTypeDefault

title*

The title of the item.

string

-

icon

An icon to illustrate the value of the item.

-

text

The text value of the item. Specifying color will display the text in the provided color. Defaults to Color.SecondaryText.

string or { color?: Color; value: string }

-

An item to display a link.

Example

import { List } from "@raycast/api";

export default function Metadata() {
  return (
    <List isShowingDetail>
      <List.Item
        title="Bulbasaur"
        detail={
          <List.Item.Detail
            metadata={
              <List.Item.Detail.Metadata>
                <List.Item.Detail.Metadata.Link
                  title="Evolution"
                  target="https://www.pokemon.com/us/pokedex/pikachu"
                  text="Raichu"
                />
              </List.Item.Detail.Metadata>
            }
          />
        }
      />
    </List>
  );
}

Props

PropDescriptionTypeDefault

target*

The target of the link.

string

-

text*

The text value of the item.

string

-

title*

The title shown above the item.

string

-

List.Item.Detail.Metadata.TagList

A list of Tags displayed in a row.

Example

import { List } from "@raycast/api";

export default function Metadata() {
  return (
    <List isShowingDetail>
      <List.Item
        title="Bulbasaur"
        detail={
          <List.Item.Detail
            metadata={
              <List.Item.Detail.Metadata>
                <List.Item.Detail.Metadata.TagList title="Type">
                  <List.Item.Detail.Metadata.TagList.Item text="Electric" color={"#eed535"} />
                </List.Item.Detail.Metadata.TagList>
              </List.Item.Detail.Metadata>
            }
          />
        }
      />
    </List>
  );
}

Props

PropDescriptionTypeDefault

children*

The tags contained in the TagList.

React.ReactNode

-

title*

The title shown above the item.

string

-

List.Item.Detail.Metadata.TagList.Item

A Tag in a List.Item.Detail.Metadata.TagList.

Props

PropDescriptionTypeDefault

color

Changes the text color to the provided color and sets a transparent background with the same color.

-

icon

The optional icon tag icon. Required if the tag has no text.

-

text

The optional tag text. Required if the tag has no icon.

string

-

onAction

Callback that is triggered when the item is clicked.

() => void

-

List.Item.Detail.Metadata.Separator

A metadata item that shows a separator line. Use it for grouping and visually separating metadata items.

Example

import { List } from "@raycast/api";

export default function Metadata() {
  return (
    <List isShowingDetail>
      <List.Item
        title="Bulbasaur"
        detail={
          <List.Item.Detail
            metadata={
              <List.Item.Detail.Metadata>
                <List.Item.Detail.Metadata.Label title="Type" icon="pokemon_types/grass.svg" text="Grass" />
                <List.Item.Detail.Metadata.Separator />
                <List.Item.Detail.Metadata.Label title="Type" icon="pokemon_types/poison.svg" text="Poison" />
              </List.Item.Detail.Metadata>
            }
          />
        }
      />
    </List>
  );
}

List.Section

A group of related List.Item.

Sections are a great way to structure your list. For example, group GitHub issues with the same status and order them by priority. This way, the user can quickly access what is most relevant.

Example

import { List } from "@raycast/api";

export default function Command() {
  return (
    <List>
      <List.Section title="Lager">
        <List.Item title="Camden Hells" />
      </List.Section>
      <List.Section title="IPA">
        <List.Item title="Sierra Nevada IPA" />
      </List.Section>
    </List>
  );
}

Props

PropDescriptionTypeDefault

children

The List.Item elements of the section.

React.ReactNode

-

subtitle

An optional subtitle displayed next to the title of the section.

string

-

title

Title displayed above the section.

string

-

Types

List.Item.Accessory

An interface describing an accessory view in a List.Item.

Properties

PropertyDescriptionType

tag*

A string or Date that will be used as the label, optionally colored. The date is formatted relatively to the current time (for example new Date() will be displayed as "now", yesterday's Date will be displayed as "1d", etc.). Color changes the text color to the provided color and sets a transparent background with the same color. Defaults to Color.SecondaryText.

string or Date or undefined or null or { color?: Color.ColorLike; value: string or Date or undefined or null }

text

An optional text that will be used as the label, optionally colored. Color changes the text color to the provided color. Defaults to Color.SecondaryText.

string or null or { color?: Color; value: string or undefined or null }

date

An optional Date that will be used as the label, optionally colored. The date is formatted relatively to the current time (for example new Date() will be displayed as "now", yesterday's Date will be displayed as "1d", etc.). Color changes the text color to the provided color. Defaults to Color.SecondaryText.

Date or null or { color?: Color; value: Date or undefined or null }

icon

An optional Image.ImageLike that will be used as the icon.

tooltip

An optional tooltip shown when the accessory is hovered.

string or null

Example

import { Color, Icon, List } from "@raycast/api";

export default function Command() {
  return (
    <List>
      <List.Item
        title="An Item with Accessories"
        accessories={[
          { text: `An Accessory Text`, icon: Icon.Hammer },
          { text: { value: `A Colored Accessory Text`, color: Color.Orange }, icon: Icon.Hammer },
          { icon: Icon.Person, tooltip: "A person" },
          { text: "Just Do It!" },
          { date: new Date() },
          { tag: new Date() },
          { tag: { value: new Date(), color: Color.Magenta } },
          { tag: { value: "User", color: Color.Magenta }, tooltip: "Tag with tooltip" },
        ]}
      />
    </List>
  );
}

Last updated