fix(webapp): optimize registration layout (#8630)

* - fixed nowrap for button
- restyled bullets for slider
- relocated back links
- removed icons

* - removed icon from RegistrationSlideEmail too

* - added media query for padding

* - fixed missing constants

* - fixed padding in no-header layout

* - fixed sticky footer in registration flow

* - removed icons from inputs

* - set fixed height for back link

* - fixed invite code placeholder

* - added auto submit to invite and email code forms
- fixed layout password inputs
- added layout to checkboxes (create)
- removed unnecessary texts
- moved backLink for password-reset
- tidied up create layout

* fixed margin

* - fixed nonceLength

* lint fixes

* corrected path

---------

Co-authored-by: Sebastian Stein <sebastian@codepassion.de>
Co-authored-by: Ulf Gebhardt <ulf.gebhardt@webcraft-media.de>
This commit is contained in:
sebastian2357 2025-06-11 18:45:03 +02:00 committed by GitHub
parent a0e4b49833
commit b1c19d0c94
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 271 additions and 158 deletions

View File

@ -276,6 +276,7 @@ $size-avatar-large: 114px;
$size-button-large: 50px; $size-button-large: 50px;
$size-button-base: 36px; $size-button-base: 36px;
$size-button-small: 26px; $size-button-small: 26px;
$size-button-tiny: 18px;
/** /**
* @tokens Size Images * @tokens Size Images

View File

@ -274,6 +274,7 @@ $size-avatar-large: 114px;
$size-button-large: 50px; $size-button-large: 50px;
$size-button-base: 36px; $size-button-base: 36px;
$size-button-small: 26px; $size-button-small: 26px;
$size-button-tiny: 18px;
/** /**
* @tokens Size Images * @tokens Size Images

View File

@ -38,8 +38,8 @@
<base-button <base-button
:class="['selection-dot']" :class="['selection-dot']"
style="float: left" style="float: left"
:circle="true" :bullet="true"
size="small" size="tiny"
type="submit" type="submit"
filled filled
:loading="false" :loading="false"
@ -54,6 +54,7 @@
:icon="sliderData.sliders[sliderIndex].button.icon" :icon="sliderData.sliders[sliderIndex].button.icon"
type="submit" type="submit"
filled filled
padding
:loading=" :loading="
sliderData.sliders[sliderIndex].button.loading !== undefined sliderData.sliders[sliderIndex].button.loading !== undefined
? sliderData.sliders[sliderIndex].button.loading ? sliderData.sliders[sliderIndex].button.loading

View File

@ -28,6 +28,8 @@
</template> </template>
<script> <script>
import registrationConstants from '~/constants/registration'
export default { export default {
props: { props: {
email: { type: String, required: true }, email: { type: String, required: true },
@ -43,7 +45,9 @@ export default {
min: 5, min: 5,
max: 5, max: 5,
required: true, required: true,
message: this.$t('components.registration.email-nonce.form.validations.length'), message: this.$t('components.registration.email-nonce.form.validations.length', {
nonceLength: registrationConstants.NONCE_LENGTH,
}),
}, },
}, },
disabled: true, disabled: true,

View File

@ -1,5 +1,5 @@
<template> <template>
<div id="footer" class="ds-footer"> <div id="footer" class="ds-footer" :class="{ 'is-sticky': isSticky }">
<!-- links to internal or external pages --> <!-- links to internal or external pages -->
<span v-for="pageParams in links.FOOTER_LINK_LIST" :key="pageParams.name"> <span v-for="pageParams in links.FOOTER_LINK_LIST" :key="pageParams.name">
<page-params-link :pageParams="pageParams"> <page-params-link :pageParams="pageParams">
@ -26,6 +26,12 @@ export default {
components: { components: {
PageParamsLink, PageParamsLink,
}, },
props: {
isSticky: {
type: Boolean,
default: true,
},
},
data() { data() {
return { links, version: `v${this.$env.VERSION}` } return { links, version: `v${this.$env.VERSION}` }
}, },
@ -35,13 +41,16 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.ds-footer { .ds-footer {
text-align: center; text-align: center;
position: fixed;
bottom: 0px;
z-index: 10; z-index: 10;
background-color: $color-footer-background; background-color: $color-footer-background;
width: 100%; width: 100%;
padding: 10px 10px; padding: 10px 10px;
box-shadow: 0px -6px 12px -4px rgba(0, 0, 0, 0.1); box-shadow: 0px -6px 12px -4px rgba(0, 0, 0, 0.1);
&.is-sticky {
position: fixed;
bottom: 0px;
}
} }
.ds-footer a { .ds-footer a {
color: $color-footer-link; color: $color-footer-link;

View File

@ -24,9 +24,9 @@
:disabled="disabled" :disabled="disabled"
:loading="$apollo.loading" :loading="$apollo.loading"
filled filled
padding
name="submit" name="submit"
type="submit" type="submit"
icon="envelope"
> >
{{ $t('components.password-reset.request.form.submit') }} {{ $t('components.password-reset.request.form.submit') }}
</base-button> </base-button>

View File

@ -1,6 +1,5 @@
<template> <template>
<ds-text> <ds-text>
{{ $t('components.registration.email-display.yourEmail') }}
<b v-if="emailAsString.length > 0"> <b v-if="emailAsString.length > 0">
{{ emailAsString }} {{ emailAsString }}
<b v-if="!isEmailFormat" class="email-warning"> <b v-if="!isEmailFormat" class="email-warning">

View File

@ -35,19 +35,19 @@
<!-- leave this here in case the scoped variable is needed in the future nobody would remember this --> <!-- leave this here in case the scoped variable is needed in the future nobody would remember this -->
<!-- <template v-slot="{ errors }"> --> <!-- <template v-slot="{ errors }"> -->
<template> <template>
<email-display-and-verify :email="sliderData.collectedInputData.email" />
<div v-if="askForRealName" class="full-name"> <div v-if="askForRealName" class="full-name">
<!-- <p>{{ $t('settings.data.realNamePlease') }}</p>--> <!-- <p>{{ $t('settings.data.realNamePlease') }}</p>-->
<ds-input <ds-input
id="givenName" id="givenName"
model="givenName" model="givenName"
icon="user"
:label="$t('settings.data.givenName')" :label="$t('settings.data.givenName')"
:placeholder="$t('settings.data.givenNamePlaceholder')" :placeholder="$t('settings.data.givenNamePlaceholder')"
/> />
<ds-input <ds-input
id="surName" id="surName"
model="surName" model="surName"
icon="user"
:label="$t('settings.data.surName')" :label="$t('settings.data.surName')"
:placeholder="$t('settings.data.surNamePlaceholder')" :placeholder="$t('settings.data.surNamePlaceholder')"
/> />
@ -56,90 +56,99 @@
v-else v-else
id="name" id="name"
model="name" model="name"
icon="user"
:label="$t('settings.data.labelName')" :label="$t('settings.data.labelName')"
:placeholder="$t('settings.data.namePlaceholder')" :placeholder="$t('settings.data.namePlaceholder')"
/> />
<label for="password">
{{ $t('settings.security.change-password.label-new-password') }}
</label>
<div class="password-wrapper"> <div class="password-wrapper">
<ds-input <ds-input
id="password" id="password"
model="password" model="password"
:type="showPassword ? 'text' : 'password'" :type="showPassword ? 'text' : 'password'"
:label="$t('settings.security.change-password.label-new-password')"
autocomplete="off" autocomplete="off"
class="password-field" class="password-field"
ref="password" ref="password"
/> />
<show-password <show-password
class="show-password-toggle with-label"
@show-password="toggleShowPassword('password')" @show-password="toggleShowPassword('password')"
:iconName="iconNamePassword" :iconName="iconNamePassword"
/> />
</div> </div>
<label for="passwordConfirmation">
{{ $t('settings.security.change-password.label-new-password-confirm') }}
</label>
<div class="password-wrapper"> <div class="password-wrapper">
<ds-input <ds-input
id="passwordConfirmation" id="passwordConfirmation"
model="passwordConfirmation" model="passwordConfirmation"
:type="showPasswordConfirm ? 'text' : 'password'" :type="showPasswordConfirm ? 'text' : 'password'"
:label="$t('settings.security.change-password.label-new-password-confirm')"
autocomplete="off" autocomplete="off"
class="password-field" class="password-field"
ref="confirmPassword" ref="confirmPassword"
/> />
<show-password <show-password
class="show-password-toggle with-label"
@show-password="toggleShowPassword('confirmPassword')" @show-password="toggleShowPassword('confirmPassword')"
:iconName="iconNamePasswordConfirm" :iconName="iconNamePasswordConfirm"
/> />
</div> </div>
<password-strength class="password-strength" :password="formData.password" /> <password-strength
class="password-strength"
:password="formData.password"
style="margin: 30px 0 20px 0"
/>
<!-- location --> <!-- location -->
<location-select <location-select
v-if="locationRequired" v-if="locationRequired"
class="location-select"
v-model="locationName" v-model="locationName"
:canBeCleared="false" :canBeCleared="false"
:showPreviousLocation="false" :showPreviousLocation="false"
/> />
<email-display-and-verify :email="sliderData.collectedInputData.email" /> <div class="checkbox-group">
<ds-text> <div class="checkbox-item">
<input <input
id="checkbox0" id="checkbox0"
type="checkbox" type="checkbox"
v-model="termsAndConditionsConfirmed" v-model="termsAndConditionsConfirmed"
:checked="termsAndConditionsConfirmed" :checked="termsAndConditionsConfirmed"
/> class="checkbox-input"
<label for="checkbox0"> />
{{ $t('components.registration.create-user-account.termsAndCondsEtcConfirmed') }} <label for="checkbox0" class="checkbox-label">
<br /> <span class="checkbox-text">
<page-params-link :pageParams="links.TERMS_AND_CONDITIONS" forceTargetBlank> {{ $t('components.registration.create-user-account.termsAndCondsEtcConfirmed') }}
{{ $t('site.termsAndConditions') }} </span>
</page-params-link> <div class="checkbox-links">
<br /> <page-params-link :pageParams="links.TERMS_AND_CONDITIONS" forceTargetBlank>
<page-params-link :pageParams="links.DATA_PRIVACY" forceTargetBlank> {{ $t('site.termsAndConditions') }}
{{ $t('site.data-privacy') }} </page-params-link>
</page-params-link> <span class="separator"></span>
</label> <page-params-link :pageParams="links.DATA_PRIVACY" forceTargetBlank>
</ds-text> {{ $t('site.data-privacy') }}
<ds-text> </page-params-link>
<input </div>
id="checkbox1" </label>
type="checkbox" </div>
v-model="receiveCommunicationAsEmailsEtcConfirmed"
:checked="receiveCommunicationAsEmailsEtcConfirmed" <div class="checkbox-item">
/> <input
<label for="checkbox1"> id="checkbox1"
{{ type="checkbox"
$t( v-model="receiveCommunicationAsEmailsEtcConfirmed"
'components.registration.create-user-account.receiveCommunicationAsEmailsEtcConfirmed', :checked="receiveCommunicationAsEmailsEtcConfirmed"
) class="checkbox-input"
}} />
</label> <label for="checkbox1" class="checkbox-label">
</ds-text> <span class="checkbox-text">
{{
$t(
'components.registration.create-user-account.receiveCommunicationAsEmailsEtcConfirmed',
)
}}
</span>
</label>
</div>
</div>
</template> </template>
<ds-space margin="xxx-small" /> <ds-space margin="xxx-small" />
</ds-form> </ds-form>
@ -395,39 +404,19 @@ export default {
display: flex; display: flex;
width: 100%; width: 100%;
align-items: center; align-items: center;
padding: $input-padding-vertical $space-x-small; padding: 0;
padding-left: 0;
padding-right: 0;
height: $input-height; height: $input-height;
margin-bottom: 10px; margin-top: 40px;
margin-bottom: $space-small; margin-bottom: 16px;
color: $text-color-base;
background: $background-color-disabled;
border: $input-border-size solid $border-color-softer;
border-left: none;
border-radius: $border-radius-base;
outline: none;
transition: all $duration-short $ease-out;
&:focus-within {
background-color: $background-color-base;
border: $input-border-size solid $border-color-active;
.toggle-icon {
color: $text-color-base;
}
}
.password-field { .password-field {
position: relative;
padding-top: $space-small;
border: none;
border-style: none;
appearance: none;
margin-left: 0;
width: 100%; width: 100%;
padding: 0;
}
::v-deep .ds-input-wrap {
bottom: 4px;
left: -1px;
} }
} }
@ -435,7 +424,60 @@ export default {
padding-bottom: $space-small; padding-bottom: $space-small;
} }
.location-select { .checkbox-group {
padding-bottom: $space-base; margin: 20px 0;
}
.checkbox-item {
display: flex;
align-items: flex-start;
margin-bottom: 16px;
padding: 16px;
background-color: #f8f9fa; // Light gray background
border-radius: 8px;
transition: background-color 0.2s ease;
&:hover {
background-color: #f0f2f5; // Slightly darker on hover
}
&:last-child {
margin-bottom: 0;
}
}
.checkbox-input {
flex-shrink: 0;
width: 18px;
height: 18px;
margin-right: 12px;
margin-top: 2px; // Align with first line of text
cursor: pointer;
}
.checkbox-label {
flex: 1;
cursor: pointer;
line-height: 1.5;
color: #374151; // Dark gray text
}
.checkbox-text {
display: block;
margin-bottom: 8px;
font-weight: 500;
}
.checkbox-links {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
font-size: 0.875rem; // Slightly smaller text for links
.separator {
color: #9ca3af; // Light gray separator
font-size: 0.75rem;
}
} }
</style> </style>

View File

@ -9,14 +9,7 @@
<ds-text> <ds-text>
{{ $t('components.registration.signup.form.description') }} {{ $t('components.registration.signup.form.description') }}
</ds-text> </ds-text>
<ds-input <ds-input :placeholder="$t('login.email')" type="email" id="email" model="email" name="email" />
:placeholder="$t('login.email')"
type="email"
id="email"
model="email"
name="email"
icon="envelope"
/>
<slot></slot> <slot></slot>
<ds-text v-if="sliderData.collectedInputData.emailSend"> <ds-text v-if="sliderData.collectedInputData.emailSend">
<input id="checkbox" type="checkbox" v-model="sendEmailAgain" :checked="sendEmailAgain" /> <input id="checkbox" type="checkbox" v-model="sendEmailAgain" :checked="sendEmailAgain" />
@ -111,11 +104,7 @@ export default {
? 'components.registration.email.buttonTitle.resend' ? 'components.registration.email.buttonTitle.resend'
: 'components.registration.email.buttonTitle.skipResend' : 'components.registration.email.buttonTitle.skipResend'
: 'components.registration.email.buttonTitle.send', : 'components.registration.email.buttonTitle.send',
buttonIcon: this.sliderData.collectedInputData.emailSend buttonIcon: null,
? this.sendEmailAgain
? 'envelope'
: 'arrow-right'
: 'envelope',
}, },
} }
}, },

View File

@ -7,11 +7,12 @@
@input-valid="handleInputValid" @input-valid="handleInputValid"
> >
<ds-input <ds-input
:placeholder="$t('components.registration.invite-code.form.invite-code')" :placeholder="formSchema.inviteCode.placeholder"
:minlength="formSchema.inviteCode.minLength"
:maxlength="formSchema.inviteCode.maxLength"
model="inviteCode" model="inviteCode"
name="inviteCode" name="inviteCode"
id="inviteCode" id="inviteCode"
icon="question-circle"
/> />
<ds-text v-if="!validInput"> <ds-text v-if="!validInput">
{{ $t('components.registration.invite-code.form.description') }} {{ $t('components.registration.invite-code.form.description') }}
@ -43,7 +44,7 @@
</template> </template>
<script> <script>
import registrationConstants from '~/constants/registration' import registrationConstants from '~/constants/registrationBranded.js'
import { validateInviteCode } from '~/graphql/InviteCode' import { validateInviteCode } from '~/graphql/InviteCode'
import ProfileAvatar from '~/components/_new/generic/ProfileAvatar/ProfileAvatar' import ProfileAvatar from '~/components/_new/generic/ProfileAvatar/ProfileAvatar'
@ -69,6 +70,7 @@ export default {
message: this.$t('components.registration.invite-code.form.validations.length', { message: this.$t('components.registration.invite-code.form.validations.length', {
inviteCodeLength: registrationConstants.INVITE_CODE_LENGTH, inviteCodeLength: registrationConstants.INVITE_CODE_LENGTH,
}), }),
placeholder: this.$t('components.registration.invite-code.form.invite-code'),
}, },
}, },
dbRequestInProgress: false, dbRequestInProgress: false,
@ -141,11 +143,16 @@ export default {
const validationResult = response.data.validateInviteCode const validationResult = response.data.validateInviteCode
if (validationResult && validationResult.isValid) { if (validationResult && validationResult.isValid) {
this.$toast.success( // Auto-advance to next slide
this.$t('components.registration.invite-code.form.validations.success', { const currentIndex = this.sliderData.sliderIndex
inviteCode, const nextIndex = currentIndex + 1
}),
) if (
this.sliderData.sliderSelectorCallback &&
nextIndex < this.sliderData.sliders.length
) {
this.sliderData.sliderSelectorCallback(nextIndex)
}
return true return true
} else { } else {
this.$toast.error( this.$toast.error(

View File

@ -13,14 +13,10 @@
model="nonce" model="nonce"
name="nonce" name="nonce"
id="nonce" id="nonce"
icon="question-circle"
/> />
<ds-text> <ds-text>
{{ $t('components.registration.email-nonce.form.description') }} {{ $t('components.registration.email-nonce.form.description') }}
</ds-text> </ds-text>
<ds-text>
{{ $t('components.registration.email-nonce.form.click-next') }}
</ds-text>
<slot></slot> <slot></slot>
<ds-space margin="xxx-small" /> <ds-space margin="xxx-small" />
</ds-form> </ds-form>
@ -120,12 +116,16 @@ export default {
if (this.sliderData.sliders[this.sliderIndex].data.response) { if (this.sliderData.sliders[this.sliderIndex].data.response) {
if (this.sliderData.sliders[this.sliderIndex].data.response.VerifyNonce) { if (this.sliderData.sliders[this.sliderIndex].data.response.VerifyNonce) {
this.$toast.success( // Auto-advance to next slide
this.$t('components.registration.email-nonce.form.validations.success', { const currentIndex = this.sliderData.sliderIndex
email, const nextIndex = currentIndex + 1
nonce,
}), if (
) this.sliderData.sliderSelectorCallback &&
nextIndex < this.sliderData.sliders.length
) {
this.sliderData.sliderSelectorCallback(nextIndex)
}
} else { } else {
this.$toast.error( this.$toast.error(
this.$t('components.registration.email-nonce.form.validations.error', { this.$t('components.registration.email-nonce.form.validations.error', {

View File

@ -1,5 +1,8 @@
<template> <template>
<section class="registration-slider"> <section class="registration-slider">
<div v-if="registrationType !== 'no-public-registration'" class="back-link" left>
<nuxt-link :to="loginLink">{{ $t('site.back-to-login') }}</nuxt-link>
</div>
<base-card> <base-card>
<template #imageColumn> <template #imageColumn>
<page-params-link :pageParams="links.ORGANIZATION" :title="$t('login.moreInfo', metadata)"> <page-params-link :pageParams="links.ORGANIZATION" :title="$t('login.moreInfo', metadata)">
@ -27,12 +30,6 @@
<template #create-user-account> <template #create-user-account>
<registration-slide-create :sliderData="sliderData" /> <registration-slide-create :sliderData="sliderData" />
</template> </template>
<template v-if="registrationType !== 'no-public-registration'" #footer>
<ds-space margin-bottom="xxx-small" margin-top="small" centered>
<nuxt-link :to="loginLink">{{ $t('site.back-to-login') }}</nuxt-link>
</ds-space>
</template>
</component-slider> </component-slider>
<template #topMenu> <template #topMenu>
@ -94,7 +91,7 @@ export default {
data: { request: null, response: { isValidInviteCode: false } }, data: { request: null, response: { isValidInviteCode: false } },
button: { button: {
titleIdent: 'components.registration.invite-code.buttonTitle', titleIdent: 'components.registration.invite-code.buttonTitle',
icon: 'arrow-right', icon: null,
callback: this.buttonCallback, callback: this.buttonCallback,
sliderCallback: null, // optional set by slot sliderCallback: null, // optional set by slot
}, },
@ -106,7 +103,7 @@ export default {
data: { request: null, response: null }, data: { request: null, response: null },
button: { button: {
titleIdent: 'components.registration.email.buttonTitle.send', // changed by slider component titleIdent: 'components.registration.email.buttonTitle.send', // changed by slider component
icon: 'envelope', // changed by slider component icon: null,
callback: this.buttonCallback, callback: this.buttonCallback,
sliderCallback: null, // optional set by slot sliderCallback: null, // optional set by slot
}, },
@ -118,7 +115,7 @@ export default {
data: { request: null, response: { VerifyNonce: false } }, data: { request: null, response: { VerifyNonce: false } },
button: { button: {
titleIdent: 'components.registration.email-nonce.buttonTitle', titleIdent: 'components.registration.email-nonce.buttonTitle',
icon: 'arrow-right', icon: null,
callback: this.buttonCallback, callback: this.buttonCallback,
sliderCallback: null, // optional set by slot sliderCallback: null, // optional set by slot
}, },
@ -130,7 +127,7 @@ export default {
data: { request: null, response: null }, data: { request: null, response: null },
button: { button: {
titleIdent: 'components.registration.create-user-account.buttonTitle', titleIdent: 'components.registration.create-user-account.buttonTitle',
icon: 'check', icon: null,
loading: false, loading: false,
callback: this.buttonCallback, callback: this.buttonCallback,
sliderCallback: null, // optional set by slot sliderCallback: null, // optional set by slot
@ -266,4 +263,7 @@ export default {
max-width: 620px; max-width: 620px;
margin: auto; margin: auto;
} }
.back-link {
height: 35px;
}
</style> </style>

View File

@ -29,7 +29,6 @@
id="email" id="email"
model="email" model="email"
name="email" name="email"
icon="envelope"
/> />
<base-button <base-button
:disabled="disabled" :disabled="disabled"
@ -37,7 +36,6 @@
filled filled
name="submit" name="submit"
type="submit" type="submit"
icon="envelope"
> >
{{ $t('components.registration.signup.form.submit') }} {{ $t('components.registration.signup.form.submit') }}
</base-button> </base-button>

View File

@ -19,6 +19,10 @@ export default {
LoadingSpinner, LoadingSpinner,
}, },
props: { props: {
bullet: {
type: Boolean,
default: false,
},
circle: { circle: {
type: Boolean, type: Boolean,
default: false, default: false,
@ -46,9 +50,13 @@ export default {
type: String, type: String,
default: 'regular', default: 'regular',
validator(value) { validator(value) {
return value.match(/(small|regular|large)/) return value.match(/(tiny|small|regular|large)/)
}, },
}, },
padding: {
type: Boolean,
default: false,
},
type: { type: {
type: String, type: String,
default: 'button', default: 'button',
@ -66,11 +74,14 @@ export default {
let buttonClass = 'base-button' let buttonClass = 'base-button'
if (this.$slots.default === undefined) buttonClass += ' --icon-only' if (this.$slots.default === undefined) buttonClass += ' --icon-only'
if (this.bullet) buttonClass += ' --bullet'
if (this.circle) buttonClass += ' --circle' if (this.circle) buttonClass += ' --circle'
if (this.danger) buttonClass += ' --danger' if (this.danger) buttonClass += ' --danger'
if (this.loading) buttonClass += ' --loading' if (this.loading) buttonClass += ' --loading'
if (this.size === 'tiny') buttonClass += ' --tiny'
if (this.size === 'small') buttonClass += ' --small' if (this.size === 'small') buttonClass += ' --small'
if (this.size === 'large') buttonClass += ' --large' if (this.size === 'large') buttonClass += ' --large'
if (this.padding) buttonClass += ' --padding'
if (this.filled) buttonClass += ' --filled' if (this.filled) buttonClass += ' --filled'
else if (this.ghost) buttonClass += ' --ghost' else if (this.ghost) buttonClass += ' --ghost'
@ -98,6 +109,7 @@ export default {
font-weight: $font-weight-bold; font-weight: $font-weight-bold;
letter-spacing: $letter-spacing-large; letter-spacing: $letter-spacing-large;
cursor: pointer; cursor: pointer;
white-space: nowrap;
&.--danger { &.--danger {
@include buttonStates($color-scheme: danger); @include buttonStates($color-scheme: danger);
@ -117,14 +129,33 @@ export default {
border-radius: 50%; border-radius: 50%;
} }
&.--bullet {
width: 18px;
height: 18px;
border-radius: 50%;
&[disabled] {
background-color: transparent;
border: 1px solid $color-neutral-80;
}
}
&.--ghost { &.--ghost {
border: none; border: none;
} }
&.--tiny {
height: $size-button-tiny;
&.--bullet,
&.--circle {
width: $size-button-tiny;
}
}
&.--small { &.--small {
height: $size-button-small; height: $size-button-small;
font-size: $font-size-small; font-size: $font-size-small;
&.--bullet,
&.--circle { &.--circle {
width: $size-button-small; width: $size-button-small;
} }
@ -134,11 +165,21 @@ export default {
height: $size-button-large; height: $size-button-large;
font-size: $font-size-large; font-size: $font-size-large;
&.--bullet,
&.--circle { &.--circle {
width: $size-button-large; width: $size-button-large;
} }
} }
&.--padding {
padding: 0 20px;
}
@media screen and (max-width: 400px) {
&.--padding {
padding: 0 15px;
}
}
&:not(.--icon-only) > .base-icon { &:not(.--icon-only) > .base-icon {
margin-right: $space-xx-small; margin-right: $space-xx-small;
} }

View File

@ -1,11 +1,13 @@
<template> <template>
<div class="layout-blank"> <div class="layout-blank">
<ds-container> <div class="layout-content">
<div style="padding: 5rem 2rem"> <ds-container>
<nuxt /> <div>
</div> <nuxt />
</ds-container> </div>
<page-footer /> </ds-container>
</div>
<page-footer :is-sticky="false" />
<div id="overlay" /> <div id="overlay" />
</div> </div>
</template> </template>
@ -26,3 +28,25 @@ export default {
}, },
} }
</script> </script>
<style lang="scss">
.layout-blank {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.layout-content {
flex: 1;
}
.layout-blank > .layout-content > .ds-container > div {
padding: 5rem 2rem;
}
@media only screen and (max-width: 500px) {
.layout-blank > .layout-content > .ds-container > div {
padding: 3rem 0;
}
}
</style>

View File

@ -227,8 +227,7 @@
}, },
"email-display": { "email-display": {
"warningFormat": "⚠️ E-Mail hat ein ungültiges Format!", "warningFormat": "⚠️ E-Mail hat ein ungültiges Format!",
"warningUndef": "⚠️ Keine E-Mail definiert!", "warningUndef": "⚠️ Keine E-Mail definiert!"
"yourEmail": "Deine E-Mail-Adresse:"
}, },
"email-nonce": { "email-nonce": {
"buttonTitle": "Weiter", "buttonTitle": "Weiter",

View File

@ -227,8 +227,7 @@
}, },
"email-display": { "email-display": {
"warningFormat": "⚠️ E-mail has wrong format!", "warningFormat": "⚠️ E-mail has wrong format!",
"warningUndef": "⚠️ No e-mail defined!", "warningUndef": "⚠️ No e-mail defined!"
"yourEmail": "Your e-mail address:"
}, },
"email-nonce": { "email-nonce": {
"buttonTitle": "Continue", "buttonTitle": "Continue",

View File

@ -227,8 +227,7 @@
}, },
"email-display": { "email-display": {
"warningFormat": null, "warningFormat": null,
"warningUndef": null, "warningUndef": null
"yourEmail": null
}, },
"email-nonce": { "email-nonce": {
"buttonTitle": null, "buttonTitle": null,

View File

@ -227,8 +227,7 @@
}, },
"email-display": { "email-display": {
"warningFormat": null, "warningFormat": null,
"warningUndef": null, "warningUndef": null
"yourEmail": null
}, },
"email-nonce": { "email-nonce": {
"buttonTitle": null, "buttonTitle": null,

View File

@ -227,8 +227,7 @@
}, },
"email-display": { "email-display": {
"warningFormat": null, "warningFormat": null,
"warningUndef": null, "warningUndef": null
"yourEmail": null
}, },
"email-nonce": { "email-nonce": {
"buttonTitle": null, "buttonTitle": null,

View File

@ -227,8 +227,7 @@
}, },
"email-display": { "email-display": {
"warningFormat": null, "warningFormat": null,
"warningUndef": null, "warningUndef": null
"yourEmail": null
}, },
"email-nonce": { "email-nonce": {
"buttonTitle": null, "buttonTitle": null,

View File

@ -227,8 +227,7 @@
}, },
"email-display": { "email-display": {
"warningFormat": null, "warningFormat": null,
"warningUndef": null, "warningUndef": null
"yourEmail": null
}, },
"email-nonce": { "email-nonce": {
"buttonTitle": null, "buttonTitle": null,

View File

@ -227,8 +227,7 @@
}, },
"email-display": { "email-display": {
"warningFormat": null, "warningFormat": null,
"warningUndef": null, "warningUndef": null
"yourEmail": null
}, },
"email-nonce": { "email-nonce": {
"buttonTitle": null, "buttonTitle": null,

View File

@ -227,8 +227,7 @@
}, },
"email-display": { "email-display": {
"warningFormat": null, "warningFormat": null,
"warningUndef": null, "warningUndef": null
"yourEmail": null
}, },
"email-nonce": { "email-nonce": {
"buttonTitle": null, "buttonTitle": null,

View File

@ -1,5 +1,9 @@
<template> <template>
<ds-container width="small" class="password-reset"> <ds-container width="small" class="password-reset">
<div class="back-link">
<nuxt-link to="/login">{{ $t('site.back-to-login') }}</nuxt-link>
</div>
<base-card> <base-card>
<template #imageColumn> <template #imageColumn>
<page-params-link :pageParams="links.ORGANIZATION" :title="$t('login.moreInfo', metadata)"> <page-params-link :pageParams="links.ORGANIZATION" :title="$t('login.moreInfo', metadata)">
@ -42,3 +46,9 @@ export default {
}, },
} }
</script> </script>
<style lang="scss">
.back-link {
height: 35px;
}
</style>

View File

@ -1,9 +1,5 @@
<template> <template>
<request @handleSubmitted="handlePasswordResetRequested"> <request @handleSubmitted="handlePasswordResetRequested"></request>
<ds-space margin-bottom="xxx-small" margin-top="large" centered>
<nuxt-link to="/login">{{ $t('site.back-to-login') }}</nuxt-link>
</ds-space>
</request>
</template> </template>
<script> <script>