feat(ui): more consistent props
This commit is contained in:
parent
37d99e1a53
commit
c65b4bd4f0
|
@ -90,9 +90,9 @@ onMounted(() => {
|
|||
|
||||
line-height: 1em;
|
||||
|
||||
padding: 0.642857142857em 0.714em 0.714em 0.714em;
|
||||
padding: 9px 10px 11px 10px;
|
||||
&.is-icon-only {
|
||||
padding: 0.675em 0.714em 0.678em 0.714em;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
border-radius: var(--fw-border-radius);
|
||||
|
@ -161,6 +161,8 @@ onMounted(() => {
|
|||
&.large {
|
||||
font-size:2rem;
|
||||
}
|
||||
/* Must not increase the height of the button */
|
||||
margin: -0.5rem 0;
|
||||
}
|
||||
|
||||
i.bi + span:not(:empty) {
|
||||
|
|
|
@ -16,21 +16,35 @@ const props = defineProps<{
|
|||
tags?: string[]
|
||||
image?: string | { src: string, style?: "withPadding" }
|
||||
icon?: string
|
||||
} & ({
|
||||
[Width in 'small' | 'auto']?: true
|
||||
} | { width: string }) & Partial<RouterLinkProps> & (PastelProps | ColorProps | DefaultProps) & RaisedProps & VariantProps>()
|
||||
} & (
|
||||
{ [Width in 'large' | 'medium' | 'small' | 'auto']?: true } | { width?: string }
|
||||
) & Partial<RouterLinkProps> & (PastelProps | ColorProps | DefaultProps) & RaisedProps & VariantProps>()
|
||||
|
||||
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(() => {
|
||||
return typeof props.to === 'string' && props.to.startsWith('http')
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Layout stack
|
||||
<Layout stack no-gap
|
||||
:class="{ [$style.card]: true, [$style['is-category']]: category }"
|
||||
style="--gap:16px"
|
||||
v-bind="propsToColor({...(props.to? { interactive: true, solid: true, default: true } : {}), ...props})"
|
||||
>
|
||||
|
||||
|
@ -46,7 +60,7 @@ const isExternalLink = computed(() => {
|
|||
</div>
|
||||
<img v-else-if="image" :src="image?.src"
|
||||
:class="{ [$style.image]: true, [$style['with-padding']]: image?.style === 'withPadding' }" />
|
||||
<Spacer v-else :size="'small' in props ? 4 : 12" />
|
||||
<Spacer v-else :size="'small' in props ? 20 : 28" />
|
||||
|
||||
<!-- Icon -->
|
||||
|
||||
|
@ -83,15 +97,14 @@ const isExternalLink = computed(() => {
|
|||
<slot name="action" />
|
||||
</div>
|
||||
|
||||
<Spacer v-if="!$slots.footer && !$slots.action" :size="'small' in props? 8 : 16" />
|
||||
<Spacer v-if="!$slots.footer && !$slots.action" :size="'small' in props? 24 : 32" />
|
||||
|
||||
</Layout>
|
||||
</template>
|
||||
|
||||
<style module>
|
||||
.card {
|
||||
/* Override --width with your preferred value */
|
||||
--fw-card-width: var(--width, v-bind("'small' in props ? 'min-content' : 'auto' in props ? 'auto' : props.width || '320px'"));
|
||||
--fw-card-width: v-bind(width);
|
||||
--fw-card-padding: v-bind("props.small ? '16px' : '24px'");
|
||||
|
||||
position: relative;
|
||||
|
@ -169,6 +182,9 @@ const isExternalLink = computed(() => {
|
|||
font-size: 1.75em;
|
||||
padding-bottom: .125em;
|
||||
}
|
||||
&:has(>.image:not(.with-padding))>.title {
|
||||
margin-top:16px;
|
||||
}
|
||||
|
||||
>.alert {
|
||||
padding-left: var(--fw-card-padding);
|
||||
|
@ -178,6 +194,7 @@ const isExternalLink = computed(() => {
|
|||
>.tags {
|
||||
/* Tags have an inherent padding which we offset here: */
|
||||
padding: 0 calc(var(--fw-card-padding) - 12px);
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
>.content {
|
||||
|
@ -185,6 +202,7 @@ const isExternalLink = computed(() => {
|
|||
/* Consider making all line height, vertical paddings, margins and borders,
|
||||
a multiple of a global vertical rhythm so that side-by-side lines coincide */
|
||||
line-height: 24px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
>.footer {
|
||||
|
@ -203,6 +221,7 @@ const isExternalLink = computed(() => {
|
|||
background: color-mix(in oklab, var(--fw-bg-color) 80%, var(--fw-gray-500));
|
||||
border-bottom-left-radius: var(--fw-border-radius);
|
||||
border-bottom-right-radius: var(--fw-border-radius);
|
||||
margin-top:16px;
|
||||
|
||||
>*:not(.with-padding) {
|
||||
margin: 0;
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
const props = defineProps<{
|
||||
columnWidth?: number,
|
||||
noGap?:true,
|
||||
noRule?:true
|
||||
noRule?:true,
|
||||
noWrap?:true
|
||||
}
|
||||
& { [P in "stack" | "grid" | "flex" | "columns"]?: true | string }
|
||||
& { [C in "nav" | "aside" | "header" | "footer" | "main"]?:true }>()
|
||||
|
@ -15,6 +16,7 @@ const columnWidth = props.columnWidth ?? 320
|
|||
:class="[
|
||||
$style.layout,
|
||||
noGap || $style.gap,
|
||||
noWrap || $style.wrap,
|
||||
props.grid ? $style[props.grid===true ? 'grid' : 'grid-custom']
|
||||
: props.flex ? $style.flex
|
||||
: props.columns? $style.columns
|
||||
|
@ -77,7 +79,7 @@ const columnWidth = props.columnWidth ?? 320
|
|||
&.flex {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
flex-wrap: v-bind('props.noWrap ? "no-wrap" : "wrap"');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -108,9 +108,9 @@ const isSimple = propsToColor(colorProps).class === ''
|
|||
border-radius: var(--fw-border-radius);
|
||||
margin: 0 0.5ch;
|
||||
|
||||
padding: 0.642857142857em 0.714em 0.714em 0.714em;
|
||||
padding: 9px 10px 11px 10px;
|
||||
&.is-icon-only {
|
||||
padding: 0.675em 0.714em 0.678em 0.714em;
|
||||
padding: 10px;
|
||||
}
|
||||
&.no-spacing{
|
||||
padding: 0;
|
||||
|
|
|
@ -12,8 +12,7 @@ const props = defineProps<PastelProps | ColorProps>()
|
|||
|
||||
<template>
|
||||
<button
|
||||
type="button"
|
||||
class="funkwhale is-colored pill"
|
||||
class="funkwhale pill outline"
|
||||
v-bind="propsToColor({...props, interactive:true})"
|
||||
@click.stop="handleClick"
|
||||
>
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, watchEffect } from 'vue';
|
||||
|
||||
const { grow, shrink, title, size = 16 } = defineProps<{ grow?:true, shrink?:true, title?:string, size?:number }>()
|
||||
const { grow, shrink, title, size = 16, ...direction } = defineProps<{
|
||||
grow?:true;
|
||||
shrink?:true;
|
||||
title?:string;
|
||||
size?:number;
|
||||
} & { [Direction in 'h' | 'v']? : true }>()
|
||||
|
||||
const minSize = 32
|
||||
const minSize = 0;
|
||||
|
||||
const measure = ref()
|
||||
|
||||
watchEffect(() => { measure.value = {
|
||||
size: `${Math.max(size, minSize)}px`,
|
||||
margin: `${(size-Math.max(size, minSize))/2}px`
|
||||
}
|
||||
watchEffect(() => measure.value = {
|
||||
size: `${Math.max(size, minSize)}px`,
|
||||
margin: `${(size-Math.max(size, minSize))/2}px`
|
||||
})
|
||||
|
||||
console.log(size)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -22,8 +28,8 @@ watchEffect(() => { measure.value = {
|
|||
|
||||
<style module lang="scss">
|
||||
.spacer {
|
||||
width: v-bind('measure.size');
|
||||
height: v-bind('measure.size');
|
||||
width: v-bind('direction.v ? 0 : measure.size');
|
||||
height: v-bind('direction.h ? 0 : measure.size');
|
||||
margin: v-bind('measure.margin');
|
||||
flex-grow:v-bind('grow ? 1 : 0');
|
||||
flex-shrink:v-bind('shrink ? 1 : 0');
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
|
||||
--hover-color:var(--fw-gray-800);
|
||||
--hover-background-color:var(--fw-beige-200);
|
||||
--hover-border-color:var(--fw-gray-800);
|
||||
--hover-border-color:var(--fw-gray-500);
|
||||
|
||||
--active-color:var(--fw-gray-900);
|
||||
--active-background-color:var(--fw-beige-400);
|
||||
|
@ -573,9 +573,9 @@
|
|||
background-color: transparent;
|
||||
border: 1px solid var(--border-color);
|
||||
|
||||
&.interactive{
|
||||
&:hover{
|
||||
border-color: var(--hover-background-color);
|
||||
&.interactive, button {
|
||||
&:hover {
|
||||
border-color: var(--hover-border-color);
|
||||
}
|
||||
&[aria-pressed=true] {
|
||||
color: var(--pressed-color, var(--active-color));
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
main {
|
||||
padding: 56px 48px;
|
||||
font-size: 16px;
|
||||
max-width: 78rem;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -99,34 +99,34 @@ Category cards are basic cards that contain only a title. To create a category c
|
|||
|
||||
Pass an image source to the `image` prop or set both `image.src` and `image.style` by passing an object.
|
||||
|
||||
<Layout :columnWidth="200" grid>
|
||||
<Layout grid>
|
||||
|
||||
<div style="max-width: 320px;">
|
||||
|
||||
```vue-html{4,11-12}
|
||||
<Card
|
||||
style="--width:208px"
|
||||
<Card medium
|
||||
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">
|
||||
/>
|
||||
|
||||
|
||||
<Card
|
||||
style="--width:208px"
|
||||
<Card medium
|
||||
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',
|
||||
style:'withPadding' }"
|
||||
/>
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<Layout stack class="preview">
|
||||
<Card
|
||||
<Card medium
|
||||
title="For music lovers"
|
||||
style="--width:208px"
|
||||
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"
|
||||
style="--width:208px"
|
||||
: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' }"
|
||||
/>
|
||||
|
@ -212,7 +212,7 @@ Large Buttons or links at the bottom edge of the card serve as Call-to-Actions (
|
|||
<Card title="Join an existing pod">
|
||||
The easiest way to get started with Funkwhale is to register an account on a public pod.
|
||||
<template #action>
|
||||
<Button @click="alert('Open the pod picker')">Action!
|
||||
<Button secondary @click="alert('Open the pod picker')">Action!
|
||||
</Button>
|
||||
</template>
|
||||
</Card>
|
||||
|
@ -222,7 +222,7 @@ Large Buttons or links at the bottom edge of the card serve as Call-to-Actions (
|
|||
<Card title="Join an existing pod">
|
||||
The easiest way to get started with Funkwhale is to register an account on a public pod.
|
||||
<template #action>
|
||||
<Button @click="alert('Open the pod picker')">Action!
|
||||
<Button secondary @click="alert('Open the pod picker')">Action!
|
||||
</Button>
|
||||
</template>
|
||||
</Card>
|
||||
|
@ -231,28 +231,28 @@ Large Buttons or links at the bottom edge of the card serve as Call-to-Actions (
|
|||
If there are multiple actions, they will be presented in a row:
|
||||
|
||||
```vue-html{4,7}
|
||||
<Card title="Delete this pod?">
|
||||
You cannot undo this action.
|
||||
<Card title="Creating a new playlist...">
|
||||
All items have been assimilated. Ready to go!
|
||||
<template #action>
|
||||
<Button style="justify-content: flex-start;" icon="bi-chevron-left" color="secondary" variant="ghost">
|
||||
<Button secondary ghost style="justify-content: flex-start;" icon="bi-chevron-left">
|
||||
Back
|
||||
</Button>
|
||||
<Button style="flex-grow:0;" color="destructive" @click="alert('Deleted')">
|
||||
Delete
|
||||
<Button style="flex-grow:0;" primary @click="alert('Yay')">
|
||||
Create
|
||||
</Button>
|
||||
</template>
|
||||
</Card>
|
||||
```
|
||||
|
||||
<div class="preview">
|
||||
<Card title="Delete this pod?">
|
||||
You cannot undo this action.
|
||||
<Card title="Creating a new playlist...">
|
||||
All items have been assimilated. Ready to go!
|
||||
<template #action>
|
||||
<Button style="width:50%; justify-content: flex-start;" icon="bi-chevron-left" color="secondary" variant="ghost">
|
||||
<Button secondary ghost style="width:50%; justify-content: flex-start;" icon="bi-chevron-left">
|
||||
Back
|
||||
</Button>
|
||||
<Button style="width:50%" color="destructive" @click="alert('Deleted')">
|
||||
Delete
|
||||
<Button style="width:50%" primary @click="alert('Yay')">
|
||||
Next: Pick a color
|
||||
</Button>
|
||||
</template>
|
||||
</Card>
|
||||
|
|
|
@ -18,28 +18,28 @@ const noGap = ref(true)
|
|||
|
||||
The following containers are responsive. Change your window's size or select a device preset from your browser's dev tools to see how layouts are affected by available space.
|
||||
|
||||
<Layout grid="auto / repeat(auto-fit, minmax(min-content, 163px))" style="--gap:8px">
|
||||
<Card auto title="flex" to="./layout/flex" >
|
||||
<Layout flex style="--gap:8px">
|
||||
<Card width="163px" title="flex" to="./layout/flex" >
|
||||
<Layout flex>
|
||||
<Button primary icon="bi-eye" />
|
||||
<Button secondary icon="bi-eye" />
|
||||
<Button destructive icon="bi-eye" />
|
||||
</Layout>
|
||||
</Card>
|
||||
<Card auto title="grid" to="./layout/grid" >
|
||||
<Card width="163px" title="grid" to="./layout/grid" >
|
||||
<Layout grid column-width="40">
|
||||
<Button primary icon="bi-eye" />
|
||||
<Button secondary icon="bi-eye" style="grid-row: span 2; height: 100%;" />
|
||||
<Button destructive icon="bi-eye" />
|
||||
</Layout>
|
||||
</Card>
|
||||
<Card auto title="stack" to="./layout/stack" >
|
||||
<Card width="163px" title="stack" to="./layout/stack" >
|
||||
<Layout stack style="--gap:0; margin:-8px;">
|
||||
<Button primary icon="bi-eye" />
|
||||
<Button secondary icon="bi-eye" />
|
||||
<Button destructive icon="bi-eye" />
|
||||
</Layout></Card>
|
||||
<Card auto title="columns" to="./layout/columns" >
|
||||
<Card width="163px" title="columns" to="./layout/columns" >
|
||||
<Layout columns column-width="40">
|
||||
<Button primary icon="bi-eye" />
|
||||
<Button secondary icon="bi-eye" />
|
||||
|
|
|
@ -30,22 +30,18 @@ By default, all items in a row assume the same (maximum) height.
|
|||
</Layout>
|
||||
```
|
||||
|
||||
<div class="preview">
|
||||
<Layout flex>
|
||||
<Layout flex class="preview">
|
||||
<Card title="A" style="width:100px; min-width:100px"></Card>
|
||||
<Card title="B" :tags="['funk', 'dunk', 'punk']"></Card>
|
||||
<Card title="C" style="width:100px; min-width:100px"></Card>
|
||||
<Card title="D"></Card>
|
||||
</Layout>
|
||||
</div>
|
||||
|
||||
## Use additional `flexbox` properties
|
||||
|
||||
<Layout flex
|
||||
class="preview"
|
||||
style="font-size:11px; font-weight:bold; --gap: 4px;"
|
||||
|
||||
>
|
||||
style="font-size:11px; font-weight:bold; --gap: 4px;">
|
||||
|
||||
--gap: 4px
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ const size = ref(1);
|
|||
</div>
|
||||
</Layout>
|
||||
|
||||
## Make the Spacer elastic
|
||||
## Make the Spacer elastic (responsive)
|
||||
|
||||
<Layout flex>
|
||||
|
||||
|
@ -154,3 +154,15 @@ const size = ref(1);
|
|||
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
## Use the Spacer to vary an element's dimensions
|
||||
|
||||
<Layout flex style="align-items:flex-start">
|
||||
<Input v-model="size" type="range" />
|
||||
<Card small title="h">
|
||||
<Spacer h :size="size * 4" style="border:5px dashed;" />
|
||||
</Card>
|
||||
<Card small title="v">
|
||||
<Spacer v :size="size * 4" style="border:5px dashed;" />
|
||||
</Card>
|
||||
</Layout>
|
||||
|
|
|
@ -13,11 +13,17 @@ const route = useRoute();
|
|||
const here = route.path
|
||||
</script>
|
||||
|
||||
<Link disabled to="#theme-color-definitions">Want to fix colors?</Link>
|
||||
<Alert blue style="margin: 0 -48px">
|
||||
Want to fix colors?
|
||||
<Spacer h />
|
||||
<Layout flex no-gap>
|
||||
<Link solid primary to="#change-a-color-value">Change a color value</Link>
|
||||
<Link solid primary to="#alter-the-shade-of-a-color">Alter the shade of a color</Link>
|
||||
<Link solid primary to="#choose-a-different-style-for-a-specific-variant">Modify a specific variant</Link>
|
||||
</Layout>
|
||||
</Alert>
|
||||
|
||||
<Spacer />
|
||||
# Using Color
|
||||
|
||||
## Add color via props
|
||||
|
|
Loading…
Reference in New Issue