feat(ui): default height of 48px for all inputs

This commit is contained in:
upsiflu 2025-01-04 14:34:49 +01:00
parent 6e5c9bad76
commit 6c1d1c5785
10 changed files with 104 additions and 94 deletions

View File

@ -24,6 +24,7 @@ import Input from '~/components/ui/Input.vue'
import Toggle from '~/components/ui/Toggle.vue' import Toggle from '~/components/ui/Toggle.vue'
import Alert from '~/components/ui/Alert.vue' import Alert from '~/components/ui/Alert.vue'
import Spacer from '~/components/ui/layout/Spacer.vue' import Spacer from '~/components/ui/layout/Spacer.vue'
import Pills from '~/components/ui/Pills.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels' import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering' import useOrdering from '~/composables/navigation/useOrdering'
@ -122,6 +123,11 @@ const labels = computed(() => ({
title: t('components.library.Artists.title') title: t('components.library.Artists.title')
})) }))
const tagList = computed(() => ({
current: tags.value,
others: []
}))
const paginateOptions = computed(() => sortedUniq([12, 30, 50, paginateBy.value].sort((a, b) => a - b))) const paginateOptions = computed(() => sortedUniq([12, 30, 50, paginateBy.value].sort((a, b) => a - b)))
</script> </script>
@ -143,8 +149,8 @@ const paginateOptions = computed(() => sortedUniq([12, 30, 50, paginateBy.value]
:placeholder="labels.searchPlaceholder" :placeholder="labels.searchPlaceholder"
> >
</Input> </Input>
<Input <Pills
v-model="tags" v-model="tagList"
:label="t('components.library.Artists.label.tags')" :label="t('components.library.Artists.label.tags')"
style="max-width: 150px;" style="max-width: 150px;"
/> />

View File

@ -88,14 +88,15 @@ onMounted(() => {
// Layout // Layout
--padding: 10px; --padding: 16px;
--shift-by: 0.5px;
position: relative; position: relative;
display: inline-flex; display: inline-flex;
white-space: nowrap; white-space: nowrap;
justify-content: space-between; justify-content: space-between;
padding: 9px var(--padding) 11px var(--padding); padding: calc(var(--padding) - var(--shift-by)) var(--padding) calc(var(--padding) + var(--shift-by)) var(--padding);
&.is-icon-only { &.is-icon-only {
padding: var(--padding); padding: var(--padding);
} }

View File

@ -2,6 +2,7 @@
import { computed, onMounted, ref } from 'vue' import { computed, onMounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import onKeyboardShortcut from '~/composables/onKeyboardShortcut'; import onKeyboardShortcut from '~/composables/onKeyboardShortcut';
import { color } from "~/composables/color.ts";
import Button from "~/components/ui/Button.vue" import Button from "~/components/ui/Button.vue"
import Layout from "~/components/ui/Layout.vue" import Layout from "~/components/ui/Layout.vue"
@ -59,7 +60,7 @@ const model = defineModel<string|number>()
</span> </span>
<input <input
v-bind="{...$attrs, ...attributes}" v-bind="{...$attrs, ...attributes, ...color({}, ['default', 'raised', 'solid'])()}"
v-model="model" v-model="model"
ref="input" ref="input"
:placeholder="placeholder" :placeholder="placeholder"
@ -81,7 +82,7 @@ const model = defineModel<string|number>()
<!-- Right side --> <!-- Right side -->
<div v-if="$slots['input-right']" class="input-right"> <div v-if="$slots['input-right']" class="input-right">
<span> <span class="span-right">
<slot name="input-right" /> <slot name="input-right" />
</span> </span>
</div> </div>

View File

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { type ColorProps, type PastelProps, type VariantProps, color } from '~/composables/color' import { type ColorProps, type PastelProps, type VariantProps, type RaisedProps, color } from '~/composables/color'
const emit = defineEmits<{ const emit = defineEmits<{
click: [event: MouseEvent] click: [event: MouseEvent]
@ -7,7 +7,7 @@ const emit = defineEmits<{
const handleClick = (event: MouseEvent) => { const handleClick = (event: MouseEvent) => {
emit('click', event) emit('click', event)
} }
const props = defineProps<{ noUnderline?:true } & (PastelProps | ColorProps) & VariantProps>() const props = defineProps<{ noUnderline?:true } & (PastelProps | ColorProps) & VariantProps & RaisedProps>()
</script> </script>
<template> <template>

View File

@ -66,28 +66,35 @@ const deselectPill = (value:string) =>
<!-- List of Pills --> <!-- List of Pills -->
<Layout flex gap-8 <Layout flex gap-8
style="padding:4px; border-radius: 18px;"
v-bind="color({}, ['solid', 'default', 'raised'])()" v-bind="color({}, ['solid', 'default', 'raised'])()"
:class="$style.list" :class="$style.list"
> >
<Pill solid v-for="value in model.current" v-if="!model.others"> <Pill outline raised
v-for="value in model.current"
v-if="!model.others"
:class="$style.pill"
>
<span>{{ value }}</span> <span>{{ value }}</span>
</Pill> </Pill>
<Pill solid no-underline @click="deselectPill(value)" v-for="value in model.current" v-if="model.others"> <Pill outline raised
no-underline @click="deselectPill(value)"
v-for="value in model.current"
v-if="model.others"
:class="$style.pill"
>
<span :class="$style['pill-content']">{{ value }}</span>   × <span :class="$style['pill-content']">{{ value }}</span>   ×
</Pill> </Pill>
<Spacer h grow />
<!-- Add more pills --> <!-- Add more pills -->
<select v-if="model.others" <select
v-if="model.others"
name="dropdown" name="dropdown"
v-model="selectedLabel" v-model="selectedLabel"
:class="$style.dropdown" :class="$style.dropdown"
@change="e => e.target.value='+'" @change="e => e.target.value='+'"
> >
<option value="+">+</option> <option value="+"></option>
<option v-for="value in model.others" :value="value"> <option v-for="value in model.others" :value="value">
{{ value }} {{ value }}
</option> </option>
@ -96,28 +103,47 @@ const deselectPill = (value:string) =>
</Layout> </Layout>
</template> </template>
<style module> <style module lang="scss">
.pills { .pills {
>.label { >.label {
margin-top: -18px; margin-top: -18px;
padding-bottom: 8px; padding-bottom: 8px;
font-size:14px; font-size: 14px;
font-weight:600; font-weight: 600;
} }
>.list{ >.list {
padding:4px;
border-radius: 24px;
min-height: 48px;
min-width: 160px;
>:is(:hover, :focus-visible) .pill-content { >:is(:hover, :focus-visible) .pill-content {
text-decoration: line-through !important; text-decoration: line-through !important;
} }
> .pill {
margin: 4px;
padding: 2px;
}
>.dropdown{ >.dropdown{
border-radius: 15px; border-radius: 15px;
padding: 2px 11.25px; padding: 2px 11.25px;
width:30px; flex-grow: 1;
} text-align: right;
>.dropdown:focus-visible { background: transparent;
outline: 3px solid var(--fw-secondary); appearance: auto;
outline-offset: 2px; margin-right: 12px;
}
}
// From vitepress default, needed for app
border: 0;
color: inherit;
}
}
&:hover>.list {
box-shadow: inset 0 0 0 4px var(--border-color)
}
:has(>.dropdown:focus) {
box-shadow: inset 0 0 0 4px var(--focus-ring-color)
}
} }
</style> </style>

View File

@ -1,14 +1,19 @@
.funkwhale.input { .funkwhale.input {
position: relative; position: relative;
flex-grow: 1; flex-grow: 1;
--padding-v: 9px;
--padding: 16px;
> input { > input {
background-color: var(--fw-bg-color); background-color: var(--fw-bg-color);
box-shadow: inset 0 0 0 4px var(--fw-border-color); box-shadow: inset 0 0 0 4px var(--fw-border-color);
outline: none; outline: none;
border:none;
width: 100%; width: 100%;
padding: 8px 12px; padding: 9px 16px;
padding: calc(var(--padding-v) - 1px) var(--padding) calc(var(--padding-v) + 1px) var(--padding);
font-size: 14px; font-size: 14px;
font-family: $font-main; font-family: $font-main;
line-height: 28px; line-height: 28px;
@ -19,41 +24,16 @@
&:focus-visible { &:focus-visible {
outline: none !important; outline: none !important;
} }
&:hover {
box-shadow: inset 0 0 0 4px var(--border-color)
}
&:focus {
box-shadow: inset 0 0 0 4px var(--focus-ring-color)
}
&::placeholder { &::placeholder {
color: var(--fw-placeholder-color); color: var(--fw-placeholder-color);
} }
@include light-theme {
--fw-bg-color: var(--fw-gray-200);
--fw-border-color: var(--fw-bg-color);
--fw-placeholder-color: var(--fw-gray-600);
&:hover {
--fw-border-color: var(--fw-gray-300);
}
&:focus-within {
--fw-border-color: var(--fw-primary);
--fw-bg-color: var(--fw-blue-010);
}
}
@include dark-theme {
color: var(--fw-gray-300);
--fw-bg-color: var(--fw-gray-850);
--fw-border-color: var(--fw-bg-color);
--fw-placeholder-color: var(--fw-gray-300);
&:hover {
--fw-border-color: var(--fw-gray-700);
}
&:focus-within {
--fw-border-color: var(--fw-gray-600);
--fw-bg-color: var(--fw-gray-800);
}
}
} }
&.has-icon > input { &.has-icon > input {
@ -79,8 +59,8 @@
left: 0; left: 0;
bottom: 0; bottom: 0;
height: 44px; height: 48px;
min-width: 44px; min-width: 48px;
display: flex; display: flex;
> i { > i {
@ -97,14 +77,17 @@
position: absolute; position: absolute;
right: 0px; right: 0px;
bottom: 0px; bottom: 0px;
height: 48px;
height: 44px; min-width: 48px;
min-width: 44px;
display: flex; display: flex;
> i { > i {
font-size:18px; font-size:18px;
} }
> .span-right {
padding: calc(var(--padding-v) - 1px) var(--padding) calc(var(--padding-v) + 1px) var(--padding);
}
} }
> .search { > .search {
@ -131,12 +114,9 @@
} }
form.ui.form { form.ui.form {
select.dropdown {
/* display: none !important; */
}
select.dropdown { select.dropdown {
display: block; display: block;
height: 44px; height: 48px;
margin-top: 7px; margin-top: 7px;
border-radius: var(--fw-border-radius); border-radius: var(--fw-border-radius);
font-size: 14px; font-size: 14px;
@ -152,31 +132,12 @@ form.ui.form {
color: var(--fw-gray-800); color: var(--fw-gray-800);
background-color: var(--fw-gray-200); background-color: var(--fw-gray-200);
border-color: transparent; border-color: transparent;
&:hover {
outline: 4px solid var(--fw-gray-300);
}
&:focus-within {
outline: 4px solid var(--fw-primary);
}
} }
@include dark-theme { @include dark-theme {
color: var(--fw-gray-300); color: var(--fw-gray-300);
background-color: var(--fw-gray-850); background-color: var(--fw-gray-850);
border-color: var(--fw-gray-850); border-color: var(--fw-gray-850);
&:hover,
&:focus-visible {
outline: 4px solid var(--fw-gray-700);
outline-offset: -4px;
} }
} }
& option {
color: red;
}
}
.selection.active.dropdown, .ui.selection.active.dropdown .menu {}
} }

View File

@ -82,6 +82,8 @@
// Light theme // Light theme
:is(body.theme-light, html:not(.dark)>body:not(.theme-dark)), .force-light-theme.force-light-theme.force-light-theme { :is(body.theme-light, html:not(.dark)>body:not(.theme-dark)), .force-light-theme.force-light-theme.force-light-theme {
--focus-ring-color: var(--fw-primary);
.default, .funkwhale, .VPDoc { .default, .funkwhale, .VPDoc {
--link-color:var(--fw-blue-400); --link-color:var(--fw-blue-400);
--link-hover-color:var(--fw-blue-500); --link-hover-color:var(--fw-blue-500);
@ -296,6 +298,8 @@
// Dark theme // Dark theme
:is(body.theme-dark, html.dark>body:not(.theme-light)), .force-dark-theme.force-dark-theme.force-dark-theme { :is(body.theme-dark, html.dark>body:not(.theme-light)), .force-dark-theme.force-dark-theme.force-dark-theme {
--focus-ring-color: var(--fw-gray-600);
.default, .funkwhale, .VPDoc { .default, .funkwhale, .VPDoc {
--link-color:var(--fw-gray-300); --link-color:var(--fw-gray-300);
--link-hover-color:var(--fw-gray-200); --link-hover-color:var(--fw-gray-200);
@ -320,7 +324,7 @@
--disabled-border-color:var(--fw-gray-950); --disabled-border-color:var(--fw-gray-950);
&.raised{ &.raised{
--background-color:var(--fw-gray-900); --background-color:var(--fw-gray-850);
--border-color:var(--fw-gray-600); --border-color:var(--fw-gray-600);
--link-color:var(--fw-gray-400); --link-color:var(--fw-gray-400);
--link-hover-color:var(--fw-gray-200); --link-hover-color:var(--fw-gray-200);
@ -520,7 +524,7 @@
// Fallback for focused elements without explicit focus-outline // Fallback for focused elements without explicit focus-outline
:is(button, input, a):focus-visible { :is(button, input, a):focus-visible {
outline: 3px solid var(--fw-secondary); outline: 3px solid var(--focus-ring-color);
outline-offset: 2px; outline-offset: 2px;
} }

View File

@ -1,5 +1,3 @@
@import "./theme.scss";
@mixin docs { @mixin docs {
@if $docs { @if $docs {
.vp-doc & { .vp-doc & {

View File

@ -3,14 +3,20 @@ import { computed, ref } from 'vue'
import Pills from '~/components/ui/Pills.vue'; import Pills from '~/components/ui/Pills.vue';
import Layout from '~/components/ui/Layout.vue'; import Layout from '~/components/ui/Layout.vue';
import Input from '~/components/ui/Input.vue';
const nullModel = ref({
current: [],
others: []
});
const staticModel = ref({ const staticModel = ref({
current: ["Noise", "Field Recording", "Experiment"] current: ["#Noise", "#FieldRecording", "#Experiment"]
}); });
const interactiveModel = ref({ const interactiveModel = ref({
current: ["Noise", "Field Recording", "Experiment"], current: ["#Noise", "#FieldRecording", "#Experiment"],
others: ["Melody", "Rhythm"] others: ["#Melody", "#Rhythm"]
}); });
</script> </script>
@ -24,4 +30,11 @@ Select a set of pills from presets, and add and remove custom ones
<Layout class="preview" style="padding:16px"> <Layout class="preview" style="padding:16px">
<Pills v-model="interactiveModel" label="Tags" /> <Pills v-model="interactiveModel" label="Tags" />
<Input label="Label" placeholder="Placeholder"></Input>
</Layout>
## No pills
<Layout class="preview" style="padding:16px">
<Pills v-model="nullModel" />
</Layout> </Layout>

View File

@ -55,7 +55,7 @@ Want to fix colors?
```vue ```vue
<script setup> <script setup>
import { color } from "~/composables/colors.ts"; import { color } from "~/composables/color.ts";
</script> </script>
<template> <template>