> ## Documentation Index
> Fetch the complete documentation index at: https://anvil.servicetitan.com/llms.txt
> Use this file to discover all available pages before exploring further.

# List – Code

> Implement ordered and unordered lists with the List component.

export const LiveCode = ({children, customHeight, clickToLoad, example, fullWidth, fullHeight, hideCodeInLiveCode, screenshot, screenshotOnly, showCode: showCodeProp}) => {
  const SCREENSHOTS_BASE = "https://servicetitan.github.io/anvil2-docs-live-code/screenshots";
  const STACKBLITZ_BASE = "https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples";
  const [showCodeBlock, setShowCodeBlock] = useState(showCodeProp ?? false);
  const [isLocalOverride, setIsLocalOverride] = useState(false);
  useEffect(() => {
    const examplePath = `/images/live-code-screenshots-tmp/${example}.png`;
    fetch(examplePath, {
      method: "HEAD"
    }).then(r => {
      if (r.ok) setIsLocalOverride(true);
    }).catch(() => {});
  }, [example]);
  const screenshotBase = isLocalOverride ? "/images/live-code-screenshots-tmp" : SCREENSHOTS_BASE;
  if (screenshotOnly) {
    return <Frame className="flex flex-col">
        <div className="flex dark:hidden" style={{
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined,
      background: "#FFFFFF"
    }}>
          <img srcset={`${screenshotBase}/${example}.png, ${screenshotBase}/${example}-2x.png 2x`} src={`${screenshotBase}/${example}.png`} alt={example} noZoom />
        </div>
        <div className="hidden dark:flex" style={{
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined,
      background: "#141414"
    }}>
          <img srcset={`${screenshotBase}/${example}-dark.png, ${screenshotBase}/${example}-dark-2x.png 2x`} src={`${screenshotBase}/${example}-dark.png`} alt={example} noZoom />
        </div>
      </Frame>;
  }
  if (screenshot) {
    return <Frame className="flex flex-col -mb-2">
        <div className="flex dark:hidden bg-white dark:bg-codeblock border border-gray-950/10 dark:border-white/10 dark:twoslash-dark rounded-2xl overflow-hidden" style={{
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined
    }}>
          <img srcset={`${screenshotBase}/${example}.png, ${screenshotBase}/${example}-2x.png 2x`} src={`${screenshotBase}/${example}.png`} alt={example} noZoom />
        </div>

        <div className="hidden dark:flex bg-white dark:bg-codeblock border border-gray-950/10 dark:border-white/10 dark:twoslash-dark rounded-2xl overflow-hidden" style={{
      background: "#141414",
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined
    }}>
          <img srcset={`${screenshotBase}/${example}-dark.png, ${screenshotBase}/${example}-dark-2x.png 2x`} src={`${screenshotBase}/${example}-dark.png`} alt={example} noZoom />
        </div>

        <div className="flex justify-end items-center text-xs py-2 px-1 gap-4">
          {!showCodeProp ? <button className="inline-flex justify-end items-center text-gray-700 dark:text-gray-50 hover:text-blue-500 dark:hover:text-blue-300 transition-colors group self-end gap-1 cursor-pointer" onClick={() => setShowCodeBlock(!showCodeBlock)} style={{
      appearance: "none"
    }}>
              <Icon icon="code" size="12px" className="group-hover:bg-blue-500 dark:group-hover:bg-blue-300" />
              <span>{showCodeBlock ? "Hide code" : "Show code"}</span>
            </button> : null}

          <a className="inline-flex justify-end items-center hover:text-blue-500 dark:hover:text-blue-300 transition-colors group self-end gap-1" href={`${STACKBLITZ_BASE}/${example}?file=src/App.tsx`} target="_blank" rel="noreferrer">
            <Icon icon="bolt" size="12px" className="group-hover:bg-blue-500 dark:group-hover:bg-blue-300" />
            <span>StackBlitz demo</span>
          </a>
        </div>

        <div className="grid transition-[grid-template-rows] duration-300 ease-in-out overflow-auto overflow-y-hidden overflow-x-auto" style={showCodeBlock ? {
      gridTemplateRows: "1fr"
    } : {
      gridTemplateRows: "0fr"
    }}>
          <div style={{
      minHeight: 0,
      overflowX: "auto",
      overflowY: "hidden",
      marginBlockStart: "-1.25rem",
      marginBlockEnd: "-1.5rem"
    }}>
            {children}
          </div>
        </div>
      </Frame>;
  } else {
    return <div style={{
      display: "flex",
      width: fullWidth ? "100%" : "50%",
      minHeight: customHeight ? customHeight : "316px",
      resize: "vertical",
      overflow: "auto"
    }}>
        <iframe title={example} style={{
      flex: 1,
      width: fullWidth ? "100%" : "50%",
      minHeight: customHeight ? customHeight : "316px"
    }} src={`${STACKBLITZ_BASE}/${example}?embed=1&hideNavigation=1&hideExplorer=1&terminalHeight=0&file=src/App.tsx${clickToLoad ? "&ctl=1" : ""}${hideCodeInLiveCode ? "&view=preview" : ""}`} allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts" />
      </div>;
  }
};

<Tabs>
  <Tab title="Implementation">
    <LiveCode showCode example="list-basic" fullWidth screenshot>
      ```tsx lines expandable theme={null}
      import { List } from "@servicetitan/anvil2";

      function App() {
        return (
          <List>
            <List.Item>First item</List.Item>
            <List.Item>Second item</List.Item>
            <List.Item>Third item</List.Item>
          </List>
        );
      }

      export default App;
      ```
    </LiveCode>

    ## Common Examples

    ```tsx theme={null}
    import { List } from "@servicetitan/anvil2";

    function UnorderedExample() {
      return (
        <List>
          <List.Item>Item one</List.Item>
          <List.Item>Item two</List.Item>
        </List>
      );
    }

    function OrderedExample() {
      return (
        <List variant="ordered">
          <List.Item>Step one</List.Item>
          <List.Item>Step two</List.Item>
        </List>
      );
    }
    ```

    ### Unordered list (default)

    Omit `variant` or set `variant="unordered"` to render a `ul` with bullet markers.

    <LiveCode showCode example="list-basic" fullWidth screenshot>
      ```tsx lines expandable theme={null}
      import { List } from "@servicetitan/anvil2";

      function App() {
        return (
          <List>
            <List.Item>First item</List.Item>
            <List.Item>Second item</List.Item>
            <List.Item>Third item</List.Item>
          </List>
        );
      }

      export default App;
      ```
    </LiveCode>

    ### Ordered list

    Set `variant="ordered"` to render an `ol` with numeric markers. You can pass native `ol` attributes such as `start` and `reversed`.

    <LiveCode showCode example="list-ordered" fullWidth screenshot>
      ```tsx lines expandable theme={null}
      import { List } from "@servicetitan/anvil2";

      function App() {
        return (
          <List variant="ordered">
            <List.Item>Step one</List.Item>
            <List.Item>Step two</List.Item>
            <List.Item>Step three</List.Item>
          </List>
        );
      }

      export default App;
      ```
    </LiveCode>

    ### Size

    Use `size` to control typography (`small`, `medium`, `large`).

    <LiveCode showCode example="list-design-size" fullWidth screenshot>
      ```tsx lines expandable theme={null}
      import { List, Flex } from "@servicetitan/anvil2";

      function App() {
        return (
          <Flex direction="column" gap="4">
            <List size="small">
              <List.Item>Small list item</List.Item>
              <List.Item>Second item</List.Item>
            </List>
            <List size="medium">
              <List.Item>Medium list item</List.Item>
              <List.Item>Second item</List.Item>
            </List>
            <List size="large">
              <List.Item>Large list item</List.Item>
              <List.Item>Second item</List.Item>
            </List>
          </Flex>
        );
      }

      export default App;
      ```
    </LiveCode>

    ### Nested lists

    Render a `List` inside a `List.Item` to create sub-lists. Use a different variant (e.g., ordered inside unordered) when it fits the content.

    <LiveCode showCode example="list-nested" fullWidth screenshot>
      ```tsx lines expandable theme={null}
      import { List } from "@servicetitan/anvil2";

      function App() {
        return (
          <List>
            <List.Item>
              Parent item one
              <List variant="ordered">
                <List.Item>Sub-step one</List.Item>
                <List.Item>Sub-step two</List.Item>
              </List>
            </List.Item>
            <List.Item>Parent item two</List.Item>
          </List>
        );
      }

      export default App;
      ```
    </LiveCode>

    ### Ordered with start and reversed

    When `variant="ordered"`, you can pass `start` (number) and `reversed` (boolean) as with native `ol`.

    <LiveCode showCode example="list-ordered-start-reversed" fullWidth screenshot>
      ```tsx lines expandable theme={null}
      import { List, Flex } from "@servicetitan/anvil2";

      function App() {
        return (
          <Flex direction="column" gap="4">
            <List variant="ordered" start={5}>
              <List.Item>Five</List.Item>
              <List.Item>Six</List.Item>
            </List>
            <List variant="ordered" reversed>
              <List.Item>Third</List.Item>
              <List.Item>Second</List.Item>
              <List.Item>First</List.Item>
            </List>
          </Flex>
        );
      }

      export default App;
      ```
    </LiveCode>

    ## React Accessibility

    The `List` component renders semantic `ul`/`ol` and `li` elements, so list structure is exposed to assistive technologies without extra ARIA. Screen readers can announce the list and the number of items. Keep list item content readable and avoid using List for interactive selection; use [`Listbox`](/docs/web/components/listbox/code) or [`Menu`](/docs/web/components/menu/code) for that.
  </Tab>

  <Tab title="List Props">
    ```tsx theme={null}
    <List variant="unordered" size="medium">
      <List.Item>Item</List.Item>
    </List>
    ```

    ## `List` Props

    <ParamField path="size" type={`"small" | "medium" | "large"`} default="medium">
      Typography size for list content. Maps to design system paragraph tokens.
    </ParamField>

    <ParamField path="variant" type={`"unordered" | "ordered"`} default="unordered">
      Renders as `ul` when `"unordered"` (default) or `ol` when `"ordered"`. When `"ordered"`, native `ol` props such as `start` and `reversed` are supported.
    </ParamField>
  </Tab>

  <Tab title="List.Item Props">
    ```tsx theme={null}
    <List.Item>Item content</List.Item>
    ```

    ## `List.Item` Props

    `List.Item` accepts all standard `li` HTML attributes.
  </Tab>
</Tabs>
