More button options and dividers in overflow menus

This commit is contained in:
Prospector 2023-10-11 14:57:23 -07:00
parent ffc46d6a48
commit f9a9ece320
No known key found for this signature in database
8 changed files with 201 additions and 68 deletions

View File

@ -58,6 +58,38 @@
<Button color="blue" transparent><GlobeIcon/> Visit website</Button> <Button color="blue" transparent><GlobeIcon/> Visit website</Button>
``` ```
## Hover-filled
<DemoContainer>
<Button color="green" transparent hoverFilled><PlayIcon /> Play</Button>
<Button color="red" transparent hoverFilled><TrashIcon /> Delete</Button>
<Button color="green" outline hoverFilled><PlayIcon /> Play</Button>
<Button color="red" outline hoverFilled><TrashIcon /> Delete</Button>
</DemoContainer>
```vue
<Button color="green" transparent hoverFilled><PlayIcon /> Play</Button>
<Button color="red" transparent hoverFilled><TrashIcon /> Delete</Button>
<Button color="green" outline hoverFilled><PlayIcon /> Play</Button>
<Button color="red" outline hoverFilled><TrashIcon /> Delete</Button>
```
## Hover-filled-only
<DemoContainer>
<Button color="green" transparent hoverFilledOnly><PlayIcon /> Play</Button>
<Button color="red" transparent hoverFilledOnly><TrashIcon /> Delete</Button>
<Button color="green" outline hoverFilledOnly><PlayIcon /> Play</Button>
<Button color="red" outline hoverFilledOnly><TrashIcon /> Delete</Button>
</DemoContainer>
```vue
<Button color="green" transparent hoverFilledOnly><PlayIcon /> Play</Button>
<Button color="red" transparent hoverFilledOnly><TrashIcon /> Delete</Button>
<Button color="green" outline hoverFilledOnly><PlayIcon /> Play</Button>
<Button color="red" outline hoverFilledOnly><TrashIcon /> Delete</Button>
```
## Icon-only ## Icon-only
<DemoContainer> <DemoContainer>

View File

@ -1,32 +1,47 @@
<script setup> # Overflow Menu
const options = [ <DemoContainer>
<OverflowMenu :options="[
{ {
'id': 'like', 'id': 'play',
'color': 'primary', 'color': 'primary',
'action': () => {},
'hoverFilledOnly': true
},
{ divider: true },
{
'id': 'duplicate',
'action': () => {} 'action': () => {}
}, },
{ {
'id': 'report', 'id': 'report',
'action': () => {} 'action': () => {}
}, },
{
'id': 'remain',
'action': () => {},
'remainOnClick': true,
},
{ divider: true },
{ {
'id': 'delete', 'id': 'delete',
'color': 'danger', 'color': 'danger',
'action': () => {} 'action': () => {},
'hoverFilled': true,
} }
] ]" class="btn">
</script>
# Overflow Menu
<DemoContainer>
<OverflowMenu :options="options" class="btn">
More options... More options...
<template #like> <template #play>
<HeartIcon /> Like <PlayIcon /> Play
</template>
<template #duplicate>
<CopyIcon /> Duplicate
</template> </template>
<template #report> <template #report>
<ReportIcon /> Report <ReportIcon /> Report
</template> </template>
<template #remain>
<ClearIcon /> I shall remain
</template>
<template #delete> <template #delete>
<TrashIcon /> Delete <TrashIcon /> Delete
</template> </template>
@ -34,7 +49,37 @@ const options = [
</DemoContainer> </DemoContainer>
```vue ```vue
<OverflowMenu :options="options" class="btn"> <OverflowMenu
class="btn"
:options="[
{
'id': 'play',
'color': 'primary',
'action': () => {},
'hoverFilledOnly': true
},
{ divider: true },
{
'id': 'duplicate',
'action': () => {}
},
{
'id': 'report',
'action': () => {}
},
{
'id': 'remain',
'action': () => {},
'remainOnClick': true,
},
{ divider: true },
{
'id': 'delete',
'color': 'danger',
'action': () => {},
'hoverFilled': true,
}
]">
More options... More options...
<template #like> <template #like>
<HeartIcon /> Like <HeartIcon /> Like

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-copy"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>

After

Width:  |  Height:  |  Size: 337 B

View File

@ -266,10 +266,13 @@ a,
&:focus-visible:not(&:disabled), &:focus-visible:not(&:disabled),
&:hover:not(&:disabled) { &:hover:not(&:disabled) {
cursor: pointer; cursor: pointer;
filter: brightness(0.85);
&:not(.btn-outline.btn-hover-filled, .btn-transparent) {
filter: brightness(0.85);
}
} }
&:active:not(&:disabled) { &:active:not(&:disabled, .btn-outline.btn-hover-filled, .btn-transparent) {
filter: brightness(0.8); filter: brightness(0.8);
} }
@ -321,86 +324,118 @@ a,
.btn { .btn {
@extend .button-base; @extend .button-base;
--text-color: var(--color-base); --_text-color: var(--color-base);
--background-color: var(--color-button-bg); --_background-color: var(--color-button-bg);
--shadow: var(--shadow-inset-sm), 0 0 0 0 transparent; --_accent-color: var(--color-base);
--_shadow: var(--shadow-inset-sm), 0 0 0 0 transparent;
&.btn-outline, &.btn-outline,
&.btn-transparent { &.btn-transparent {
--background-color: var(--color-base);
--text-color: var(--color-raised-bg);
box-sizing: border-box; box-sizing: border-box;
background-color: transparent; background-color: transparent;
color: var(--background-color); transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out , color 0.2s ease-in-out;
transition: background-color 0.2s ease-in-out; box-shadow: none;
}
&.btn-transparent {
--_accent-color: var(--color-base);
color: var(--_accent-color);
&.btn-hover-filled-only {
color: var(--color-base);
}
&:focus-visible:not(&:disabled), &:focus-visible:not(&:disabled),
&:hover:not(&:disabled) { &:hover:not(&:disabled) {
background-color: var(--color-button-bg); background-color: var(--color-button-bg);
filter: none;
&.btn-hover-filled, &.btn-hover-filled-only {
color: var(--_text-color);
background-color: var(--_background-color);
}
} }
} }
&.btn-outline { &.btn-outline {
--background-color: var(--color-contrast); --_accent-color: var(--color-contrast);
border: 2px solid var(--background-color); border: 2px solid var(--_accent-color);
padding-block: calc(var(--gap-sm) - 2px); padding-block: calc(var(--gap-sm) - 2px);
} color: var(--_background-color);
&.btn-raised { &.btn-hover-filled-only {
--shadow: var(--shadow-inset-sm), var(--shadow-raised); color: var(--color-contrast);
--background-color: var(--color-raised-bg); border-color: var(--color-contrast);
}
&:focus-visible:not(&:disabled),
&:hover:not(&:disabled) {
&.btn-hover-filled, &.btn-hover-filled-only {
border-color: var(--_accent-color);
color: var(--_text-color);
background-color: var(--_background-color);
}
}
} }
&.btn-danger { &.btn-danger {
--text-color: var(--color-accent-contrast); --_text-color: var(--color-accent-contrast);
--background-color: var(--color-red); --_background-color: var(--color-red);
--_accent-color: var(--color-red);
} }
&.btn-primary { &.btn-primary {
--text-color: var(--color-accent-contrast); --_text-color: var(--color-accent-contrast);
--background-color: var(--color-brand); --_background-color: var(--color-brand);
--_accent-color: var(--color-brand);
} }
&.btn-secondary { &.btn-secondary {
--text-color: var(--color-contrast); --_text-color: var(--color-contrast);
--background-color: var(--color-brand-highlight); --_background-color: var(--color-brand-highlight);
--_accent-color: var(--color-brand-highlight);
} }
&.btn-highlight { &.btn-highlight {
--text-color: var(--color-accent-contrast); --_text-color: var(--color-accent-contrast);
--background-color: var(--color-orange); --_background-color: var(--color-orange);
--_accent-color: var(--color-orange);
} }
&.btn-red { &.btn-red {
--text-color: var(--color-accent-contrast); --_text-color: var(--color-accent-contrast);
--background-color: var(--color-red); --_background-color: var(--color-red);
--_accent-color: var(--color-red);
} }
&.btn-orange { &.btn-orange {
--text-color: var(--color-accent-contrast); --_text-color: var(--color-accent-contrast);
--background-color: var(--color-orange); --_background-color: var(--color-orange);
--_accent-color: var(--color-orange);
} }
&.btn-green { &.btn-green {
--text-color: var(--color-accent-contrast); --_text-color: var(--color-accent-contrast);
--background-color: var(--color-green); --_background-color: var(--color-green);
--_accent-color: var(--color-green);
} }
&.btn-blue { &.btn-blue {
--text-color: var(--color-accent-contrast); --_text-color: var(--color-accent-contrast);
--background-color: var(--color-blue); --_background-color: var(--color-blue);
--_accent-color: var(--color-blue);
} }
&.btn-purple { &.btn-purple {
--text-color: var(--color-accent-contrast); --_text-color: var(--color-accent-contrast);
--background-color: var(--color-purple); --_background-color: var(--color-purple);
--_accent-color: var(--color-purple);
} }
&.btn-gray { &.btn-gray {
--text-color: var(--color-accent-contrast); --_text-color: var(--color-accent-contrast);
--background-color: var(--color-gray); --_background-color: var(--color-gray);
--_accent-color: var(--color-gray);
} }
&.btn-large { &.btn-large {
@ -410,9 +445,9 @@ a,
box-sizing: border-box; box-sizing: border-box;
color: var(--text-color); color: var(--_text-color);
background-color: var(--background-color); background-color: var(--_background-color);
box-shadow: var(--shadow); box-shadow: var(--_shadow);
border-radius: var(--radius-md); border-radius: var(--radius-md);
padding: var(--gap-sm) var(--gap-lg); padding: var(--gap-sm) var(--gap-lg);

View File

@ -36,6 +36,14 @@ const props = defineProps({
type: Boolean, type: Boolean,
default: false, default: false,
}, },
hoverFilled: {
type: Boolean,
default: false,
},
hoverFilledOnly: {
type: Boolean,
default: false,
},
}) })
const accentedButton = computed(() => const accentedButton = computed(() =>
@ -61,6 +69,8 @@ const accentedButton = computed(() =>
'btn-purple': color === 'purple', 'btn-purple': color === 'purple',
'btn-gray': color === 'gray', 'btn-gray': color === 'gray',
'btn-transparent': transparent, 'btn-transparent': transparent,
'btn-hover-filled': hoverFilled,
'btn-hover-filled-only': hoverFilledOnly,
'btn-outline': outline, 'btn-outline': outline,
'color-accent-contrast': accentedButton, 'color-accent-contrast': accentedButton,
}" }"
@ -88,6 +98,8 @@ const accentedButton = computed(() =>
'btn-purple': color === 'purple', 'btn-purple': color === 'purple',
'btn-gray': color === 'gray', 'btn-gray': color === 'gray',
'btn-transparent': transparent, 'btn-transparent': transparent,
'btn-hover-filled': hoverFilled,
'btn-hover-filled-only': hoverFilledOnly,
'btn-outline': outline, 'btn-outline': outline,
'color-accent-contrast': accentedButton, 'color-accent-contrast': accentedButton,
}" }"

View File

@ -8,21 +8,28 @@
> >
<slot></slot> <slot></slot>
<template #menu> <template #menu>
<Button <template v-for="(option, index) in options">
v-for="option in options" <div v-if="option.divider" :key="`divider-${index}`" class="card-divider"></div>
:key="`option-${option.id}`" <Button
:color="option.color ? option.color : 'default'" v-else
transparent :key="`option-${option.id}`"
:action=" :color="option.color ? option.color : 'default'"
() => { :hover-filled="option.hoverFilled"
option.action() :hover-filled-only="option.hoverFilledOnly"
close() transparent
} :action="
" () => {
> option.action()
<template v-if="!$slots[option.id]">{{ option.id }}</template> if (!option.remainOnClick) {
<slot :name="option.id"></slot> close()
</Button> }
}
"
>
<template v-if="!$slots[option.id]">{{ option.id }}</template>
<slot :name="option.id"></slot>
</Button>
</template>
</template> </template>
</PopoutMenu> </PopoutMenu>
</template> </template>

View File

@ -89,7 +89,7 @@ onBeforeUnmount(() => {
position: absolute; position: absolute;
scale: 0.75; scale: 0.75;
border: 1px solid var(--color-button-bg); border: 1px solid var(--color-button-bg);
padding: var(--gap-md); padding: var(--gap-sm);
width: fit-content; width: fit-content;
border-radius: var(--radius-md); border-radius: var(--radius-md);
background-color: var(--color-raised-bg); background-color: var(--color-raised-bg);

View File

@ -59,6 +59,7 @@ export { default as ClipboardCopyIcon } from '@/assets/icons/clipboard-copy.svg'
export { default as CodeIcon } from '@/assets/icons/code.svg' export { default as CodeIcon } from '@/assets/icons/code.svg'
export { default as CoinsIcon } from '@/assets/icons/coins.svg' export { default as CoinsIcon } from '@/assets/icons/coins.svg'
export { default as ContractIcon } from '@/assets/icons/contract.svg' export { default as ContractIcon } from '@/assets/icons/contract.svg'
export { default as CopyIcon } from '@/assets/icons/copy.svg'
export { default as CopyrightIcon } from '@/assets/icons/copyright.svg' export { default as CopyrightIcon } from '@/assets/icons/copyright.svg'
export { default as CurrencyIcon } from '@/assets/icons/currency.svg' export { default as CurrencyIcon } from '@/assets/icons/currency.svg'
export { default as DashboardIcon } from '@/assets/icons/dashboard.svg' export { default as DashboardIcon } from '@/assets/icons/dashboard.svg'