Table

Overview

Table is a component showing information having same properties. For instance, customer orders list in an e-commerce shop.

Astropine Table component provides you two greats features working out of the box: sorting and filtering.

We will see in this page the many possibilities you can achieve with this component.

Basic Table

Here we have a basic table, taking just two props : columns and items.

P.S: Notice that columns is an array of items keys.

Copied !

---
import Table from "$components/table/Table.astro";
import {
  TableHeadColumnType,
  TableBodyItemRowType,
} from "$components/table/types";

const columns: TableHeadColumnType[] = [
  {
    key: "name",
    label: "Name",
  },
  {
    key: "age",
    label: "Age",
  },
  { key: "address", label: "Address" },
  { key: "action", label: "Action" },
];
const items: TableBodyItemRowType[] = [
  {
    name: { text: "Richard Hendricks" },
    age: { text: 30 },
    address: {
      html: "<p class='text-slate-600 italic'>Pied Piper HQ, Palo Alto</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Erlich Bachman" },
    age: { text: 40 },
    address: {
      html: "<p class='text-slate-600 italic'>5230 Penfield Ave, Woodland Hills</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Monica Hall" },
    age: { text: 35 },
    address: {
      html: "<p class='text-slate-600 italic'>2030 Stewart Drive, Sunnyvale</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Dinesh Chugtai" },
    age: { text: 28 },
    address: {
      html: "<p class='text-slate-600 italic'>Pied Piper HQ, Palo Alto</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Gilfoyle" },
    age: { text: 32 },
    address: {
      html: "<p class='text-slate-600 italic'>Pied Piper HQ, Palo Alto</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
];
---

<Table class="bg-white rounded-lg border" {columns} {items} />

Styling Table

About styling, Table component provides theadClass and tbodyClass props, which respectfully stylized thead and tbody tags.

Two examples below. First is about adding borders between columns. Second applied class only on even rows.

Copied !

---
import Table from "$components/table/Table.astro";
import {
  TableHeadColumnType,
  TableBodyItemRowType,
} from "$components/table/types";

const columns: TableHeadColumnType[] = [
  {
    key: "name",
    label: "Name",
  },
  {
    key: "age",
    label: "Age",
  },
  { key: "address", label: "Address" },
  { key: "action", label: "Action" },
];
const items: TableBodyItemRowType[] = [
  {
    name: { text: "Richard Hendricks" },
    age: { text: 30 },
    address: {
      html: "<p class='text-slate-600 italic'>Pied Piper HQ, Palo Alto</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Erlich Bachman" },
    age: { text: 40 },
    address: {
      html: "<p class='text-slate-600 italic'>5230 Penfield Ave, Woodland Hills</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Monica Hall" },
    age: { text: 35 },
    address: {
      html: "<p class='text-slate-600 italic'>2030 Stewart Drive, Sunnyvale</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Dinesh Chugtai" },
    age: { text: 28 },
    address: {
      html: "<p class='text-slate-600 italic'>Pied Piper HQ, Palo Alto</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Gilfoyle" },
    age: { text: 32 },
    address: {
      html: "<p class='text-slate-600 italic'>Pied Piper HQ, Palo Alto</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
];
---

<div class="flex flex-col gap-y-8">
  <div>
    <Table
      class="bg-white rounded-lg border"
      {columns}
      {items}
      theadClass="divide-x"
      tbodyClass="[&>*]:divide-x"
    />
  </div>
  <div>
    <Table
      class="bg-white rounded-lg border"
      {columns}
      {items}
      tbodyClass="[&>*:nth-child(even)]:bg-slate-100 divide-y-0"
    />
  </div>
</div>

Sorting Table

Table can be sorted. When enabling sorting, an icon will appear aside column label.

P.S: Just remember one rule, sorting applies to only one column.

Copied !

---
import Table from "$components/table/Table.astro";
import {
  TableHeadColumnType,
  TableBodyItemRowType,
} from "$components/table/types";

const columns: TableHeadColumnType[] = [
  {
    key: "name",
    label: "Name",
    sort: "STRING",
  },
  {
    key: "age",
    label: "Age",
    sort: "NUMBER",
  },
  { key: "address", label: "Address" },
  { key: "action", label: "Action" },
];
const items: TableBodyItemRowType[] = [
  {
    name: { text: "Richard Hendricks" },
    age: { text: 30 },
    address: {
      html: "<p class='text-slate-600 italic'>Pied Piper HQ, Palo Alto</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Erlich Bachman" },
    age: { text: 40 },
    address: {
      html: "<p class='text-slate-600 italic'>5230 Penfield Ave, Woodland Hills</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Monica Hall" },
    age: { text: 35 },
    address: {
      html: "<p class='text-slate-600 italic'>2030 Stewart Drive, Sunnyvale</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Dinesh Chugtai" },
    age: { text: 28 },
    address: {
      html: "<p class='text-slate-600 italic'>Pied Piper HQ, Palo Alto</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Gilfoyle" },
    age: { text: 32 },
    address: {
      html: "<p class='text-slate-600 italic'>Pied Piper HQ, Palo Alto</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
];
---

<Table class="bg-white rounded-lg border" {columns} {items} />

Filtering Table

About filtering, a set of predefined filtering are provided to handle most cases. Check code part to see how this example handles filtering.

P.S: Multiple criterias are accepted when it comes to filter.

Copied !

---
import Table from "$components/table/Table.astro";
import {
  TableSelectFilterOperatorOptionType,
  TableHeadColumnType,
  TableBodyItemRowType,
} from "$components/table/types";

const selectOptions: TableSelectFilterOperatorOptionType[] = [
  {
    value: "",
    label: "All age",
  },
  {
    operator: "GreaterThan",
    value: 32,
    label: "age > 32",
  },
  {
    operator: "LesserThanOrEqual",
    value: 35,
    label: "age <= 35",
  },
];
const columns: TableHeadColumnType[] = [
  {
    key: "name",
    label: "Name",
    filter: {
      type: "search",
      placeholder: "Type here to filter by name",
      operator: "Like",
    },
  },
  {
    key: "age",
    label: "Age",
    filter: {
      type: "select",
      placeholder: "Select age",
      operators: selectOptions,
    },
  },
  { key: "address", label: "Address" },
  { key: "action", label: "Action" },
];
const items: TableBodyItemRowType[] = [
  {
    name: { text: "Richard Hendricks" },
    age: { text: 30 },
    address: {
      html: "<p class='text-slate-600 italic'>Pied Piper HQ, Palo Alto</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Erlich Bachman" },
    age: { text: 40 },
    address: {
      html: "<p class='text-slate-600 italic'>5230 Penfield Ave, Woodland Hills</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Monica Hall" },
    age: { text: 35 },
    address: {
      html: "<p class='text-slate-600 italic'>2030 Stewart Drive, Sunnyvale</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Dinesh Chugtai" },
    age: { text: 28 },
    address: {
      html: "<p class='text-slate-600 italic'>Pied Piper HQ, Palo Alto</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Gilfoyle" },
    age: { text: 32 },
    address: {
      html: "<p class='text-slate-600 italic'>Pied Piper HQ, Palo Alto</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
];
---

<Table class="bg-white rounded-lg border" {columns} {items} />

Sorting and Filtering Table

This example is just a combination of sorting and filtering.

Copied !

---
import Table from "$components/table/Table.astro";
import {
  TableSelectFilterOperatorOptionType,
  TableHeadColumnType,
  TableBodyItemRowType,
} from "$components/table/types";

const selectOptions: TableSelectFilterOperatorOptionType[] = [
  {
    value: "",
    label: "All age",
  },
  {
    operator: "GreaterThan",
    value: 32,
    label: "age > 32",
  },
  {
    operator: "LesserThanOrEqual",
    value: 35,
    label: "age <= 35",
  },
];
const columns: TableHeadColumnType[] = [
  {
    key: "name",
    label: "Name",
    sort: "STRING",
    filter: {
      type: "search",
      placeholder: "Type here to filter by name",
      operator: "Like",
    },
  },
  {
    key: "age",
    label: "Age",
    sort: "NUMBER",
    filter: {
      type: "select",
      placeholder: "Select age",
      operators: selectOptions,
    },
  },
  { key: "address", label: "Address" },
  { key: "action", label: "Action" },
];
const items: TableBodyItemRowType[] = [
  {
    name: { text: "Richard Hendricks" },
    age: { text: 30 },
    address: {
      html: "<p class='text-slate-600 italic'>Pied Piper HQ, Palo Alto</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Erlich Bachman" },
    age: { text: 40 },
    address: {
      html: "<p class='text-slate-600 italic'>5230 Penfield Ave, Woodland Hills</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Monica Hall" },
    age: { text: 35 },
    address: {
      html: "<p class='text-slate-600 italic'>2030 Stewart Drive, Sunnyvale</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Dinesh Chugtai" },
    age: { text: 28 },
    address: {
      html: "<p class='text-slate-600 italic'>Pied Piper HQ, Palo Alto</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
  {
    name: { text: "Gilfoyle" },
    age: { text: 32 },
    address: {
      html: "<p class='text-slate-600 italic'>Pied Piper HQ, Palo Alto</p>",
    },
    action: {
      html: '<button class="btn btn-info-outlined rounded py-1 px-2 text-center w-full" href="#">Edit</button>',
    },
  },
];
---

<Table
  class="bg-white rounded-lg border"
  {columns}
  {items}
  theadClass="divide-x"
  tbodyClass="[&>*]:divide-x"
/>