mirror of
https://github.com/ibelick/webclaw.git
synced 2026-08-14 09:02:04 +00:00
feat: update command-session UI
This commit is contained in:
@@ -53,11 +53,11 @@ function CommandDialogViewport({
|
||||
...props
|
||||
}: CommandDialogPrimitive.Viewport.Props) {
|
||||
return (
|
||||
<CommandDialogPrimitive.Viewport
|
||||
className={cn(
|
||||
'fixed inset-0 z-50 flex flex-col items-center px-4 py-[max(--spacing(4),4vh)] sm:py-[10vh]',
|
||||
className,
|
||||
)}
|
||||
<CommandDialogPrimitive.Viewport
|
||||
className={cn(
|
||||
'fixed inset-0 z-50 flex flex-col items-center justify-center px-4 py-[max(--spacing(4),4vh)]',
|
||||
className,
|
||||
)}
|
||||
data-slot="command-dialog-viewport"
|
||||
{...props}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import { Fragment, useMemo } from 'react'
|
||||
import { Fragment, useMemo, useState } from 'react'
|
||||
import { HugeiconsIcon } from '@hugeicons/react'
|
||||
import { ArrowDown01Icon, ArrowUp01Icon } from '@hugeicons/core-free-icons'
|
||||
import {
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
CommandCollection,
|
||||
CommandDialog,
|
||||
CommandDialogPopup,
|
||||
CommandEmpty,
|
||||
CommandFooter,
|
||||
CommandGroup,
|
||||
CommandGroupLabel,
|
||||
@@ -18,6 +17,7 @@ import {
|
||||
CommandPanel,
|
||||
CommandSeparator,
|
||||
} from '@/components/ui/command'
|
||||
import { useAutocompleteFilter } from '@/components/ui/autocomplete'
|
||||
|
||||
type CommandSession = {
|
||||
key: string
|
||||
@@ -58,6 +58,9 @@ function CommandSessionDialog({
|
||||
onOpenChange,
|
||||
onSelect,
|
||||
}: CommandSessionProps) {
|
||||
const [value, setValue] = useState('')
|
||||
const filter = useAutocompleteFilter({ sensitivity: 'base' })
|
||||
|
||||
const groupedItems = useMemo<Array<CommandSessionGroup>>(() => {
|
||||
return [
|
||||
{
|
||||
@@ -72,39 +75,65 @@ function CommandSessionDialog({
|
||||
]
|
||||
}, [sessions])
|
||||
|
||||
const filteredGroups = useMemo(() => {
|
||||
const query = value.trim()
|
||||
if (!query) return groupedItems
|
||||
|
||||
return groupedItems
|
||||
.map((group) => ({
|
||||
...group,
|
||||
items: group.items.filter((item) =>
|
||||
filter.contains(item, query, (target) => target.label),
|
||||
),
|
||||
}))
|
||||
.filter((group) => group.items.length > 0)
|
||||
}, [filter, groupedItems, value])
|
||||
|
||||
const isEmpty = filteredGroups.length === 0
|
||||
|
||||
return (
|
||||
<CommandDialog open={open} onOpenChange={onOpenChange}>
|
||||
<CommandDialogPopup>
|
||||
<Command items={groupedItems}>
|
||||
<CommandDialogPopup className="mx-auto self-center">
|
||||
<Command
|
||||
items={groupedItems}
|
||||
value={value}
|
||||
onValueChange={setValue}
|
||||
mode="none"
|
||||
>
|
||||
<CommandInput placeholder="Search sessions" />
|
||||
<CommandPanel className="flex min-h-0 flex-1 flex-col">
|
||||
<CommandEmpty>No sessions found.</CommandEmpty>
|
||||
<CommandList className="max-h-72 min-h-0">
|
||||
{(group: CommandSessionGroup, index: number) => (
|
||||
<Fragment key={`${group.value}-${index}`}>
|
||||
<CommandGroup items={group.items}>
|
||||
<CommandGroupLabel>{group.value}</CommandGroupLabel>
|
||||
<CommandCollection>
|
||||
{(item: CommandSessionItem) => (
|
||||
<CommandItem
|
||||
key={item.value}
|
||||
value={item.label}
|
||||
onClick={() => onSelect(item.session)}
|
||||
className="gap-2"
|
||||
>
|
||||
<span className="text-sm font-[450] line-clamp-1">
|
||||
{item.label}
|
||||
</span>
|
||||
</CommandItem>
|
||||
)}
|
||||
</CommandCollection>
|
||||
</CommandGroup>
|
||||
{index < groupedItems.length - 1 ? (
|
||||
<CommandSeparator />
|
||||
) : null}
|
||||
</Fragment>
|
||||
)}
|
||||
</CommandList>
|
||||
{isEmpty ? (
|
||||
<div className="h-72 min-h-0 flex items-center justify-center text-sm text-primary-600">
|
||||
No sessions found.
|
||||
</div>
|
||||
) : (
|
||||
<CommandList className="h-72 min-h-0">
|
||||
{filteredGroups.map((group, index) => (
|
||||
<Fragment key={`${group.value}-${index}`}>
|
||||
<CommandGroup items={group.items}>
|
||||
<CommandGroupLabel>{group.value}</CommandGroupLabel>
|
||||
<CommandCollection>
|
||||
{(item) => (
|
||||
<CommandItem
|
||||
key={item.value}
|
||||
value={item.label}
|
||||
onClick={() => onSelect(item.session)}
|
||||
className="gap-2"
|
||||
>
|
||||
<span className="text-sm font-[450] line-clamp-1">
|
||||
{item.label}
|
||||
</span>
|
||||
</CommandItem>
|
||||
)}
|
||||
</CommandCollection>
|
||||
</CommandGroup>
|
||||
{index < filteredGroups.length - 1 ? (
|
||||
<CommandSeparator />
|
||||
) : null}
|
||||
</Fragment>
|
||||
))}
|
||||
</CommandList>
|
||||
)}
|
||||
</CommandPanel>
|
||||
<CommandFooter>
|
||||
<div className="flex items-center gap-4 text-primary-700">
|
||||
|
||||
Reference in New Issue
Block a user