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;
+    }
   }
 }