Rc Table
React table component with useful functions.
Installation
- Install the rc-table package.
 
npm i rc-table
- Create a table component, components/table.tsx
 
import React from "react";
import Table from "rc-table";
import { Empty, cn } from "rizzui";
export type ExtractProps<T> = T extends React.ComponentType<infer P> ? P : T;
const tableStyles = {
  table:
    "[&_.rc-table-content]:overflow-x-auto [&_table]:w-full [&_.rc-table-row:hover]:bg-muted/60",
  thead:
    "[&_thead]:text-left [&_thead]:rtl:text-right [&_th.rc-table-cell]:uppercase [&_th.rc-table-cell]:text-xs [&_th.rc-table-cell]:font-medium [&_th.rc-table-cell]:tracking-wide",
  tCell:
    "[&_.rc-table-cell]:px-3 [&_th.rc-table-cell]:py-3 [&_td.rc-table-cell]:py-4",
  variants: {
    classic:
      "[&_thead]:bg-muted/50 [&_.rc-table-container]:border-x [&_.rc-table-container]:border-muted [&_td.rc-table-cell]:border-b [&_td.rc-table-cell]:border-muted [&_thead]:border-y [&_thead]:border-muted",
    modern:
      "[&_thead]:bg-muted/50 [&_td.rc-table-cell]:border-b [&_td.rc-table-cell]:border-muted",
    minimal: "[&_thead]:bg-muted/50",
    elegant:
      "[&_thead]:border-y [&_thead]:border-muted [&_td.rc-table-cell]:border-b [&_td.rc-table-cell]:border-muted",
  },
  striped: "[&_.rc-table-row:nth-child(2n)_.rc-table-cell]:bg-muted/40",
};
type RCTableProps = ExtractProps<typeof Table>;
export interface TableProps
  extends Omit<RCTableProps, "className" | "emptyText"> {
  emptyText?: React.ReactElement;
  variant?: keyof typeof tableStyles.variants;
  striped?: boolean;
  className?: string;
}
export default function RcTable({
  striped,
  variant = "classic",
  emptyText,
  className,
  ...props
}: TableProps) {
  return (
    <Table
      className={cn(
        tableStyles.table,
        tableStyles.thead,
        tableStyles.tCell,
        tableStyles.variants[variant],
        striped && tableStyles.striped,
        className
      )}
      emptyText={emptyText ?? <Empty />}
      {...props}
    />
  );
}
RcTable.displayName = "Table";
- You need to create one more component for the table header cell
 
import React from "react";
import { cn } from "rizzui";
type TextAlign = "left" | "center" | "right";
export interface HeaderCellProps {
  title: React.ReactNode;
  width?: number;
  align?: TextAlign;
  ellipsis?: boolean;
  sortable?: boolean;
  ascending?: boolean;
  iconClassName?: string;
  className?: string;
}
function handleTextAlignment(align: TextAlign) {
  if (align === "center") return "justify-center";
  if (align === "right") return "justify-end rtl:justify-start";
  return "";
}
export default function HeaderCell({
  title,
  align = "left",
  width,
  ellipsis,
  sortable,
  ascending,
  iconClassName,
  className,
}: HeaderCellProps) {
  if (ellipsis && width === undefined) {
    console.warn(
      "When ellipsis is true make sure you are using the same column width in HeaderCell component too."
    );
  }
  if (width !== undefined && ellipsis !== true) {
    console.warn(
      "width prop without ellipsis won't work, please set ellipsis prop true."
    );
  }
  return (
    <div
      className={cn(
        "flex items-center gap-1",
        sortable && "cursor-pointer",
        handleTextAlignment(align),
        className
      )}
    >
      <div
        {...(ellipsis && { className: "truncate" })}
        {...(ellipsis && width && { style: { width } })}
      >
        {title}
      </div>
      {sortable && (
        <div className="inline-flex">
          {ascending ? (
            <svg
              xmlns="http://www.w3.org/2000/svg"
              fill="currentColor"
              className={cn("h-auto w-3", iconClassName)}
              viewBox="0 0 16 16"
            >
              <path d="m7.247 4.86-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z" />
            </svg>
          ) : (
            <svg
              xmlns="http://www.w3.org/2000/svg"
              fill="currentColor"
              className={cn("h-auto w-3", iconClassName)}
              viewBox="0 0 16 16"
            >
              <path d="M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z" />
            </svg>
          )}
        </div>
      )}
    </div>
  );
}
HeaderCell.displayName = "HeaderCell";
Default
The default style of Table component.
Id  | Employee  | Designation  | Phone Number  | Email  | Status  | ||
|---|---|---|---|---|---|---|---|
| 1 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 2 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 3 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 4 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 5 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 6 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | 
import React from "react";
import Table from "@components/table";
import HeaderCell from "@components/header-cell";
import { Checkbox, Avatar, Text, Badge } from "rizzui";
const initialData = [
  {
    id: "1",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/1.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "2",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/2.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "3",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/3.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "4",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/4.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "5",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/5.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "6",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/6.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
];
function getStatusBadge(status: string) {
  switch (status.toLowerCase()) {
    case "pending":
      return <Badge variant="flat">{status}</Badge>;
    case "active":
      return (
        <Badge
          variant="flat"
          color="success"
        >
          {status}
        </Badge>
      );
    case "warning":
      return (
        <Badge
          variant="flat"
          color="warning"
        >
          {status}
        </Badge>
      );
    case "danger":
      return (
        <Badge
          variant="flat"
          color="danger"
        >
          {status}
        </Badge>
      );
    default:
      return null;
  }
}
const getColumns = (order: string, column: string, onHeaderClick: (value: string) => any) => [
  {
    title: <></>,
    dataIndex: "checked",
    key: "checked",
    width: 50,
    render: () => (
      <div className="inline-flex cursor-pointer">
        <Checkbox variant="flat" />
      </div>
    ),
  },
  {
    title: (
      <HeaderCell
        title="Id"
        sortable
        ascending={order === "asc" && column === "id"}
      />
    ),
    onHeaderCell: () => onHeaderClick("id"),
    dataIndex: "id",
    key: "id",
    width: 50,
  },
  {
    title: <HeaderCell title="Employee" />,
    dataIndex: "employee",
    key: "employee",
    width: 250,
    render: (employee: any) => (
      <div className="flex items-center">
        <Avatar
          name="John Doe"
          src={employee.avatar}
        />
        <div className="ml-3 rtl:ml-0 rtl:mr-3">
          <Text
            as="h6"
            className="mb-0.5 !text-sm font-medium"
          >
            {employee.name}
          </Text>
          <Text
            as="p"
            className="text-xs text-gray-400"
          >
            {employee.userName}
          </Text>
        </div>
      </div>
    ),
  },
  {
    title: <HeaderCell title="Designation" />,
    dataIndex: "designation",
    key: "designation",
    width: 320,
    render: (designation: any) => (
      <div>
        <Text
          as="h6"
          className="mb-0.5 !text-sm font-medium"
        >
          {designation.role}
        </Text>
        <Text
          as="p"
          className="text-xs text-gray-400"
        >
          {designation.company}
        </Text>
      </div>
    ),
  },
  {
    title: <HeaderCell title="Phone Number" />,
    dataIndex: "phoneNumber",
    key: "phoneNumber",
    width: 200,
  },
  {
    title: <HeaderCell title="Email" />,
    dataIndex: "email",
    key: "email",
    width: 200,
  },
  {
    title: <HeaderCell title="Status" />,
    dataIndex: "status",
    key: "status",
    width: 120,
    render: (value: string) => getStatusBadge(value),
  },
  {
    title: <></>,
    dataIndex: "action",
    key: "action",
    width: 120,
    render: (_: string, row: any) => (
      <div className="flex items-center gap-2">
        <button
          type="button"
          className="text-primary underline"
          onClick={() => alert(`Edit item #${row.id}`)}
        >
          Edit
        </button>
        <button
          type="button"
          className="underline"
        >
          View
        </button>
      </div>
    ),
  },
];
export default function App() {
  const [order, setOrder] = React.useState<string>("desc");
  const [column, setColumn] = React.useState<string>("");
  const [data, setData] = React.useState<typeof initialData>(initialData);
  const onHeaderClick = (value: string) => ({
    onClick: () => {
      setColumn(value);
      setOrder(order === "desc" ? "asc" : "desc");
      if (order === "desc") {
        // @ts-ignore
        setData([...data.sort((a, b) => (a[value] > b[value] ? -1 : 1))]);
      } else {
        // @ts-ignore
        setData([...data.sort((a, b) => (a[value] > b[value] ? 1 : -1))]);
      }
    },
  });
  const columns: any = React.useMemo(
    () => getColumns(order, column, onHeaderClick),
    [order, column, onHeaderClick]
  );
  return (
    <Table
      data={data}
      columns={columns}
      className="text-sm"
    />
  );
}
Modern
You can change the style of Table by changing property variant.
Id  | Employee  | Designation  | Phone Number  | Email  | Status  | ||
|---|---|---|---|---|---|---|---|
| 1 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 2 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 3 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 4 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 5 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 6 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | 
import React from "react";
import Table from "@components/table";
import HeaderCell from "@components/header-cell";
import { Checkbox, Avatar, Text, Badge } from "rizzui";
const initialData = [
  {
    id: "1",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/1.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "2",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/2.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "3",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/3.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "4",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/4.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "5",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/5.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "6",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/6.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
];
function getStatusBadge(status: string) {
  switch (status.toLowerCase()) {
    case "pending":
      return <Badge variant="flat">{status}</Badge>;
    case "active":
      return (
        <Badge
          variant="flat"
          color="success"
        >
          {status}
        </Badge>
      );
    case "warning":
      return (
        <Badge
          variant="flat"
          color="warning"
        >
          {status}
        </Badge>
      );
    case "danger":
      return (
        <Badge
          variant="flat"
          color="danger"
        >
          {status}
        </Badge>
      );
    default:
      return null;
  }
}
const getColumns = (order: string, column: string, onHeaderClick: (value: string) => any) => [
  {
    title: <></>,
    dataIndex: "checked",
    key: "checked",
    width: 50,
    render: () => (
      <div className="inline-flex cursor-pointer">
        <Checkbox variant="flat" />
      </div>
    ),
  },
  {
    title: (
      <HeaderCell
        title="Id"
        sortable
        ascending={order === "asc" && column === "id"}
      />
    ),
    onHeaderCell: () => onHeaderClick("id"),
    dataIndex: "id",
    key: "id",
    width: 50,
  },
  {
    title: <HeaderCell title="Employee" />,
    dataIndex: "employee",
    key: "employee",
    width: 250,
    render: (employee: any) => (
      <div className="flex items-center">
        <Avatar
          name="John Doe"
          src={employee.avatar}
        />
        <div className="ml-3 rtl:ml-0 rtl:mr-3">
          <Text
            as="h6"
            className="mb-0.5 !text-sm font-medium"
          >
            {employee.name}
          </Text>
          <Text
            as="p"
            className="text-xs text-gray-400"
          >
            {employee.userName}
          </Text>
        </div>
      </div>
    ),
  },
  {
    title: <HeaderCell title="Designation" />,
    dataIndex: "designation",
    key: "designation",
    width: 320,
    render: (designation: any) => (
      <div>
        <Text
          as="h6"
          className="mb-0.5 !text-sm font-medium"
        >
          {designation.role}
        </Text>
        <Text
          as="p"
          className="text-xs text-gray-400"
        >
          {designation.company}
        </Text>
      </div>
    ),
  },
  {
    title: <HeaderCell title="Phone Number" />,
    dataIndex: "phoneNumber",
    key: "phoneNumber",
    width: 200,
  },
  {
    title: <HeaderCell title="Email" />,
    dataIndex: "email",
    key: "email",
    width: 200,
  },
  {
    title: <HeaderCell title="Status" />,
    dataIndex: "status",
    key: "status",
    width: 120,
    render: (value: string) => getStatusBadge(value),
  },
  {
    title: <></>,
    dataIndex: "action",
    key: "action",
    width: 120,
    render: (_: string, row: any) => (
      <div className="flex items-center gap-2">
        <button
          type="button"
          className="text-primary underline"
          onClick={() => alert(`Edit item #${row.id}`)}
        >
          Edit
        </button>
        <button
          type="button"
          className="underline"
        >
          View
        </button>
      </div>
    ),
  },
];
export default function App() {
  const [order, setOrder] = React.useState<string>("desc");
  const [column, setColumn] = React.useState<string>("");
  const [data, setData] = React.useState<typeof initialData>(initialData);
  const onHeaderClick = (value: string) => ({
    onClick: () => {
      setColumn(value);
      setOrder(order === "desc" ? "asc" : "desc");
      if (order === "desc") {
        // @ts-ignore
        setData([...data.sort((a, b) => (a[value] > b[value] ? -1 : 1))]);
      } else {
        // @ts-ignore
        setData([...data.sort((a, b) => (a[value] > b[value] ? 1 : -1))]);
      }
    },
  });
  const columns: any = React.useMemo(
    () => getColumns(order, column, onHeaderClick),
    [order, column, onHeaderClick]
  );
  return (
    <Table
      data={data}
      columns={columns}
      className="text-sm"
      variant="modern"
    />
  );
}
Elegant
You can change the style of Table by changing property variant.
Id  | Employee  | Designation  | Phone Number  | Email  | Status  | ||
|---|---|---|---|---|---|---|---|
| 1 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 2 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 3 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 4 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 5 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 6 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | 
import React from "react";
import Table from "@components/table";
import HeaderCell from "@components/header-cell";
import { Checkbox, Avatar, Text, Badge } from "rizzui";
const initialData = [
  {
    id: "1",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/1.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "2",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/2.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "3",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/3.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "4",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/4.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "5",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/5.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "6",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/6.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
];
function getStatusBadge(status: string) {
  switch (status.toLowerCase()) {
    case "pending":
      return <Badge variant="flat">{status}</Badge>;
    case "active":
      return (
        <Badge
          variant="flat"
          color="success"
        >
          {status}
        </Badge>
      );
    case "warning":
      return (
        <Badge
          variant="flat"
          color="warning"
        >
          {status}
        </Badge>
      );
    case "danger":
      return (
        <Badge
          variant="flat"
          color="danger"
        >
          {status}
        </Badge>
      );
    default:
      return null;
  }
}
const getColumns = (order: string, column: string, onHeaderClick: (value: string) => any) => [
  {
    title: <></>,
    dataIndex: "checked",
    key: "checked",
    width: 50,
    render: () => (
      <div className="inline-flex cursor-pointer">
        <Checkbox variant="flat" />
      </div>
    ),
  },
  {
    title: (
      <HeaderCell
        title="Id"
        sortable
        ascending={order === "asc" && column === "id"}
      />
    ),
    onHeaderCell: () => onHeaderClick("id"),
    dataIndex: "id",
    key: "id",
    width: 50,
  },
  {
    title: <HeaderCell title="Employee" />,
    dataIndex: "employee",
    key: "employee",
    width: 250,
    render: (employee: any) => (
      <div className="flex items-center">
        <Avatar
          name="John Doe"
          src={employee.avatar}
        />
        <div className="ml-3 rtl:ml-0 rtl:mr-3">
          <Text
            as="h6"
            className="mb-0.5 !text-sm font-medium"
          >
            {employee.name}
          </Text>
          <Text
            as="p"
            className="text-xs text-gray-400"
          >
            {employee.userName}
          </Text>
        </div>
      </div>
    ),
  },
  {
    title: <HeaderCell title="Designation" />,
    dataIndex: "designation",
    key: "designation",
    width: 320,
    render: (designation: any) => (
      <div>
        <Text
          as="h6"
          className="mb-0.5 !text-sm font-medium"
        >
          {designation.role}
        </Text>
        <Text
          as="p"
          className="text-xs text-gray-400"
        >
          {designation.company}
        </Text>
      </div>
    ),
  },
  {
    title: <HeaderCell title="Phone Number" />,
    dataIndex: "phoneNumber",
    key: "phoneNumber",
    width: 200,
  },
  {
    title: <HeaderCell title="Email" />,
    dataIndex: "email",
    key: "email",
    width: 200,
  },
  {
    title: <HeaderCell title="Status" />,
    dataIndex: "status",
    key: "status",
    width: 120,
    render: (value: string) => getStatusBadge(value),
  },
  {
    title: <></>,
    dataIndex: "action",
    key: "action",
    width: 120,
    render: (_: string, row: any) => (
      <div className="flex items-center gap-2">
        <button
          type="button"
          className="text-primary underline"
          onClick={() => alert(`Edit item #${row.id}`)}
        >
          Edit
        </button>
        <button
          type="button"
          className="underline"
        >
          View
        </button>
      </div>
    ),
  },
];
export default function App() {
  const [order, setOrder] = React.useState<string>("desc");
  const [column, setColumn] = React.useState<string>("");
  const [data, setData] = React.useState<typeof initialData>(initialData);
  const onHeaderClick = (value: string) => ({
    onClick: () => {
      setColumn(value);
      setOrder(order === "desc" ? "asc" : "desc");
      if (order === "desc") {
        // @ts-ignore
        setData([...data.sort((a, b) => (a[value] > b[value] ? -1 : 1))]);
      } else {
        // @ts-ignore
        setData([...data.sort((a, b) => (a[value] > b[value] ? 1 : -1))]);
      }
    },
  });
  const columns: any = React.useMemo(
    () => getColumns(order, column, onHeaderClick),
    [order, column, onHeaderClick]
  );
  return (
    <Table
      data={data}
      columns={columns}
      className="text-sm"
      variant="elegant"
    />
  );
}
Minimal
You can change the style of Table by changing property variant.
Id  | Employee  | Designation  | Phone Number  | Email  | Status  | ||
|---|---|---|---|---|---|---|---|
| 1 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 2 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 3 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 4 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 5 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | ||
| 6 | Jon Brown @fredchaparro  | Front-End Developer REDQ  | +880136987584 | jhondoe@aegonui.com | Active | 
import React from "react";
import Table from "@components/table";
import HeaderCell from "@components/header-cell";
import { Checkbox, Avatar, Text, Badge } from "rizzui";
const initialData = [
  {
    id: "1",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/1.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "2",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/2.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "3",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/3.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "4",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/4.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "5",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/5.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
  {
    id: "6",
    employee: {
      name: "Jon Brown",
      userName: "@fredchaparro",
      avatar: "https://randomuser.me/api/portraits/men/6.jpg",
    },
    designation: {
      role: "Front-End Developer",
      company: "REDQ",
    },
    phoneNumber: "+880136987584",
    email: "jhondoe@aegonui.com",
    status: "Active",
  },
];
function getStatusBadge(status: string) {
  switch (status.toLowerCase()) {
    case "pending":
      return <Badge variant="flat">{status}</Badge>;
    case "active":
      return (
        <Badge
          variant="flat"
          color="success"
        >
          {status}
        </Badge>
      );
    case "warning":
      return (
        <Badge
          variant="flat"
          color="warning"
        >
          {status}
        </Badge>
      );
    case "danger":
      return (
        <Badge
          variant="flat"
          color="danger"
        >
          {status}
        </Badge>
      );
    default:
      return null;
  }
}
const getColumns = (order: string, column: string, onHeaderClick: (value: string) => any) => [
  {
    title: <></>,
    dataIndex: "checked",
    key: "checked",
    width: 50,
    render: () => (
      <div className="inline-flex cursor-pointer">
        <Checkbox variant="flat" />
      </div>
    ),
  },
  {
    title: (
      <HeaderCell
        title="Id"
        sortable
        ascending={order === "asc" && column === "id"}
      />
    ),
    onHeaderCell: () => onHeaderClick("id"),
    dataIndex: "id",
    key: "id",
    width: 50,
  },
  {
    title: <HeaderCell title="Employee" />,
    dataIndex: "employee",
    key: "employee",
    width: 250,
    render: (employee: any) => (
      <div className="flex items-center">
        <Avatar
          name="John Doe"
          src={employee.avatar}
        />
        <div className="ml-3 rtl:ml-0 rtl:mr-3">
          <Text
            as="h6"
            className="mb-0.5 !text-sm font-medium"
          >
            {employee.name}
          </Text>
          <Text
            as="p"
            className="text-xs text-gray-400"
          >
            {employee.userName}
          </Text>
        </div>
      </div>
    ),
  },
  {
    title: <HeaderCell title="Designation" />,
    dataIndex: "designation",
    key: "designation",
    width: 320,
    render: (designation: any) => (
      <div>
        <Text
          as="h6"
          className="mb-0.5 !text-sm font-medium"
        >
          {designation.role}
        </Text>
        <Text
          as="p"
          className="text-xs text-gray-400"
        >
          {designation.company}
        </Text>
      </div>
    ),
  },
  {
    title: <HeaderCell title="Phone Number" />,
    dataIndex: "phoneNumber",
    key: "phoneNumber",
    width: 200,
  },
  {
    title: <HeaderCell title="Email" />,
    dataIndex: "email",
    key: "email",
    width: 200,
  },
  {
    title: <HeaderCell title="Status" />,
    dataIndex: "status",
    key: "status",
    width: 120,
    render: (value: string) => getStatusBadge(value),
  },
  {
    title: <></>,
    dataIndex: "action",
    key: "action",
    width: 120,
    render: (_: string, row: any) => (
      <div className="flex items-center gap-2">
        <button
          type="button"
          className="text-primary underline"
          onClick={() => alert(`Edit item #${row.id}`)}
        >
          Edit
        </button>
        <button
          type="button"
          className="underline"
        >
          View
        </button>
      </div>
    ),
  },
];
export default function App() {
  const [order, setOrder] = React.useState<string>("desc");
  const [column, setColumn] = React.useState<string>("");
  const [data, setData] = React.useState<typeof initialData>(initialData);
  const onHeaderClick = (value: string) => ({
    onClick: () => {
      setColumn(value);
      setOrder(order === "desc" ? "asc" : "desc");
      if (order === "desc") {
        // @ts-ignore
        setData([...data.sort((a, b) => (a[value] > b[value] ? -1 : 1))]);
      } else {
        // @ts-ignore
        setData([...data.sort((a, b) => (a[value] > b[value] ? 1 : -1))]);
      }
    },
  });
  const columns: any = React.useMemo(
    () => getColumns(order, column, onHeaderClick),
    [order, column, onHeaderClick]
  );
  return (
    <Table
      data={data}
      columns={columns}
      className="text-sm"
      variant="minimal"
    />
  );
}
API Reference
Table Props
Here is the API documentation of the Table component.
| Props | Type | Description | Default | 
|---|---|---|---|
| emptyText | ReactNode | Set empty text, it will only appear when table has no data | __ | 
| variant | TableVariants | The variants of the component are: | "classic" | 
| striped | boolean | Add striping style | __ | 
| className | string | Add custom classes for extra style | __ | 
| id | string | __ | |
| style | CSSProperties | __ | |
| title | PanelRender<DefaultRecordType> | __ | |
| caption | ReactNode | __ | |
| data | readonly DefaultRecordType[] | __ | |
| footer | PanelRender<DefaultRecordType> | __ | |
| summary | ((data: readonly DefaultRecordType[]) => ReactNode) | __ | |
| prefixCls | string | __ | |
| direction | ltr rtl | __ | |
| expandedRowKeys | Key[] | __ | |
| defaultExpandedRowKeys | key[] | __ | |
| expandedRowRender | ExpandedRowRender<DefaultRecordType> | __ | |
| expandRowByClick | boolean | __ | |
| expandIcon | RenderExpandIcon<DefaultRecordType> | __ | |
| onExpand | ((expanded: boolean, record: DefaultRecordType) => void) | __ | |
| onExpandedRowsChange | ((expandedKeys: Key[]) => void) | __ | |
| defaultExpandAllRows | boolean | __ | |
| indentSize | number | __ | |
| expandIconColumnIndex | number | __ | |
| expandedRowClassName | RowClassName<DefaultRecordType> | __ | |
| childrenColumnName | string | __ | |
| columns | ColumnsType<DefaultRecordType> | __ | |
| rowKey | string GetRowKey<DefaultRecordType> | __ | |
| tableLayout | fixed auto | __ | |
| scroll | TableScroll | __ | |
| expandable | ExpandableConfig<DefaultRecordType> | Config expand rows | __ | 
| rowClassName | string RowClassName<DefaultRecordType> | __ | |
| showHeader | boolean | __ | |
| components | TableComponents<DefaultRecordType> | __ | |
| onRow | GetComponentProps<DefaultRecordType> | __ | |
| onHeaderRow | GetComponentProps<readonly ColumnType<DefaultRecordType>[]> | __ | |
| internalHooks | string | __ | |
| transformColumns | TableTransformColumns | __ | |
| internalRefs | { body: MutableRefObject<HTMLDivElement>; } | __ | |
| sticky | sticky tableSticky | __ | 
- Note: You can check rc-table documentation for more details.
 
Table Variants
type TableVariants = "classic" | "modern" | "minimal" | "elegant";
Table Scroll
type TableScroll = { x?: string | number | true; y?: string | number } | undefined;
Table Transform Columns
type TableTransformColumns = (
  columns: ColumnsType<DefaultRecordType>
) => ColumnsType<DefaultRecordType>;