Compare commits

...
Author SHA1 Message Date
tdgao 7c4b4d97dc update auth with new designs 2026-03-25 09:40:05 -06:00
4 changed files with 212 additions and 160 deletions
+2 -2
View File
@@ -267,10 +267,10 @@
"message": "Enter code..."
},
"auth.sign-in.additional-options": {
"message": "<forgot-password-link>Forgot password?</forgot-password-link> • <create-account-link>Create an account</create-account-link>"
"message": "<forgot-password-link>Forgot password</forgot-password-link> • Don't have an account? <create-account-link>Sign up</create-account-link>"
},
"auth.sign-in.sign-in-with": {
"message": "Sign in with"
"message": "Sign into Modrinth"
},
"auth.sign-in.title": {
"message": "Sign In"
+3 -21
View File
@@ -8,12 +8,12 @@ useSeoMeta({
})
</script>
<template>
<NuxtPage class="auth-container universal-card" />
<NuxtPage class="auth-container universal-card border border-solid border-surface-5" />
</template>
<style>
.auth-container {
width: 26rem;
width: 28rem;
max-width: calc(100% - 2rem);
margin: 1rem auto;
display: flex;
@@ -45,24 +45,6 @@ useSeoMeta({
margin: 0 0 0 0.5rem;
}
.third-party {
display: grid;
gap: var(--gap-md);
grid-template-columns: repeat(2, 1fr);
width: 100%;
}
.third-party .btn {
width: 100%;
vertical-align: middle;
}
.third-party .btn svg {
margin-right: var(--gap-sm);
width: 1.25rem;
height: 1.25rem;
}
@media screen and (max-width: 25.5rem) {
.third-party .btn {
grid-column: 1 / 3;
@@ -84,7 +66,7 @@ useSeoMeta({
align-items: center;
display: flex;
justify-content: center;
gap: var(--gap-md);
gap: var(--gap-xs);
flex-wrap: wrap;
}
+125 -94
View File
@@ -5,7 +5,7 @@
class="fixed left-0 top-0 z-[9999] m-0 h-full w-full border-0 p-0"
></iframe>
</div>
<div v-else>
<div v-else c>
<template v-if="flow && !subtleLauncherRedirectUri">
<label for="two-factor-code">
<span class="label__title">{{ formatMessage(messages.twoFactorCodeLabel) }}</span>
@@ -28,98 +28,120 @@
</button>
</template>
<template v-else>
<h1>{{ formatMessage(messages.signInWithLabel) }}</h1>
<section class="third-party">
<a class="btn" :href="getAuthUrl('discord', redirectTarget)">
<DiscordColorIcon />
<span>Discord</span>
</a>
<a class="btn" :href="getAuthUrl('github', redirectTarget)">
<GitHubColorIcon />
<span>GitHub</span>
</a>
<a class="btn" :href="getAuthUrl('microsoft', redirectTarget)">
<MicrosoftColorIcon />
<span>Microsoft</span>
</a>
<a class="btn" :href="getAuthUrl('google', redirectTarget)">
<GoogleColorIcon />
<span>Google</span>
</a>
<a class="btn" :href="getAuthUrl('steam', redirectTarget)">
<SteamColorIcon />
<span>Steam</span>
</a>
<a class="btn" :href="getAuthUrl('gitlab', redirectTarget)">
<GitLabColorIcon />
<span>GitLab</span>
</a>
</section>
<h1>{{ formatMessage(messages.usePasswordLabel) }}</h1>
<section class="auth-form">
<label for="email" hidden>{{ formatMessage(commonMessages.emailUsernameLabel) }}</label>
<StyledInput
id="email"
v-model="email"
:icon="MailIcon"
type="text"
inputmode="email"
autocomplete="username"
:placeholder="formatMessage(commonMessages.emailUsernameLabel)"
wrapper-class="w-full"
/>
<label for="password" hidden>{{ formatMessage(commonMessages.passwordLabel) }}</label>
<StyledInput
id="password"
v-model="password"
:icon="KeyIcon"
type="password"
autocomplete="current-password"
:placeholder="formatMessage(commonMessages.passwordLabel)"
wrapper-class="w-full"
/>
<HCaptcha v-if="globals?.captcha_enabled" ref="captcha" v-model="token" />
<button
class="btn btn-primary continue-btn centered-btn"
:disabled="globals?.captcha_enabled ? !token : false"
@click="beginPasswordSignIn()"
>
{{ formatMessage(commonMessages.signInButton) }} <RightArrowIcon />
</button>
<div class="auth-form__additional-options">
<IntlFormatted :message-id="messages.additionalOptionsLabel">
<template #forgot-password-link="{ children }">
<NuxtLink
class="text-link"
:to="{
path: '/auth/reset-password',
query: route.query,
}"
>
<component :is="() => children" />
</NuxtLink>
</template>
<template #create-account-link="{ children }">
<NuxtLink
class="text-link"
:to="{
path: '/auth/sign-up',
query: route.query,
}"
>
<component :is="() => children" />
</NuxtLink>
</template>
</IntlFormatted>
<div class="flex flex-col gap-6">
<div class="text-center text-2xl font-semibold text-contrast">
{{ formatMessage(messages.signInWithLabel) }}
</div>
</section>
<section class="flex flex-col gap-2.5">
<ButtonStyled>
<a class="!shadow-none" :href="getAuthUrl('google', redirectTarget)">
<GoogleColorIcon />
<span class="ml-1">{{ formatMessage(messages.continueWithProvider, { provider: 'Google' }) }}</span>
</a>
</ButtonStyled>
<ButtonStyled>
<a class="!shadow-none" :href="getAuthUrl('microsoft', redirectTarget)">
<MicrosoftColorIcon />
<span class="ml-1">{{ formatMessage(messages.continueWithProvider, { provider: 'Microsoft' }) }}</span>
</a>
</ButtonStyled>
<ButtonStyled>
<a class="!shadow-none" :href="getAuthUrl('discord', redirectTarget)">
<DiscordColorIcon />
<span class="ml-1">{{ formatMessage(messages.continueWithProvider, { provider: 'Discord' }) }}</span>
</a>
</ButtonStyled>
<ButtonStyled>
<a class="!shadow-none" :href="getAuthUrl('github', redirectTarget)">
<GitHubColorIcon />
<span class="ml-1">{{ formatMessage(messages.continueWithProvider, { provider: 'GitHub' }) }}</span>
</a>
</ButtonStyled>
<ButtonStyled>
<a class="!shadow-none" :href="getAuthUrl('gitlab', redirectTarget)">
<GitLabColorIcon />
<span class="ml-1">{{ formatMessage(messages.continueWithProvider, { provider: 'GitLab' }) }}</span>
</a>
</ButtonStyled>
<ButtonStyled>
<a class="!shadow-none" :href="getAuthUrl('steam', redirectTarget)">
<SteamColorIcon />
<span class="ml-1">{{ formatMessage(messages.continueWithProvider, { provider: 'Steam' }) }}</span>
</a>
</ButtonStyled>
</section>
<div class="h-px w-full bg-surface-5"></div>
<section class="auth-form">
<label for="email" hidden>{{ formatMessage(commonMessages.emailUsernameLabel) }}</label>
<StyledInput
id="email"
v-model="email"
:icon="MailIcon"
type="text"
inputmode="email"
autocomplete="username"
:placeholder="formatMessage(commonMessages.emailUsernameLabel)"
wrapper-class="w-full"
/>
<label for="password" hidden>{{ formatMessage(commonMessages.passwordLabel) }}</label>
<StyledInput
id="password"
v-model="password"
:icon="KeyIcon"
type="password"
autocomplete="current-password"
:placeholder="formatMessage(commonMessages.passwordLabel)"
wrapper-class="w-full"
/>
<HCaptcha
v-if="globals?.captcha_enabled && email && password"
ref="captcha"
v-model="token"
/>
<ButtonStyled color="brand">
<button
class="!w-full"
:disabled="globals?.captcha_enabled ? !token : false"
@click="beginPasswordSignIn()"
>
{{ formatMessage(messages.continueWithEmail) }} <RightArrowIcon />
</button>
</ButtonStyled>
<div class="auth-form__additional-options !text-base">
<IntlFormatted :message-id="messages.additionalOptionsLabel">
<template #forgot-password-link="{ children }">
<NuxtLink
class="text-link"
:to="{
path: '/auth/reset-password',
query: route.query,
}"
>
<component :is="() => children" />
</NuxtLink>
</template>
<template #create-account-link="{ children }">
<NuxtLink
class="inline text-link"
:to="{
path: '/auth/sign-up',
query: route.query,
}"
>
<component :is="() => children" />
</NuxtLink>
</template>
</IntlFormatted>
</div>
</section>
</div>
</template>
</div>
</template>
@@ -137,6 +159,7 @@ import {
SteamColorIcon,
} from '@modrinth/assets'
import {
ButtonStyled,
commonMessages,
defineMessages,
injectModrinthClient,
@@ -159,11 +182,11 @@ const messages = defineMessages({
additionalOptionsLabel: {
id: 'auth.sign-in.additional-options',
defaultMessage:
'<forgot-password-link>Forgot password?</forgot-password-link> • <create-account-link>Create an account</create-account-link>',
"<forgot-password-link>Forgot password</forgot-password-link> • Don't have an account? <create-account-link>Sign up</create-account-link>",
},
signInWithLabel: {
id: 'auth.sign-in.sign-in-with',
defaultMessage: 'Sign in with',
defaultMessage: 'Sign into Modrinth',
},
signInTitle: {
id: 'auth.sign-in.title',
@@ -185,6 +208,14 @@ const messages = defineMessages({
id: 'auth.sign-in.use-password',
defaultMessage: 'Or use a password',
},
continueWithProvider: {
id: 'auth.continue-with-provider',
defaultMessage: 'Continue with {provider}',
},
continueWithEmail: {
id: 'auth.sign-in.continue-with-email',
defaultMessage: 'Continue with Email',
},
})
useHead({
+82 -43
View File
@@ -1,37 +1,56 @@
<template>
<div>
<h1>{{ formatMessage(messages.signUpWithTitle) }}</h1>
<section class="third-party">
<a class="btn discord-btn" :href="getAuthUrl('discord', redirectTarget)">
<DiscordColorIcon />
<span>Discord</span>
</a>
<a class="btn" :href="getAuthUrl('github', redirectTarget)">
<GitHubColorIcon />
<span>GitHub</span>
</a>
<a class="btn" :href="getAuthUrl('microsoft', redirectTarget)">
<MicrosoftColorIcon />
<span>Microsoft</span>
</a>
<a class="btn" :href="getAuthUrl('google', redirectTarget)">
<GoogleColorIcon />
<span>Google</span>
</a>
<a class="btn" :href="getAuthUrl('steam', redirectTarget)">
<SteamColorIcon />
<span>Steam</span>
</a>
<a class="btn" :href="getAuthUrl('gitlab', redirectTarget)">
<GitLabColorIcon />
<span>GitLab</span>
</a>
<div class="flex flex-col gap-6">
<div class="text-center text-2xl font-semibold text-contrast">{{ formatMessage(messages.signUpWithTitle) }}</div>
<section class="flex flex-col gap-2.5">
<ButtonStyled>
<a class="!shadow-none" :href="getAuthUrl('google', redirectTarget)">
<GoogleColorIcon />
<span>{{ formatMessage(messages.continueWithProvider, { provider: 'Google' }) }}</span>
</a>
</ButtonStyled>
<ButtonStyled>
<a class="!shadow-none" :href="getAuthUrl('microsoft', redirectTarget)">
<MicrosoftColorIcon />
<span>{{ formatMessage(messages.continueWithProvider, { provider: 'Microsoft' }) }}</span>
</a>
</ButtonStyled>
<ButtonStyled>
<a class="!shadow-none" :href="getAuthUrl('discord', redirectTarget)">
<DiscordColorIcon />
<span>{{ formatMessage(messages.continueWithProvider, { provider: 'Discord' }) }}</span>
</a>
</ButtonStyled>
<template v-if="showOtherOptions">
<ButtonStyled>
<a class="!shadow-none" :href="getAuthUrl('github', redirectTarget)">
<GitHubColorIcon />
<span>{{ formatMessage(messages.continueWithProvider, { provider: 'GitHub' }) }}</span>
</a>
</ButtonStyled>
<ButtonStyled>
<a class="!shadow-none" :href="getAuthUrl('gitlab', redirectTarget)">
<GitLabColorIcon />
<span>{{ formatMessage(messages.continueWithProvider, { provider: 'GitLab' }) }}</span>
</a>
</ButtonStyled>
<ButtonStyled>
<a class="!shadow-none" :href="getAuthUrl('steam', redirectTarget)">
<SteamColorIcon />
<span>{{ formatMessage(messages.continueWithProvider, { provider: 'Steam' }) }}</span>
</a>
</ButtonStyled>
</template>
<button
class="mx-auto -mb-3 bg-transparent pt-1 text-center text-base font-semibold text-secondary transition-all hover:text-primary"
@click="showOtherOptions = !showOtherOptions"
>
{{ showOtherOptions ? formatMessage(messages.showFewerOptions) : formatMessage(messages.showOtherOptions) }}
</button>
</section>
<h1>{{ formatMessage(messages.createAccountTitle) }}</h1>
<div class="h-px w-full bg-surface-5"></div>
<section class="auth-form">
<section class="flex flex-col gap-2.5">
<label for="email" hidden>{{ formatMessage(commonMessages.emailLabel) }}</label>
<StyledInput
id="email"
@@ -98,15 +117,21 @@
</IntlFormatted>
</p>
<HCaptcha v-if="globals?.captcha_enabled" ref="captcha" v-model="token" />
<HCaptcha
v-if="globals?.captcha_enabled && email && password && confirmPassword && username"
ref="captcha"
v-model="token"
/>
<button
class="btn btn-primary continue-btn centered-btn"
:disabled="globals?.captcha_enabled ? !token : false"
@click="createAccount"
>
{{ formatMessage(messages.createAccountButton) }} <RightArrowIcon />
</button>
<ButtonStyled color="brand">
<button
class="!w-full"
:disabled="globals?.captcha_enabled ? !token : false"
@click="createAccount"
>
{{ formatMessage(messages.continueWithEmail) }} <RightArrowIcon />
</button>
</ButtonStyled>
<div class="auth-form__additional-options">
{{ formatMessage(messages.alreadyHaveAccountLabel) }}
@@ -138,6 +163,7 @@ import {
UserIcon,
} from '@modrinth/assets'
import {
ButtonStyled,
Checkbox,
commonMessages,
defineMessages,
@@ -163,11 +189,7 @@ const messages = defineMessages({
},
signUpWithTitle: {
id: 'auth.sign-up.title.sign-up-with',
defaultMessage: 'Sign up with',
},
createAccountTitle: {
id: 'auth.sign-up.title.create-account',
defaultMessage: 'Or create an account yourself',
defaultMessage: 'Create an Account',
},
subscribeLabel: {
id: 'auth.sign-up.subscribe.label',
@@ -186,6 +208,22 @@ const messages = defineMessages({
id: 'auth.sign-up.sign-in-option.title',
defaultMessage: 'Already have an account?',
},
continueWithProvider: {
id: 'auth.continue-with-provider',
defaultMessage: 'Continue with {provider}',
},
continueWithEmail: {
id: 'auth.sign-up.continue-with-email',
defaultMessage: 'Continue with Email',
},
showFewerOptions: {
id: 'auth.sign-up.show-fewer-options',
defaultMessage: 'Show fewer options',
},
showOtherOptions: {
id: 'auth.sign-up.show-other-options',
defaultMessage: 'Show other options',
},
})
useHead({
@@ -196,6 +234,7 @@ const auth = await useAuth()
const route = useNativeRoute()
const redirectTarget = route.query.redirect
const showOtherOptions = ref(false)
if (auth.value.user) {
await navigateTo('/dashboard')