improvement(ui): updated kb tag component to match existing table (#2498)

* improvement(ui): updated kb tag component to match existing table

* fix selection

* fix more ui

---------

Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai>
This commit is contained in:
Waleed
2025-12-19 22:26:24 -08:00
committed by GitHub
parent f91beb324e
commit 6385d82b85
4 changed files with 148 additions and 236 deletions

View File

@@ -1,18 +1,9 @@
'use client'
import { useMemo, useRef, useState } from 'react'
import { useMemo, useRef } from 'react'
import { Plus } from 'lucide-react'
import {
Button,
Input,
Label,
Popover,
PopoverAnchor,
PopoverContent,
PopoverItem,
PopoverScrollArea,
Trash,
} from '@/components/emcn'
import { Button, Combobox, type ComboboxOption, Label, Trash } from '@/components/emcn'
import { Input } from '@/components/ui/input'
import { FIELD_TYPE_LABELS, getPlaceholderForFieldType } from '@/lib/knowledge/constants'
import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text'
import { TagDropdown } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown'
@@ -74,9 +65,6 @@ export function DocumentTagEntry({
const emitTagSelection = useTagSelection(blockId, subBlock.id)
// State for tag name dropdown visibility - one for each row
const [dropdownStates, setDropdownStates] = useState<Record<number, boolean>>({})
// Use preview value when in preview mode, otherwise use store value
const currentValue = isPreview ? previewValue : storeValue
@@ -194,7 +182,13 @@ export function DocumentTagEntry({
}
const handleDeleteRow = (rowIndex: number) => {
if (isPreview || disabled || rows.length <= 1) return
if (isPreview || disabled) return
if (rows.length <= 1) {
// Clear the single row instead of deleting
setStoreValue('')
return
}
const updatedRows = rows.filter((_, idx) => idx !== rowIndex)
const tableDataForStorage = updatedRows.map((row) => ({
@@ -227,88 +221,55 @@ export function DocumentTagEntry({
if (tagDefinitions.length === 0) {
return (
<div className='rounded-md border p-4 text-center text-muted-foreground text-sm'>
No tags defined for this knowledge base.
<br />
Define tags at the knowledge base level first.
<div className='flex h-32 items-center justify-center rounded-lg border border-muted-foreground/25 bg-muted/20'>
<div className='text-center'>
<p className='font-medium text-[var(--text-secondary)] text-sm'>
No tags defined for this knowledge base
</p>
<p className='mt-1 text-[var(--text-muted)] text-xs'>
Define tags at the knowledge base level first
</p>
</div>
</div>
)
}
const renderHeader = () => (
<thead>
<tr className='border-b'>
<th className='w-2/5 border-r px-4 py-2 text-center font-medium text-sm'>Tag</th>
<th className='border-r px-4 py-2 text-center font-medium text-sm'>Value</th>
<th className='w-10' />
<thead className='bg-transparent'>
<tr className='border-[var(--border-strong)] border-b bg-transparent'>
<th className='w-[50%] min-w-0 border-[var(--border-strong)] border-r bg-transparent px-[10px] py-[5px] text-left font-medium text-[14px] text-[var(--text-tertiary)]'>
Tag
</th>
<th className='w-[50%] min-w-0 bg-transparent px-[10px] py-[5px] text-left font-medium text-[14px] text-[var(--text-tertiary)]'>
Value
</th>
</tr>
</thead>
)
const renderTagNameCell = (row: DocumentTagRow, rowIndex: number) => {
const cellValue = row.cells.tagName || ''
const isOpen = dropdownStates[rowIndex] || false
const setIsOpen = (open: boolean) => {
setDropdownStates((prev) => ({ ...prev, [rowIndex]: open }))
}
// Show tags that are either available OR currently selected for this row
const selectableTags = tagDefinitions.filter(
(def) => def.displayName === cellValue || !usedTagNames.has(def.displayName.toLowerCase())
)
const tagOptions: ComboboxOption[] = selectableTags.map((tag) => ({
value: tag.displayName,
label: `${tag.displayName} (${FIELD_TYPE_LABELS[tag.fieldType] || 'Text'})`,
}))
return (
<td className='relative border-r p-1'>
<Popover open={isOpen} onOpenChange={setIsOpen}>
<PopoverAnchor asChild>
<div
className='relative w-full cursor-pointer'
onClick={() => !disabled && setIsOpen(true)}
>
<Input
value={cellValue}
readOnly
disabled={disabled}
autoComplete='off'
placeholder='Select tag'
className='w-full cursor-pointer border-0 text-transparent caret-foreground placeholder:text-muted-foreground/50 focus-visible:ring-0 focus-visible:ring-offset-0'
/>
<div className='pointer-events-none absolute inset-0 flex items-center overflow-hidden bg-transparent px-[8px] font-medium font-sans text-sm'>
<span className='truncate'>
{cellValue || <span className='text-muted-foreground/50'>Select tag</span>}
</span>
</div>
</div>
</PopoverAnchor>
{selectableTags.length > 0 && (
<PopoverContent
side='bottom'
align='start'
sideOffset={4}
maxHeight={192}
className='w-[200px]'
>
<PopoverScrollArea>
{selectableTags.map((tagDef) => (
<PopoverItem
key={tagDef.id}
active={tagDef.displayName === cellValue}
onClick={() => {
handleTagSelection(rowIndex, tagDef.displayName)
setIsOpen(false)
}}
>
<span className='flex-1 truncate'>{tagDef.displayName}</span>
<span className='flex-shrink-0 rounded bg-muted px-1 py-0.5 text-[10px] text-muted-foreground'>
{FIELD_TYPE_LABELS[tagDef.fieldType] || 'Text'}
</span>
</PopoverItem>
))}
</PopoverScrollArea>
</PopoverContent>
)}
</Popover>
<td className='relative min-w-0 overflow-hidden border-[var(--border-strong)] border-r bg-transparent p-0'>
<Combobox
options={tagOptions}
value={cellValue}
onChange={(value) => handleTagSelection(rowIndex, value)}
disabled={disabled || isLoading}
placeholder='Select tag'
className='!border-0 !bg-transparent hover:!bg-transparent px-[10px] py-[8px] font-medium text-sm leading-[21px] focus-visible:ring-0 focus-visible:ring-offset-0 [&>span]:truncate'
/>
</td>
)
}
@@ -333,7 +294,7 @@ export function DocumentTagEntry({
)
return (
<td className='p-1'>
<td className='relative min-w-0 overflow-hidden bg-transparent p-0'>
<div className='relative w-full'>
<Input
ref={(el) => {
@@ -347,10 +308,10 @@ export function DocumentTagEntry({
disabled={disabled || !isTagSelected}
autoComplete='off'
placeholder={isTagSelected ? placeholder : 'Select a tag first'}
className='w-full border-0 text-transparent caret-foreground placeholder:text-muted-foreground/50 focus-visible:ring-0 focus-visible:ring-offset-0'
className='w-full border-0 bg-transparent px-[10px] py-[8px] font-medium text-sm text-transparent leading-[21px] caret-[var(--text-primary)] placeholder:text-[var(--text-muted)] focus-visible:ring-0 focus-visible:ring-offset-0'
/>
<div className='pointer-events-none absolute inset-0 flex items-center overflow-hidden bg-transparent px-[8px] font-medium font-sans text-sm'>
<div className='whitespace-pre'>
<div className='scrollbar-hide pointer-events-none absolute top-0 right-[10px] bottom-0 left-[10px] overflow-x-auto overflow-y-hidden bg-transparent'>
<div className='whitespace-pre py-[8px] font-medium text-[var(--text-primary)] text-sm leading-[21px]'>
{formatDisplayText(cellValue, {
accessiblePrefixes,
highlightAll: !accessiblePrefixes,
@@ -379,29 +340,32 @@ export function DocumentTagEntry({
}
const renderDeleteButton = (rowIndex: number) => {
const canDelete = !isPreview && !disabled
if (isPreview || disabled) return null
return canDelete ? (
<td className='w-10 p-1'>
return (
<td className='w-0 p-0'>
<Button
variant='ghost'
className='h-8 w-8 p-0 opacity-0 group-hover:opacity-100'
className='-translate-y-1/2 absolute top-1/2 right-[8px] transition-opacity'
onClick={() => handleDeleteRow(rowIndex)}
>
<Trash className='h-4 w-4 text-muted-foreground' />
<Trash className='h-[14px] w-[14px]' />
</Button>
</td>
) : null
)
}
return (
<div className='relative'>
<div className='overflow-visible rounded-md border'>
<table className='w-full'>
<div className='relative w-full'>
<div className='overflow-hidden rounded-[4px] border border-[var(--border-strong)] bg-[var(--surface-2)] dark:bg-[#1F1F1F]'>
<table className='w-full table-fixed bg-transparent'>
{renderHeader()}
<tbody>
<tbody className='bg-transparent'>
{rows.map((row, rowIndex) => (
<tr key={row.id} className='group relative border-t'>
<tr
key={row.id}
className='group relative border-[var(--border-strong)] border-t bg-transparent'
>
{renderTagNameCell(row, rowIndex)}
{renderValueCell(row, rowIndex)}
{renderDeleteButton(rowIndex)}
@@ -411,15 +375,10 @@ export function DocumentTagEntry({
</table>
</div>
{/* Add Row Button */}
{/* Add Tag Button */}
{!isPreview && !disabled && (
<div className='mt-3'>
<Button
variant='outline'
onClick={handleAddRow}
disabled={!canAddMoreTags}
className='h-7 px-2 text-xs'
>
<Button onClick={handleAddRow} disabled={!canAddMoreTags} className='h-7 px-2 text-xs'>
<Plus className='mr-1 h-2.5 w-2.5' />
Add Tag
</Button>

View File

@@ -2,19 +2,8 @@
import { useState } from 'react'
import { Plus } from 'lucide-react'
import {
Button,
Combobox,
type ComboboxOption,
Input,
Label,
Popover,
PopoverAnchor,
PopoverContent,
PopoverItem,
PopoverScrollArea,
Trash,
} from '@/components/emcn'
import { Button, Combobox, type ComboboxOption, Label, Trash } from '@/components/emcn'
import { Input } from '@/components/ui/input'
import { FIELD_TYPE_LABELS, getPlaceholderForFieldType } from '@/lib/knowledge/constants'
import { type FilterFieldType, getOperatorsForFieldType } from '@/lib/knowledge/filters/types'
import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text'
@@ -66,21 +55,15 @@ export function KnowledgeTagFilters({
previewValue,
}: KnowledgeTagFiltersProps) {
const [storeValue, setStoreValue] = useSubBlockValue<string | null>(blockId, subBlock.id)
// Hook for immediate tag/dropdown selections
const emitTagSelection = useTagSelection(blockId, subBlock.id)
// Get the knowledge base ID from other sub-blocks
const [knowledgeBaseIdValue] = useSubBlockValue(blockId, 'knowledgeBaseId')
const knowledgeBaseId = knowledgeBaseIdValue || null
// Use KB tag definitions hook to get available tags
const { tagDefinitions, isLoading } = useKnowledgeBaseTagDefinitions(knowledgeBaseId)
// Get accessible prefixes for variable highlighting
const accessiblePrefixes = useAccessibleReferencePrefixes(blockId)
// State for managing tag dropdown
const [activeTagDropdown, setActiveTagDropdown] = useState<{
rowIndex: number
showTags: boolean
@@ -89,15 +72,10 @@ export function KnowledgeTagFilters({
element?: HTMLElement | null
} | null>(null)
// State for dropdown visibility - one for each row
const [dropdownStates, setDropdownStates] = useState<Record<number, boolean>>({})
// Parse the current value to extract filters
const parseFilters = (filterValue: string | null): TagFilter[] => {
if (!filterValue) return []
try {
const parsed = JSON.parse(filterValue)
// Handle legacy format (without fieldType/operator)
return parsed.map((f: TagFilter) => ({
...f,
fieldType: f.fieldType || 'text',
@@ -111,7 +89,6 @@ export function KnowledgeTagFilters({
const currentValue = isPreview ? previewValue : storeValue
const filters = parseFilters(currentValue || null)
// Transform filters to table format for display
const rows: TagFilterRow[] =
filters.length > 0
? filters.map((filter) => ({
@@ -128,7 +105,7 @@ export function KnowledgeTagFilters({
: [
{
id: 'empty-row-0',
cells: { tagName: '', fieldType: 'text', operator: 'eq', value: '' },
cells: { tagName: '', fieldType: 'text', operator: '', value: '' },
},
]
@@ -138,17 +115,18 @@ export function KnowledgeTagFilters({
setStoreValue(value)
}
/** Convert rows back to TagFilter format */
const rowsToFilters = (rowsToConvert: TagFilterRow[]): TagFilter[] => {
return rowsToConvert.map((row) => ({
id: row.id,
tagName: row.cells.tagName || '',
tagSlot: row.cells.tagSlot,
fieldType: row.cells.fieldType || 'text',
operator: row.cells.operator || 'eq',
tagValue: row.cells.value || '',
valueTo: row.cells.valueTo,
}))
return rowsToConvert
.filter((row) => row.cells.tagName?.trim())
.map((row) => ({
id: row.id,
tagName: row.cells.tagName || '',
tagSlot: row.cells.tagSlot,
fieldType: row.cells.fieldType || 'text',
operator: row.cells.operator || 'eq',
tagValue: row.cells.value || '',
valueTo: row.cells.valueTo,
}))
}
const handleCellChange = (rowIndex: number, column: string, value: string | FilterFieldType) => {
@@ -158,15 +136,13 @@ export function KnowledgeTagFilters({
if (idx === rowIndex) {
const newCells = { ...row.cells, [column]: value }
// Reset operator when field type changes
if (column === 'fieldType') {
const operators = getOperatorsForFieldType(value as FilterFieldType)
newCells.operator = operators[0]?.value || 'eq'
newCells.value = '' // Reset value when type changes
newCells.value = ''
newCells.valueTo = undefined
}
// Reset valueTo if operator is not 'between'
if (column === 'operator' && value !== 'between') {
newCells.valueTo = undefined
}
@@ -179,11 +155,9 @@ export function KnowledgeTagFilters({
updateFilters(rowsToFilters(updatedRows))
}
/** Handle tag name selection from dropdown */
const handleTagNameSelection = (rowIndex: number, tagName: string) => {
if (isPreview || disabled) return
// Find the tag definition to get fieldType and tagSlot
const tagDef = tagDefinitions.find((t) => t.displayName === tagName)
const fieldType = (tagDef?.fieldType || 'text') as FilterFieldType
const operators = getOperatorsForFieldType(fieldType)
@@ -198,7 +172,7 @@ export function KnowledgeTagFilters({
tagSlot: tagDef?.tagSlot,
fieldType,
operator: operators[0]?.value || 'eq',
value: '', // Reset value when tag changes
value: '',
valueTo: undefined,
},
}
@@ -242,7 +216,14 @@ export function KnowledgeTagFilters({
}
const handleDeleteRow = (rowIndex: number) => {
if (isPreview || disabled || rows.length <= 1) return
if (isPreview || disabled) return
if (rows.length <= 1) {
// Clear the single row instead of deleting
setStoreValue(null)
return
}
const updatedRows = rows.filter((_, idx) => idx !== rowIndex)
updateFilters(rowsToFilters(updatedRows))
}
@@ -261,80 +242,48 @@ export function KnowledgeTagFilters({
}
const renderHeader = () => (
<thead>
<tr className='border-b'>
<th className='w-[35%] border-r px-2 py-2 text-center font-medium text-sm'>Tag</th>
<th className='w-[25%] border-r px-2 py-2 text-center font-medium text-sm'>Operator</th>
<th className='border-r px-2 py-2 text-center font-medium text-sm'>Value</th>
<th className='w-10' />
<thead className='bg-transparent'>
<tr className='border-[var(--border-strong)] border-b bg-transparent'>
<th className='w-[35%] min-w-0 border-[var(--border-strong)] border-r bg-transparent px-[10px] py-[5px] text-left font-medium text-[14px] text-[var(--text-tertiary)]'>
Tag
</th>
<th className='w-[35%] min-w-0 border-[var(--border-strong)] border-r bg-transparent px-[10px] py-[5px] text-left font-medium text-[14px] text-[var(--text-tertiary)]'>
Operator
</th>
<th className='w-[30%] min-w-0 bg-transparent px-[10px] py-[5px] text-left font-medium text-[14px] text-[var(--text-tertiary)]'>
Value
</th>
</tr>
</thead>
)
const renderTagNameCell = (row: TagFilterRow, rowIndex: number) => {
const cellValue = row.cells.tagName || ''
const isOpen = dropdownStates[rowIndex] || false
const setIsOpen = (open: boolean) => {
setDropdownStates((prev) => ({ ...prev, [rowIndex]: open }))
}
const tagOptions: ComboboxOption[] = tagDefinitions.map((tag) => ({
value: tag.displayName,
label: `${tag.displayName} (${FIELD_TYPE_LABELS[tag.fieldType] || 'Text'})`,
}))
return (
<td className='relative border-r p-1'>
<Popover open={isOpen} onOpenChange={setIsOpen}>
<PopoverAnchor asChild>
<div
className='relative w-full cursor-pointer'
onClick={() => !disabled && !isLoading && setIsOpen(true)}
>
<Input
value={cellValue}
readOnly
disabled={disabled || isLoading}
autoComplete='off'
className='w-full cursor-pointer border-0 text-transparent caret-foreground placeholder:text-muted-foreground/50 focus-visible:ring-0 focus-visible:ring-offset-0'
/>
<div className='pointer-events-none absolute inset-0 flex items-center overflow-hidden bg-transparent px-[8px] font-medium font-sans text-sm'>
<span className='truncate'>{cellValue || 'Select tag'}</span>
</div>
</div>
</PopoverAnchor>
{tagDefinitions.length > 0 && (
<PopoverContent
side='bottom'
align='start'
sideOffset={4}
maxHeight={192}
className='w-[200px]'
>
<PopoverScrollArea>
{tagDefinitions.map((tag) => (
<PopoverItem
key={tag.id}
onClick={() => {
handleTagNameSelection(rowIndex, tag.displayName)
setIsOpen(false)
}}
>
<span className='flex-1 truncate'>{tag.displayName}</span>
<span className='flex-shrink-0 rounded bg-muted px-1 py-0.5 text-[10px] text-muted-foreground'>
{FIELD_TYPE_LABELS[tag.fieldType] || 'Text'}
</span>
</PopoverItem>
))}
</PopoverScrollArea>
</PopoverContent>
)}
</Popover>
<td className='relative min-w-0 overflow-hidden border-[var(--border-strong)] border-r bg-transparent p-0'>
<Combobox
options={tagOptions}
value={cellValue}
onChange={(value) => handleTagNameSelection(rowIndex, value)}
disabled={disabled || isLoading}
placeholder='Select tag'
className='!border-0 !bg-transparent hover:!bg-transparent px-[10px] py-[8px] font-medium text-sm leading-[21px] focus-visible:ring-0 focus-visible:ring-offset-0 [&>span]:truncate'
/>
</td>
)
}
/** Render operator cell */
const renderOperatorCell = (row: TagFilterRow, rowIndex: number) => {
const fieldType = row.cells.fieldType || 'text'
const operator = row.cells.operator || 'eq'
const operator = row.cells.operator || ''
const operators = getOperatorsForFieldType(fieldType)
const isOperatorDisabled = disabled || !row.cells.tagName
const operatorOptions: ComboboxOption[] = operators.map((op) => ({
value: op.value,
@@ -342,14 +291,14 @@ export function KnowledgeTagFilters({
}))
return (
<td className='border-r p-1'>
<td className='relative min-w-0 overflow-hidden border-[var(--border-strong)] border-r bg-transparent p-0'>
<Combobox
options={operatorOptions}
value={operator}
onChange={(value) => handleCellChange(rowIndex, 'operator', value)}
disabled={disabled || !row.cells.tagName}
placeholder='Operator'
size='sm'
disabled={isOperatorDisabled}
placeholder='Select operator'
className='!border-0 !bg-transparent hover:!bg-transparent px-[10px] py-[8px] font-medium text-sm leading-[21px] focus-visible:ring-0 focus-visible:ring-offset-0 [&>span]:truncate'
/>
</td>
)
@@ -364,7 +313,6 @@ export function KnowledgeTagFilters({
const isDisabled = disabled || !row.cells.tagName
const placeholder = getPlaceholderForFieldType(fieldType)
// Single text input for all field types with variable support
const renderInput = (value: string, column: 'value' | 'valueTo') => (
<div className='relative w-full'>
<Input
@@ -375,7 +323,6 @@ export function KnowledgeTagFilters({
handleCellChange(rowIndex, column, newValue)
// Check for tag trigger (only for primary value input)
if (column === 'value') {
const tagTrigger = checkTagTrigger(newValue, cursorPosition)
@@ -412,10 +359,10 @@ export function KnowledgeTagFilters({
disabled={isDisabled}
autoComplete='off'
placeholder={placeholder}
className='w-full border-0 text-transparent caret-foreground placeholder:text-muted-foreground/50 focus-visible:ring-0 focus-visible:ring-offset-0'
className='w-full border-0 bg-transparent px-[10px] py-[8px] font-medium text-sm text-transparent leading-[21px] caret-[var(--text-primary)] placeholder:text-[var(--text-muted)] focus-visible:ring-0 focus-visible:ring-offset-0'
/>
<div className='pointer-events-none absolute inset-0 flex items-center overflow-hidden bg-transparent px-[8px] font-medium font-sans text-sm'>
<div className='whitespace-pre'>
<div className='scrollbar-hide pointer-events-none absolute top-0 right-[10px] bottom-0 left-[10px] overflow-x-auto overflow-y-hidden bg-transparent'>
<div className='whitespace-pre py-[8px] font-medium text-[var(--text-primary)] text-sm leading-[21px]'>
{formatDisplayText(value || '', {
accessiblePrefixes,
highlightAll: !accessiblePrefixes,
@@ -425,11 +372,10 @@ export function KnowledgeTagFilters({
</div>
)
// Render with optional "between" second input
if (isBetween) {
return (
<td className='p-1'>
<div className='flex items-center gap-1'>
<td className='relative min-w-0 overflow-hidden bg-transparent p-0'>
<div className='flex items-center gap-1 px-[10px]'>
{renderInput(cellValue, 'value')}
<span className='flex-shrink-0 text-muted-foreground text-xs'>to</span>
{renderInput(valueTo, 'valueTo')}
@@ -438,23 +384,27 @@ export function KnowledgeTagFilters({
)
}
return <td className='p-1'>{renderInput(cellValue, 'value')}</td>
return (
<td className='relative min-w-0 overflow-hidden bg-transparent p-0'>
{renderInput(cellValue, 'value')}
</td>
)
}
const renderDeleteButton = (rowIndex: number) => {
const canDelete = !isPreview && !disabled
if (isPreview || disabled) return null
return canDelete ? (
<td className='w-10 p-1'>
return (
<td className='w-0 p-0'>
<Button
variant='ghost'
className='h-8 w-8 p-0 opacity-0 group-hover:opacity-100'
className='-translate-y-1/2 absolute top-1/2 right-[8px] transition-opacity'
onClick={() => handleDeleteRow(rowIndex)}
>
<Trash className='h-4 w-4 text-muted-foreground' />
<Trash className='h-[14px] w-[14px]' />
</Button>
</td>
) : null
)
}
if (isLoading) {
@@ -462,13 +412,16 @@ export function KnowledgeTagFilters({
}
return (
<div className='relative'>
<div className='overflow-visible rounded-md border'>
<table className='w-full'>
<div className='relative w-full'>
<div className='overflow-hidden rounded-[4px] border border-[var(--border-strong)] bg-[var(--surface-2)] dark:bg-[#1F1F1F]'>
<table className='w-full table-fixed bg-transparent'>
{renderHeader()}
<tbody>
<tbody className='bg-transparent'>
{rows.map((row, rowIndex) => (
<tr key={row.id} className='group relative border-t'>
<tr
key={row.id}
className='group relative border-[var(--border-strong)] border-t bg-transparent'
>
{renderTagNameCell(row, rowIndex)}
{renderOperatorCell(row, rowIndex)}
{renderValueCell(row, rowIndex)}
@@ -502,7 +455,7 @@ export function KnowledgeTagFilters({
{/* Add Filter Button */}
{!isPreview && !disabled && (
<div className='mt-3 flex items-center justify-between'>
<Button variant='outline' onClick={handleAddRow} className='h-7 px-2 text-xs'>
<Button onClick={handleAddRow} className='h-7 px-2 text-xs'>
<Plus className='mr-1 h-2.5 w-2.5' />
Add Filter
</Button>

View File

@@ -57,7 +57,6 @@ export const KnowledgeBlock: BlockConfig = {
type: 'knowledge-tag-filters',
placeholder: 'Add tag filters',
condition: { field: 'operation', value: 'search' },
mode: 'advanced',
},
{
id: 'documentId',

View File

@@ -18,8 +18,13 @@
import * as React from 'react'
import { cva, type VariantProps } from 'class-variance-authority'
import { ChevronDown, ChevronLeft, ChevronRight } from 'lucide-react'
import { Button } from '@/components/emcn/components/button/button'
import {
Popover,
PopoverAnchor,
PopoverContent,
} from '@/components/emcn/components/popover/popover'
import { cn } from '@/lib/core/utils/cn'
import { Popover, PopoverAnchor, PopoverContent } from '../popover/popover'
/**
* Variant styles for the date picker trigger button.
@@ -388,13 +393,9 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
{/* Today Button */}
<div className='border-[var(--surface-11)] border-t px-[8px] py-[8px]'>
<button
type='button'
className='w-full rounded-[4px] py-[6px] text-[12px] text-[var(--text-muted)] transition-colors hover:bg-[var(--surface-9)] hover:text-[var(--text-primary)]'
onClick={handleSelectToday}
>
<Button variant='active' className='w-full' onClick={handleSelectToday}>
Today
</button>
</Button>
</div>
</PopoverContent>
</div>