Refactor dropdown menu components in various files to prevent event propagation, enhancing user interaction. Update CountedLineTabs component documentation with preview links for better clarity. Improve styling and layout in resource page and user columns for consistency and visual appeal.
This commit is contained in:
@@ -17,7 +17,11 @@ interface CountedLineTabsProps {
|
|||||||
children?: ReactNode
|
children?: ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Line tabs with count pills (c-tabs-2 / data-grid-filtering-2). */
|
/**
|
||||||
|
* Line tabs with count pills — ReUI PRO DNA.
|
||||||
|
* Preview: https://reui.io/preview/base/components/c-tabs-2
|
||||||
|
* Lists: https://reui.io/preview/base/data-grid-filtering-2
|
||||||
|
*/
|
||||||
export function CountedLineTabs({
|
export function CountedLineTabs({
|
||||||
tabs,
|
tabs,
|
||||||
value,
|
value,
|
||||||
@@ -28,12 +32,23 @@ export function CountedLineTabs({
|
|||||||
}: CountedLineTabsProps) {
|
}: CountedLineTabsProps) {
|
||||||
return (
|
return (
|
||||||
<Tabs value={value} onValueChange={onValueChange} className={className}>
|
<Tabs value={value} onValueChange={onValueChange} className={className}>
|
||||||
<TabsList variant="line" className={cn('gap-5', listClassName)}>
|
<TabsList
|
||||||
|
variant="line"
|
||||||
|
className={cn(
|
||||||
|
'h-auto w-full justify-start gap-5 rounded-none bg-transparent p-0',
|
||||||
|
listClassName,
|
||||||
|
)}
|
||||||
|
>
|
||||||
{tabs.map((tab) => (
|
{tabs.map((tab) => (
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
key={tab.id}
|
key={tab.id}
|
||||||
value={tab.id}
|
value={tab.id}
|
||||||
className="text-muted-foreground hover:text-foreground h-auto gap-2 px-0 pb-3 after:bottom-0"
|
className={cn(
|
||||||
|
'text-muted-foreground hover:text-foreground h-auto flex-none gap-2 rounded-none px-0 pb-3 shadow-none',
|
||||||
|
'data-active:bg-transparent data-active:text-foreground data-active:shadow-none',
|
||||||
|
'dark:data-active:border-transparent dark:data-active:bg-transparent',
|
||||||
|
'after:bottom-0 after:bg-foreground',
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
<span>{tab.label}</span>
|
<span>{tab.label}</span>
|
||||||
{tab.count !== undefined ? (
|
{tab.count !== undefined ? (
|
||||||
|
|||||||
@@ -251,6 +251,11 @@ function RowActions({
|
|||||||
onOpen: (row: TelemtErrorRow) => void
|
onOpen: (row: TelemtErrorRow) => void
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
|
<div
|
||||||
|
className="flex items-center justify-center"
|
||||||
|
onClick={(event) => event.stopPropagation()}
|
||||||
|
onPointerDown={(event) => event.stopPropagation()}
|
||||||
|
>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger
|
<DropdownMenuTrigger
|
||||||
render={
|
render={
|
||||||
@@ -271,6 +276,7 @@ function RowActions({
|
|||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -570,14 +570,13 @@ function ResourcePageFiltered<T extends object>({
|
|||||||
<FramePanel className="p-0 shadow-none!">
|
<FramePanel className="p-0 shadow-none!">
|
||||||
{countedTabs.length > 0 ? (
|
{countedTabs.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
<div className="px-(--frame-panel-header-px) pt-(--frame-panel-header-py)">
|
<div className="border-border flex flex-col gap-0 border-b px-(--frame-panel-header-px) pt-(--frame-panel-header-py)">
|
||||||
<CountedLineTabs
|
<CountedLineTabs
|
||||||
tabs={countedTabs}
|
tabs={countedTabs}
|
||||||
value={activeTab}
|
value={activeTab}
|
||||||
onValueChange={handleTabChange}
|
onValueChange={handleTabChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Separator />
|
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
|||||||
@@ -1269,7 +1269,21 @@ function DataGridTableBodyRow<TData>({
|
|||||||
data-depth={row.depth || undefined}
|
data-depth={row.depth || undefined}
|
||||||
data-row-pinned={isRowPinned || undefined}
|
data-row-pinned={isRowPinned || undefined}
|
||||||
data-row-pinned-boundary={pinnedBoundary}
|
data-row-pinned-boundary={pinnedBoundary}
|
||||||
onClick={() => props.onRowClick && props.onRowClick(row.original)}
|
onClick={(event) => {
|
||||||
|
if (!props.onRowClick) return
|
||||||
|
// Interactive controls (actions menu, pin, checkbox, links) must not
|
||||||
|
// open the row detail — same contract as DataGridTableRowPin/Select.
|
||||||
|
const target = event.target
|
||||||
|
if (
|
||||||
|
target instanceof Element &&
|
||||||
|
target.closest(
|
||||||
|
'button, a, input, textarea, select, [role="button"], [role="menuitem"], [role="checkbox"], [data-slot="dropdown-menu-trigger"], [data-slot="checkbox"]'
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
props.onRowClick(row.original)
|
||||||
|
}}
|
||||||
className={cn(
|
className={cn(
|
||||||
"hover:bg-muted/40 data-[state=selected]:bg-muted/50",
|
"hover:bg-muted/40 data-[state=selected]:bg-muted/50",
|
||||||
props.onRowClick && "cursor-pointer",
|
props.onRowClick && "cursor-pointer",
|
||||||
|
|||||||
@@ -199,6 +199,11 @@ export function ActionsCell({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<div
|
||||||
|
className="flex items-center justify-center"
|
||||||
|
onClick={(event) => event.stopPropagation()}
|
||||||
|
onPointerDown={(event) => event.stopPropagation()}
|
||||||
|
>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger
|
<DropdownMenuTrigger
|
||||||
render={
|
render={
|
||||||
@@ -248,6 +253,7 @@ export function ActionsCell({
|
|||||||
</DropdownMenuGroup>
|
</DropdownMenuGroup>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
|
|
||||||
<AlertDialog open={deleteOpen} onOpenChange={setDeleteOpen}>
|
<AlertDialog open={deleteOpen} onOpenChange={setDeleteOpen}>
|
||||||
<AlertDialogContent size="sm">
|
<AlertDialogContent size="sm">
|
||||||
|
|||||||
Reference in New Issue
Block a user