Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/web/app/playground/playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import DropdownMenuDeepSearchLinear from '@/registry/examples/dropdown-menu/deep-search-linear'
import DropdownMenuDeepSearchLinearAsync from '@/registry/examples/dropdown-menu/deep-search-linear-async'
import DropdownMenuDeepSearchLinearAsyncTanstack from '@/registry/examples/dropdown-menu/deep-search-linear-async-tanstack'
import DropdownMenuDeepSearchSubpagesLinear from '@/registry/examples/dropdown-menu/deep-search-subpages-linear'

export function Playground() {
return (
Expand All @@ -12,6 +13,7 @@ export function Playground() {
<DropdownMenuDeepSearchLinear />
<DropdownMenuDeepSearchLinearAsync />
<DropdownMenuDeepSearchLinearAsyncTanstack />
<DropdownMenuDeepSearchSubpagesLinear />
</div>
</div>
)
Expand Down
4 changes: 4 additions & 0 deletions apps/web/content/docs/dropdown-menu/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ Use virtualization to efficiently render large lists with thousands of items. Th

<Example name="dropdown-menu-deep-search-linear" />

### Deep search + subpages (creatable labels)

<Example name="dropdown-menu-deep-search-subpages-linear" />

### Async + Deep Search

<Example name="dropdown-menu-deep-search-linear-async" />
Expand Down
2 changes: 1 addition & 1 deletion apps/web/public/r/base/filters-dropdown-menu.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions apps/web/public/r/base/filters.json

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions apps/web/registry/__index__.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,19 @@ export const examples: RegistryIndex = {
'registry/examples/dropdown-menu/deep-search-linear/icons.tsx',
],
},
'dropdown-menu-deep-search-subpages-linear': {
name: 'dropdown-menu-deep-search-subpages-linear',
type: 'registry:example',
component: React.lazy(
() =>
import('@/registry/examples/dropdown-menu/deep-search-subpages-linear'),
),
files: [
'registry/examples/dropdown-menu/deep-search-subpages-linear/index.tsx',
'registry/examples/dropdown-menu/deep-search-subpages-linear/components.tsx',
'registry/examples/dropdown-menu/deep-search-subpages-linear/icons.tsx',
],
},
'dropdown-menu-deep-search-linear-async': {
name: 'dropdown-menu-deep-search-linear-async',
type: 'registry:example',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import type {
NodeDef,
SubmenuDef,
SubmenuRenderParams,
SubpageContentRenderParams,
SubpageDef,
SubpageTriggerRenderParams,
} from '@bazza-ui/react/dropdown-menu'
import type * as React from 'react'
import { toast } from 'sonner'
Expand Down Expand Up @@ -44,12 +47,19 @@ export type TW_COLOR = keyof typeof LABEL_STYLES_BG
// Label Dot Component
// =============================================================================

export function LabelDot({ color }: { color: string }) {
export function LabelDot({
color,
className,
}: {
color: string
className?: string
}) {
return (
<div
className={cn(
'rounded-full size-2.5',
LABEL_STYLES_BG[color as TW_COLOR] ?? 'bg-neutral-500',
className,
)}
/>
)
Expand Down Expand Up @@ -251,3 +261,64 @@ export function createSubmenuNode(
),
}
}

/**
* Creates a subpage node with deep search enabled.
* Subpage content is rendered by DataSubpages as a Popup sibling to DataSurface.
*/
export function createSubpageNode(
id: string,
title: string,
icon: React.ReactNode,
childNodes: NodeDef[],
options?: {
inputPlaceholder?: string
hideInputUntilActive?: boolean
},
): SubpageDef {
const { inputPlaceholder = `${title}...`, hideInputUntilActive = false } =
options ?? {}

return {
kind: 'subpage',
id,
value: title,
deepSearch: true,
nodes: childNodes,
renderTrigger: ({ props, context }: SubpageTriggerRenderParams) => (
<DropdownMenu.SubpageTrigger {...props}>
<div className="flex items-center gap-2">
<DropdownMenu.Icon>{icon}</DropdownMenu.Icon>
<LabelWithBreadcrumbs
label={title}
breadcrumbs={
context.isDeepSearchResult ? context.breadcrumbs : undefined
}
/>
</div>
</DropdownMenu.SubpageTrigger>
),
renderContent: ({ pageId, context }: SubpageContentRenderParams) => (
<DropdownMenu.Subpage pageId={pageId}>
<DropdownMenu.Surface>
<DropdownMenu.DataInput
placeholder={inputPlaceholder}
hideUntilActive={hideInputUntilActive}
/>
<DropdownMenu.DataList virtualized>
{({ nodes: filteredNodes, renderNode: renderFilteredNode }) => (
<>
{!context.isDeepSearchResult ? (
<DropdownMenu.SubpageBackItem>
Back
</DropdownMenu.SubpageBackItem>
) : null}
{filteredNodes.map((node) => renderFilteredNode(node))}
</>
)}
</DropdownMenu.DataList>
</DropdownMenu.Surface>
</DropdownMenu.Subpage>
),
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ import type { NodeDef } from '@bazza-ui/react/dropdown-menu'
import * as React from 'react'
import { Button } from '@/components/ui/button'
import { DropdownMenu } from '@/registry/ui/dropdown-menu'
import { AIFilterIcon } from '../subpage-linear/icons'
import {
createAssigneeItemNode,
createItemNode,
createLabelItemNode,
createSubmenuNode,
createSubpageNode,
FilterIcon,
} from './components'
import {
AssigneeIcon,
DurationIcon,
LabelsIcon,
ProjectLeadIcon,
ProjectPriority,
Expand Down Expand Up @@ -150,6 +153,29 @@ function buildMenuContent(): NodeDef[] {
{ inputPlaceholder: 'Labels...' },
)

const aiFilterSubpage = createSubpageNode(
'ai-filter',
'AI Filter',
<AIFilterIcon />,
[
createItemNode('ai-triage', 'Smart triage'),
createItemNode('ai-risk', 'Risk prediction'),
createItemNode('ai-duplicates', 'Duplicate detection'),
createSubmenuNode(
'ai-confidence',
'Confidence',
<ProjectPriorityIcon />,
[
createItemNode('high-confidence', 'High confidence'),
createItemNode('medium-confidence', 'Medium confidence'),
createItemNode('low-confidence', 'Low confidence'),
],
{ inputPlaceholder: 'AI confidence...' },
),
],
{ inputPlaceholder: 'AI filters...' },
)

// Project Properties > Project Status submenu
const projectStatusMenu = createSubmenuNode(
'project-status',
Expand Down Expand Up @@ -253,6 +279,7 @@ function buildMenuContent(): NodeDef[] {
assigneeMenu,
priorityMenu,
labelsMenu,
aiFilterSubpage,
projectPropertiesMenu,
]
}
Expand Down Expand Up @@ -284,6 +311,7 @@ export default function DropdownMenuDeepSearchLinear() {
)}
</DropdownMenu.DataList>
</DropdownMenu.DataSurface>
<DropdownMenu.DataSubpages />
</DropdownMenu.Popup>
</DropdownMenu.Positioner>
</DropdownMenu.Portal>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use client'

export * from '../deep-search-linear/components'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from '../deep-search-linear/icons'
Loading
Loading