Skip to content

Commit

Permalink
feat(table): add option to control display count of avatars (#416) (#417
Browse files Browse the repository at this point in the history
)

close #416 

---------

Co-authored-by: Divyansh Singh <40380293+brc-dd@users.noreply.github.com>
  • Loading branch information
kiaking and brc-dd committed Dec 19, 2023
1 parent c80d100 commit 303f377
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 22 deletions.
2 changes: 2 additions & 0 deletions lib/components/STableCell.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ const computedCell = computed<TableCell | undefined>(() =>
:record="record"
:avatars="computedCell.avatars"
:color="computedCell.color"
:avatar-count="computedCell.avatarCount"
:name-count="computedCell.nameCount"
/>
<STableCellActions
v-else-if="computedCell.type === 'actions'"
Expand Down
83 changes: 61 additions & 22 deletions lib/components/STableCellAvatars.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,75 @@ import { computed } from 'vue'
import { type TableCellAvatarsOption } from '../composables/Table'
import SAvatar from './SAvatar.vue'
const props = defineProps<{
const props = withDefaults(defineProps<{
value?: any
record?: any
avatars: TableCellAvatarsOption[] | ((value: any, record: any) => TableCellAvatarsOption[])
color?: 'neutral' | 'soft' | 'mute'
}>()
avatarCount?: number
nameCount?: number
}>(), {
avatarCount: 2,
nameCount: 2
})
const _avatars = computed(() => {
return typeof props.avatars === 'function'
? props.avatars(props.value, props.record)
: props.avatars
})
const avatarDiff = computed(() => {
return _avatars.value.length - props.avatarCount
})
const displayAvatars = computed(() => {
return _avatars.value.slice(0, 3)
return _avatars.value.slice(0, props.avatarCount)
})
const nameDiff = computed(() => {
return _avatars.value.length - props.nameCount
})
const names = computed(() => {
if (_avatars.value.length === 0) {
const displayNames = computed(() => {
// If the count is 0, treat it as "disabling" the name display.
if (props.nameCount === 0) {
return null
}
if (_avatars.value.length === 1) {
return _avatars.value[0].name
}
const slicedAvatars = _avatars.value.slice(0, props.nameCount)
const names = slicedAvatars.map((avatar) => avatar.name).join(', ')
if (_avatars.value.length === 2) {
return `${_avatars.value[0].name}, ${_avatars.value[1].name}`
if (nameDiff.value > 0) {
return `${names}, ...`
}
return `${_avatars.value[0].name}, ${_avatars.value[1].name} +${_avatars.value.length - 2}`
return names
})
</script>

<template>
<div class="STableCellAvatars" :class="[color]">
<div class="container">
<div class="avatars">
<div v-for="(avatar, index) in displayAvatars" :key="index" class="avatar">
<div v-if="displayAvatars.length" class="avatars">
<div
v-for="(avatar, index) in displayAvatars"
:key="index"
class="avatar"
>
<div class="avatar-box">
<SAvatar size="mini" :avatar="avatar.image" :name="avatar.name" />
</div>
</div>
<div v-if="avatarDiff > 0" class="avatar">
<div class="avatar-box placeholder" :class="{ small: avatarDiff >= 10 }">
+{{ avatarDiff }}
</div>
</div>
</div>
<div class="names">
{{ names }}
<div v-if="displayNames" class="names">
{{ displayNames }}
</div>
</div>
</div>
Expand All @@ -72,28 +95,44 @@ const names = computed(() => {
.avatar {
position: relative;
width: 20px;
}
&:nth-child(1) { z-index: 30; }
&:nth-child(2) { z-index: 20; }
&:nth-child(3) { z-index: 10; }
.avatar.placeholder {
display: flex;
justify-content: center;
align-items: center;
}
.avatar-box {
display: flex;
justify-content: center;
align-items: center;
border: 2px solid var(--c-bg-elv-3);
border-radius: 50%;
width: 28px;
height: 28px;
.row:hover & {
border: 2px solid var(--c-bg-elv-4);
}
&.placeholder {
font-size: 10px;
font-weight: 500;
color: var(--c-text-2);
background-color: var(--c-bg-mute-1);
}
&.placeholder.small {
font-size: 9px;
}
}
.names {
line-height: 28px;
font-size: 12px;
font-weight: 500;
.STableCellAvatars.soft & { color: var(--c-text-2); }
.STableCellAvatars.mute & { color: var(--c-text-3); }
}
.STableCellAvatars.soft .names { color: var(--c-text-2); }
.STableCellAvatars.mute .names { color: var(--c-text-3); }
</style>
2 changes: 2 additions & 0 deletions lib/composables/Table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ export interface TableCellAvatars<V = any, R = any> extends TableCellBase {
type: 'avatars'
avatars: TableCellAvatarsOption[] | ((value: V, record: R) => TableCellAvatarsOption[])
color?: 'neutral' | 'soft' | 'mute'
avatarCount?: number
nameCount?: number
}

export interface TableCellAvatarsOption {
Expand Down
31 changes: 31 additions & 0 deletions stories/components/STable.01_Playground.story.vue
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ const data = shallowRef([
status: 'Published',
type: 'Photo',
width: 1280,
authors: [
{ image: 'https://i.pravatar.cc/64?img=1', name: 'Jane Doe' },
{ image: 'https://i.pravatar.cc/64?img=2', name: 'Daniel Green' }
],
createdAt: day('2022-10-10'),
tags: ['Info', 'News', 'Latest']
},
Expand All @@ -139,6 +143,9 @@ const data = shallowRef([
status: 'Draft',
type: 'Icon',
width: 1280,
authors: [
{ image: 'https://i.pravatar.cc/64?img=3', name: 'John Black' }
],
createdAt: day('2022-10-09'),
tags: ['Info']
},
Expand All @@ -148,6 +155,11 @@ const data = shallowRef([
status: 'Published',
type: 'Photo',
width: 1920,
authors: [
{ image: 'https://i.pravatar.cc/64?img=4', name: 'Kris James' },
{ image: 'https://i.pravatar.cc/64?img=5', name: 'Becky Lu' },
{ image: 'https://i.pravatar.cc/64?img=7', name: 'Thomas Wane' }
],
createdAt: day('2022-10-02'),
tags: ['Info', 'News']
},
Expand All @@ -157,6 +169,10 @@ const data = shallowRef([
status: 'Published',
type: 'Illustration',
width: 768,
authors: [
{ image: 'https://i.pravatar.cc/64?img=1', name: 'Jane Doe' },
{ image: 'https://i.pravatar.cc/64?img=2', name: 'Daniel Green' }
],
createdAt: day('2022-09-12'),
tags: ['Info', 'News']
},
Expand All @@ -166,6 +182,11 @@ const data = shallowRef([
status: 'Archived',
type: 'Other',
width: 512,
authors: [
{ image: 'https://i.pravatar.cc/64?img=4', name: 'Kris James' },
{ image: 'https://i.pravatar.cc/64?img=5', name: 'Becky Lu' },
{ image: 'https://i.pravatar.cc/64?img=7', name: 'Thomas Wane' }
],
createdAt: day('2022-09-08'),
tags: ['Info']
}
Expand All @@ -186,6 +207,7 @@ const table = useTable({
orders: [
'name',
'status',
'authors',
'type',
'width',
'tags',
Expand Down Expand Up @@ -217,6 +239,14 @@ const table = useTable({
})
},
authors: {
label: 'Authors',
cell: (authors) => ({
type: 'avatars',
avatars: authors
})
},
type: {
label: 'Type',
show: !optionsSelected.value.includes('hide-type'),
Expand Down Expand Up @@ -367,6 +397,7 @@ function updateTagsFilter(value: string) {
<style scoped>
.table :deep(.col-name) { --table-col-width: 160px; }
.table :deep(.col-status) { --table-col-width: 144px; }
.table :deep(.col-authors) { --table-col-width: 240px; }
.table :deep(.col-type) { --table-col-width: 128px; }
.table :deep(.col-width) { --table-col-width: 128px; }
.table :deep(.col-tags) { --table-col-width: 192px; }
Expand Down

0 comments on commit 303f377

Please sign in to comment.