p-autocomplete-10

PreviousNext

Autocomplete with grouped items

Docs
cossblock

Preview

Loading preview…
registry/default/particles/p-autocomplete-10.tsx
"use client";

import * as React from "react";

import {
  Autocomplete,
  AutocompleteCollection,
  AutocompleteEmpty,
  AutocompleteGroup,
  AutocompleteGroupLabel,
  AutocompleteInput,
  AutocompleteItem,
  AutocompleteList,
  AutocompletePopup,
  AutocompleteSeparator,
} from "@/registry/default/ui/autocomplete";

// Grouped items demo
type Tag = { id: string; label: string; group: "Status" | "Priority" | "Team" };
type TagGroup = { value: string; items: Tag[] };

const tagsData: Tag[] = [
  // Status
  { group: "Status", id: "s-open", label: "Open" },
  { group: "Status", id: "s-in-progress", label: "In progress" },
  { group: "Status", id: "s-blocked", label: "Blocked" },
  { group: "Status", id: "s-resolved", label: "Resolved" },
  { group: "Status", id: "s-closed", label: "Closed" },
  // Priority
  { group: "Priority", id: "p-low", label: "Low" },
  { group: "Priority", id: "p-medium", label: "Medium" },
  { group: "Priority", id: "p-high", label: "High" },
  { group: "Priority", id: "p-urgent", label: "Urgent" },
  // Team
  { group: "Team", id: "t-design", label: "Design" },
  { group: "Team", id: "t-frontend", label: "Frontend" },
  { group: "Team", id: "t-backend", label: "Backend" },
  { group: "Team", id: "t-devops", label: "DevOps" },
  { group: "Team", id: "t-qa", label: "QA" },
  { group: "Team", id: "t-mobile", label: "Mobile" },
  { group: "Team", id: "t-data", label: "Data" },
  { group: "Team", id: "t-security", label: "Security" },
  { group: "Team", id: "t-platform", label: "Platform" },
  { group: "Team", id: "t-infra", label: "Infrastructure" },
  { group: "Team", id: "t-product", label: "Product" },
  { group: "Team", id: "t-marketing", label: "Marketing" },
  { group: "Team", id: "t-sales", label: "Sales" },
  { group: "Team", id: "t-support", label: "Support" },
  { group: "Team", id: "t-research", label: "Research" },
  { group: "Team", id: "t-content", label: "Content" },
  { group: "Team", id: "t-analytics", label: "Analytics" },
  { group: "Team", id: "t-operations", label: "Operations" },
  { group: "Team", id: "t-finance", label: "Finance" },
  { group: "Team", id: "t-hr", label: "HR" },
  { group: "Team", id: "t-legal", label: "Legal" },
  { group: "Team", id: "t-growth", label: "Growth" },
  { group: "Team", id: "t-partner", label: "Partner" },
  { group: "Team", id: "t-community", label: "Community" },
  { group: "Team", id: "t-docs", label: "Docs" },
  { group: "Team", id: "t-l10n", label: "Localization" },
  { group: "Team", id: "t-a11y", label: "Accessibility" },
  { group: "Team", id: "t-sre", label: "SRE" },
  { group: "Team", id: "t-release", label: "Release" },
  { group: "Team", id: "t-architecture", label: "Architecture" },
  { group: "Team", id: "t-ux", label: "UX" },
  { group: "Team", id: "t-ui", label: "UI" },
  { group: "Team", id: "t-management", label: "Management" },
];

function groupTags(tags: Tag[]): TagGroup[] {
  const groups: Record<string, Tag[]> = {};
  for (const tag of tags) {
    if (!groups[tag.group]) {
      groups[tag.group] = [];
    }
    // biome-ignore lint/style/noNonNullAssertion: will never be null
    groups[tag.group]!.push(tag);
  }

  const order: Array<TagGroup["value"]> = ["Status", "Priority", "Team"];
  return order.map((value) => ({ items: groups[value] ?? [], value }));
}

const groupedTags: TagGroup[] = groupTags(tagsData);

export default function Particle() {
  return (
    <Autocomplete items={groupedTags}>
      <div className="flex flex-col items-start gap-2">
        <AutocompleteInput
          aria-label="Search tags"
          placeholder="e.g. feature"
        />
      </div>
      <AutocompletePopup>
        <AutocompleteEmpty>No tags found.</AutocompleteEmpty>
        <AutocompleteList>
          {(group: TagGroup) => (
            <React.Fragment key={group.value}>
              <AutocompleteGroup items={group.items}>
                <AutocompleteGroupLabel>{group.value}</AutocompleteGroupLabel>
                <AutocompleteCollection>
                  {(tag: Tag) => (
                    <AutocompleteItem key={tag.id} value={tag}>
                      {tag.label}
                    </AutocompleteItem>
                  )}
                </AutocompleteCollection>
              </AutocompleteGroup>
              {group.value !== "Team" && <AutocompleteSeparator />}
            </React.Fragment>
          )}
        </AutocompleteList>
      </AutocompletePopup>
    </Autocomplete>
  );
}

Installation

npx shadcn@latest add @coss/p-autocomplete-10

Usage

import { PAutocomplete10 } from "@/components/p-autocomplete-10"
<PAutocomplete10 />