import { ArgsTable, Meta, Story } from "@storybook/addon-docs";
import { Avatar } from "@components/avatar";
import { ComponentInfo, Preview, Tagline } from "@stories/components";
import { IconList, PlaceholderMajorIcon, UfoMajorIcon, TelescopeMajorIcon, RocketMajorIcon } from "@components/icons";
import { Inline } from "@components/layout";
import { InnerItem, InnerSection, Item, Section } from "@components/collection";
import { InnerListbox, InnerListboxOption, InnerListboxSection, Listbox } from "@components/listbox";
import { Text } from "@components/typography";
import { Tooltip, TooltipTrigger } from "@components/tooltip";

<Meta
    title="Components/Listbox"
    id="listbox"
/>

# Listbox

<Tagline>A listbox presents a list of options and allows a user to select one or more of them</Tagline>

<ComponentInfo
    usage={"import { Listbox, Item, Section, ListboxContext, useListboxContext } from \"@sharegate/orbit-ui\";"}
    ariaPath="listbox"
    githubPath="/packages/components/src/listbox/src"
/>

## Guidelines

### Accessibility

- A listbox should have an [`aria-label`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label) property describing the content of the list.

## Usage

### Default

A default listbox.

<Preview>
    <Story name="default">
        <Listbox aria-label="Planets">
            <Item key="earth">Earth</Item>
            <Item key="jupiter">Jupiter</Item>
            <Item key="mars">Mars</Item>
            <Item key="mercury">Mercury</Item>
            <Item key="neptune">Neptune</Item>
            <Item key="saturn">Saturn</Item>
            <Item key="uranus">Uranus</Item>
        </Listbox>
    </Story>
</Preview>

### Selection mode

A listbox support `single` and `multiple` selection mode.

<Preview>
    <Story name="selection">
        <Inline gap={10}>
            <Listbox aria-label="Planets">
                <Item key="earth">Earth</Item>
                <Item key="jupiter">Jupiter</Item>
                <Item key="mars">Mars</Item>
                <Item key="mercury">Mercury</Item>
                <Item key="neptune">Neptune</Item>
                <Item key="saturn">Saturn</Item>
                <Item key="uranus">Uranus</Item>
            </Listbox>
            <Listbox selectionMode="multiple" aria-label="Planets">
                <Item key="earth">Earth</Item>
                <Item key="jupiter">Jupiter</Item>
                <Item key="mars">Mars</Item>
                <Item key="mercury">Mercury</Item>
                <Item key="neptune">Neptune</Item>
                <Item key="saturn">Saturn</Item>
                <Item key="uranus">Uranus</Item>
            </Listbox>
        </Inline>
    </Story>
</Preview>

### Sections

A listbox items can be group by sections.

<Preview>
    <Story name="sections">
        <Listbox aria-label="Planets">
            <Section title="Visited">
                <Item key="earth">Earth</Item>
                <Item key="mars">Mars</Item>
                <Item key="saturn">Saturn</Item>
            </Section>
            <Section title="Not Visited">
                <Item key="jupiter">Jupiter</Item>
                <Item key="mercury">Mercury</Item>
                <Item key="neptune">Neptune</Item>
                <Item key="uranus">Uranus</Item>
            </Section>
        </Listbox>
    </Story>
</Preview>

### Item icon

A listbox item can have [icons](?path=/docs/icon-gallery--page).

<Preview>
    <Story name="item icon">
        <Listbox aria-label="Planets">
            <Item key="earth">
                <PlaceholderMajorIcon />
                <Text>Earth</Text>
            </Item>
            <Item key="jupiter">
                <PlaceholderMajorIcon />
                <Text>Jupiter</Text>
            </Item>
            <Item key="mars">
                <PlaceholderMajorIcon />
                <Text>Mars</Text>
            </Item>
        </Listbox>
    </Story>
</Preview>

### Item end icon

A listbox item can have *non standard* end [icons](?path=/docs/icon-gallery--page) can be provided to handle special cases like displaying a list of icons.

However, think twice before adding *end* icons, *start* icons should be your go to.

<Preview>
    <Story name="item end icon">
        <Listbox aria-label="Planets">
            <Item key="earth">
                <Text>Earth</Text>
                <IconList slot="end-icon">
                    <UfoMajorIcon />
                    <TelescopeMajorIcon />
                    <RocketMajorIcon />
                </IconList>
            </Item>
            <Item key="jupiter">
                <Text>Jupiter</Text>
                <PlaceholderMajorIcon slot="end-icon" />
            </Item>
            <Item key="mars">
                <Text>Mars</Text>
                <IconList slot="end-icon">
                    <UfoMajorIcon />
                    <TelescopeMajorIcon />
                    <RocketMajorIcon />
                </IconList>
            </Item>
        </Listbox>
    </Story>
</Preview>

### Item description

A listbox item can have a **single line** description.

<Preview>
    <Story name="item description">
        <Listbox aria-label="Planets">
            <Item key="earth">
                <Text>Earth</Text>
                <Text slot="description">Home sweet home!</Text>
            </Item>
            <Item key="jupiter">
                <Text>Jupiter</Text>
                <Text slot="description">The fourth-brightest object in the sky</Text>
            </Item>
            <Item key="mars">
                <Text>Mars</Text>
                <Text slot="description">See you in 2026</Text>
            </Item>
        </Listbox>
    </Story>
</Preview>

A description can be paired with an [icon](?path=/docs/icon-gallery--page).

<Preview>
    <Story name="item description + icon">
        <Listbox aria-label="Planets">
            <Item key="earth">
                <PlaceholderMajorIcon />
                <Text>Earth</Text>
                <Text slot="description">Home sweet home!</Text>
            </Item>
            <Item key="jupiter">
                <PlaceholderMajorIcon />
                <Text>Jupiter</Text>
                <Text slot="description">The fourth-brightest object in the sky</Text>
            </Item>
            <Item key="mars">
                <PlaceholderMajorIcon />
                <Text>Mars</Text>
                <Text slot="description">See you in 2026</Text>
            </Item>
        </Listbox>
    </Story>
</Preview>

A description can also be paired with an [avatar](?path=/docs/avatar--default-story).

<Preview>
    <Story name="item description + avatar">
        <Listbox aria-label="Planets">
            <Item key="earth">
                <Avatar name="Earth" />
                <Text>Earth</Text>
                <Text slot="description">Home sweet home!</Text>
            </Item>
            <Item key="jupiter">
                <Avatar name="Jupiter" />
                <Text>Jupiter</Text>
                <Text slot="description">The fourth-brightest object in the sky</Text>
            </Item>
            <Item key="mars">
                <Avatar name="Mars" />
                <Text>Mars</Text>
                <Text slot="description">See you in 2026</Text>
            </Item>
        </Listbox>
    </Story>
</Preview>

### Item tooltip

A listbox item can have a basic tooltip.

<Preview>
    <Story name="item tooltip">
        <Listbox aria-label="Planets">
            <TooltipTrigger>
                <Item key="earth">Earth</Item>
                <Tooltip>Home sweet home!</Tooltip>
            </TooltipTrigger>
            <TooltipTrigger>
                <Item key="jupiter">Jupiter</Item>
                <Tooltip>The fourth-brightest object in the sky</Tooltip>
            </TooltipTrigger>
            <TooltipTrigger>
                <Item key="mars">Mars</Item>
                <Tooltip>See you in 2026</Tooltip>
            </TooltipTrigger>
        </Listbox>
    </Story>
</Preview>

### Array map

A listbox items can be rendered with an array map.

<Preview>
    <Story name="array map">
        <Listbox aria-label="Planets">
            {["Earth", "Jupiter", "Mars"].map(x => (
                <Item key={x.toLowerCase()}>{x}</Item>
            ))}
        </Listbox>
    </Story>
</Preview>

### Listbox context

The `selectedKeys` state can be retrieved from `useListboxContext`.

<Preview filePath="/listbox/docs/ListboxContext" />

### Disabled item

A listbox item can be disabled.

<Preview>
    <Story name="disabled item">
        <Listbox aria-label="Planets">
            <Item disabled key="earth">Earth</Item>
            <Item key="jupiter">Jupiter</Item>
            <Item key="mars">Mars</Item>
            <Item disabled key="mercury">Mercury</Item>
            <Item key="neptune">Neptune</Item>
            <Item key="saturn">Saturn</Item>
            <Item key="uranus">Uranus</Item>
        </Listbox>
    </Story>
</Preview>

### Fluid

A listbox can take the width of it's container.

<Preview>
    <Story name="fluid">
        <Listbox fluid aria-label="Planets">
            <Item key="earth">Earth</Item>
            <Item key="jupiter">Jupiter</Item>
            <Item key="mars">Mars</Item>
            <Item key="mercury">Mercury</Item>
            <Item key="neptune">Neptune</Item>
            <Item key="saturn">Saturn</Item>
            <Item key="uranus">Uranus</Item>
        </Listbox>
    </Story>
</Preview>

### Validation

A listbox can display a validation state to communicate to the user whether the current value is valid or invalid. Implement your own validation logic in your app and pass either `"valid"` or `"invalid"` to the listbox via the `validationState` prop.

<Preview>
    <Story name="validation">
        <Listbox validationState="invalid" defaultSelectedKeys={["mars"]} aria-label="Planets">
            <Item key="earth">Earth</Item>
            <Item key="jupiter">Jupiter</Item>
            <Item key="mars">Mars</Item>
            <Item key="mercury">Mercury</Item>
            <Item key="neptune">Neptune</Item>
            <Item key="saturn">Saturn</Item>
            <Item key="uranus">Uranus</Item>
        </Listbox>
    </Story>
</Preview>

### Controlled

The `selectedKeys` state can be handled in controlled mode.

<Preview filePath="/listbox/docs/ControlledListbox" />

## API

### Listbox

<ComponentInfo
    usage={"import { Listbox } from \"@sharegate/orbit-ui\";"}
    inherits={[InnerListbox.defaultElement, "styled-component"]}
    compact
/>

<ArgsTable of={InnerListbox} sort="alpha" />

### Item

<ComponentInfo
    usage={"import { Item } from \"@sharegate/orbit-ui\";"}
    slots={["icon", "avatar", "text", "description", "end-icon"]}
    inherits={[InnerItem.defaultElement, "styled-component"]}
    compact
/>

<ArgsTable of={InnerItem} sort="alpha" />

### Section

<ComponentInfo
    usage={"import { Section } from \"@sharegate/orbit-ui\";"}
    inherits={[InnerSection.defaultElement, "styled-component"]}
    compact
/>

<ArgsTable of={InnerSection} sort="alpha" />

### ListboxOption

<ComponentInfo
    usage={"import { ListboxOption } from \"@sharegate/orbit-ui\";"}
    slots={["icon", "avatar", "text", "description", "end-icon"]}
    inherits={[InnerListboxOption.defaultElement, "styled-component"]}
    compact
/>

<ArgsTable of={InnerListboxOption} sort="alpha" />

### ListboxSection

<ComponentInfo
    usage={"import { ListboxSection } from \"@sharegate/orbit-ui\";"}
    inherits={[InnerListboxSection.defaultElement, "styled-component"]}
    compact
/>

<ArgsTable of={InnerListboxSection} sort="alpha" />
