fix: fix UI regression related to DataTable (#17943)

* fix: fix UI regression regarding DataTable

* update comment
This commit is contained in:
Eunjae Lee authored and GitHub committed 2024-12-02 18:54:58 +00:00
1 parent b33ca2f937
commit 27cd2457e8
5 files changed
+127 -102

No files matched your search

@@ -62,12 +62,13 @@ export function DataTable<TData, TValue>({
const columnSizeVars = useMemo(() => {
const headers = table.getFlatHeaders();
const colSizes: { [key: string]: number } = {};
const colSizes: { [key: string]: string } = {};
for (let i = 0; i < headers.length; i++) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const header = headers[i]!;
colSizes[`--header-${header.id}-size`] = header.getSize();
colSizes[`--col-${header.column.id}-size`] = header.column.getSize();
const isAutoWidth = header.column.columnDef.meta?.autoWidth;
colSizes[`--header-${header.id}-size`] = isAutoWidth ? "auto" : `${header.getSize()}px`;
colSizes[`--col-${header.column.id}-size`] = isAutoWidth ? "auto" : `${header.column.getSize()}px`;
}
return colSizes;
}, [table.getFlatHeaders(), table.getState().columnSizingInfo, table.getState().columnSizing]);
@@ -102,7 +103,7 @@ export function DataTable<TData, TValue>({
style={{
...(meta?.sticky?.position === "left" && { left: `${meta.sticky.gap || 0}px` }),
...(meta?.sticky?.position === "right" && { right: `${meta.sticky.gap || 0}px` }),
width: `calc(var(--header-${header?.id}-size) * 1px)`,
width: `var(--header-${header?.id}-size)`,
}}
className={classNames(
"flex shrink-0 items-center",
@@ -162,7 +163,7 @@ export function DataTable<TData, TValue>({
style={{
...(meta?.sticky?.position === "left" && { left: `${meta.sticky.gap || 0}px` }),
...(meta?.sticky?.position === "right" && { right: `${meta.sticky.gap || 0}px` }),
width: `calc(var(--col-${cell.column.id}-size) * 1px)`,
width: `var(--col-${cell.column.id}-size)`,
}}
className={classNames(
"flex shrink-0 items-center overflow-hidden",
@@ -28,6 +28,7 @@ const GroupTeamMappingTable = () => {
{
id: "name",
header: t("team"),
size: 200,
cell: ({ row }) => {
const { name } = row.original;
@@ -37,6 +38,7 @@ const GroupTeamMappingTable = () => {
{
id: "group",
header: t("group_name"),
size: 200,
cell: ({ row }) => {
const { id, groupNames, directoryId } = row.original;
@@ -45,6 +45,7 @@ import {
DialogFooter,
Dropdown,
DropdownItem,
DropdownMenuPortal,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
@@ -283,6 +284,7 @@ export default function MemberList(props: Props) {
id: "select",
enableHiding: false,
enableSorting: false,
size: 30,
header: ({ table }) => (
<Checkbox
checked={table.getIsAllPageRowsSelected()}
@@ -305,6 +307,7 @@ export default function MemberList(props: Props) {
accessorFn: (data) => data.email,
enableHiding: false,
header: `Member (${totalDBRowCount})`,
size: 250,
cell: ({ row }) => {
const { username, email, avatarUrl, accepted, name } = row.original;
const memberName =
@@ -344,6 +347,7 @@ export default function MemberList(props: Props) {
id: "role",
accessorFn: (data) => data.role,
header: "Role",
size: 100,
cell: ({ row, table }) => {
const { role, accepted } = row.original;
return (
@@ -387,6 +391,10 @@ export default function MemberList(props: Props) {
},
{
id: "actions",
size: 80,
meta: {
sticky: { position: "right" },
},
cell: ({ row }) => {
const user = row.original;
const isSelf = user.id === session?.user.id;
@@ -454,99 +462,8 @@ export default function MemberList(props: Props) {
StartIcon="ellipsis"
/>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>
<DropdownItem
type="button"
onClick={() =>
dispatch({
type: "EDIT_USER_SHEET",
payload: {
user,
showModal: true,
},
})
}
StartIcon="pencil">
{t("edit")}
</DropdownItem>
</DropdownMenuItem>
{impersonationMode && (
<>
<DropdownMenuItem>
<DropdownItem
type="button"
onClick={() =>
dispatch({
type: "SET_IMPERSONATE_ID",
payload: {
user,
showModal: true,
},
})
}
StartIcon="lock">
{t("impersonate")}
</DropdownItem>
</DropdownMenuItem>
<DropdownMenuSeparator />
</>
)}
{resendInvitation && (
<DropdownMenuItem>
<DropdownItem
type="button"
onClick={() => {
resendInvitationMutation.mutate({
teamId: props.team?.id,
email: user.email,
language: i18n.language,
});
}}
StartIcon="send">
{t("resend_invitation")}
</DropdownItem>
</DropdownMenuItem>
)}
<DropdownMenuItem>
<DropdownItem
type="button"
onClick={() =>
dispatch({
type: "SET_DELETE_ID",
payload: {
user,
showModal: true,
},
})
}
color="destructive"
StartIcon="user-x">
{t("remove")}
</DropdownItem>
</DropdownMenuItem>
</DropdownMenuContent>
</Dropdown>
)}
</ButtonGroup>
<div className="flex md:hidden">
<Dropdown>
<DropdownMenuTrigger asChild>
<Button type="button" variant="icon" color="minimal" StartIcon="ellipsis" />
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem className="outline-none">
<DropdownItem
disabled={!user.accepted}
href={!user.accepted ? undefined : `/${user.username}`}
target="_blank"
type="button"
StartIcon="external-link">
{t("view_public_page")}
</DropdownItem>
</DropdownMenuItem>
{editMode && (
<>
<DropdownMenuPortal>
<DropdownMenuContent>
<DropdownMenuItem>
<DropdownItem
type="button"
@@ -563,10 +480,46 @@ export default function MemberList(props: Props) {
{t("edit")}
</DropdownItem>
</DropdownMenuItem>
{impersonationMode && (
<>
<DropdownMenuItem>
<DropdownItem
type="button"
onClick={() =>
dispatch({
type: "SET_IMPERSONATE_ID",
payload: {
user,
showModal: true,
},
})
}
StartIcon="lock">
{t("impersonate")}
</DropdownItem>
</DropdownMenuItem>
<DropdownMenuSeparator />
</>
)}
{resendInvitation && (
<DropdownMenuItem>
<DropdownItem
type="button"
onClick={() => {
resendInvitationMutation.mutate({
teamId: props.team?.id,
email: user.email,
language: i18n.language,
});
}}
StartIcon="send">
{t("resend_invitation")}
</DropdownItem>
</DropdownMenuItem>
)}
<DropdownMenuItem>
<DropdownItem
type="button"
color="destructive"
onClick={() =>
dispatch({
type: "SET_DELETE_ID",
@@ -576,13 +529,72 @@ export default function MemberList(props: Props) {
},
})
}
color="destructive"
StartIcon="user-x">
{t("remove")}
</DropdownItem>
</DropdownMenuItem>
</>
)}
</DropdownMenuContent>
</DropdownMenuContent>
</DropdownMenuPortal>
</Dropdown>
)}
</ButtonGroup>
<div className="flex md:hidden">
<Dropdown>
<DropdownMenuTrigger asChild>
<Button type="button" variant="icon" color="minimal" StartIcon="ellipsis" />
</DropdownMenuTrigger>
<DropdownMenuPortal>
<DropdownMenuContent>
<DropdownMenuItem className="outline-none">
<DropdownItem
disabled={!user.accepted}
href={!user.accepted ? undefined : `/${user.username}`}
target="_blank"
type="button"
StartIcon="external-link">
{t("view_public_page")}
</DropdownItem>
</DropdownMenuItem>
{editMode && (
<>
<DropdownMenuItem>
<DropdownItem
type="button"
onClick={() =>
dispatch({
type: "EDIT_USER_SHEET",
payload: {
user,
showModal: true,
},
})
}
StartIcon="pencil">
{t("edit")}
</DropdownItem>
</DropdownMenuItem>
<DropdownMenuItem>
<DropdownItem
type="button"
color="destructive"
onClick={() =>
dispatch({
type: "SET_DELETE_ID",
payload: {
user,
showModal: true,
},
})
}
StartIcon="user-x">
{t("remove")}
</DropdownItem>
</DropdownMenuItem>
</>
)}
</DropdownMenuContent>
</DropdownMenuPortal>
</Dropdown>
</div>
</div>
@@ -95,6 +95,7 @@ export function AvailabilitySliderTable(props: { userTimeFormat: number | null;
id: "member",
accessorFn: (data) => data.username,
header: "Member",
size: 200,
cell: ({ row }) => {
const { username, email, timeZone, name, avatarUrl, profile } = row.original;
return (
@@ -125,6 +126,7 @@ export function AvailabilitySliderTable(props: { userTimeFormat: number | null;
id: "timezone",
accessorFn: (data) => data.timeZone,
header: "Timezone",
size: 160,
cell: ({ row }) => {
const { timeZone } = row.original;
const timeRaw = dayjs().tz(timeZone);
@@ -146,6 +148,9 @@ export function AvailabilitySliderTable(props: { userTimeFormat: number | null;
},
{
id: "slider",
meta: {
autoWidth: true,
},
header: () => {
return (
<div className="flex items-center space-x-2">
+5
View File
@@ -7,5 +7,10 @@ declare module "@tanstack/table-core" {
gap?: number;
};
filterType?: "select" | "text";
// `autoWidth` can make the column size dynamic,
// allowing each row to have a different width based on its content.
// As a result, scrolling may be flaky, unless the content size is consistent.
autoWidth?: boolean;
}
}