feat(lite/buttons): Add multiple button colors, outlined and transparent (#6393)

This commit is contained in:
Thierry Goettelmann 2022-09-16 14:03:26 +02:00 committed by Julien Fontanet
parent 6d1086539e
commit 94b2b8ec70
4 changed files with 137 additions and 47 deletions

View File

@ -73,7 +73,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, watch } from "vue"; import { computed, watch } from "vue";
import { useI18n } from "vue-i18n";
import type { import type {
Filter, Filter,
FilterComparisonType, FilterComparisonType,

View File

@ -1,20 +1,21 @@
<template> <template>
<button <button
:class="[ :class="className"
`color-${buttonColor}`,
{ busy: isBusy, disabled: isDisabled, active },
]"
:disabled="isBusy || isDisabled" :disabled="isBusy || isDisabled"
:type="type || 'button'" :type="type || 'button'"
class="ui-button" class="ui-button"
> >
<UiIcon :busy="isBusy" :icon="icon" class="icon" /> <span v-if="isBusy" class="loader" />
<slot v-if="!isBusy" /> <template v-else>
<UiIcon :icon="icon" class="icon" />
<slot />
</template>
</button> </button>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, inject, unref } from "vue"; import { computed, inject, unref } from "vue";
import type { Color } from "@/types";
import type { IconDefinition } from "@fortawesome/fontawesome-common-types"; import type { IconDefinition } from "@fortawesome/fontawesome-common-types";
import UiIcon from "@/components/ui/UiIcon.vue"; import UiIcon from "@/components/ui/UiIcon.vue";
@ -24,10 +25,12 @@ const props = withDefaults(
busy?: boolean; busy?: boolean;
disabled?: boolean; disabled?: boolean;
icon?: IconDefinition; icon?: IconDefinition;
color?: "primary" | "secondary"; color?: Color;
outlined?: boolean;
transparent?: boolean;
active?: boolean; active?: boolean;
}>(), }>(),
{ busy: undefined, disabled: undefined } { busy: undefined, disabled: undefined, outlined: undefined }
); );
const isGroupBusy = inject("isButtonGroupBusy", false); const isGroupBusy = inject("isButtonGroupBusy", false);
@ -36,8 +39,24 @@ const isBusy = computed(() => props.busy ?? unref(isGroupBusy));
const isGroupDisabled = inject("isButtonGroupDisabled", false); const isGroupDisabled = inject("isButtonGroupDisabled", false);
const isDisabled = computed(() => props.disabled ?? unref(isGroupDisabled)); const isDisabled = computed(() => props.disabled ?? unref(isGroupDisabled));
const buttonGroupColor = inject("buttonGroupColor", "primary"); const isGroupOutlined = inject("isButtonGroupOutlined", false);
const isGroupTransparent = inject("isButtonGroupTransparent", false);
const buttonGroupColor = inject("buttonGroupColor", "info");
const buttonColor = computed(() => props.color ?? unref(buttonGroupColor)); const buttonColor = computed(() => props.color ?? unref(buttonGroupColor));
const className = computed(() => {
return [
`color-${buttonColor.value}`,
{
busy: isBusy.value,
active: props.active,
disabled: isDisabled.value,
outlined: props.outlined ?? unref(isGroupOutlined),
transparent: props.transparent ?? unref(isGroupTransparent),
},
];
});
</script> </script>
<style lang="postcss" scoped> <style lang="postcss" scoped>
@ -47,57 +66,117 @@ const buttonColor = computed(() => props.color ?? unref(buttonGroupColor));
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
min-width: 5em;
min-height: 2.5em; min-height: 2.5em;
padding: 0 0.75em; padding: 0 0.75em;
cursor: pointer;
vertical-align: middle; vertical-align: middle;
border: none; color: var(--button-color);
border-radius: 0.4em; border: 1px solid var(--button-border-color);
box-shadow: var(--shadow-100); border-radius: 0.5em;
background-color: var(--button-background-color);
gap: 0.75em; gap: 0.75em;
&:not(.transparent) {
box-shadow: var(--shadow-100);
}
&.color-info {
--button-accent-color: var(--color-extra-blue-base);
--button-accent-color-hover: var(--color-extra-blue-d20);
--button-accent-color-active: var(--color-extra-blue-d40);
}
&.color-success {
--button-accent-color: var(--color-green-infra-base);
--button-accent-color-hover: var(--color-green-infra-d20);
--button-accent-color-active: var(--color-green-infra-d40);
}
&.color-warning {
--button-accent-color: var(--color-orange-world-base);
--button-accent-color-hover: var(--color-orange-world-d20);
--button-accent-color-active: var(--color-orange-world-d40);
}
&.color-error {
--button-accent-color: var(--color-red-vates-base);
--button-accent-color-hover: var(--color-red-vates-d20);
--button-accent-color-active: var(--color-red-vates-d40);
}
&:hover {
--button-accent-color: var(--button-accent-color-hover);
}
&:active,
&.active,
&.busy {
--button-accent-color: var(--button-accent-color-active);
}
--button-color: var(--color-blue-scale-500);
--button-border-color: transparent;
--button-background-color: var(--button-accent-color);
&.outlined {
--button-color: var(--button-accent-color);
--button-border-color: var(--button-accent-color);
--button-background-color: var(--background-color-primary);
}
&.transparent {
--button-color: var(--button-accent-color);
--button-border-color: transparent;
--button-background-color: transparent;
}
&.busy {
cursor: not-allowed;
}
&.disabled { &.disabled {
color: var(--color-blue-scale-400); cursor: not-allowed;
background-color: var(--background-color-secondary); --button-color: var(--color-blue-scale-400);
} --button-border-color: transparent;
--button-background-color: var(--background-color-secondary);
&:not(.disabled) {
&.color-primary {
color: var(--color-blue-scale-500);
background-color: var(--color-extra-blue-base);
&:hover {
background-color: var(--color-extra-blue-d20);
}
&:active,
&.active,
&.busy {
background-color: var(--color-extra-blue-d40);
}
}
&.color-secondary {
color: var(--color-extra-blue-base);
border: 1px solid var(--color-extra-blue-base);
background-color: var(--color-blue-scale-500);
&:hover {
color: var(--color-extra-blue-d20);
border-color: var(--color-extra-blue-d20);
}
&:active,
&.active,
&.busy {
color: var(--color-extra-blue-d40);
border-color: var(--color-extra-blue-d40);
}
}
} }
} }
.icon { .icon {
font-size: 0.8em; font-size: 0.8em;
} }
.loader {
display: inline-flex;
align-items: center;
justify-content: center;
width: 1.5em;
height: 1.5em;
animation: spin 1s infinite linear;
border-radius: 0.75em;
background: conic-gradient(
from 90deg at 50% 50%,
rgba(255, 255, 255, 0) 0deg,
rgba(255, 255, 255, 0) 0.04deg,
var(--button-color) 360deg
);
&::after {
width: 1.2em;
height: 1.2em;
content: "";
border-radius: 0.6em;
background-color: var(--button-background-color);
}
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
</style> </style>

View File

@ -6,11 +6,14 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, provide } from "vue"; import { computed, provide } from "vue";
import type { Color } from "@/types";
const props = defineProps<{ const props = defineProps<{
busy?: boolean; busy?: boolean;
disabled?: boolean; disabled?: boolean;
color?: "primary" | "secondary"; color?: Color;
outlined?: boolean;
transparent?: boolean;
}>(); }>();
provide( provide(
"isButtonGroupBusy", "isButtonGroupBusy",
@ -22,7 +25,15 @@ provide(
); );
provide( provide(
"buttonGroupColor", "buttonGroupColor",
computed(() => props.color ?? "primary") computed(() => props.color ?? "info")
);
provide(
"isButtonGroupOutlined",
computed(() => props.outlined ?? false)
);
provide(
"isButtonGroupTransparent",
computed(() => props.transparent ?? false)
); );
</script> </script>

View File

@ -0,0 +1 @@
export type Color = "info" | "error" | "warning" | "success";