combobox

Invisible combobox with member tags

Invisible combobox with member tags

Загрузка превью…

src/combobox/c-combobox-20.vue

<!--
  Unsplash-URL заменены локальным 1x1 data-URI (см. `c-combobox-10.vue`).
-->
<script setup lang="ts">
import { ref } from "vue"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxContent, ComboboxEmpty, ComboboxItem, ComboboxList, ComboboxValue, useComboboxAnchor } from "@/components/ui/combobox"
import { Field } from "@/components/ui/field"
import { Item, ItemContent, ItemDescription, ItemTitle } from "@/components/ui/item"

const PIXEL =
  "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAUwAOw=="

const users = [
  { id: "1", name: "Alex Johnson", email: "alex@example.com", initials: "AJ" },
  { id: "2", name: "Sarah Chen", email: "sarah@example.com", initials: "SC" },
  { id: "3", name: "Michael Rodriguez", email: "michael@example.com", initials: "MR" },
  { id: "4", name: "Emma Wilson", email: "emma@example.com", initials: "EW" },
  { id: "5", name: "David Kim", email: "david@example.com", initials: "DK" },
  { id: "6", name: "Aron Thompson", email: "lisa@example.com", initials: "LT" },
  { id: "7", name: "James Brown", email: "james@example.com", initials: "JB" },
  { id: "8", name: "Maria Garcia", email: "maria@example.com", initials: "MG" },
  { id: "9", name: "Nick Johnson", email: "nick@example.com", initials: "NJ" },
  { id: "10", name: "Liam Thompson", email: "liam@example.com", initials: "LT" },
]

const members = users.map((user, index) => ({
  ...user,
  avatar: PIXEL,
  position: ["Software Engineer", "Product Manager", "UX Designer", "Technical Lead", "CTO"][
    index % 5
  ],
}))

type Member = (typeof members)[number]

const anchor = useComboboxAnchor()
const selected = ref<Member[]>([members[5]!, members[9]!, members[3]!])

function handleRemove(id: string) {
  selected.value = selected.value.filter((m) => m.id !== id)
}
</script>

<template>
  <Field class="max-w-xs">
    <Combobox
      multiple
      :by="(a, b) => (a as Member).id === (b as Member).id"
      :model-value="selected"
      @update:model-value="(v) => (selected = v as unknown as Member[])"
    >
      <ComboboxChips class="border-none bg-transparent p-0 shadow-none ring-0 focus-within:ring-0">
        <ComboboxValue v-slot="{ value }">
          <ComboboxChip
            v-for="member in (value as Member[]) ?? []"
            :key="member.id"
            :show-remove="true"
            class="bg-background rounded-full inline-flex h-auto items-center gap-1.5 border py-0.5 pl-2 shadow-xs **:data-[slot=combobox-chip-remove]:mr-0.5 **:data-[slot=combobox-chip-remove]:bg-transparent"
            @remove="handleRemove(member.id)"
          >
            <Avatar class="size-4">
              <AvatarImage :src="member.avatar" :alt="member.name" />
              <AvatarFallback class="text-[8px]">{{ member.initials }}</AvatarFallback>
            </Avatar>
            {{ member.name }}
          </ComboboxChip>
          <ComboboxChipsInput placeholder="Add members..." class="bg-transparent" />
        </ComboboxValue>
      </ComboboxChips>
      <ComboboxContent :anchor="anchor" class="max-w-(--anchor-width) min-w-(--anchor-width)">
        <ComboboxEmpty>No members found.</ComboboxEmpty>
        <ComboboxList>
          <ComboboxItem v-for="member in members" :key="member.id" :value="member">
            <Item size="xs" class="p-0">
              <Avatar class="size-6">
                <AvatarImage :src="member.avatar" :alt="member.name" />
                <AvatarFallback>{{ member.initials }}</AvatarFallback>
              </Avatar>
              <ItemContent>
                <ItemTitle class="whitespace-nowrap">{{ member.name }}</ItemTitle>
                <ItemDescription>{{ member.position }}</ItemDescription>
              </ItemContent>
            </Item>
          </ComboboxItem>
        </ComboboxList>
      </ComboboxContent>
    </Combobox>
  </Field>
</template>

Установка

npx shadcn-vue@latest add https://revueui.rootapi.dev/r/c-combobox-20.json

Зависимости реестра

Источник: порт из ReUI (Keenthemes, MIT)