feat(ui): form layout
This commit is contained in:
parent
2ebda850c7
commit
8ff2c05e05
|
@ -80,7 +80,7 @@ const submit = async () => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<form
|
||||
<Layout form stack
|
||||
style="max-width: 600px"
|
||||
@submit.prevent="submit()"
|
||||
>
|
||||
|
@ -107,7 +107,6 @@ const submit = async () => {
|
|||
</Alert>
|
||||
<Spacer v-if="errors.length > 0" />
|
||||
<template v-if="domain === store.getters['instance/domain']">
|
||||
<div style="margin-bottom: 16px">
|
||||
<Input
|
||||
id="username-field"
|
||||
ref="username"
|
||||
|
@ -128,8 +127,6 @@ const submit = async () => {
|
|||
</template>
|
||||
</template>
|
||||
</Input>
|
||||
</div>
|
||||
<div style="margin-bottom: 16px">
|
||||
<Input password
|
||||
v-model="credentials.password"
|
||||
field-id="password-field"
|
||||
|
@ -146,7 +143,6 @@ const submit = async () => {
|
|||
</router-link>
|
||||
</template>
|
||||
</Input>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<p>
|
||||
|
@ -161,5 +157,5 @@ const submit = async () => {
|
|||
>
|
||||
{{ t('components.auth.LoginForm.button.login') }}
|
||||
</Button>
|
||||
</form>
|
||||
</Layout>
|
||||
</template>
|
||||
|
|
|
@ -106,7 +106,7 @@ fetchInstanceSettings()
|
|||
:show-signup="false"
|
||||
/>
|
||||
</div>
|
||||
<form
|
||||
<Layout form stack
|
||||
v-else
|
||||
style="max-width: 600px"
|
||||
@submit.prevent="submit()"
|
||||
|
@ -116,20 +116,17 @@ fetchInstanceSettings()
|
|||
>
|
||||
{{ t('components.auth.SignupForm.message.registrationClosed') }}
|
||||
</Alert>
|
||||
<Spacer v-if="!store.state.instance.settings.users.registration_enabled.value"/>
|
||||
<Alert yellow
|
||||
v-else-if="signupRequiresApproval"
|
||||
>
|
||||
{{ t('components.auth.SignupForm.message.requiresReview') }}
|
||||
</Alert>
|
||||
<Spacer v-else-if="signupRequiresApproval" />
|
||||
<template v-if="formCustomization?.help_text">
|
||||
<rendered-description
|
||||
:content="formCustomization.help_text"
|
||||
:fetch-html="fetchDescriptionHtml"
|
||||
:permissive="true"
|
||||
/>
|
||||
<div class="ui hidden divider" />
|
||||
</template>
|
||||
<Alert red
|
||||
v-if="errors.length > 0"
|
||||
|
@ -146,7 +143,6 @@ fetchInstanceSettings()
|
|||
</li>
|
||||
</ul>
|
||||
</Alert>
|
||||
<div class="required field">
|
||||
<Input
|
||||
id="username-field"
|
||||
:label = "t('components.auth.SignupForm.label.username')"
|
||||
|
@ -158,8 +154,6 @@ fetchInstanceSettings()
|
|||
autofocus
|
||||
:placeholder="labels.usernamePlaceholder"
|
||||
/>
|
||||
</div>
|
||||
<div class="required field">
|
||||
<Input
|
||||
:label="t('components.auth.SignupForm.label.email')"
|
||||
id="email-field"
|
||||
|
@ -170,19 +164,12 @@ fetchInstanceSettings()
|
|||
type="email"
|
||||
:placeholder="labels.emailPlaceholder"
|
||||
/>
|
||||
</div>
|
||||
<div class="required field">
|
||||
<Input password
|
||||
:label="t('components.auth.SignupForm.label.password')"
|
||||
v-model="payload.password1"
|
||||
field-id="password-field"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="!store.state.instance.settings.users.registration_enabled.value"
|
||||
class="required field"
|
||||
>
|
||||
<Input
|
||||
<Input v-if="!store.state.instance.settings.users.registration_enabled.value"
|
||||
:label="t('components.auth.SignupForm.label.invitation')"
|
||||
id="invitation-code"
|
||||
v-model="payload.invitation"
|
||||
|
@ -191,14 +178,11 @@ fetchInstanceSettings()
|
|||
name="invitation"
|
||||
:placeholder="labels.placeholder"
|
||||
/>
|
||||
</div>
|
||||
<template v-if="signupRequiresApproval && (formCustomization?.fields.length ?? 0) > 0">
|
||||
<div
|
||||
<div v-if="signupRequiresApproval && (formCustomization?.fields.length ?? 0) > 0"
|
||||
v-for="(field, idx) in formCustomization?.fields"
|
||||
:key="idx"
|
||||
:class="[{required: field.required}, 'field']"
|
||||
>
|
||||
<!-- TODO: Add `label` prop to `Textarea` component -->
|
||||
<Textarea
|
||||
:label="field.label"
|
||||
v-if="field.input_type === 'long_text'"
|
||||
|
@ -216,8 +200,6 @@ fetchInstanceSettings()
|
|||
:required="field.required"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<Spacer />
|
||||
<Button
|
||||
primary
|
||||
auto
|
||||
|
@ -225,5 +207,5 @@ fetchInstanceSettings()
|
|||
>
|
||||
{{ t('components.auth.SignupForm.button.create') }}
|
||||
</Button>
|
||||
</form>
|
||||
</Layout>
|
||||
</template>
|
||||
|
|
|
@ -107,12 +107,6 @@ onMounted(() => {
|
|||
padding: 10px;
|
||||
}
|
||||
|
||||
// Margin
|
||||
|
||||
&+.button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
border-radius: var(--fw-border-radius);
|
||||
|
||||
transform: translateX(var(--fw-translate-x)) translateY(var(--fw-translate-y)) scale(var(--fw-scale));
|
||||
|
|
|
@ -5,24 +5,26 @@ const props = defineProps<{
|
|||
noRule?:true,
|
||||
noWrap?:true
|
||||
}
|
||||
& { [P in "stack" | "grid" | "flex" | "columns"]?: true | string }
|
||||
& { [C in "nav" | "aside" | "header" | "footer" | "main" | "label" | "h1" | "h2" | "h3" | "h4" | "h5"]?:true }>()
|
||||
const columnWidth = props.columnWidth ?? 46
|
||||
& { [P in "stack" | "grid" | "flex" | "columns" | "row" | "page"]?: true | string }
|
||||
& { [C in "nav" | "aside" | "header" | "footer" | "main" | "label" | "form" | "h1" | "h2" | "h3" | "h4" | "h5"]?:true }>()
|
||||
|
||||
const columnWidth = props.columnWidth ?? 46
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component
|
||||
:is="props.nav ? 'nav' : props.aside ? 'aside' : props.header ? 'header' : props.footer ? 'footer' : props.main ? 'main' : props.label ? 'label' : props.h1? 'h1' : props.h2? 'h2' : props.h3? 'h3' : props.h4? 'h4' : props.h5? 'h5' : 'div'"
|
||||
: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
|
||||
: $style.stack
|
||||
]">
|
||||
<slot />
|
||||
<component
|
||||
:is="props.nav ? 'nav' : props.aside ? 'aside' : props.header ? 'header' : props.footer ? 'footer' : props.main ? 'main' : props.label ? 'label' : props.form ? 'form' : props.h1? 'h1' : props.h2? 'h2' : props.h3? 'h3' : props.h4? 'h4' : props.h5? 'h5' : 'div'"
|
||||
: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
|
||||
: $style.stack
|
||||
]">
|
||||
<slot />
|
||||
</component>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
}
|
||||
|
||||
> .label {
|
||||
margin-top: -18px;
|
||||
padding-bottom: 8px;
|
||||
font-size:14px;
|
||||
font-weight:600;
|
||||
|
|
|
@ -8,6 +8,7 @@ import { useRouter } from 'vue-router'
|
|||
import Input from '~/components/ui/Input.vue'
|
||||
import Button from '~/components/ui/Button.vue'
|
||||
import Spacer from '~/components/ui/layout/Spacer.vue'
|
||||
import Layout from '~/components/ui/Layout.vue'
|
||||
|
||||
import axios from 'axios'
|
||||
|
||||
|
@ -55,7 +56,7 @@ onMounted(() => emailInput.value.focus())
|
|||
<h2>
|
||||
{{ t('views.auth.PasswordReset.header.reset') }}
|
||||
</h2>
|
||||
<form
|
||||
<Layout form stack
|
||||
@submit.prevent="submit()"
|
||||
style="max-width: 600px"
|
||||
>
|
||||
|
@ -79,35 +80,34 @@ onMounted(() => emailInput.value.focus())
|
|||
<p>
|
||||
{{ t('views.auth.PasswordReset.help.form') }}
|
||||
</p>
|
||||
<div class="field">
|
||||
<Input
|
||||
:label="t('views.auth.PasswordReset.label.email')"
|
||||
id="account-email"
|
||||
ref="emailInput"
|
||||
v-model="email"
|
||||
required
|
||||
type="email"
|
||||
name="email"
|
||||
autofocus
|
||||
:placeholder="labels.placeholder"
|
||||
/>
|
||||
</div>
|
||||
<Spacer />
|
||||
<Button
|
||||
:class="['ui', {'loading': isLoading}, 'success', 'button']"
|
||||
type="submit"
|
||||
primary
|
||||
auto
|
||||
>
|
||||
{{ t('views.auth.PasswordReset.button.requestReset') }}
|
||||
</Button>
|
||||
<Button
|
||||
:to="{path: '/login'}"
|
||||
ghost
|
||||
auto
|
||||
>
|
||||
{{ t('views.auth.PasswordReset.link.back') }}
|
||||
</Button>
|
||||
</form>
|
||||
<Input
|
||||
:label="t('views.auth.PasswordReset.label.email')"
|
||||
id="account-email"
|
||||
ref="emailInput"
|
||||
v-model="email"
|
||||
required
|
||||
type="email"
|
||||
name="email"
|
||||
autofocus
|
||||
:placeholder="labels.placeholder"
|
||||
/>
|
||||
<Layout flex>
|
||||
<Button
|
||||
:class="['ui', {'loading': isLoading}, 'success', 'button']"
|
||||
type="submit"
|
||||
primary
|
||||
auto
|
||||
>
|
||||
{{ t('views.auth.PasswordReset.button.requestReset') }}
|
||||
</Button>
|
||||
<Button
|
||||
:to="{path: '/login'}"
|
||||
ghost
|
||||
auto
|
||||
>
|
||||
{{ t('views.auth.PasswordReset.link.back') }}
|
||||
</Button>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</main>
|
||||
</template>
|
||||
|
|
|
@ -3,6 +3,7 @@ import Input from "~/components/ui/Input.vue"
|
|||
import Button from "~/components/ui/Button.vue"
|
||||
import Layout from "~/components/ui/Layout.vue"
|
||||
import Spacer from "~/components/ui/layout/Spacer.vue"
|
||||
import Alert from "~/components/ui/Alert.vue"
|
||||
</script>
|
||||
|
||||
# Input
|
||||
|
@ -90,54 +91,32 @@ You can add a template on the right-hand side of the input to guide the user's i
|
|||
### Password
|
||||
|
||||
```vue-html
|
||||
<Layout flex no-gap style="align-items:flex-end">
|
||||
<Spacer v
|
||||
:size="80"
|
||||
style="align-self: baseline;"
|
||||
/>
|
||||
<Input>
|
||||
<template #label>
|
||||
User name
|
||||
</template>
|
||||
</Input>
|
||||
</Layout>
|
||||
<Layout flex no-gap style="align-items:flex-end">
|
||||
<Spacer v
|
||||
:size="80"
|
||||
style="align-self: baseline;"
|
||||
/>
|
||||
<Input password>
|
||||
<template #label>
|
||||
Password
|
||||
</template>
|
||||
</Input>
|
||||
<Spacer :size="64" />
|
||||
<Layout form stack>
|
||||
<Input label="User name" />
|
||||
<Input password label="Password" />
|
||||
<Layout flex>
|
||||
<Button primary> Submit </Button>
|
||||
<Button> Cancel </Button>
|
||||
</Layout>
|
||||
</Layout>
|
||||
```
|
||||
|
||||
<!-- Implement a component for baseline alignments like this -->
|
||||
<Spacer :size="64" />
|
||||
<Layout form stack>
|
||||
<Input label="User name" />
|
||||
<Input password label="Password" />
|
||||
<Layout flex>
|
||||
<Button primary> Submit </Button>
|
||||
<Button> Cancel </Button>
|
||||
</Layout>
|
||||
</Layout>
|
||||
|
||||
<Layout flex no-gap style="align-items:flex-end">
|
||||
<Spacer v
|
||||
:size="80"
|
||||
style="align-self: baseline;"
|
||||
/>
|
||||
<Input>
|
||||
<template #label>
|
||||
User name
|
||||
</template>
|
||||
</Input>
|
||||
</Layout>
|
||||
<Layout flex no-gap style="align-items:flex-end">
|
||||
<Spacer v
|
||||
:size="80"
|
||||
style="align-self: baseline;"
|
||||
/>
|
||||
<Input password>
|
||||
<template #label>
|
||||
Password
|
||||
</template>
|
||||
</Input>
|
||||
</Layout>
|
||||
::: tip
|
||||
|
||||
We use the spacer to simulate the baseline alignment on page layouts (64px between sections)
|
||||
|
||||
:::
|
||||
|
||||
## Fallthrough attributes
|
||||
|
||||
|
|
Loading…
Reference in New Issue