Skip to content

Commit

Permalink
feat: add max width for table cells (#387)
Browse files Browse the repository at this point in the history
  • Loading branch information
islxyqwe authored May 26, 2024
1 parent f5e805a commit 5ce9b8c
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 12 deletions.
1 change: 1 addition & 0 deletions packages/graphic-walker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@radix-ui/react-context-menu": "^2.1.5",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-hover-card": "^1.0.7",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-popover": "^1.0.7",
Expand Down
79 changes: 70 additions & 9 deletions packages/graphic-walker/src/components/dataTable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ import { PureFilterEditDialog } from '../../fields/filterField/filterEditDialog'
import { BarsArrowDownIcon, BarsArrowUpIcon, FunnelIcon } from '@heroicons/react/24/outline';
import { ComputationContext } from '../../store';
import { parsedOffsetDate } from '../../lib/op/offset';
import { formatDate } from '../../utils';
import { cn, formatDate } from '../../utils';
import { FieldProfiling } from './profiling';
import { addFilterForQuery, createFilter } from '../../utils/workflow';
import { Button, buttonVariants } from '../ui/button';
import { Badge } from '../ui/badge';
import { HoverCard, HoverCardContent, HoverCardTrigger } from '../ui/hover-card';

interface DataTableProps {
/** page limit */
Expand Down Expand Up @@ -164,12 +165,66 @@ function useFilters(metas: IMutField[]) {
return { filters, options, editingFilterIdx, onSelectFilter, onDeleteFilter, onWriteFilter, onClose };
}

function FieldValue(props: { field: IMutField; item: IRow; displayOffset?: number }) {
function fieldValue(props: { field: IMutField; item: IRow; displayOffset?: number }) {
const { field, item } = props;
if (field.semanticType === 'temporal') {
return <>{formatDate(parsedOffsetDate(props.displayOffset, field.offset)(item[field.fid]))}</>;
return formatDate(parsedOffsetDate(props.displayOffset, field.offset)(item[field.fid]));
}
return <>{`${item[field.fid]}`}</>;
return `${item[field.fid]}`;
}

function CopyButton(props: { value: string }) {
const [copied, setCopied] = useState(false);
useEffect(() => {
if (copied) {
const timer = setTimeout(() => {
setCopied(false);
}, 2000);
return () => {
clearTimeout(timer);
};
}
}, [copied]);
return (
<Button
variant="secondary"
className="h-6 px-2 text-xs w-14"
size="sm"
onClick={() => {
try {
navigator.clipboard.writeText(props.value);
setCopied(true);
} catch (e) {
console.error(e);
}
}}
disabled={copied}
>
{copied ? 'Copied' : 'Copy'}
</Button>
);
}

function TruncateDector(props: { value: string }) {
const ref = useRef<HTMLAnchorElement>(null);
const [isTruncate, setIsTruncate] = useState(false);
const [open, setOpen] = useState(false);
useEffect(() => {
if (ref.current) {
setIsTruncate(ref.current.offsetWidth < ref.current.scrollWidth);
}
}, [ref.current]);
return (
<HoverCard open={open && isTruncate} onOpenChange={setOpen}>
<HoverCardTrigger ref={ref} className="truncate block">
{props.value}
</HoverCardTrigger>
<HoverCardContent className="flex space-x-2 items-center w-fit py-2 px-3">
<p className="text-xs max-w-[360px] line-clamp-4 break-all">{props.value}</p>
<CopyButton value={props.value} />
</HoverCardContent>
</HoverCard>
);
}

const DataTable: React.FC<DataTableProps> = (props) => {
Expand Down Expand Up @@ -442,11 +497,17 @@ const DataTable: React.FC<DataTableProps> = (props) => {
<tbody className="divide-y divide-border bg-background font-mono">
{rows.map((row, index) => (
<tr className="divide-x divide-border" key={index}>
{metas.map((field) => (
<td key={field.fid + index} className={getHeaderType(field) + ' whitespace-nowrap py-2 px-4 text-xs text-muted-foreground'}>
<FieldValue field={field} item={row} displayOffset={displayOffset} />
</td>
))}
{metas.map((field) => {
const value = fieldValue({ field, item: row, displayOffset });
return (
<td
key={field.fid + index}
className={getHeaderType(field) + ' whitespace-nowrap py-2 px-4 text-xs text-muted-foreground max-w-[240px]'}
>
<TruncateDector value={value} />
</td>
);
})}
</tr>
))}
</tbody>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function NominalProfiling({ computation, field, valueRenderer = (s) => `${s}` }:
return (
<Tooltip key={idx} content={displayValue}>
<div className="w-full rounded-md px-2 py-1 hover:bg-accent flex justify-between space-x-2">
<div className="min-w-[0px] flex-shrink whitespace-nowrap text-ellipsis overflow-hidden">{displayValue}</div>
<div className="min-w-[0px] flex-shrink truncate max-w-[180px]">{displayValue}</div>
<div className="flex-shrink-0">{Math.floor((100 * count) / meta.total)}%</div>
</div>
</Tooltip>
Expand Down
30 changes: 30 additions & 0 deletions packages/graphic-walker/src/components/ui/hover-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as React from 'react';
import * as HoverCardPrimitive from '@radix-ui/react-hover-card';

import { cn } from '@/utils';
import { portalContainerContext } from '@/store/theme';

const HoverCard = HoverCardPrimitive.Root;

const HoverCardTrigger = HoverCardPrimitive.Trigger;

const HoverCardContent = React.forwardRef<
React.ElementRef<typeof HoverCardPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>
>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
<HoverCardPrimitive.Portal container={React.useContext(portalContainerContext)}>
<HoverCardPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
'z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className
)}
{...props}
/>
</HoverCardPrimitive.Portal>
));
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;

export { HoverCard, HoverCardTrigger, HoverCardContent };
20 changes: 18 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1297,6 +1297,22 @@
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-use-callback-ref" "1.0.1"

"@radix-ui/react-hover-card@^1.0.7":
version "1.0.7"
resolved "https://registry.yarnpkg.com/@radix-ui/react-hover-card/-/react-hover-card-1.0.7.tgz#684bca2504432566357e7157e087051aa3577948"
integrity sha512-OcUN2FU0YpmajD/qkph3XzMcK/NmSk9hGWnjV68p6QiZMgILugusgQwnLSDs3oFSJYGKf3Y49zgFedhGh04k9A==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "1.0.1"
"@radix-ui/react-compose-refs" "1.0.1"
"@radix-ui/react-context" "1.0.1"
"@radix-ui/react-dismissable-layer" "1.0.5"
"@radix-ui/react-popper" "1.1.3"
"@radix-ui/react-portal" "1.0.4"
"@radix-ui/react-presence" "1.0.1"
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-use-controllable-state" "1.0.1"

"@radix-ui/react-icons@^1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-icons/-/react-icons-1.3.0.tgz#c61af8f323d87682c5ca76b856d60c2312dbcb69"
Expand Down Expand Up @@ -2060,7 +2076,7 @@
"@types/react" "*"
"@types/reactcss" "*"

"@types/react-dom@*", "@types/react-dom@^18.2.15", "@types/react-dom@^18.x":
"@types/react-dom@*", "@types/react-dom@^18.2.15":
version "18.3.0"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0"
integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==
Expand All @@ -2074,7 +2090,7 @@
dependencies:
"@types/react" "*"

"@types/react@*", "@types/react@^18.2.37", "@types/react@^18.x":
"@types/react@*", "@types/react@^18.2.37":
version "18.3.2"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.2.tgz#462ae4904973bc212fa910424d901e3d137dbfcd"
integrity sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==
Expand Down

0 comments on commit 5ce9b8c

Please sign in to comment.