Files
zeekayandHanzo Dev 751ef5c778 rename the framework to @hanzo/gui and the loader to @hanzogui/loader
Both old names are owned by a different npm account (artemis-prime), so
publishing them returns 403 — which is how this surfaced: the 8.0.0 run
shipped @hanzogui/logo and @hanzogui/demos depending on [email protected], a
version that cannot be published and therefore does not exist. Those two
were uninstallable.

@hanzo/gui and @hanzogui/* are ours, so the framework now carries the name
it is imported by everywhere downstream, and the loader moves under the
scope we control.

The rewrite is limited to package references. `DEBUG?.startsWith('hanzogui')`
is a log-namespace filter and join(dir, 'hanzogui') is a path — rewriting
either would change behaviour, so both are untouched.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-30 20:23:18 -07:00

349 lines
9.4 KiB
Plaintext

---
title: ListItem
description: A component for displaying rows of items
name: list-item
component: ListItem
package: list-item
demoName: ListItem
---
<HeroContainer>
<ListItemDemo />
</HeroContainer>
```tsx hero template=ListItem
```
<Highlights
features={[
'Accepts size prop that works on all styles.',
'Place an icon before or after.',
'Works with themes, animations, Group.',
'Supports variant prop (e.g., outlined).',
'Use Apply to pass color/size/variant to children.',
]}
/>
## Installation
ListItem is already installed in `hanzogui`, or you can install it independently:
```bash
npm install @hanzogui/list-item
```
## Usage
Basic usage involves providing children or using the `title` and `subTitle` props.
```tsx
import { ListItem, Separator, YGroup } from '@hanzo/gui'
import { ChevronRight } from '@hanzogui/lucide-icons-2' // Example icon
export default () => (
<YGroup
self="center"
borderWidth={1}
borderColor="$borderColor"
rounded="$4"
width={240}
size="$4"
>
<YGroup.Item>
<ListItem title="Star" icon={ChevronRight} />
</YGroup.Item>
<YGroup.Item>
<ListItem title="Moon" subTitle="Subtitle for Moon" iconAfter={ChevronRight} />
</YGroup.Item>
<YGroup.Item>
<ListItem>Custom children content</ListItem>
</YGroup.Item>
</YGroup>
)
```
## Sizing
The `size` prop adjusts various properties of the ListItem, including padding, minimum height, and the default size for text elements within it. It accepts theme size tokens (e.g., `"$3"`, `"$4"`).
```tsx
import { ListItem } from '@hanzo/gui'
export default () => <ListItem size="$5" title="Large List Item" />
```
## Title and SubTitle
Use the `title` and `subTitle` props for a structured layout. These props accept `ReactNode`, so you can pass strings or more complex JSX.
- If `title` or `subTitle` is provided, children will be rendered inside the main text area (under title/subtitle).
- `ListItem.Title` and `ListItem.Subtitle` components are used internally and can be targeted for styling (see Customization).
```tsx
import { ListItem, Avatar } from '@hanzo/gui'
import { User } from '@hanzogui/lucide-icons-2'
export default () => (
<ListItem
icon={
<Avatar circular size="$3">
<Avatar.Image src="/placeholder.png" />
<Avatar.Fallback bc="$backgroundFocus" />
</Avatar>
}
title="User Profile"
subTitle="View and edit your profile details."
iconAfter={User}
size="$4"
/>
)
```
## Icon Theming
Icons can be passed to `icon` (before content) or `iconAfter` (after content) props.
- **Automatic Sizing & Spacing**: Icons are automatically sized based on the ListItem's `size` prop. You can override this with the `iconSize` prop (accepts `SizeTokens`). Spacing between the icon and text is also automatically applied (40% of the icon's final size).
- **Scaling**: Use `scaleIcon` (number, default: 1) to further adjust the icon size relative to its base size.
- **Component Props**: If you pass a component as an icon, it will receive `size` (the calculated pixel size) as a prop.
```tsx
import { ListItem } from '@hanzo/gui'
import { Star, Settings } from '@hanzogui/lucide-icons-2'
export default () => (
<>
<ListItem icon={Star} title="Default Icon Size" size="$4" />
<ListItem
icon={Settings}
iconSize="$2"
title="Explicit Icon Size"
subTitle="iconSize='$2'"
size="$5"
/>
<ListItem
icon={Star}
scaleIcon={1.5}
title="Scaled Icon"
subTitle="scaleIcon={1.5}"
size="$4"
/>
</>
)
```
## Variant
ListItem supports a `variant` prop for different visual styles:
```tsx
import { ListItem } from '@hanzo/gui'
export default () => <ListItem variant="outlined" title="Outlined Style" />
```
Currently supports `outlined` (transparent background with border).
## Apply (Context)
Use `ListItem.Apply` to pass `color`, `size`, and `variant` to multiple children via context:
```tsx
import { ListItem, YGroup } from '@hanzo/gui'
import { Trash } from '@hanzogui/lucide-icons-2'
export default () => (
<YGroup>
<ListItem.Apply color="$red10">
<YGroup.Item>
<ListItem icon={Trash} title="Delete item" />
</YGroup.Item>
<YGroup.Item>
<ListItem icon={Trash} title="Remove all" />
</YGroup.Item>
</ListItem.Apply>
</YGroup>
)
```
The `color` prop passed to `Apply` will be inherited by icons within children.
## Customization
For customization, Gui exports the building blocks: `ListItem.Frame`, `ListItem.Text`, `ListItem.Title`, `ListItem.Subtitle`, and `ListItem.Icon`.
```tsx
import { YStack, ListItem as GuiListItem } from '@hanzo/gui'
import { GetProps, styled } from '@hanzogui/web'
const CustomFrame = styled(GuiListItem.Frame, {
padding: '$5',
backgroundColor: '$backgroundHover',
})
const CustomTitle = styled(GuiListItem.Title, {
color: '$red10',
fontWeight: 'bold',
})
const CustomSubtitle = styled(GuiListItem.Subtitle, {
color: '$gray10',
fontStyle: 'italic',
})
// Recompose, for example, if you need a different internal structure
export const MyAdvancedListItem = ({
icon,
title,
subTitle,
children,
...frameProps
}) => {
return (
<CustomFrame {...frameProps}>
{icon && <GuiListItem.Icon>{icon}</GuiListItem.Icon>}
<YStack flex={1} justify="center">
{title && <CustomTitle>{title}</CustomTitle>}
{subTitle && <CustomSubtitle>{subTitle}</CustomSubtitle>}
{children && <GuiListItem.Text>{children}</GuiListItem.Text>}
</YStack>
{/* iconAfter could go here */}
</CustomFrame>
)
}
```
## API Reference
### ListItem
ListItems extend Stack views, inheriting all the [Gui standard props](/docs/intro/props), plus:
<PropsTable
data={[
{
name: 'title',
required: false,
type: 'React.ReactNode',
description: 'Main text content of the list item. Renders using `ListItem.Title`.',
},
{
name: 'subTitle',
required: false,
type: 'React.ReactNode',
description:
'Secondary text content, rendered below the title. Renders using `ListItem.Subtitle`.',
},
{
name: 'size',
required: false,
type: 'SizeTokens',
description:
'Adjusts padding, min-height, and default font/icon sizes. Uses theme size tokens (e.g., "$3", "$4").',
},
{
name: 'variant',
required: false,
type: "'outlined'",
description:
'Visual variant style. Currently supports "outlined" (transparent background with border).',
},
{
name: 'icon',
required: false,
type: 'JSX.Element | React.ComponentType<{ size?: number }>',
description:
'Icon element or component displayed before the main content. Receives `size` prop if a component.',
},
{
name: 'iconAfter',
required: false,
type: 'JSX.Element | React.ComponentType<{ size?: number }>',
description:
'Icon element or component displayed after the main content. Receives `size` prop if a component.',
},
{
name: 'iconSize',
required: false,
type: 'SizeTokens',
description:
'Explicitly set the size of the icon, overriding the default size derived from the ListItem\'s `size` prop. Uses theme size tokens (e.g., "$2").',
},
{
name: 'scaleIcon',
required: false,
type: 'number',
description:
'Scale factor for the icon (default: 1). Applied after `iconSize` or default size calculation.',
},
{
name: 'disabled',
required: false,
type: 'boolean',
description: 'If true, reduces opacity and disables pointer events.',
},
{
name: 'unstyled',
required: false,
type: 'boolean',
description:
'Removes all default Gui styles (padding, background, etc.). Default is `false` unless `GUI_HEADLESS` is set.',
},
{
name: '// Styling Text',
type: '---',
description:
'To style the `title`, `subTitle`, or general `children` text, use `styled(ListItem, { ... })` to target nested `ListItem.Title`, `ListItem.Subtitle`, or `ListItem.Text` components, or compose your own with these parts. Direct text styling props are not passed for simplicity and performance.',
},
]}
/>
### ListItem.Apply
A context provider that passes `color`, `size`, and `variant` to all ListItem children.
<PropsTable
data={[
{
name: 'color',
required: false,
type: 'ColorTokens | string',
description: 'Color token to pass to icons in children ListItems.',
},
{
name: 'size',
required: false,
type: 'SizeTokens',
description: 'Size token to apply to children ListItems.',
},
{
name: 'variant',
required: false,
type: "'outlined'",
description: 'Variant to apply to children ListItems.',
},
]}
/>
### ListItem.Frame
The base `View` component for the ListItem. Inherits `Stack` props.
### ListItem.Text
Used for wrapping `children` when `title` or `subTitle` are not used. Extends `SizableText`.
### ListItem.Title
Used for rendering the `title` prop. Extends `SizableText`.
### ListItem.Subtitle
Used for rendering the `subTitle` prop. Extends `SizableText`. Its font size is automatically set to one step smaller than the ListItem's main `size`.
### ListItem.Icon
A helper component for rendering icons within ListItem, handling size and color.
Typically used internally but can be leveraged in custom compositions.