refactor(ui): composable widths; default colors and widths; consistent props;
This commit is contained in:
parent
c65b4bd4f0
commit
4069d2ba71
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type PastelProps, propsToColor } from '~/composables/colors'
|
import { type PastelProps, color } from '~/composables/colors'
|
||||||
|
|
||||||
type Props = PastelProps
|
type Props = PastelProps
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ const props = defineProps<Props>()
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="funkwhale is-colored solid alert"
|
class="funkwhale is-colored solid alert"
|
||||||
v-bind="propsToColor(props)"
|
v-bind="color(props)"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, useSlots, onMounted } from 'vue'
|
import { ref, computed, useSlots, onMounted } from 'vue'
|
||||||
import { type ColorProps, type VariantProps, type DefaultProps, type RaisedProps, propsToColor } from '~/composables/colors';
|
|
||||||
|
import { type ColorProps, type VariantProps, type DefaultProps, type RaisedProps, color } from '~/composables/colors';
|
||||||
|
import { type WidthProps, width } from '~/composables/widths'
|
||||||
|
|
||||||
import Loader from '~/components/ui/Loader.vue'
|
import Loader from '~/components/ui/Loader.vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
width?: 'standard' | 'auto' | 'full'
|
|
||||||
alignText?: 'left' | 'center' | 'right'
|
alignText?: 'left' | 'center' | 'right'
|
||||||
alignSelf?: 'start' | 'center' | 'end'
|
alignSelf?: 'start' | 'center' | 'end' | 'baseline'
|
||||||
thin?: true
|
thin?: true
|
||||||
|
|
||||||
isActive?: boolean
|
isActive?: boolean
|
||||||
|
@ -21,7 +22,14 @@ const props = defineProps<{
|
||||||
|
|
||||||
autofocus? : boolean
|
autofocus? : boolean
|
||||||
ariaPressed? : true
|
ariaPressed? : true
|
||||||
} & (ColorProps | DefaultProps) & VariantProps & RaisedProps>()
|
} & (ColorProps | DefaultProps)
|
||||||
|
& VariantProps
|
||||||
|
& RaisedProps
|
||||||
|
& WidthProps>()
|
||||||
|
|
||||||
|
if ('minContent' in props) {
|
||||||
|
console.log("MIN CONTENT")
|
||||||
|
}
|
||||||
|
|
||||||
const slots = useSlots()
|
const slots = useSlots()
|
||||||
const isIconOnly = computed(() => !!props.icon && !slots.default)
|
const isIconOnly = computed(() => !!props.icon && !slots.default)
|
||||||
|
@ -33,6 +41,11 @@ const fontWeight = props.thin ? 400 : 900
|
||||||
|
|
||||||
const button = ref()
|
const button = ref()
|
||||||
|
|
||||||
|
const attributes = computed(() => ({
|
||||||
|
...color(props, ['interactive']),
|
||||||
|
...width(props, [isIconOnly.value ? 'minContent' : 'buttonWidth'])
|
||||||
|
}))
|
||||||
|
|
||||||
const click = async (...args: any[]) => {
|
const click = async (...args: any[]) => {
|
||||||
internalLoader.value = true
|
internalLoader.value = true
|
||||||
|
|
||||||
|
@ -50,10 +63,9 @@ onMounted(() => {
|
||||||
<template>
|
<template>
|
||||||
<button ref="button"
|
<button ref="button"
|
||||||
:aria-pressed="props.ariaPressed"
|
:aria-pressed="props.ariaPressed"
|
||||||
v-bind="propsToColor({...props, interactive:true})"
|
v-bind="attributes"
|
||||||
class="funkwhale button"
|
class="funkwhale button"
|
||||||
:class="[
|
:class="[
|
||||||
'is-' + width,
|
|
||||||
'is-text-aligned-' + (alignText ?? 'center'),
|
'is-text-aligned-' + (alignText ?? 'center'),
|
||||||
'is-self-aligned-' + (alignSelf ?? 'center'),
|
'is-self-aligned-' + (alignSelf ?? 'center'),
|
||||||
{
|
{
|
||||||
|
@ -79,6 +91,8 @@ onMounted(() => {
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.funkwhale {
|
.funkwhale {
|
||||||
&.button {
|
&.button {
|
||||||
|
--padding: 10px;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -86,11 +100,11 @@ onMounted(() => {
|
||||||
|
|
||||||
font-family: $font-main;
|
font-family: $font-main;
|
||||||
font-weight: v-bind(fontWeight);
|
font-weight: v-bind(fontWeight);
|
||||||
font-size: 0.875em;
|
font-size: 14px;
|
||||||
|
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
|
|
||||||
padding: 9px 10px 11px 10px;
|
padding: 9px var(--padding) 11px var(--padding);
|
||||||
&.is-icon-only {
|
&.is-icon-only {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
@ -117,10 +131,6 @@ onMounted(() => {
|
||||||
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.2);
|
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.is-icon-only):not(.is-auto), &.is-standard {
|
|
||||||
min-width: 8.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
align-self: start;
|
align-self: start;
|
||||||
|
|
||||||
&.is-self-aligned-start {
|
&.is-self-aligned-start {
|
||||||
|
@ -135,6 +145,10 @@ onMounted(() => {
|
||||||
align-self: flex-end;
|
align-self: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-self-aligned-baseline {
|
||||||
|
align-self: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
&.is-full {
|
&.is-full {
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
@ -157,16 +171,16 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
i.bi {
|
i.bi {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;/* Must not increase the height of the button */
|
||||||
|
margin: -0.1rem;
|
||||||
&.large {
|
&.large {
|
||||||
font-size:2rem;
|
font-size:2rem;
|
||||||
|
margin: -0.1rem;
|
||||||
}
|
}
|
||||||
/* Must not increase the height of the button */
|
|
||||||
margin: -0.5rem 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i.bi + span:not(:empty) {
|
i.bi + span:not(:empty) {
|
||||||
margin-left: 1ch;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
import { type RouterLinkProps, RouterLink } from 'vue-router';
|
import { type RouterLinkProps, RouterLink } from 'vue-router';
|
||||||
import { type ColorProps, type DefaultProps, type PastelProps, type RaisedProps, type VariantProps, propsToColor } from '~/composables/colors'
|
import { type ColorProps, type DefaultProps, type PastelProps, type RaisedProps, type VariantProps, color } from '~/composables/colors'
|
||||||
|
import { type WidthProps, width } from '~/composables/widths'
|
||||||
|
|
||||||
import Pill from './Pill.vue'
|
import Pill from './Pill.vue'
|
||||||
import Alert from './Alert.vue'
|
import Alert from './Alert.vue'
|
||||||
|
@ -16,36 +17,29 @@ const props = defineProps<{
|
||||||
tags?: string[]
|
tags?: string[]
|
||||||
image?: string | { src: string, style?: "withPadding" }
|
image?: string | { src: string, style?: "withPadding" }
|
||||||
icon?: string
|
icon?: string
|
||||||
} & (
|
} & Partial<RouterLinkProps>
|
||||||
{ [Width in 'large' | 'medium' | 'small' | 'auto']?: true } | { width?: string }
|
& (PastelProps | ColorProps | DefaultProps)
|
||||||
) & Partial<RouterLinkProps> & (PastelProps | ColorProps | DefaultProps) & RaisedProps & VariantProps>()
|
& RaisedProps
|
||||||
|
& VariantProps
|
||||||
|
& WidthProps
|
||||||
|
>()
|
||||||
|
|
||||||
const image = typeof props.image === 'string' ? { src: props.image } : props.image
|
const image = typeof props.image === 'string' ? { src: props.image } : props.image
|
||||||
|
|
||||||
const width =
|
|
||||||
'width' in props && props.width
|
|
||||||
? props.width
|
|
||||||
: 'auto' in props && props.auto
|
|
||||||
? 'auto'
|
|
||||||
: 'large' in props && props.large ?
|
|
||||||
'304px'
|
|
||||||
: 'medium' in props && props.medium ?
|
|
||||||
'208px'
|
|
||||||
: 'small' in props && props.small ?
|
|
||||||
'min-content'
|
|
||||||
: '304px'
|
|
||||||
|
|
||||||
console.log("WIDTH", width, props)
|
|
||||||
|
|
||||||
const isExternalLink = computed(() => {
|
const isExternalLink = computed(() => {
|
||||||
return typeof props.to === 'string' && props.to.startsWith('http')
|
return typeof props.to === 'string' && props.to.startsWith('http')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const attributes = computed(() => ({
|
||||||
|
...color(props, props.to ? ['interactive', 'solid'] : []),
|
||||||
|
...width(props, ['medium'])
|
||||||
|
}))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Layout stack no-gap
|
<Layout stack no-gap
|
||||||
:class="{ [$style.card]: true, [$style['is-category']]: category }"
|
:class="{ [$style.card]: true, [$style['is-category']]: category }"
|
||||||
v-bind="propsToColor({...(props.to? { interactive: true, solid: true, default: true } : {}), ...props})"
|
v-bind="attributes"
|
||||||
>
|
>
|
||||||
|
|
||||||
<!-- Link -->
|
<!-- Link -->
|
||||||
|
@ -68,7 +62,11 @@ const isExternalLink = computed(() => {
|
||||||
|
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
|
|
||||||
<component :class="$style.title" :is="typeof category === 'string' ? category : 'h6'">{{ title }}</component>
|
<component :is="typeof category === 'string' ? category : 'h6'"
|
||||||
|
:class="$style.title"
|
||||||
|
>
|
||||||
|
{{ title }}
|
||||||
|
</component>
|
||||||
|
|
||||||
<!-- Content -->
|
<!-- Content -->
|
||||||
|
|
||||||
|
@ -86,9 +84,10 @@ const isExternalLink = computed(() => {
|
||||||
<slot />
|
<slot />
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<Spacer grow :size="0" />
|
<Spacer grow :size=0 />
|
||||||
|
|
||||||
<!-- Footer and Action -->
|
<!-- Footer and Action -->
|
||||||
|
|
||||||
<div v-if="$slots.footer" :class="$style.footer">
|
<div v-if="$slots.footer" :class="$style.footer">
|
||||||
<slot name="footer" />
|
<slot name="footer" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -104,7 +103,6 @@ const isExternalLink = computed(() => {
|
||||||
|
|
||||||
<style module>
|
<style module>
|
||||||
.card {
|
.card {
|
||||||
--fw-card-width: v-bind(width);
|
|
||||||
--fw-card-padding: v-bind("props.small ? '16px' : '24px'");
|
--fw-card-padding: v-bind("props.small ? '16px' : '24px'");
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -116,8 +114,6 @@ const isExternalLink = computed(() => {
|
||||||
border-radius: var(--fw-border-radius);
|
border-radius: var(--fw-border-radius);
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
|
|
||||||
width: var(--fw-card-width);
|
|
||||||
|
|
||||||
>.covering {
|
>.covering {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
|
@ -125,7 +121,6 @@ const isExternalLink = computed(() => {
|
||||||
&~:is(.title, .content) {
|
&~:is(.title, .content) {
|
||||||
pointer-events:none;
|
pointer-events:none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover~:is(.content) {
|
&:hover~:is(.content) {
|
||||||
text-decoration: underline
|
text-decoration: underline
|
||||||
}
|
}
|
||||||
|
@ -151,10 +146,12 @@ const isExternalLink = computed(() => {
|
||||||
|
|
||||||
>.icon {
|
>.icon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 22px;
|
top: 20px;
|
||||||
right: 22px;
|
right: 20px;
|
||||||
|
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
&:has(>.image)>.icon {
|
&:has(>.image)>.icon {
|
||||||
top: var(--fw-card-padding);
|
top: var(--fw-card-padding);
|
||||||
|
@ -175,7 +172,7 @@ const isExternalLink = computed(() => {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
&:has(>.icon)>.title {
|
&:has(>.icon):not(:has(.image))>.title {
|
||||||
padding-right:calc(var(--fw-card-padding) + 22px);
|
padding-right:calc(var(--fw-card-padding) + 22px);
|
||||||
}
|
}
|
||||||
&.is-category>.title {
|
&.is-category>.title {
|
||||||
|
@ -189,6 +186,7 @@ const isExternalLink = computed(() => {
|
||||||
>.alert {
|
>.alert {
|
||||||
padding-left: var(--fw-card-padding);
|
padding-left: var(--fw-card-padding);
|
||||||
padding-right: var(--fw-card-padding);
|
padding-right: var(--fw-card-padding);
|
||||||
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
>.tags {
|
>.tags {
|
||||||
|
@ -229,12 +227,9 @@ const isExternalLink = computed(() => {
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
border: 8px solid transparent;
|
border: 8px solid transparent;
|
||||||
|
|
||||||
&:not(:first-child) {
|
&:not(:first-child) {
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(:last-child) {
|
&:not(:last-child) {
|
||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,13 @@ const props = defineProps<{
|
||||||
noWrap?:true
|
noWrap?:true
|
||||||
}
|
}
|
||||||
& { [P in "stack" | "grid" | "flex" | "columns"]?: true | string }
|
& { [P in "stack" | "grid" | "flex" | "columns"]?: true | string }
|
||||||
& { [C in "nav" | "aside" | "header" | "footer" | "main"]?:true }>()
|
& { [C in "nav" | "aside" | "header" | "footer" | "main" | "h1" | "h2" | "h3" | "h4" | "h5"]?:true }>()
|
||||||
const columnWidth = props.columnWidth ?? 320
|
const columnWidth = props.columnWidth ?? 46
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<component
|
<component
|
||||||
:is="props.nav ? 'nav' : props.aside ? 'aside' : props.header ? 'header' : props.footer ? 'footer' : props.main ? 'main' : 'div'"
|
:is="props.nav ? 'nav' : props.aside ? 'aside' : props.header ? 'header' : props.footer ? 'footer' : props.main ? 'main' : props.h1? 'h1' : props.h2? 'h2' : props.h3? 'h3' : props.h4? 'h4' : props.h5? 'h5' : 'div'"
|
||||||
:class="[
|
:class="[
|
||||||
$style.layout,
|
$style.layout,
|
||||||
noGap || $style.gap,
|
noGap || $style.gap,
|
||||||
|
@ -59,7 +59,7 @@ const columnWidth = props.columnWidth ?? 320
|
||||||
&.grid {
|
&.grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns:
|
grid-template-columns:
|
||||||
repeat(auto-fit, minmax(min-content, calc(v-bind(columnWidth) * 1px)));
|
repeat(auto-fit, calc(v-bind(columnWidth) * 1px));
|
||||||
grid-auto-flow: row dense;
|
grid-auto-flow: row dense;
|
||||||
place-content: center; /* If the grid has a fixed size smaller than its container, center it */
|
place-content: center; /* If the grid has a fixed size smaller than its container, center it */
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,42 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { type RouterLinkProps, RouterLink } from 'vue-router'
|
|
||||||
import { type ColorProps, type DefaultProps, type VariantProps, propsToColor } from '~/composables/colors';
|
|
||||||
|
|
||||||
const { to, icon, thickWhenActive, round, ...colorProps } = defineProps<{
|
import { type RouterLinkProps, RouterLink } from 'vue-router'
|
||||||
width?: 'standard' | 'auto' | 'full'
|
import { type ColorProps, type DefaultProps, type VariantProps, color, isNoColors } from '~/composables/colors';
|
||||||
|
import { type WidthProps, width } from '~/composables/widths'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
alignText?: 'left' | 'center' | 'right' | 'stretch'
|
alignText?: 'left' | 'center' | 'right' | 'stretch'
|
||||||
alignSelf?: 'start' | 'center' | 'end'
|
alignSelf?: 'start' | 'center' | 'end'
|
||||||
thickWhenActive?: true
|
thickWhenActive?: true
|
||||||
|
|
||||||
|
thin?: true
|
||||||
|
|
||||||
icon?: string;
|
icon?: string;
|
||||||
round?: true;
|
round?: true;
|
||||||
} & RouterLinkProps & (ColorProps | DefaultProps) & VariantProps>()
|
} & RouterLinkProps
|
||||||
|
& (ColorProps | DefaultProps)
|
||||||
|
& VariantProps
|
||||||
|
& WidthProps>()
|
||||||
|
|
||||||
const isExternalLink = computed(() => {
|
const isExternalLink = computed(() => {
|
||||||
return typeof to === 'string' && to.startsWith('http')
|
return typeof props.to === 'string' && props.to.startsWith('http')
|
||||||
})
|
})
|
||||||
|
|
||||||
const [fontWeight, activeFontWeight] = thickWhenActive ? [600, 900] : [400, 400]
|
const [fontWeight, activeFontWeight] = props.thickWhenActive ? [600, 900] : [400, 400]
|
||||||
|
|
||||||
const isIconOnly = computed(() => !!icon)
|
const isIconOnly = computed(() => !!props.icon)
|
||||||
const isSimple = propsToColor(colorProps).class === ''
|
const isSimple = isNoColors(props)
|
||||||
|
|
||||||
|
const attributes = computed(() => ({
|
||||||
|
...color(props, ['interactive']),
|
||||||
|
...width(props, ['auto'])
|
||||||
|
}))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<a v-if="isExternalLink"
|
<a v-if="isExternalLink"
|
||||||
v-bind="propsToColor({ ...colorProps, interactive: true })"
|
v-bind="attributes"
|
||||||
:class="[
|
:class="[
|
||||||
$style.link,
|
$style.link,
|
||||||
$style['is-' + width],
|
$style['is-' + width],
|
||||||
|
@ -46,7 +57,7 @@ const isSimple = propsToColor(colorProps).class === ''
|
||||||
</a>
|
</a>
|
||||||
<RouterLink v-else
|
<RouterLink v-else
|
||||||
:to="to"
|
:to="to"
|
||||||
v-bind="propsToColor({ ...colorProps, interactive: true })"
|
v-bind="color(props, ['interactive'])"
|
||||||
:class="[
|
:class="[
|
||||||
$style.link,
|
$style.link,
|
||||||
$style['is-' + width],
|
$style['is-' + width],
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type ColorProps, type DefaultProps, propsToColor } from '~/composables/colors';
|
import { type ColorProps, type DefaultProps, color } from '~/composables/colors';
|
||||||
import { watchEffect } from 'vue';
|
import { watchEffect } from 'vue';
|
||||||
import onKeyboardShortcut from '~/composables/onKeyboardShortcut';
|
import onKeyboardShortcut from '~/composables/onKeyboardShortcut';
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ onKeyboardShortcut('escape', () => isOpen.value = false)
|
||||||
<div @click.stop
|
<div @click.stop
|
||||||
class="funkwhale modal raised"
|
class="funkwhale modal raised"
|
||||||
:class="[$slots.alert && 'has-alert', overPopover && 'over-popover']"
|
:class="[$slots.alert && 'has-alert', overPopover && 'over-popover']"
|
||||||
v-bind="propsToColor(colorProps)"
|
v-bind="color(colorProps)"
|
||||||
>
|
>
|
||||||
<h2>
|
<h2>
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type ColorProps, type PastelProps, propsToColor } from '~/composables/colors'
|
import { type ColorProps, type PastelProps, color } from '~/composables/colors'
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
click: [event: MouseEvent]
|
click: [event: MouseEvent]
|
||||||
|
@ -13,7 +13,7 @@ const props = defineProps<PastelProps | ColorProps>()
|
||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
class="funkwhale pill outline"
|
class="funkwhale pill outline"
|
||||||
v-bind="propsToColor({...props, interactive:true})"
|
v-bind="color(props, ['interactive'])"
|
||||||
@click.stop="handleClick"
|
@click.stop="handleClick"
|
||||||
>
|
>
|
||||||
<div v-if="!!$slots.image" class="pill-image">
|
<div v-if="!!$slots.image" class="pill-image">
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { whenever, useElementBounding, onClickOutside } from '@vueuse/core'
|
||||||
|
|
||||||
import { isMobileView, useScreenSize } from '~/composables/screen'
|
import { isMobileView, useScreenSize } from '~/composables/screen'
|
||||||
import { POPOVER_INJECTION_KEY, POPOVER_CONTEXT_INJECTION_KEY } from '~/injection-keys'
|
import { POPOVER_INJECTION_KEY, POPOVER_CONTEXT_INJECTION_KEY } from '~/injection-keys'
|
||||||
import { type ColorProps, type DefaultProps, type RaisedProps, propsToColor } from '~/composables/colors';
|
import { type ColorProps, type DefaultProps, type RaisedProps, color } from '~/composables/colors';
|
||||||
|
|
||||||
/* TODO: Basic accessibility
|
/* TODO: Basic accessibility
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ watch(open, (isOpen) => {
|
||||||
:style="position"
|
:style="position"
|
||||||
:class="{ 'is-mobile': isMobile }"
|
:class="{ 'is-mobile': isMobile }"
|
||||||
class="funkwhale popover"
|
class="funkwhale popover"
|
||||||
v-bind="propsToColor(colorProps)"
|
v-bind="color(colorProps)"
|
||||||
style="display:flex; flex-direction:column;"
|
style="display:flex; flex-direction:column;"
|
||||||
>
|
>
|
||||||
<slot name="items" />
|
<slot name="items" />
|
||||||
|
|
|
@ -67,6 +67,8 @@
|
||||||
grid-template-columns: auto 1fr auto;
|
grid-template-columns: auto 1fr auto;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
|
|
||||||
|
grid-column: span 4;
|
||||||
|
|
||||||
> .activity-image {
|
> .activity-image {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
|
|
|
@ -32,28 +32,71 @@ export type RaisedProps =
|
||||||
| { raised?: true }
|
| { raised?: true }
|
||||||
export type Raised = KeysOfUnion<RaisedProps>
|
export type Raised = KeysOfUnion<RaisedProps>
|
||||||
|
|
||||||
export type Props =
|
/* Props to Classes */
|
||||||
DefaultProps & ColorProps & PastelProps & VariantProps & InteractiveProps & RaisedProps
|
|
||||||
|
|
||||||
export type ColorSelector =
|
export type Props =
|
||||||
`${Color | Pastel | Default}${'' | ` ${Variant}${'' | ' interactive'}${'' | ' raised'}`}`
|
(DefaultProps | ColorProps | PastelProps) & VariantProps & InteractiveProps & RaisedProps
|
||||||
|
|
||||||
|
export type Key =
|
||||||
|
KeysOfUnion<Props>
|
||||||
|
|
||||||
|
// You can only have one color
|
||||||
|
const conflicts: Set<Key>[] = [
|
||||||
|
new Set(['default', 'primary', 'secondary', 'destructive', 'red', 'blue', 'purple', 'green', 'yellow']),
|
||||||
|
new Set(['solid', 'outline', 'ghost'])
|
||||||
|
]
|
||||||
|
|
||||||
|
const classes = {
|
||||||
|
default: "default",
|
||||||
|
primary: "primary",
|
||||||
|
secondary: "secondary",
|
||||||
|
destructive: "destructive",
|
||||||
|
red: "red",
|
||||||
|
blue: "blue",
|
||||||
|
purple: "purple",
|
||||||
|
green: "green",
|
||||||
|
yellow: "yellow",
|
||||||
|
solid: "solid",
|
||||||
|
outline: "outline",
|
||||||
|
ghost: "ghost",
|
||||||
|
raised: "raised",
|
||||||
|
interactive: "interactive"
|
||||||
|
} satisfies Record<Key, string>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply a color class for setting `color`, `background-color` and `border` styles.
|
* @param props A superset of `{ Key? : true }`
|
||||||
* You can override it with `style="..."`.
|
* @returns the number of actually applied classes (if there are no defaults)
|
||||||
*
|
|
||||||
* @param color Choose a semantic color or the default page background.
|
|
||||||
* This will affect the text color.
|
|
||||||
* To add an outline or filled background, add a `Variant`: `'solid' | 'outline'`.
|
|
||||||
* If the surface should stand out, add `raised`.
|
|
||||||
* If the surface reacts to mouse input, add `interactive`.
|
|
||||||
* @returns the corresponding `class` object
|
|
||||||
*
|
|
||||||
* Note: Make sure to implement the necessary classes in `colors.scss`!
|
|
||||||
*/
|
*/
|
||||||
export const color = (color: ColorSelector) =>
|
export const isNoColors = (props: Partial<Props>) =>
|
||||||
({ class: color })
|
color(props).class===''
|
||||||
|
|
||||||
// Color from Props
|
/**
|
||||||
export const propsToColor = (props: Partial<Props>) =>
|
* Add color classes to your component.
|
||||||
({ class: Object.entries(props).filter(([key, value])=>value && key).map(([key,_])=>key).join(" ") })
|
* Color classes are defined in `colors.scss`. Make sure to implement the correct style there!
|
||||||
|
*
|
||||||
|
* (1) Add a subset of `& (DefaultProps | ColorProps | PastelProps) & VariantProps & InteractiveProps & RaisedProps` to your `Props` type
|
||||||
|
* (2) Call `v-bind="propsToColor(props)"` on your component template
|
||||||
|
* (3) Now your component accepts color props such as `secondary outline raised`.
|
||||||
|
*
|
||||||
|
* @param props Your component's props (or ...rest props if you have destructured them already)
|
||||||
|
* @returns the corresponding `class` object
|
||||||
|
*/
|
||||||
|
export const color = (props: Partial<Props>, defaults?: Key[]) => ({
|
||||||
|
class:
|
||||||
|
Object.entries(props).reduce(
|
||||||
|
((acc, [key, value]) =>
|
||||||
|
value && key in classes ?
|
||||||
|
acc.filter(accKey => !conflicts.find(set => set.has(accKey) && set.has(key as Key)))
|
||||||
|
.concat([key as Key])
|
||||||
|
: acc
|
||||||
|
),
|
||||||
|
defaults || []
|
||||||
|
).join(' ')
|
||||||
|
})
|
||||||
|
|
||||||
|
type ColorSelector =
|
||||||
|
`${Color | Pastel | Default}${'' | ` ${Variant}${'' | ' interactive'}${'' | ' raised'}`}`
|
||||||
|
|
||||||
|
// Convenience function for applying default colors. Prefer using `color`
|
||||||
|
export const setColors = (color: ColorSelector) =>
|
||||||
|
({ class: color })
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
import type { KeysOfUnion } from "type-fest"
|
||||||
|
|
||||||
|
export type WidthProps =
|
||||||
|
| { minContent?: true }
|
||||||
|
| { tiny?: true }
|
||||||
|
| { buttonWidth?: true }
|
||||||
|
| { small?: true }
|
||||||
|
| { medium?: true }
|
||||||
|
| { auto?: true }
|
||||||
|
| { full?: true }
|
||||||
|
export type Key = KeysOfUnion<WidthProps>
|
||||||
|
|
||||||
|
const styles : Record<Key, string> = {
|
||||||
|
minContent: 'width: min-content;',
|
||||||
|
tiny: "width: 124px; grid-column: span 2;",
|
||||||
|
buttonWidth: "width: 136px; grid-column: span 2; flex-grow:0;",
|
||||||
|
small: "width: 202px; grid-column: span 3;",
|
||||||
|
medium: "width: 280px; grid-column: span 4;",
|
||||||
|
auto: "width: auto;",
|
||||||
|
full: "width: auto; grid-column: 1 / -1; align-self: auto;",
|
||||||
|
};
|
||||||
|
|
||||||
|
// All keys are exclusive
|
||||||
|
const conflicts: Set<Key>[] = [
|
||||||
|
new Set(Object.keys(styles) as Key[])
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a width style to your component.
|
||||||
|
* Widths are designed to work both in a page-grid context and in a flex or normal context.
|
||||||
|
*
|
||||||
|
* (1) Add `& WidthProps` to your `Props` type
|
||||||
|
* (2) Call `v-bind="propsToWidth(props)"` on your component template
|
||||||
|
* (3) Now your component accepts width props such as `small`, `medium`, `stretch`.
|
||||||
|
*
|
||||||
|
* @param props Your component's props (or ...rest props if you have destructured them already)
|
||||||
|
* @returns the corresponding `style` object
|
||||||
|
*/
|
||||||
|
export const width = (props: Partial<WidthProps>, defaults: Key[] = []) => ({
|
||||||
|
style:
|
||||||
|
Object.entries(props).reduce(
|
||||||
|
((acc, [key, value]) =>
|
||||||
|
value && key in styles ?
|
||||||
|
acc.filter(accKey => !conflicts.find(set => set.has(accKey) && set.has(key as Key)))
|
||||||
|
.concat([key as Key])
|
||||||
|
: acc
|
||||||
|
),
|
||||||
|
defaults
|
||||||
|
).map(key => styles[key])
|
||||||
|
.join(' ')
|
||||||
|
})
|
|
@ -17,7 +17,7 @@ onMounted(async () => {
|
||||||
<template>
|
<template>
|
||||||
<div class="funkwhale grid">
|
<div class="funkwhale grid">
|
||||||
<Sidebar/>
|
<Sidebar/>
|
||||||
<RouterView v-bind="color('default solid')" />
|
<RouterView v-bind="color({}, ['default', 'solid'])" />
|
||||||
<LanguagesModal />
|
<LanguagesModal />
|
||||||
<ShortcutsModal />
|
<ShortcutsModal />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -33,7 +33,7 @@ const uploads = useUploadsStore()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Layout aside :class="[$style.sidebar, $style['sticky-content']]" v-bind="color('default solid raised')">
|
<Layout aside :class="[$style.sidebar, $style['sticky-content']]" v-bind="color({}, ['default', 'solid', 'raised'])">
|
||||||
<Layout flex no-gap header style="justify-content:space-between; padding-right:8px;">
|
<Layout flex no-gap header style="justify-content:space-between; padding-right:8px;">
|
||||||
<Link to="/"
|
<Link to="/"
|
||||||
:class="$style['logo']"
|
:class="$style['logo']"
|
||||||
|
|
|
@ -45,13 +45,12 @@ const labels = computed(() => ({
|
||||||
<template>
|
<template>
|
||||||
<Popover raised v-model:open="isOpen">
|
<Popover raised v-model:open="isOpen">
|
||||||
<Button
|
<Button
|
||||||
|
min-content
|
||||||
@click="isOpen = !isOpen"
|
@click="isOpen = !isOpen"
|
||||||
round
|
round
|
||||||
default
|
default
|
||||||
raised
|
raised
|
||||||
icon=""
|
|
||||||
ghost
|
ghost
|
||||||
class="is-icon-only"
|
|
||||||
:ariaPressed="isOpen ? true : undefined"
|
:ariaPressed="isOpen ? true : undefined"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
|
|
|
@ -29,12 +29,11 @@ const isOpen = computed({
|
||||||
:title="t('components.common.UserMenu.label.language')"
|
:title="t('components.common.UserMenu.label.language')"
|
||||||
v-model="isOpen"
|
v-model="isOpen"
|
||||||
>
|
>
|
||||||
<Layout columns :column-width="140">
|
<Layout columns :column-width="200">
|
||||||
<Button ghost thin
|
<Button ghost thin small
|
||||||
v-for="(language, key) in SUPPORTED_LOCALES"
|
v-for="(language, key) in SUPPORTED_LOCALES"
|
||||||
width="full"
|
|
||||||
align-text="left"
|
align-text="left"
|
||||||
:aria-pressed="key===locale"
|
:aria-pressed="key===locale || undefined"
|
||||||
:key="key"
|
:key="key"
|
||||||
@click="setI18nLanguage(key)"
|
@click="setI18nLanguage(key)"
|
||||||
>
|
>
|
||||||
|
|
|
@ -10,15 +10,28 @@ 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.
|
Buttons are UI elements that users can interact with to perform actions. Funkwhale uses buttons in many contexts.
|
||||||
|
|
||||||
| Prop | Data type | Required? | Default | Description |
|
```ts
|
||||||
| -------------- | --------- | --------- | ------- | ---------------------------------------------- |
|
{
|
||||||
| `shadow` | Boolean | No | `false` | Whether to render the button with a shadow |
|
alignText?: 'left' | 'center' | 'right'
|
||||||
| `round` | Boolean | No | `false` | Whether to render the button as a round button |
|
alignSelf?: 'start' | 'center' | 'end'
|
||||||
| `icon` | String | No | | The icon attached to the button |
|
thin?: true
|
||||||
| `aria-pressed` | Boolean | No | `false` | Whether the button is in an active state |
|
|
||||||
| `is-loading` | Boolean | No | `false` | Whether the button is in a loading state |
|
|
||||||
|
|
||||||
In addition, use [Colors] and [Variants]
|
isActive?: boolean
|
||||||
|
isLoading?: boolean
|
||||||
|
|
||||||
|
shadow?: boolean
|
||||||
|
round?: boolean
|
||||||
|
icon?: string
|
||||||
|
|
||||||
|
onClick?: (...args: any[]) => void | Promise<void>
|
||||||
|
|
||||||
|
autofocus? : boolean
|
||||||
|
ariaPressed? : true
|
||||||
|
} & (ColorProps | DefaultProps)
|
||||||
|
& VariantProps
|
||||||
|
& RaisedProps
|
||||||
|
& WidthProps
|
||||||
|
```
|
||||||
|
|
||||||
## Button colors
|
## Button colors
|
||||||
|
|
||||||
|
@ -307,27 +320,31 @@ Icon buttons shrink down to the icon size if you don't pass any content. If you
|
||||||
```vue-html
|
```vue-html
|
||||||
<Button icon="bi-three-dots-vertical" />
|
<Button icon="bi-three-dots-vertical" />
|
||||||
<Button round icon="bi-x" />
|
<Button round icon="bi-x" />
|
||||||
<Button primary icon="bi-save" width="standard" />
|
<Button primary icon="bi-save" buttonWidth/>
|
||||||
<Button destructive icon="bi-trash">
|
<Button destructive icon="bi-trash">
|
||||||
Delete
|
Delete
|
||||||
</Button>
|
</Button>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<Layout flex>
|
||||||
<Button icon="bi-three-dots-vertical" />
|
<Button icon="bi-three-dots-vertical" />
|
||||||
<Button round icon="bi-x" />
|
<Button round secondary icon="bi-x large" />
|
||||||
<Button primary icon="bi-save" width="standard" />
|
<Button primary icon="bi-save" buttonWidth/>
|
||||||
<Button destructive icon="bi-trash">
|
<Button destructive icon="bi-trash">
|
||||||
Delete
|
Delete
|
||||||
</Button>
|
</Button>
|
||||||
|
</Layout>
|
||||||
|
|
||||||
## Width and alignment
|
## Width and alignment
|
||||||
|
|
||||||
<Layout flex>
|
<Layout flex>
|
||||||
|
|
||||||
```vue-html
|
```vue-html
|
||||||
<Button width="auto">·</Button>
|
<Button min-content>·</Button>
|
||||||
<Button width="standard">·</Button>
|
<Button small>·</Button>
|
||||||
<Button width="full">·</Button>
|
<Button buttonWidth>·</Button>
|
||||||
|
<Button medium>·</Button>
|
||||||
|
<Button auto>·</Button>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
@ -342,10 +359,12 @@ Icon buttons shrink down to the icon size if you don't pass any content. If you
|
||||||
<Button alignText="right">·</Button>
|
<Button alignText="right">·</Button>
|
||||||
```
|
```
|
||||||
|
|
||||||
<Layout class="preview solid secondary" stack no-gap>
|
<Layout class="preview solid primary" stack no-gap>
|
||||||
<Button width="auto">·</Button>
|
<Button min-content>·</Button>
|
||||||
<Button width="standard">·</Button>
|
<Button tiny>·</Button>
|
||||||
<Button width="full">·</Button>
|
<Button buttonWidth>·</Button>
|
||||||
|
<Button small>·</Button>
|
||||||
|
<Button auto>·</Button>
|
||||||
<hr />
|
<hr />
|
||||||
<Button alignSelf="start">·</Button>
|
<Button alignSelf="start">·</Button>
|
||||||
<Button alignSelf="center">·</Button>
|
<Button alignSelf="center">·</Button>
|
||||||
|
@ -354,6 +373,5 @@ Icon buttons shrink down to the icon size if you don't pass any content. If you
|
||||||
<Button alignText="left">·</Button>
|
<Button alignText="left">·</Button>
|
||||||
<Button alignText="center">·</Button>
|
<Button alignText="center">·</Button>
|
||||||
<Button alignText="right">·</Button>
|
<Button alignText="right">·</Button>
|
||||||
(Text to stretch the column)
|
|
||||||
</Layout>
|
</Layout>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
|
@ -14,32 +14,33 @@
|
||||||
|
|
||||||
Funkwhale cards are used to contain textual information, links, and interactive buttons. You can use these to create visually pleasing links to content or to present information.
|
Funkwhale cards are used to contain textual information, links, and interactive buttons. You can use these to create visually pleasing links to content or to present information.
|
||||||
|
|
||||||
::: details Parameters
|
::: details Props
|
||||||
|
|
||||||
#### Props
|
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
interface Props extends Partial<RouterLinkProps> {
|
{
|
||||||
title: string;
|
title: string
|
||||||
category?: true | "h1" | "h2" | "h3" | "h4" | "h5";
|
category?: true | "h1" | "h2" | "h3" | "h4" | "h5"
|
||||||
color?: Pastel;
|
|
||||||
image?: string | { src: string; style?: "withPadding" };
|
tags?: string[]
|
||||||
tags?: string[];
|
image?: string | { src: string, style?: "withPadding" }
|
||||||
}
|
icon?: string
|
||||||
|
} & Partial<RouterLinkProps>
|
||||||
|
& (PastelProps | ColorProps | DefaultProps)
|
||||||
|
& RaisedProps
|
||||||
|
& VariantProps
|
||||||
|
& WidthProps
|
||||||
```
|
```
|
||||||
|
|
||||||
You have to set a title for the card by passing a `title` prop.
|
|
||||||
|
|
||||||
#### Style
|
|
||||||
|
|
||||||
- Set `--width` on the element to override the default Card width.
|
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
<Layout grid :column-width=290>
|
<Layout grid class="preview">
|
||||||
|
|
||||||
|
<div style="grid-column: span 5; grid-row: span 2;">
|
||||||
|
|
||||||
```vue-html
|
```vue-html
|
||||||
<Card title="For music lovers">
|
<Card large
|
||||||
|
title="For music lovers"
|
||||||
|
>
|
||||||
Access your personal music
|
Access your personal music
|
||||||
collection from anywhere.
|
collection from anywhere.
|
||||||
Funkwhale gives you access to
|
Funkwhale gives you access to
|
||||||
|
@ -49,11 +50,11 @@ You have to set a title for the card by passing a `title` prop.
|
||||||
</Card>
|
</Card>
|
||||||
```
|
```
|
||||||
|
|
||||||
<div class="preview">
|
</div>
|
||||||
<Card title="For music lovers">
|
|
||||||
|
<Card medium title="For music lovers">
|
||||||
Access your personal music collection from anywhere. Funkwhale gives you access to publication and sharing tools that you can use to promote your content across the web.
|
Access your personal music collection from anywhere. Funkwhale gives you access to publication and sharing tools that you can use to promote your content across the web.
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
|
||||||
|
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
|
@ -61,56 +62,60 @@ You have to set a title for the card by passing a `title` prop.
|
||||||
|
|
||||||
Add a `:to` prop, either containing an external link (`"https://..."`) or a Vue Router destination:
|
Add a `:to` prop, either containing an external link (`"https://..."`) or a Vue Router destination:
|
||||||
|
|
||||||
<Layout flex>
|
<Layout flex class="preview">
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
<Card small title="Link"
|
<Card min-content title="Link"
|
||||||
:to="{name: 'library.albums.detail', params: {id: album.id}}"
|
:to="{name: 'library.albums.detail', params: {id: album.id}}"
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
||||||
<Layout class="preview">
|
<Card min-content title="Link"
|
||||||
<Card small title="Link"
|
|
||||||
:to="{name: 'library.albums.detail', params: {id: 1}}"
|
:to="{name: 'library.albums.detail', params: {id: 1}}"
|
||||||
/>
|
/>
|
||||||
</Layout>
|
</Layout>
|
||||||
</Layout>
|
|
||||||
|
|
||||||
## Card as a Category header
|
## Card as a Category header
|
||||||
|
|
||||||
Category cards are basic cards that contain only a title. To create a category card, pass a `category` prop.
|
Category cards are basic cards that contain only a title. To create a category card, pass a `category` prop.
|
||||||
|
|
||||||
<Layout flex>
|
<Layout flex class="preview">
|
||||||
|
|
||||||
|
```vue-html{1,5}
|
||||||
|
<Card category min-content
|
||||||
|
title="Good Translations"
|
||||||
|
/>
|
||||||
|
|
||||||
```vue-html{1}
|
|
||||||
<Card category
|
<Card category
|
||||||
title="Example Translations"
|
title="Bad Translations"
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
||||||
<div class="preview">
|
<Layout stack>
|
||||||
<Card category
|
<Card category min-content
|
||||||
title="Example Translations"
|
title="Good Translations"
|
||||||
/>
|
/>
|
||||||
</div>
|
<Card category
|
||||||
|
title="Bad Translations"
|
||||||
|
/>
|
||||||
|
</Layout>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
## Add an Image
|
## Add an Image
|
||||||
|
|
||||||
Pass an image source to the `image` prop or set both `image.src` and `image.style` by passing an object.
|
Pass an image source to the `image` prop or set both `image.src` and `image.style` by passing an object.
|
||||||
|
|
||||||
<Layout grid>
|
<Layout grid class="preview">
|
||||||
|
|
||||||
<div style="max-width: 320px;">
|
<div style="grid-column: span 5; grid-row: span 2">
|
||||||
|
|
||||||
```vue-html{4,11-12}
|
```vue-html{3,8-9}
|
||||||
<Card medium
|
<Card
|
||||||
title="For music lovers"
|
title="For music lovers"
|
||||||
image="https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb">
|
image="https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb">
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
<Card medium
|
|
||||||
title="For music lovers"
|
title="For music lovers"
|
||||||
:image="{ src:'https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb',
|
:image="{ src:'https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb',
|
||||||
style:'withPadding' }"
|
style:'withPadding' }"
|
||||||
|
@ -118,40 +123,57 @@ Pass an image source to the `image` prop or set both `image.src` and `image.styl
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<Card
|
||||||
<Layout stack class="preview">
|
|
||||||
<Card medium
|
|
||||||
title="For music lovers"
|
title="For music lovers"
|
||||||
image="https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb"
|
image="https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Card medium
|
<Card
|
||||||
title="For music lovers"
|
title="For music lovers"
|
||||||
:image="{ src:'https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb',
|
:image="{ src:'https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb',
|
||||||
style:'withPadding' }"
|
style:'withPadding' }"
|
||||||
/>
|
/>
|
||||||
</Layout>
|
</Layout>
|
||||||
</Layout>
|
|
||||||
|
|
||||||
## Add an Icon
|
## Add an Icon
|
||||||
|
|
||||||
<Layout columns>
|
<Layout grid class="preview">
|
||||||
|
|
||||||
```vue-html{4}
|
<div style="grid-column: span 5; grid-row: span 2;">
|
||||||
<Card
|
|
||||||
|
```vue-html{4,10}
|
||||||
|
<Card large
|
||||||
title="Uploading..."
|
title="Uploading..."
|
||||||
image="https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb"
|
image="https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb"
|
||||||
icon="bi-cloud-arrow-up-fill"
|
icon="bi-cloud-arrow-up-fill"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<Card large
|
||||||
|
to="./"
|
||||||
|
title="Find out more"
|
||||||
|
icon="bi-box-arrow-up-right"
|
||||||
|
>
|
||||||
|
Visit the Docs and learn more about developing Funkwhale
|
||||||
|
</Card>
|
||||||
```
|
```
|
||||||
|
|
||||||
<Layout class="preview">
|
</div>
|
||||||
<Card
|
|
||||||
|
<Card medium
|
||||||
title="Uploading..."
|
title="Uploading..."
|
||||||
image="https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb"
|
image="https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb"
|
||||||
icon="bi-cloud-arrow-up-fill"
|
icon="bi-cloud-arrow-up-fill"
|
||||||
/>
|
/>
|
||||||
</Layout>
|
|
||||||
|
<Card medium
|
||||||
|
to="./"
|
||||||
|
title="Find out more"
|
||||||
|
icon="bi-box-arrow-up-right">
|
||||||
|
|
||||||
|
Visit the Docs and learn more about developing Funkwhale
|
||||||
|
|
||||||
|
</Card>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
You can combine this prop with any other prop configuration. If you combine it with an image, keep an eye on the contrast ratio between the icon color and the image.
|
You can combine this prop with any other prop configuration. If you combine it with an image, keep an eye on the contrast ratio between the icon color and the image.
|
||||||
|
@ -177,10 +199,10 @@ You can combine this prop with any other prop configuration. If you combine it w
|
||||||
Items in this region are secondary and will be displayed smaller than the main content.
|
Items in this region are secondary and will be displayed smaller than the main content.
|
||||||
|
|
||||||
```vue-html{3-9}
|
```vue-html{3-9}
|
||||||
<Card title="My items">
|
<Card large title="My items">
|
||||||
<template #alert> There are no items in this list </template>
|
<template #alert> There are no items in this list </template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<Button variant="outline" icon="bi-upload" @click="alert('Uploaded. Press OK!')">
|
<Button outline icon="bi-upload" @click="alert('Uploaded. Press OK!')">
|
||||||
Upload
|
Upload
|
||||||
</Button>
|
</Button>
|
||||||
<Spacer style="flex-grow: 1" />
|
<Spacer style="flex-grow: 1" />
|
||||||
|
@ -190,13 +212,13 @@ Items in this region are secondary and will be displayed smaller than the main c
|
||||||
```
|
```
|
||||||
|
|
||||||
<div class="preview">
|
<div class="preview">
|
||||||
<Card title="My items">
|
<Card medium title="My items">
|
||||||
|
|
||||||
<template #alert>There are no items in this list
|
<template #alert>There are no items in this list
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<Button variant="outline" icon="bi-upload" @click="alert('Uploaded. Press OK!')">Upload</Button>
|
<Button outline icon="bi-upload" @click="alert('Uploaded. Press OK!')">Upload</Button>
|
||||||
<Spacer style="flex-grow: 1" />
|
<Spacer style="flex-grow: 1" />
|
||||||
<OptionsButton />
|
<OptionsButton />
|
||||||
</template>
|
</template>
|
||||||
|
@ -209,20 +231,24 @@ Items in this region are secondary and will be displayed smaller than the main c
|
||||||
Large Buttons or links at the bottom edge of the card serve as Call-to-Actions (CTA).
|
Large Buttons or links at the bottom edge of the card serve as Call-to-Actions (CTA).
|
||||||
|
|
||||||
```vue-html{3-6}
|
```vue-html{3-6}
|
||||||
<Card title="Join an existing pod">
|
<Card large
|
||||||
|
title="Join an existing pod"
|
||||||
|
>
|
||||||
The easiest way to get started with Funkwhale is to register an account on a public pod.
|
The easiest way to get started with Funkwhale is to register an account on a public pod.
|
||||||
<template #action>
|
<template #action>
|
||||||
<Button secondary @click="alert('Open the pod picker')">Action!
|
<Button secondary full @click="alert('Open the pod picker')">Action!
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</Card>
|
</Card>
|
||||||
```
|
```
|
||||||
|
|
||||||
<div class="preview">
|
<div class="preview">
|
||||||
<Card title="Join an existing pod">
|
<Card medium
|
||||||
|
title="Join an existing pod"
|
||||||
|
>
|
||||||
The easiest way to get started with Funkwhale is to register an account on a public pod.
|
The easiest way to get started with Funkwhale is to register an account on a public pod.
|
||||||
<template #action>
|
<template #action>
|
||||||
<Button secondary @click="alert('Open the pod picker')">Action!
|
<Button secondary full @click="alert('Open the pod picker')">Action!
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -245,14 +271,21 @@ If there are multiple actions, they will be presented in a row:
|
||||||
```
|
```
|
||||||
|
|
||||||
<div class="preview">
|
<div class="preview">
|
||||||
<Card title="Creating a new playlist...">
|
<Card full title="Creating a new playlist...">
|
||||||
All items have been assimilated. Ready to go!
|
All items have been assimilated. Ready to go!
|
||||||
<template #action>
|
<template #action>
|
||||||
<Button secondary ghost style="width:50%; justify-content: flex-start;" icon="bi-chevron-left">
|
<Button secondary ghost min-content
|
||||||
Back
|
alignText="left"
|
||||||
|
icon="bi-chevron-left"
|
||||||
|
>
|
||||||
|
Items
|
||||||
</Button>
|
</Button>
|
||||||
<Button style="width:50%" primary @click="alert('Yay')">
|
<Spacer h />
|
||||||
Next: Pick a color
|
<Button primary @click="alert('Yay')">
|
||||||
|
OK
|
||||||
|
</Button>
|
||||||
|
<Button destructive @click="alert('Yay')">
|
||||||
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -272,8 +305,12 @@ You can include tags on a card by adding a list of `tags`. These are rendered as
|
||||||
```
|
```
|
||||||
|
|
||||||
<div class="preview">
|
<div class="preview">
|
||||||
<Card
|
<Card medium
|
||||||
title="For music lovers"
|
title="For music lovers"
|
||||||
:tags="['rock', 'folk', 'punk']">
|
:tags="['rock', 'folk', 'punk']">
|
||||||
Access your personal music collection from anywhere. Funkwhale gives you access to publication and sharing tools that you can use to promote your content across the web.
|
Access your personal music collection from anywhere. Funkwhale gives you access to publication and sharing tools that you can use to promote your content across the web.
|
||||||
</Card></div>
|
</Card></div>
|
||||||
|
|
||||||
|
### Sizes
|
||||||
|
|
||||||
|
`large` (304px), `medium` (208px), `auto`, `small`
|
||||||
|
|
|
@ -76,10 +76,10 @@ const noGap = ref(true);
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout flex :no-gap="noGap || undefined">
|
<Layout flex :no-gap="noGap || undefined">
|
||||||
<Card title="A" small />
|
<Card title="A" tiny />
|
||||||
<Card title="B" small />
|
<Card title="B" tiny />
|
||||||
<Card title="C" small />
|
<Card title="C" tiny />
|
||||||
<Card title="D" small />
|
<Card title="D" tiny />
|
||||||
</Layout>
|
</Layout>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ Let items flow like words on a printed newspaper, Great for very long lists of b
|
||||||
|
|
||||||
Normal paragraph. Text flows like in a newspaper. Set the column width in px. Columns will be equally distributed over the width of the container.
|
Normal paragraph. Text flows like in a newspaper. Set the column width in px. Columns will be equally distributed over the width of the container.
|
||||||
|
|
||||||
<Card small title="Cards...">...break over columns...</Card>
|
<Card min-content title="Cards...">...break over columns...</Card>
|
||||||
|
|
||||||
<Button icon="bi-star"/>
|
<Button icon="bi-star"/>
|
||||||
<Button icon="bi-star"/>
|
<Button icon="bi-star"/>
|
||||||
|
@ -50,7 +50,7 @@ Normal paragraph. Text flows like in a newspaper. Set the column width in px. Co
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<Card small title="Cards...">...break over columns...</Card>
|
<Card min-content title="Cards...">...break over columns...</Card>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -30,14 +30,14 @@ You can either specify the column width (default: 320px) or set the desired num
|
||||||
:style="`width:${2 * 90 + 32}px`"
|
:style="`width:${2 * 90 + 32}px`"
|
||||||
>
|
>
|
||||||
<Alert yellow />
|
<Alert yellow />
|
||||||
<Card small title="brown" />
|
<Card min-content title="brown" />
|
||||||
<Alert blue />
|
<Alert blue />
|
||||||
</Layout>
|
</Layout>
|
||||||
```
|
```
|
||||||
|
|
||||||
<Layout grid :column-width="90" class="preview" :style="`width:${2 * 90 + 32}px`">
|
<Layout grid :column-width="90" class="preview" :style="`width:${2 * 90 + 32}px`">
|
||||||
<Alert yellow />
|
<Alert yellow />
|
||||||
<Card small title="brown" />
|
<Card min-content title="brown" />
|
||||||
<Alert blue />
|
<Alert blue />
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
|
|
|
@ -159,10 +159,10 @@ const size = ref(1);
|
||||||
|
|
||||||
<Layout flex style="align-items:flex-start">
|
<Layout flex style="align-items:flex-start">
|
||||||
<Input v-model="size" type="range" />
|
<Input v-model="size" type="range" />
|
||||||
<Card small title="h">
|
<Card min-content title="h">
|
||||||
<Spacer h :size="size * 4" style="border:5px dashed;" />
|
<Spacer h :size="size * 4" style="border:5px dashed;" />
|
||||||
</Card>
|
</Card>
|
||||||
<Card small title="v">
|
<Card min-content title="v">
|
||||||
<Spacer v :size="size * 4" style="border:5px dashed;" />
|
<Spacer v :size="size * 4" style="border:5px dashed;" />
|
||||||
</Card>
|
</Card>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 117 KiB |
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { color } from "~/composables/colors.ts"
|
import { color, setColors } from "~/composables/colors.ts"
|
||||||
import { useRoute } from "vue-router"
|
import { useRoute } from "vue-router"
|
||||||
|
|
||||||
import Button from "~/components/ui/Button.vue"
|
import Button from "~/components/ui/Button.vue"
|
||||||
|
@ -59,16 +59,37 @@ import { color } from "~/composables/colors.ts";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-bind="color('primary solid interactive raised')" />
|
<div v-bind="setColors('primary solid interactive raised')" />
|
||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
|
|
||||||
<div class="preview">
|
<div class="preview">
|
||||||
<div :class="$style.swatch" v-bind="color('primary solid interactive raised')" />
|
<div :class="$style.swatch" v-bind="setColors('primary solid interactive raised')" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
|
## Make your component accept color props
|
||||||
|
|
||||||
|
`color` accepts two parameters. The first is your props object, the second is a list of defaults.
|
||||||
|
|
||||||
|
In this case, if the user of your component doesn't specify any color, it will be 'primary'.
|
||||||
|
Since the user cannot specify the variant, it will always be 'default'.
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import { type ColorProps, color } from "~/composables/colors.ts";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
...
|
||||||
|
} & ColorProps>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-bind="color(props, ['primary', 'solid'])" />
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
## Base colors
|
## Base colors
|
||||||
|
|
||||||
Keep most of the screen neutral. Secondary surfaces indicate actionability. Use them sparingly. Primary and destructive surfaces immediately catch the eye. Use them only once or twice per screen.
|
Keep most of the screen neutral. Secondary surfaces indicate actionability. Use them sparingly. Primary and destructive surfaces immediately catch the eye. Use them only once or twice per screen.
|
||||||
|
@ -79,22 +100,22 @@ Use neutral colors for non-interactive surfaces
|
||||||
|
|
||||||
<Layout flex>
|
<Layout flex>
|
||||||
<div class="force-dark-theme">
|
<div class="force-dark-theme">
|
||||||
<div v-bind="color('default solid')">
|
<div v-bind="setColors('default solid')">
|
||||||
<div :class="$style.swatch" v-bind="color('default solid')" />
|
<div :class="$style.swatch" v-bind="setColors('default solid')" />
|
||||||
<div :class="[$style.swatch, $style.deemphasized]" v-bind="color('default solid interactive')" />
|
<div :class="[$style.swatch, $style.deemphasized]" v-bind="setColors('default solid interactive')" />
|
||||||
</div><div v-bind="color('default solid raised')">
|
</div><div v-bind="setColors('default solid raised')">
|
||||||
<div :class="$style.swatch" v-bind="color('default solid raised')" />
|
<div :class="$style.swatch" v-bind="setColors('default solid raised')" />
|
||||||
<div :class="[$style.swatch, $style.deemphasized]" v-bind="color('default solid raised interactive')" />
|
<div :class="[$style.swatch, $style.deemphasized]" v-bind="setColors('default solid raised interactive')" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="force-light-theme">
|
<div class="force-light-theme">
|
||||||
<div v-bind="color('default solid')">
|
<div v-bind="setColors('default solid')">
|
||||||
<div :class="$style.swatch" v-bind="color('default solid')" />
|
<div :class="$style.swatch" v-bind="setColors('default solid')" />
|
||||||
<div :class="[$style.swatch, $style.deemphasized]" v-bind="color('default solid interactive')" />
|
<div :class="[$style.swatch, $style.deemphasized]" v-bind="setColors('default solid interactive')" />
|
||||||
</div><div v-bind="color('default solid raised')">
|
</div><div v-bind="setColors('default solid raised')">
|
||||||
<div :class="$style.swatch" v-bind="color('default solid raised')" />
|
<div :class="$style.swatch" v-bind="setColors('default solid raised')" />
|
||||||
<div :class="[$style.swatch, $style.deemphasized]" v-bind="color('default solid raised interactive')" />
|
<div :class="[$style.swatch, $style.deemphasized]" v-bind="setColors('default solid raised interactive')" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
@ -107,22 +128,22 @@ Only use for at most one call-to-action on a screen
|
||||||
|
|
||||||
<Layout flex>
|
<Layout flex>
|
||||||
<div class="force-dark-theme">
|
<div class="force-dark-theme">
|
||||||
<div v-bind="color('default solid')">
|
<div v-bind="setColors('default solid')">
|
||||||
<div :class="[$style.swatch, $style.deemphasized]" v-bind="color('primary solid')" />
|
<div :class="[$style.swatch, $style.deemphasized]" v-bind="setColors('primary solid')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('primary solid interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('primary solid interactive')" />
|
||||||
</div><div v-bind="color('default solid raised')">
|
</div><div v-bind="setColors('default solid raised')">
|
||||||
<div :class="[$style.swatch, $style.deemphasized]" v-bind="color('primary solid raised')" />
|
<div :class="[$style.swatch, $style.deemphasized]" v-bind="setColors('primary solid raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('primary solid raised interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('primary solid raised interactive')" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="force-light-theme">
|
<div class="force-light-theme">
|
||||||
<div v-bind="color('default solid')">
|
<div v-bind="setColors('default solid')">
|
||||||
<div :class="[$style.swatch, $style.deemphasized]" v-bind="color('primary solid')" />
|
<div :class="[$style.swatch, $style.deemphasized]" v-bind="setColors('primary solid')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('primary solid interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('primary solid interactive')" />
|
||||||
</div><div v-bind="color('default solid raised')">
|
</div><div v-bind="setColors('default solid raised')">
|
||||||
<div :class="[$style.swatch, $style.deemphasized]" v-bind="color('primary solid raised')" />
|
<div :class="[$style.swatch, $style.deemphasized]" v-bind="setColors('primary solid raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('primary solid raised interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('primary solid raised interactive')" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
@ -133,22 +154,22 @@ Use for interactive items and non-permanent surfaces such as menus and modals
|
||||||
|
|
||||||
<Layout flex>
|
<Layout flex>
|
||||||
<div class="force-dark-theme">
|
<div class="force-dark-theme">
|
||||||
<div v-bind="color('default solid')">
|
<div v-bind="setColors('default solid')">
|
||||||
<div :class="$style.swatch" v-bind="color('secondary solid')" />
|
<div :class="$style.swatch" v-bind="setColors('secondary solid')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('secondary solid interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('secondary solid interactive')" />
|
||||||
</div><div v-bind="color('default solid raised')">
|
</div><div v-bind="setColors('default solid raised')">
|
||||||
<div :class="$style.swatch" v-bind="color('secondary solid raised')" />
|
<div :class="$style.swatch" v-bind="setColors('secondary solid raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('secondary solid raised interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('secondary solid raised interactive')" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="force-light-theme">
|
<div class="force-light-theme">
|
||||||
<div v-bind="color('default solid')">
|
<div v-bind="setColors('default solid')">
|
||||||
<div :class="$style.swatch" v-bind="color('secondary solid')" />
|
<div :class="$style.swatch" v-bind="setColors('secondary solid')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('secondary solid interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('secondary solid interactive')" />
|
||||||
</div><div v-bind="color('default solid raised')">
|
</div><div v-bind="setColors('default solid raised')">
|
||||||
<div :class="$style.swatch" v-bind="color('secondary solid raised')" />
|
<div :class="$style.swatch" v-bind="setColors('secondary solid raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('secondary solid raised interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('secondary solid raised interactive')" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
@ -159,22 +180,22 @@ Use for dangerous actions
|
||||||
|
|
||||||
<Layout flex>
|
<Layout flex>
|
||||||
<div class="force-dark-theme">
|
<div class="force-dark-theme">
|
||||||
<div v-bind="color('default solid')">
|
<div v-bind="setColors('default solid')">
|
||||||
<div :class="[$style.swatch, $style.deemphasized]" v-bind="color('destructive solid')" />
|
<div :class="[$style.swatch, $style.deemphasized]" v-bind="setColors('destructive solid')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('destructive solid interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('destructive solid interactive')" />
|
||||||
</div><div v-bind="color('default solid raised')">
|
</div><div v-bind="setColors('default solid raised')">
|
||||||
<div :class="[$style.swatch, $style.deemphasized]" v-bind="color('destructive solid raised')" />
|
<div :class="[$style.swatch, $style.deemphasized]" v-bind="setColors('destructive solid raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('destructive solid raised interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('destructive solid raised interactive')" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="force-light-theme">
|
<div class="force-light-theme">
|
||||||
<div v-bind="color('default solid')">
|
<div v-bind="setColors('default solid')">
|
||||||
<div :class="[$style.swatch, $style.deemphasized]" v-bind="color('destructive solid')" />
|
<div :class="[$style.swatch, $style.deemphasized]" v-bind="setColors('destructive solid')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('destructive solid interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('destructive solid interactive')" />
|
||||||
</div><div v-bind="color('default solid raised')">
|
</div><div v-bind="setColors('default solid raised')">
|
||||||
<div :class="[$style.swatch, $style.deemphasized]" v-bind="color('destructive solid raised')" />
|
<div :class="[$style.swatch, $style.deemphasized]" v-bind="setColors('destructive solid raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('destructive solid raised interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('destructive solid raised interactive')" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
@ -184,11 +205,11 @@ Use for dangerous actions
|
||||||
Use `Blue`, `Red`, `Purple`, `Green`, `Yellow` for user-defined tags and for friendly messages such as
|
Use `Blue`, `Red`, `Purple`, `Green`, `Yellow` for user-defined tags and for friendly messages such as
|
||||||
Alerts
|
Alerts
|
||||||
|
|
||||||
<div :class="$style.swatch" v-bind="color('blue solid interactive')" />
|
<div :class="$style.swatch" v-bind="setColors('blue solid interactive')" />
|
||||||
<div :class="$style.swatch" v-bind="color('red solid interactive')" />
|
<div :class="$style.swatch" v-bind="setColors('red solid interactive')" />
|
||||||
<div :class="$style.swatch" v-bind="color('purple solid interactive')" />
|
<div :class="$style.swatch" v-bind="setColors('purple solid interactive')" />
|
||||||
<div :class="$style.swatch" v-bind="color('green solid interactive')" />
|
<div :class="$style.swatch" v-bind="setColors('green solid interactive')" />
|
||||||
<div :class="$style.swatch" v-bind="color('yellow solid interactive')" />
|
<div :class="$style.swatch" v-bind="setColors('yellow solid interactive')" />
|
||||||
|
|
||||||
### Variant
|
### Variant
|
||||||
|
|
||||||
|
@ -198,7 +219,7 @@ You can de-emphasize interactive elements by hiding their background and/or outl
|
||||||
|
|
||||||
<Button round shadow icon="bi-x" solid />
|
<Button round shadow icon="bi-x" solid />
|
||||||
|
|
||||||
<div :class="$style.swatch" v-bind="color('solid raised')">
|
<div :class="$style.swatch" v-bind="setColors('solid raised')">
|
||||||
<Button round icon="bi-x" ghost />
|
<Button round icon="bi-x" ghost />
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<Button round icon="bi-x" outline />
|
<Button round icon="bi-x" outline />
|
||||||
|
@ -208,7 +229,7 @@ You can de-emphasize interactive elements by hiding their background and/or outl
|
||||||
|
|
||||||
<Button round shadow icon="bi-x" primary solid />
|
<Button round shadow icon="bi-x" primary solid />
|
||||||
|
|
||||||
<div :class="$style.swatch" v-bind="color('primary solid')">
|
<div :class="$style.swatch" v-bind="setColors('primary solid')">
|
||||||
<Button round icon="bi-x" primary ghost />
|
<Button round icon="bi-x" primary ghost />
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<Button round icon="bi-x" primary outline />
|
<Button round icon="bi-x" primary outline />
|
||||||
|
@ -223,91 +244,88 @@ Space out interactive surfaces.
|
||||||
<Layout>
|
<Layout>
|
||||||
|
|
||||||
<div class="force-light-theme">
|
<div class="force-light-theme">
|
||||||
|
|
||||||
<Layout flex>
|
<Layout flex>
|
||||||
<div>
|
<div>
|
||||||
<div v-bind="color('default solid')">
|
<div v-bind="setColors('default solid')">
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" disabled/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" disabled/>
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" aria-pressed="true"/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" aria-pressed />
|
||||||
</div>
|
</div>
|
||||||
<div v-bind="color('secondary solid')">
|
<div v-bind="setColors('secondary solid')">
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" disabled/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" disabled/>
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" aria-pressed="true"/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" aria-pressed />
|
||||||
</div>
|
</div>
|
||||||
<div v-bind="color('primary solid')">
|
<div v-bind="setColors('primary solid')">
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" disabled/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" disabled/>
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" aria-pressed="true"/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" aria-pressed />
|
||||||
</div>
|
</div>
|
||||||
</div><div>
|
</div><div>
|
||||||
<div v-bind="color('default raised solid')">
|
<div v-bind="setColors('default raised solid')">
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid raised')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" disabled/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" disabled/>
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" aria-pressed="true"/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" aria-pressed />
|
||||||
</div>
|
</div>
|
||||||
<div v-bind="color('secondary raised solid')">
|
<div v-bind="setColors('secondary raised solid')">
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid raised')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" disabled/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" disabled/>
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" aria-pressed="true"/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" aria-pressed />
|
||||||
</div>
|
</div>
|
||||||
<div v-bind="color('primary raised solid')">
|
<div v-bind="setColors('primary raised solid')">
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid raised')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" disabled/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" disabled/>
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" aria-pressed="true"/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" aria-pressed />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="force-dark-theme">
|
<div class="force-dark-theme">
|
||||||
|
|
||||||
<Layout flex>
|
<Layout flex>
|
||||||
<div>
|
<div>
|
||||||
<div v-bind="color('default solid')">
|
<div v-bind="setColors('default solid')">
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" disabled/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" disabled/>
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" aria-pressed="true"/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" aria-pressed />
|
||||||
</div>
|
</div>
|
||||||
<div v-bind="color('secondary solid')">
|
<div v-bind="setColors('secondary solid')">
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" disabled/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" disabled/>
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" aria-pressed="true"/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" aria-pressed />
|
||||||
</div>
|
</div>
|
||||||
<div v-bind="color('primary solid')">
|
<div v-bind="setColors('primary solid')">
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" disabled/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" disabled/>
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive')" aria-pressed="true"/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive')" aria-pressed />
|
||||||
</div><br/>Normal
|
</div><br/>Normal
|
||||||
</div><div>
|
</div><div>
|
||||||
<div v-bind="color('default raised solid')">
|
<div v-bind="setColors('default raised solid')">
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid raised')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" disabled/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" disabled/>
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" aria-pressed="true"/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" aria-pressed />
|
||||||
</div>
|
</div>
|
||||||
<div v-bind="color('secondary raised solid')">
|
<div v-bind="setColors('secondary raised solid')">
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid raised')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" disabled/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" disabled/>
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" aria-pressed="true"/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" aria-pressed />
|
||||||
</div>
|
</div>
|
||||||
<div v-bind="color('primary raised solid')">
|
<div v-bind="setColors('primary raised solid')">
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid raised')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" />
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" />
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" disabled/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" disabled/>
|
||||||
<div :class="[$style.swatch]" v-bind="color('solid interactive raised')" aria-pressed="true"/>
|
<div :class="[$style.swatch]" v-bind="setColors('solid interactive raised')" aria-pressed />
|
||||||
</div><br/><strong>Raised</strong>
|
</div><br/><strong>Raised</strong>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
@ -604,7 +622,7 @@ Here is the meaning the styles should convey:
|
||||||
|
|
||||||
<Layout flex>
|
<Layout flex>
|
||||||
|
|
||||||
<Card small title="Default" solid default>
|
<Card min-content title="Default" solid default>
|
||||||
<span>
|
<span>
|
||||||
Inline <Link to=""> Link </Link> and <Link to=""> Link </Link>
|
Inline <Link to=""> Link </Link> and <Link to=""> Link </Link>
|
||||||
</span>
|
</span>
|
||||||
|
@ -642,11 +660,11 @@ Here is the meaning the styles should convey:
|
||||||
<Button raised ghost> Button raised ghost </Button>
|
<Button raised ghost> Button raised ghost </Button>
|
||||||
<Button raised outline> Button raised outline </Button>
|
<Button raised outline> Button raised outline </Button>
|
||||||
<Button raised solid> Button raised solid </Button>
|
<Button raised solid> Button raised solid </Button>
|
||||||
<Button raised aria-pressed="true"> Button active </Button>
|
<Button raised aria-pressed > Button active </Button>
|
||||||
<Button raised disabled> Button disabled </Button>
|
<Button raised disabled> Button disabled </Button>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card small title="Default raised" solid default raised>
|
<Card min-content title="Default raised" solid default raised>
|
||||||
<span>
|
<span>
|
||||||
Inline <Link to=""> Link </Link> and <Link to=""> Link </Link>
|
Inline <Link to=""> Link </Link> and <Link to=""> Link </Link>
|
||||||
</span>
|
</span>
|
||||||
|
@ -684,11 +702,11 @@ Here is the meaning the styles should convey:
|
||||||
<Button raised ghost> Button raised ghost </Button>
|
<Button raised ghost> Button raised ghost </Button>
|
||||||
<Button raised outline> Button raised outline </Button>
|
<Button raised outline> Button raised outline </Button>
|
||||||
<Button raised solid> Button raised solid </Button>
|
<Button raised solid> Button raised solid </Button>
|
||||||
<Button raised aria-pressed="true"> Button active </Button>
|
<Button raised aria-pressed > Button active </Button>
|
||||||
<Button raised disabled> Button disabled </Button>
|
<Button raised disabled> Button disabled </Button>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card small title="Secondary" solid secondary>
|
<Card min-content title="Secondary" solid secondary>
|
||||||
<span>
|
<span>
|
||||||
Inline <Link to=""> Link </Link> and <Link to=""> Link </Link>
|
Inline <Link to=""> Link </Link> and <Link to=""> Link </Link>
|
||||||
</span>
|
</span>
|
||||||
|
@ -726,11 +744,11 @@ Here is the meaning the styles should convey:
|
||||||
<Button raised ghost> Button raised ghost </Button>
|
<Button raised ghost> Button raised ghost </Button>
|
||||||
<Button raised outline> Button raised outline </Button>
|
<Button raised outline> Button raised outline </Button>
|
||||||
<Button raised solid> Button raised solid </Button>
|
<Button raised solid> Button raised solid </Button>
|
||||||
<Button raised aria-pressed="true"> Button raised active </Button>
|
<Button raised aria-pressed > Button raised active </Button>
|
||||||
<Button raised disabled> Button raised disabled </Button>
|
<Button raised disabled> Button raised disabled </Button>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card small title="Secondary raised" solid secondary raised>
|
<Card min-content title="Secondary raised" solid secondary raised>
|
||||||
<span>
|
<span>
|
||||||
Inline <Link to=""> Link </Link> and <Link to=""> Link </Link>
|
Inline <Link to=""> Link </Link> and <Link to=""> Link </Link>
|
||||||
</span>
|
</span>
|
||||||
|
|
Loading…
Reference in New Issue