Status Select
An issue status Select styled with Tailwind CSS.
Example#
import {Button, Label, ListBox, ListBoxItem, Popover, Select, SelectValue} from 'react-aria-components';
import type {ListBoxItemProps} from 'react-aria-components';
import ChevronUpDownIcon from '@spectrum-icons/workflow/ChevronUpDown';
import CheckIcon from '@spectrum-icons/workflow/Checkmark';
function SelectExample() {
return (
<div className="bg-gradient-to-tl from-amber-500 to-rose-700 p-8 sm:h-[250px] rounded-lg flex justify-center">
<Select className="flex flex-col gap-1 w-[200px]">
<Label className="text-white cursor-default">Status</Label>
<Button className="flex items-center cursor-default rounded-lg border-0 bg-white bg-opacity-90 pressed:bg-opacity-100 transition py-2 pl-5 pr-2 text-base text-left leading-normal shadow-md text-gray-700 focus:outline-none focus-visible:ring-2 ring-white ring-offset-2 ring-offset-rose-700">
<SelectValue className="flex-1 truncate placeholder-shown:italic" />
<ChevronUpDownIcon size="XS" />
</Button>
<Popover className="max-h-60 w-[--trigger-width] overflow-auto rounded-md bg-white text-base shadow-lg ring-1 ring-black/5 entering:animate-in entering:fade-in exiting:animate-out exiting:fade-out">
<ListBox className="outline-none p-1">
<StatusItem textValue="Backlog">
<Status className="bg-gray-500" />
Backlog
</StatusItem>
<StatusItem textValue="In Progress">
<Status className="bg-blue-500" />
In Progress
</StatusItem>
<StatusItem textValue="In Review">
<Status className="bg-yellow-500" />
In Review
</StatusItem>
<StatusItem textValue="Done">
<Status className="bg-green-500" />
Done
</StatusItem>
<StatusItem textValue="Won't Do">
<Status className="bg-red-500" />
Won't Do
</StatusItem>
</ListBox>
</Popover>
</Select>
</div>
);
}
function StatusItem(props: ListBoxItemProps & { children: React.ReactNode }) {
return (
<ListBoxItem
{...props}
className="group flex items-center gap-2 cursor-default select-none py-2 px-4 outline-none rounded text-gray-900 focus:bg-rose-600 focus:text-white"
>
{({ isSelected }) => (
<>
<span className="flex-1 flex items-center gap-2 truncate font-normal group-selected:font-medium">
{props.children}
</span>
<span className="w-5 flex items-center text-rose-600 group-focus:text-white">
{isSelected && <CheckIcon size="S" />}
</span>
</>
)}
</ListBoxItem>
);
}
function Status({ className }: { className: string }) {
return (
<span
className={`w-3 h-3 rounded-full border border-solid border-white `}
/>
);
}
import {
Button,
Label,
ListBox,
ListBoxItem,
Popover,
Select,
SelectValue
} from 'react-aria-components';
import type {ListBoxItemProps} from 'react-aria-components';
import ChevronUpDownIcon from '@spectrum-icons/workflow/ChevronUpDown';
import CheckIcon from '@spectrum-icons/workflow/Checkmark';
function SelectExample() {
return (
<div className="bg-gradient-to-tl from-amber-500 to-rose-700 p-8 sm:h-[250px] rounded-lg flex justify-center">
<Select className="flex flex-col gap-1 w-[200px]">
<Label className="text-white cursor-default">
Status
</Label>
<Button className="flex items-center cursor-default rounded-lg border-0 bg-white bg-opacity-90 pressed:bg-opacity-100 transition py-2 pl-5 pr-2 text-base text-left leading-normal shadow-md text-gray-700 focus:outline-none focus-visible:ring-2 ring-white ring-offset-2 ring-offset-rose-700">
<SelectValue className="flex-1 truncate placeholder-shown:italic" />
<ChevronUpDownIcon size="XS" />
</Button>
<Popover className="max-h-60 w-[--trigger-width] overflow-auto rounded-md bg-white text-base shadow-lg ring-1 ring-black/5 entering:animate-in entering:fade-in exiting:animate-out exiting:fade-out">
<ListBox className="outline-none p-1">
<StatusItem textValue="Backlog">
<Status className="bg-gray-500" />
Backlog
</StatusItem>
<StatusItem textValue="In Progress">
<Status className="bg-blue-500" />
In Progress
</StatusItem>
<StatusItem textValue="In Review">
<Status className="bg-yellow-500" />
In Review
</StatusItem>
<StatusItem textValue="Done">
<Status className="bg-green-500" />
Done
</StatusItem>
<StatusItem textValue="Won't Do">
<Status className="bg-red-500" />
Won't Do
</StatusItem>
</ListBox>
</Popover>
</Select>
</div>
);
}
function StatusItem(
props: ListBoxItemProps & { children: React.ReactNode }
) {
return (
<ListBoxItem
{...props}
className="group flex items-center gap-2 cursor-default select-none py-2 px-4 outline-none rounded text-gray-900 focus:bg-rose-600 focus:text-white"
>
{({ isSelected }) => (
<>
<span className="flex-1 flex items-center gap-2 truncate font-normal group-selected:font-medium">
{props.children}
</span>
<span className="w-5 flex items-center text-rose-600 group-focus:text-white">
{isSelected && <CheckIcon size="S" />}
</span>
</>
)}
</ListBoxItem>
);
}
function Status({ className }: { className: string }) {
return (
<span
className={`w-3 h-3 rounded-full border border-solid border-white `}
/>
);
}
import {
Button,
Label,
ListBox,
ListBoxItem,
Popover,
Select,
SelectValue
} from 'react-aria-components';
import type {ListBoxItemProps} from 'react-aria-components';
import ChevronUpDownIcon from '@spectrum-icons/workflow/ChevronUpDown';
import CheckIcon from '@spectrum-icons/workflow/Checkmark';
function SelectExample() {
return (
<div className="bg-gradient-to-tl from-amber-500 to-rose-700 p-8 sm:h-[250px] rounded-lg flex justify-center">
<Select className="flex flex-col gap-1 w-[200px]">
<Label className="text-white cursor-default">
Status
</Label>
<Button className="flex items-center cursor-default rounded-lg border-0 bg-white bg-opacity-90 pressed:bg-opacity-100 transition py-2 pl-5 pr-2 text-base text-left leading-normal shadow-md text-gray-700 focus:outline-none focus-visible:ring-2 ring-white ring-offset-2 ring-offset-rose-700">
<SelectValue className="flex-1 truncate placeholder-shown:italic" />
<ChevronUpDownIcon size="XS" />
</Button>
<Popover className="max-h-60 w-[--trigger-width] overflow-auto rounded-md bg-white text-base shadow-lg ring-1 ring-black/5 entering:animate-in entering:fade-in exiting:animate-out exiting:fade-out">
<ListBox className="outline-none p-1">
<StatusItem textValue="Backlog">
<Status className="bg-gray-500" />
Backlog
</StatusItem>
<StatusItem textValue="In Progress">
<Status className="bg-blue-500" />
In Progress
</StatusItem>
<StatusItem textValue="In Review">
<Status className="bg-yellow-500" />
In Review
</StatusItem>
<StatusItem textValue="Done">
<Status className="bg-green-500" />
Done
</StatusItem>
<StatusItem textValue="Won't Do">
<Status className="bg-red-500" />
Won't Do
</StatusItem>
</ListBox>
</Popover>
</Select>
</div>
);
}
function StatusItem(
props:
& ListBoxItemProps
& {
children:
React.ReactNode;
}
) {
return (
<ListBoxItem
{...props}
className="group flex items-center gap-2 cursor-default select-none py-2 px-4 outline-none rounded text-gray-900 focus:bg-rose-600 focus:text-white"
>
{(
{ isSelected }
) => (
<>
<span className="flex-1 flex items-center gap-2 truncate font-normal group-selected:font-medium">
{props
.children}
</span>
<span className="w-5 flex items-center text-rose-600 group-focus:text-white">
{isSelected &&
(
<CheckIcon size="S" />
)}
</span>
</>
)}
</ListBoxItem>
);
}
function Status(
{ className }: {
className: string;
}
) {
return (
<span
className={`w-3 h-3 rounded-full border border-solid border-white `}
/>
);
}
Tailwind config#
This example uses the following plugins:
Add them to your tailwind.config.js
:
module.exports = {
// ...
plugins: [
require('tailwindcss-react-aria-components'),
require('tailwindcss-animate')
]
};
module.exports = {
// ...
plugins: [
require('tailwindcss-react-aria-components'),
require('tailwindcss-animate')
]
};
module.exports = {
// ...
plugins: [
require(
'tailwindcss-react-aria-components'
),
require(
'tailwindcss-animate'
)
]
};
Components#
Select
A select displays a collapsible list of options, and allows a user to select one of them.
ListBox
A listbox allows a user to select one or more options from a list.
Popover
A popover displays content in context with a trigger element.
Button
A button allows a user to perform an action.