feat: introducing a new smart table hoppscotch ui component (#3178)
Co-authored-by: Anwarul Islam <anwaarulislaam@gmail.com>
This commit is contained in:
committed by
GitHub
parent
6daa043a1b
commit
23e3739718
69
packages/hoppscotch-ui/src/components/smart/Table.vue
Normal file
69
packages/hoppscotch-ui/src/components/smart/Table.vue
Normal file
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<div class="overflow-auto rounded-md border border-dividerDark shadow-md">
|
||||
<table class="w-full">
|
||||
<thead>
|
||||
<slot name="head">
|
||||
<tr
|
||||
class="text-secondary border-b border-dividerDark text-sm text-left bg-primaryLight"
|
||||
>
|
||||
<th v-for="th in headings" scope="col" class="px-6 py-3">
|
||||
{{ th.label ?? th.key }}
|
||||
</th>
|
||||
</tr>
|
||||
</slot>
|
||||
</thead>
|
||||
|
||||
<tbody class="divide-y divide-divider">
|
||||
<!-- We are using slot props for future proofing so that in future, we can implement features like filtering -->
|
||||
<slot name="body" :list="list">
|
||||
<tr
|
||||
v-for="(rowData, rowIndex) in list"
|
||||
:key="rowIndex"
|
||||
class="text-secondaryDark hover:bg-divider hover:cursor-pointer rounded-xl"
|
||||
:class="{ 'divide-x divide-divider': showYBorder }"
|
||||
>
|
||||
<td
|
||||
v-for="cellHeading in headings"
|
||||
:key="cellHeading.key"
|
||||
@click="!cellHeading.preventClick && onRowClicked(rowData)"
|
||||
class="max-w-40 pl-6 py-1"
|
||||
>
|
||||
<!-- Dynamic column slot -->
|
||||
<slot :name="cellHeading.key" :item="rowData">
|
||||
<!-- Generic implementation of the column -->
|
||||
<div class="flex flex-col truncate">
|
||||
<span class="truncate">
|
||||
{{ rowData[cellHeading.key] ?? "-" }}
|
||||
</span>
|
||||
</div>
|
||||
</slot>
|
||||
</td>
|
||||
</tr>
|
||||
</slot>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup generic="Item extends Record<string, unknown>">
|
||||
export type CellHeading = {
|
||||
key: string
|
||||
label?: string
|
||||
preventClick?: boolean
|
||||
}
|
||||
|
||||
defineProps<{
|
||||
/** Whether to show the vertical border between columns */
|
||||
showYBorder?: boolean
|
||||
/** The list of items to be displayed in the table */
|
||||
list?: Item[]
|
||||
/** The headings of the table */
|
||||
headings?: CellHeading[]
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: "onRowClicked", item: Item): void
|
||||
}>()
|
||||
|
||||
const onRowClicked = (item: Item) => emit("onRowClicked", item)
|
||||
</script>
|
||||
@@ -16,6 +16,7 @@ export { default as HoppSmartSlideOver } from "./SlideOver.vue"
|
||||
export { default as HoppSmartSpinner } from "./Spinner.vue"
|
||||
export { default as HoppSmartTab } from "./Tab.vue"
|
||||
export { default as HoppSmartTabs } from "./Tabs.vue"
|
||||
export { default as HoppSmartTable } from "./Table.vue"
|
||||
export { default as HoppSmartToggle } from "./Toggle.vue"
|
||||
export { default as HoppSmartWindow } from "./Window.vue"
|
||||
export { default as HoppSmartWindows } from "./Windows.vue"
|
||||
|
||||
69
packages/hoppscotch-ui/src/stories/Table.story.vue
Normal file
69
packages/hoppscotch-ui/src/stories/Table.story.vue
Normal file
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<Story title="Table">
|
||||
<Variant title="General">
|
||||
<HoppSmartTable :list="list" :headings="headings" />
|
||||
</Variant>
|
||||
<Variant title="Custom">
|
||||
<HoppSmartTable>
|
||||
<template #head>
|
||||
<tr
|
||||
class="text-secondary border-b border-dividerDark text-sm text-left bg-primaryLight"
|
||||
>
|
||||
<th
|
||||
v-for="heading in headings"
|
||||
:key="heading.key"
|
||||
scope="col"
|
||||
class="px-6 py-3"
|
||||
>
|
||||
{{ heading.label }}
|
||||
</th>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
<template #body>
|
||||
<tr
|
||||
v-for="item in list"
|
||||
:key="item.id"
|
||||
class="text-secondaryDark hover:bg-divider hover:cursor-pointer rounded-xl"
|
||||
>
|
||||
<td
|
||||
v-for="cellHeading in headings"
|
||||
:key="cellHeading.key"
|
||||
class="max-w-40 pl-6 py-1"
|
||||
>
|
||||
{{ item[cellHeading.key] ?? "-" }}
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</HoppSmartTable>
|
||||
</Variant>
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartTable } from "../components/smart"
|
||||
import { CellHeading } from "~/components/smart/Table.vue"
|
||||
|
||||
// Table Headings
|
||||
const headings: CellHeading[] = [
|
||||
{ key: "id", label: "ID" },
|
||||
{ key: "name", label: "Name" },
|
||||
{ key: "members", label: "Members" },
|
||||
{ key: "role", label: "Role" },
|
||||
]
|
||||
|
||||
const list: Record<string, string | number>[] = [
|
||||
{
|
||||
id: "123455",
|
||||
name: "Joel",
|
||||
members: 10,
|
||||
role: "Frontend Engineer",
|
||||
},
|
||||
{
|
||||
id: "123456",
|
||||
name: "Anwar",
|
||||
members: 12,
|
||||
role: "Frontend Engineer",
|
||||
},
|
||||
]
|
||||
</script>
|
||||
Reference in New Issue
Block a user