diff --git a/docs/components/button/basic.md b/docs/components/button/basic.md index 916195a2dea5d7bd5b3ca395470f04958fd15cfa..8f15b5c1bd2fe7da371eef18641ecf8d26e046e9 100644 --- a/docs/components/button/basic.md +++ b/docs/components/button/basic.md @@ -6,17 +6,17 @@ const click = () => new Promise(resolve => setTimeout(resolve, 1000)) Buttons are UI elements that users can interact with to perform actions. Funkwhale uses buttons in many contexts. -| Prop | Data type | Required? | Default | Description | -| ------------- | ----------------------------------------- | --------- | --------- | -------------------------------------------------- | -| `outline` | Boolean | No | `false` | Whether to render the button as an outline button. | -| `shadow` | Boolean | No | `false` | Whether to render the button with a shadow | -| `round` | Boolean | No | `false` | Whether to render the button as a round button | -| `icon` | String | No | | The icon attached to the button | -| `is-active` | Boolean | No | `false` | Whether the button is in an active state | -| `is-loading` | Boolean | No | `false` | Whether the button is in a loading state | -| `color` | `primary` \| `secondary` \| `destructive` | No | `primary` | Renders a colored button | - -## Button types +| Prop | Data type | Required? | Default | Description | +| ------------- | ----------------------------------------- | --------- | --------- | ------------------------------------------------------------------ | +| `variant` | `solid` \| `outline` \| `ghost` | No | `solid` | Whether to render the button as an solid, outline or ghost button. | +| `shadow` | Boolean | No | `false` | Whether to render the button with a shadow | +| `round` | Boolean | No | `false` | Whether to render the button as a round button | +| `icon` | String | No | | The icon attached to the button | +| `is-active` | Boolean | No | `false` | Whether the button is in an active state | +| `is-loading` | Boolean | No | `false` | Whether the button is in a loading state | +| `color` | `primary` \| `secondary` \| `destructive` | No | `primary` | Renders a colored button | + +## Button colors Buttons come in different types depending on the type of action they represent. @@ -66,16 +66,16 @@ Desctrutive buttons represent **dangerous** actions including deleting items or Destructive button </fw-button> -## Button styles +## Button variants Buttons come in different styles that you can use depending on the location of the button. -### Filled +### Solid -Filled buttons have a solid background. Use these to emphasize the action the button performs. +Solid buttons have a filled background. Use these to emphasize the action the button performs. ::: info -This is the default style. If you don't specify a style, a filled button is rendered. +This is the default style. If you don't specify a style, a solid button is rendered. ::: ```vue-html @@ -93,15 +93,31 @@ This is the default style. If you don't specify a style, a filled button is rend Outline buttons have a transparent background. Use these to deemphasize the action the button performs. ```vue-html -<fw-button outline color="secondary"> +<fw-button variant="outline" color="secondary"> Outline button </fw-button> ``` -<fw-button outline color="secondary"> +<fw-button variant="outline" color="secondary"> Outline button </fw-button> +### Ghost + +Ghost buttons have a transparent background and border. Use these to deemphasize the action the button performs. + +```vue-html +<fw-button variant="ghost" color="secondary"> + Ghost button +</fw-button> +``` + +<fw-button variant="ghost" color="secondary"> + Ghost button +</fw-button> + +## Button styles + ### Shadow You can give a button a shadow to add depth. diff --git a/src/components/button/Button.vue b/src/components/button/Button.vue index d016203ca9466ec38af86312415ad4251b49d428..d93669134f56ec355443b678b721d39ae209ed96 100644 --- a/src/components/button/Button.vue +++ b/src/components/button/Button.vue @@ -5,7 +5,9 @@ import { ref, computed, useSlots } from 'vue' import type { ColorProps } from '~/types/common-props' interface Props { - outline?: boolean + variant?: 'solid' | 'outline' | 'ghost' + width?: 'standard' | 'auto' | 'full' + alignText?: 'left' | 'center' | 'right' isActive?: boolean isLoading?: boolean @@ -41,14 +43,28 @@ const click = async (...args: any[]) => { <template> <button class="funkwhale is-colored button" - :class="[color, { 'is-active': isActive, 'is-outline': outline, 'is-loading': isLoading, 'icon-only': iconOnly, 'is-round': round, 'is-shadow': shadow }]" + :class="[ + color, + 'is-' + (variant ?? 'solid'), + 'is-' + (width ?? 'standard'), + 'is-aligned-' + (alignText ?? 'center'), + { + 'is-active': isActive, + 'is-loading': isLoading, + 'icon-only': iconOnly, + 'has-icon': !!icon, + 'is-round': round, + 'is-shadow': shadow + } + ]" @click="click" > + <i + v-if="icon" + :class="['bi', icon]" + /> + <span> - <i - v-if="icon" - :class="['bi', icon]" - /> <slot /> </span> diff --git a/src/components/button/options/Button.vue b/src/components/button/options/Button.vue index eae30988cbf9cf29b7465eea7878a23aeb42870e..fc441633d3ae90ad521f97d443bffa68c84fc15a 100644 --- a/src/components/button/options/Button.vue +++ b/src/components/button/options/Button.vue @@ -3,7 +3,7 @@ import { FwButton } from '~/components' </script> <template> - <fw-button icon="bi-three-dots-vertical" class="options-button" color="secondary" /> + <fw-button icon="bi-three-dots-vertical" class="options-button" color="secondary" variant="ghost" /> </template> <style lang="scss"> diff --git a/src/components/button/options/style.scss b/src/components/button/options/style.scss index dd6ead83546603ebe582575588d5f616b767dd79..5aa52ad41008cf106d0456cc8afd25466fb30f75 100644 --- a/src/components/button/options/style.scss +++ b/src/components/button/options/style.scss @@ -1,25 +1,8 @@ .funkwhale { &.options-button { - - @include light-theme { - &:not(:hover):not(:active) { - --fw-bg-color: transparent !important; - } - } - - @include dark-theme { - &:not(:hover):not(:active) { - --fw-bg-color: transparent !important; - } - } - will-change: transform; transition: all .2s ease; font-size: 0.6rem !important; padding: 0.6em !important; - - i { - font-size: 1.2rem; - } } } diff --git a/src/components/button/style.scss b/src/components/button/style.scss index 39815b195731b3e6082187f40e866dd94118e34b..dcd823384d65b0b3d9acfab246fbd57b6c5dad8e 100644 --- a/src/components/button/style.scss +++ b/src/components/button/style.scss @@ -32,6 +32,13 @@ background-color: transparent !important; } } + + &.is-ghost { + &:not(:active):not(.is-active):not(:hover):not(.is-hovered) { + background-color: transparent !important; + border-color: transparent !important; + } + } } @include dark-theme { @@ -63,6 +70,13 @@ background-color: transparent !important; } } + + &.is-ghost { + &:not(:active):not(.is-active):not(:hover):not(.is-hovered) { + background-color: transparent !important; + border-color: transparent !important; + } + } } @include docs { @@ -72,7 +86,6 @@ position: relative; display: inline-flex; align-items: center; - justify-content: center; white-space: nowrap; font-family: $font-main; @@ -89,14 +102,31 @@ transform: translateX(var(--fw-translate-x)) translateY(var(--fw-translate-y)) scale(var(--fw-scale)); transition: all .2s ease; + + &.is-aligned-center { + justify-content: center; + } + + &.is-aligned-left { + justify-content: flex-start; + } + + &.is-aligned-right { + justify-content: flex-end; + } + &.is-shadow { box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.2); } - &:not(.icon-only) { + &:not(.icon-only):not(.is-auto) { min-width: 8.5rem; } + &.is-full { + display: block; + } + &.is-round { border-radius: 100vh; } @@ -113,5 +143,13 @@ opacity: 0; } } + + i.bi { + font-size: 1.2rem; + } + + i.bi + span:not(:empty) { + margin-left: 1ch; + } } }