Skip to content

Commit

Permalink
feat(table): add action column type (#360)
Browse files Browse the repository at this point in the history
Co-authored-by: Kia King Ishii <kia.king.08@gmail.com>
  • Loading branch information
brc-dd and kiaking committed Oct 24, 2023
1 parent c38a896 commit acb1313
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 22 deletions.
57 changes: 56 additions & 1 deletion docs/components/table.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ const options = useTable({
Below are the complete list of options you may pass to the text type cell.

```ts
export interface TableCellNumber {
export interface TableCellText {
// Type of the cell. Must be `text`.
type: 'text'

Expand Down Expand Up @@ -467,6 +467,61 @@ export type TableCellValueColor =
| 'danger'
```
### Actions cell
Actions type cell displays any number of actions as a clickable button in the cell by defining `type: 'actions'`. Usually, place actions at the end of the column.
```ts
import IconNotePencil from '@iconify-icons/ph/note-pencil'
import IconTrash from '@iconify-icons/ph/trash'

const options = useTable({
orders: ['actions'],
columns: {
age: {
cell: {
type: 'actions',
actions: [
{ icon: IconNotePencil, onClick: () => {} },
{ icon: IconTrash, onClick: () => {} }
]
}
}
}
})
```

Below are the complete list of options you may pass to the actions type cell. Each action is a `<SButton :type="text">` instances. You may pass options such as `mode` or `label` to them.

```ts
import { type IconifyIcon } from '@iconify/vue/dist/offline'

interface TableCellActions {
// Type of the cell. Must be `actions`.
type: 'number'

// Options for button stylings. Refer to `<SButton>` docs
// for more details. Note that for actions, `type` is fixed
// to `text`, and `mode` defaults to `mute`.
mode?: ColorModes
icon?: IconifyIcon
iconMode?: ColorModes
label?: string
labelMode?: ColorModes

// Callback function when the button is clicked.
onClick(value: any, record: any): void
}

type ColorModes =
| 'neutral'
| 'mute'
| 'info'
| 'success'
| 'warning'
| 'danger'
```
### Summary row
You may define `summary` option to display a summary row at the bottom of the table. It's useful to display information such as the total of each column.
Expand Down
7 changes: 7 additions & 0 deletions lib/components/STableCell.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup lang="ts">
import { computed } from 'vue'
import { type TableCell } from '../composables/Table'
import STableCellActions from './STableCellActions.vue'
import STableCellAvatar from './STableCellAvatar.vue'
import STableCellAvatars from './STableCellAvatars.vue'
import STableCellCustom from './STableCellCustom.vue'
Expand Down Expand Up @@ -99,6 +100,12 @@ const computedCell = computed<TableCell | undefined>(() =>
:avatars="computedCell.avatars"
:color="computedCell.color"
/>
<STableCellActions
v-else-if="computedCell.type === 'actions'"
:value="value"
:record="record"
:actions="computedCell.actions"
/>
<STableCellCustom
v-else-if="computedCell.type === 'custom'"
>
Expand Down
38 changes: 38 additions & 0 deletions lib/components/STableCellActions.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script setup lang="ts">
import { type TableCellAction } from '../composables/Table'
import SButton from './SButton.vue'
defineProps<{
value: any
record: any
actions: TableCellAction[]
}>()
</script>

<template>
<div class="STableCellActions">
<SButton
v-for="(action, i) in actions"
:key="i"
size="mini"
type="text"
:mode="action.mode ?? 'mute'"
:icon="action.icon"
:icon-mode="action.iconMode"
:label="action.label"
:label-mode="action.labelMode"
@click="action.onClick(value, record)"
/>
</div>
</template>
<style scoped lang="postcss">
.STableCellActions {
min-height: 40px;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: nowrap;
flex-direction: row;
}
</style>
4 changes: 2 additions & 2 deletions lib/components/STableHeader.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { computed } from 'vue'
import { type TableAction, type TableMenu } from '../composables/Table'
import { type TableHeaderAction, type TableMenu } from '../composables/Table'
import { format } from '../support/Num'
import { isNullish } from '../support/Utils'
import STableHeaderActions from './STableHeaderActions.vue'
Expand All @@ -10,7 +10,7 @@ const props = defineProps<{
total?: number | null
reset?: boolean
menu?: TableMenu[] | TableMenu[][]
actions?: TableAction[]
actions?: TableHeaderAction[]
borderless?: boolean
onReset?(): void
selected?: unknown[]
Expand Down
4 changes: 2 additions & 2 deletions lib/components/STableHeaderActionItem.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script setup lang="ts">
import { type TableAction } from '../composables/Table'
import { type TableHeaderAction } from '../composables/Table'
import SButton from './SButton.vue'
withDefaults(defineProps<TableAction>(), {
withDefaults(defineProps<TableHeaderAction>(), {
show: true,
mode: 'mute',
labelMode: 'neutral'
Expand Down
4 changes: 2 additions & 2 deletions lib/components/STableHeaderActions.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script setup lang="ts">
import { type TableAction } from '../composables/Table'
import { type TableHeaderAction } from '../composables/Table'
import STableHeaderActionItem from './STableHeaderActionItem.vue'
defineProps<{ actions: TableAction[] }>()
defineProps<{ actions: TableHeaderAction[] }>()
</script>

<template>
Expand Down
39 changes: 25 additions & 14 deletions lib/composables/Table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface Table<
orders: MaybeRef<O[]>
columns: MaybeRef<TableColumns<O, R, SR>>
menu?: MaybeRef<TableMenu[] | TableMenu[][]>
actions?: MaybeRef<TableAction[]>
actions?: MaybeRef<TableHeaderAction[]>
records?: MaybeRef<R[] | null | undefined>
header?: MaybeRef<boolean | undefined>
footer?: MaybeRef<boolean | undefined>
Expand Down Expand Up @@ -64,6 +64,7 @@ export type TableCell =
| TableCellCustom
| TableCellEmpty
| TableCellComponent
| TableCellActions

export type TableCellType =
| 'text'
Expand All @@ -77,6 +78,9 @@ export type TableCellType =
| 'custom'
| 'empty'
| 'component'
| 'actions'

export type ColorModes = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'

export interface TableCellBase {
type: TableCellType
Expand Down Expand Up @@ -105,14 +109,7 @@ export interface TableCellNumber extends TableCellBase {
onClick?(value: any, record: any): void
}

export type TableCellValueColor =
| 'neutral'
| 'soft'
| 'mute'
| 'info'
| 'success'
| 'warning'
| 'danger'
export type TableCellValueColor = ColorModes | 'soft'

export interface TableCellDay extends TableCellBase {
type: 'day'
Expand All @@ -128,7 +125,7 @@ export interface TableCellPill extends TableCellBase {
color?: TableCellPillColor | ((value: any, record: any) => TableCellPillColor)
}

export type TableCellPillColor = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
export type TableCellPillColor = ColorModes

export interface TableCellPills extends TableCellBase {
type: 'pills'
Expand Down Expand Up @@ -177,7 +174,21 @@ export interface TableCellComponent extends TableCellBase {
export interface TableCellState extends TableCellBase {
type: 'state'
label: string
mode?: 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
mode?: ColorModes
}

export interface TableCellActions extends TableCellBase {
type: 'actions'
actions: TableCellAction[]
}

export interface TableCellAction {
mode?: ColorModes
icon?: any
iconMode?: ColorModes
label?: string
labelMode?: ColorModes
onClick(value: any, record: any): void
}

export interface TableMenu {
Expand All @@ -186,11 +197,11 @@ export interface TableMenu {
dropdown: DropdownSection[]
}

export interface TableAction {
export interface TableHeaderAction {
show?: boolean
mode?: 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
mode?: ColorModes
label: string
labelMode?: 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
labelMode?: ColorModes
onClick(): void
}

Expand Down
29 changes: 28 additions & 1 deletion stories/components/STable.01_Playground.story.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<script setup lang="ts">
import IconCheck from '@iconify-icons/ph/check-bold'
import IconImageSquare from '@iconify-icons/ph/image-square'
import IconNotePencil from '@iconify-icons/ph/note-pencil'
import IconTrash from '@iconify-icons/ph/trash'
import { orderBy, xor } from 'lodash-es'
import STable from 'sefirot/components/STable.vue'
import { createDropdown } from 'sefirot/composables/Dropdown'
Expand Down Expand Up @@ -186,7 +189,8 @@ const table = useTable({
'type',
'width',
'tags',
'createdAt'
'createdAt',
'actions'
],
columns: computed(() => ({
Expand Down Expand Up @@ -258,6 +262,28 @@ const table = useTable({
}))
}
}
},
actions: {
cell: {
type: 'actions',
/* eslint-disable no-alert */
actions: [
{
icon: markRaw(IconCheck),
onClick: () => { alert('Publish') }
},
{
icon: markRaw(IconNotePencil),
onClick: () => { alert('Edit') }
},
{
icon: markRaw(IconTrash),
onClick: () => { alert('Delete') }
}
]
/* eslint-enable */
}
}
})),
Expand Down Expand Up @@ -344,6 +370,7 @@ function updateTagsFilter(value: string) {
.table :deep(.col-width) { --table-col-width: 128px; }
.table :deep(.col-tags) { --table-col-width: 192px; }
.table :deep(.col-createdAt) { --table-col-width: 192px; }
.table :deep(.col-actions) { --table-col-width: 100px; }
.table {
margin-bottom: 16px;
Expand Down

0 comments on commit acb1313

Please sign in to comment.