Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(desc): add actions option #582

Merged
merged 1 commit into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/components/SDescFile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const items = computed(() => {
gap: 1px;
border: 1px solid var(--c-divider);
border-radius: 6px;
margin-top: 2px;
margin-top: 4px;
background-color: var(--c-gutter);
overflow: hidden;
}
Expand Down
12 changes: 11 additions & 1 deletion lib/components/SDescItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,17 @@ const labelWidth = computed(() => {
}

.SDesc.row > .SDescItem {
grid-template-columns: var(--desc-label-width, v-bind(labelWidth)) minmax(0, 1fr);
& {
grid-template-columns: var(--desc-label-width, v-bind(labelWidth)) minmax(0, 1fr);
}

& > :deep(.SDescLabel) {
height: 24px;
}

& > :deep(.SDescLabel > .value) {
line-height: 24px;
}
}

.SDesc.divider > .SDescItem:not(:has(> .SDescFile)) {
Expand Down
73 changes: 67 additions & 6 deletions lib/components/SDescLabel.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,40 @@
<script setup lang="ts">
defineProps<{
import { type Component } from 'vue'
import { type ActionList } from './SActionList.vue'
import SActionMenu from './SActionMenu.vue'
import SButton, { type Mode, type Tooltip } from './SButton.vue'

export interface Props {
value?: string | null
}>()
actions?: Action[]
}

export type Action = ActionButton | ActionMenu

export interface ActionBase {
type?: 'button' | 'menu'
mode?: Mode
icon: Component
loading?: boolean
disabled?: boolean
tooltip?: string | Tooltip
}

export interface ActionButton extends ActionBase {
type?: 'button'
onClick(): void
}

export interface ActionMenu extends ActionBase {
type: 'menu'
options: ActionList
}

defineProps<Props>()

function isActionButton(action: Action): action is ActionButton {
return (action.type ?? 'button') === 'button'
}
</script>

<template>
Expand All @@ -10,19 +43,47 @@ defineProps<{
<slot v-if="$slots.default" />
<template v-else>{{ value }}</template>
</div>
<div v-if="actions?.length" class="actions">
<template v-for="action, index in actions" :key="index">
<SButton
v-if="isActionButton(action)"
type="text"
size="mini"
:mode="action.mode ?? 'mute'"
:icon="action.icon"
:loading="action.loading"
:disabled="action.disabled"
:tooltip="action.tooltip"
@click="action.onClick"
/>
<SActionMenu
v-else
type="text"
size="mini"
:mode="action.mode ?? 'mute'"
:icon="action.icon"
:loading="action.loading"
:disabled="action.disabled"
:tooltip="action.tooltip"
:options="[{ type: 'menu', options: action.options }]"
/>
</template>
</div>
</div>
</template>

<style scoped lang="postcss">
.SDescLabel {
display: flex;
height: 24px;
gap: 16px;
height: 28px;
}

.value {
line-height: 24px;
font-size: 12px;
font-weight: 500;
flex-grow: 1;
line-height: 28px;
font-size: 14px;
font-weight: 400;
color: var(--c-text-2);
white-space: nowrap;
overflow: hidden;
Expand Down
35 changes: 25 additions & 10 deletions stories/components/SDesc.01_Playground.story.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script setup lang="ts">
import IconDotsThree from '~icons/ph/dots-three-bold'
import IconNotePencil from '~icons/ph/note-pencil'
import SDesc from 'sefirot/components/SDesc.vue'
import SDescAvatar from 'sefirot/components/SDescAvatar.vue'
import SDescDay from 'sefirot/components/SDescDay.vue'
Expand All @@ -14,6 +16,19 @@ import SDescText from 'sefirot/components/SDescText.vue'
const title = 'Components / SDesc / 01. Playground'
const docs = '/components/desc'

const actions = [
{ icon: IconNotePencil, onClick: () => {} },
{
type: 'menu' as const,
icon: IconDotsThree,
options: [
{ label: 'Inspect', onClick: () => {} },
{ label: 'Preview', onClick: () => {} },
{ label: 'Delete', onClick: () => {} }
]
}
]

function state() {
return {
divider: true
Expand All @@ -37,8 +52,8 @@ function state() {
gap="24"
:divider="state.divider"
>
<SDescItem span="2">
<SDescLabel>Account</SDescLabel>
<SDescItem span="2" :divider="false">
<SDescLabel :actions="actions">Account</SDescLabel>
<SDescAvatar
:avatar="{
avatar: 'https://i.pravatar.cc/64?img=1',
Expand All @@ -47,35 +62,35 @@ function state() {
/>
</SDescItem>
<SDescItem span="1">
<SDescLabel>Full name</SDescLabel>
<SDescLabel :actions="actions">Full name</SDescLabel>
<SDescText>Margot Foster</SDescText>
</SDescItem>
<SDescItem span="1">
<SDescLabel>Website</SDescLabel>
<SDescLabel :actions="actions">Website</SDescLabel>
<SDescLink>https://margot.example</SDescLink>
</SDescItem>
<SDescItem span="1">
<SDescLabel>Birthday</SDescLabel>
<SDescLabel :actions="actions">Birthday</SDescLabel>
<SDescDay>1985-10-10</SDescDay>
</SDescItem>
<SDescItem span="1">
<SDescLabel>Age</SDescLabel>
<SDescLabel :actions="actions">Age</SDescLabel>
<SDescNumber>37</SDescNumber>
</SDescItem>
<SDescItem span="1">
<SDescLabel>Application for</SDescLabel>
<SDescLabel :actions="actions">Application for</SDescLabel>
<SDescPill :pill="{ label: 'Frontend Developer' }" />
</SDescItem>
<SDescItem span="1">
<SDescLabel>Interview status</SDescLabel>
<SDescLabel :actions="actions">Interview status</SDescLabel>
<SDescState :state="{ mode: 'info', label: 'In progress' }" />
</SDescItem>
<SDescItem span="2">
<SDescLabel>About</SDescLabel>
<SDescLabel :actions="actions">About</SDescLabel>
<SDescText>Fugiat ipsum ipsum deserunt culpa aute sint do nostrud anim incididunt cillum culpa consequat. Excepteur <a href="https://hello.com">qui ipsum aliquip consequat</a> sint. Sit id mollit nulla mollit nostrud in ea officia proident. Irure nostrud pariatur mollit ad adipisicing reprehenderit deserunt qui eu.</SDescText>
</SDescItem>
<SDescItem span="2">
<SDescLabel>Attachments</SDescLabel>
<SDescLabel :actions="actions">Attachments</SDescLabel>
<SDescFile
:item="[
{ name: 'John-Doe-Resume-19851010.pdf', onDownload: () => {} },
Expand Down