Improve auth UI: theme toggle, inline register/login links, and mobile guest frame.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-06 20:14:41 +02:00
co-authored by Cursor
parent 72ff454c90
commit 38864704f1
7 changed files with 151 additions and 29 deletions
+43 -19
View File
@@ -104,36 +104,60 @@
}
}
/* ── Guest pages (login, checkout) ── */
/* ── Guest pages (login, register, checkout) — all breakpoints ── */
.app-shell--no-nav {
align-items: center;
justify-content: center;
padding: 16px;
background: var(--color-page-background);
}
.app-shell--no-nav .app-layout {
max-width: var(--form-max-width);
width: 100%;
height: auto;
max-height: calc(100dvh - 32px);
}
.app-shell--no-nav .app-frame {
max-width: var(--form-max-width);
width: 100%;
height: auto;
max-height: calc(100dvh - 32px);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-frame);
background: var(--color-surface);
}
.app-shell--no-nav .app-content {
padding-inline: var(--page-padding);
}
.app-shell--no-nav .page {
background: transparent;
}
.app-shell--no-nav.app-shell--wide .app-layout,
.app-shell--no-nav.app-shell--wide .app-frame {
max-width: min(var(--content-max-width), calc(100vw - 32px));
}
.app-shell--no-nav.app-shell--wide .app-frame {
background: var(--color-bg);
}
@media (min-width: 768px) {
.app-shell--no-nav {
align-items: center;
justify-content: center;
padding: 24px;
background: var(--color-page-background);
}
.app-shell--no-nav .app-layout {
max-width: var(--form-max-width);
width: 100%;
height: auto;
max-height: calc(100dvh - 48px);
}
.app-shell--no-nav .app-layout,
.app-shell--no-nav .app-frame {
max-width: var(--form-max-width);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-frame);
max-height: calc(100dvh - 48px);
background: var(--color-surface);
}
.app-shell--no-nav.app-shell--wide .app-layout,
.app-shell--no-nav.app-shell--wide .app-frame {
max-width: min(var(--content-max-width), calc(100vw - 48px));
}
.app-shell--no-nav.app-shell--wide .app-frame {
background: var(--color-bg);
}
}
+7
View File
@@ -204,6 +204,13 @@ input[type='number'] {
color: var(--color-text);
}
.auth-page .card {
background: transparent;
border: none;
box-shadow: none;
padding-inline: 0;
}
.card + .card {
margin-top: var(--page-gap);
}
+59
View File
@@ -0,0 +1,59 @@
<script setup lang="ts">
import { computed } from 'vue'
import { storeToRefs } from 'pinia'
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import { useThemeStore } from '@/stores/theme'
const themeStore = useThemeStore()
const { isDark } = storeToRefs(themeStore)
const themeIcon = computed(() =>
isDark.value ? 'vuesax-linear:sun-1' : 'vuesax-linear:moon',
)
const themeLabel = computed(() =>
isDark.value ? 'تغییر به تم روشن' : 'تغییر به تم تاریک',
)
</script>
<template>
<button
type="button"
class="auth-theme-toggle"
:aria-label="themeLabel"
:title="themeLabel"
@click="themeStore.toggleLightDark()"
>
<BasicIcon :icon="themeIcon" :size="22" :stroke-width="1.5" />
</button>
</template>
<style scoped>
.auth-theme-toggle {
position: fixed;
top: calc(12px + env(safe-area-inset-top, 0px));
inset-inline-end: 16px;
z-index: 100;
display: inline-flex;
align-items: center;
justify-content: center;
width: 44px;
height: 44px;
padding: 0;
border: 1px solid var(--color-border);
border-radius: 12px;
background: var(--color-surface);
color: var(--color-text);
box-shadow: var(--shadow-sm);
cursor: pointer;
transition:
background-color 0.15s ease,
border-color 0.15s ease,
color 0.15s ease;
}
.auth-theme-toggle:hover {
border-color: var(--color-primary);
background: var(--color-primary-soft);
color: var(--color-primary);
}
</style>
+13
View File
@@ -25,10 +25,23 @@ export const useThemeStore = defineStore('theme', () => {
preference.value = value
}
function cyclePreference() {
const order: ThemePreference[] = ['light', 'dark', 'system']
const index = order.indexOf(preference.value)
preference.value = order[(index + 1) % order.length]!
}
/** Explicit light ↔ dark toggle (skips system). */
function toggleLightDark() {
preference.value = isDark.value ? 'light' : 'dark'
}
return {
preference,
resolved,
isDark,
setPreference,
cyclePreference,
toggleLightDark,
}
})
+13 -5
View File
@@ -5,6 +5,7 @@ import { useAuthStore } from '@/stores/auth'
import BaseInput from '@/components/ui/BaseInput.vue'
import FormErrorBanner from '@/components/ui/FormErrorBanner.vue'
import BaseButton from '@/components/ui/BaseButton.vue'
import AuthThemeToggle from '@/components/ui/AuthThemeToggle.vue'
import { normalizePhone, toPersianDigits } from '@/utils/format'
import { validatePhone } from '@/utils/validation'
import {
@@ -72,6 +73,8 @@ async function submit() {
<template>
<div class="page page-shell auth-page">
<AuthThemeToggle />
<div class="page__scroll flex flex-col justify-center py-6">
<div class="auth-header">
<div class="text-5xl mb-3">🧵</div>
@@ -100,11 +103,16 @@ async function submit() {
<BaseButton block type="submit" :loading="auth.loading">دریافت کد تأیید</BaseButton>
</form>
<div class="mt-6 w-full max-w-[var(--form-max-width)]">
<p class="m-0 mb-2.5 text-center text-sm text-muted">حساب کاربری ندارید؟</p>
<RouterLink v-slot="{ navigate }" to="/register" custom>
<BaseButton block variant="outline" type="button" @click="navigate">ثبت‌نام</BaseButton>
</RouterLink>
<div class="mt-6 w-full max-w-[var(--form-max-width)] text-center">
<p class="m-0 text-sm text-muted">
حساب کاربری ندارید؟
<RouterLink
to="/register"
class="ms-1 font-bold text-primary no-underline hover:underline"
>
ثبت نام کنید
</RouterLink>
</p>
</div>
</div>
</div>
+3
View File
@@ -5,6 +5,7 @@ import { useIntervalFn } from '@vueuse/core'
import { useAuthStore } from '@/stores/auth'
import FormErrorBanner from '@/components/ui/FormErrorBanner.vue'
import BaseButton from '@/components/ui/BaseButton.vue'
import AuthThemeToggle from '@/components/ui/AuthThemeToggle.vue'
import { toPersianDigits, extractNumericString } from '@/utils/format'
import {
FORM_VALIDATION_SUMMARY,
@@ -209,6 +210,8 @@ onMounted(() => {
<template>
<div class="page page-shell auth-page">
<AuthThemeToggle />
<div class="page__scroll flex flex-col justify-center py-6">
<div class="auth-header">
<h1 class="page-title">تأیید شماره موبایل</h1>
+13 -5
View File
@@ -5,6 +5,7 @@ import { useAuthStore } from '@/stores/auth'
import BaseInput from '@/components/ui/BaseInput.vue'
import FormErrorBanner from '@/components/ui/FormErrorBanner.vue'
import BaseButton from '@/components/ui/BaseButton.vue'
import AuthThemeToggle from '@/components/ui/AuthThemeToggle.vue'
import { normalizePhone } from '@/utils/format'
import { validatePhone } from '@/utils/validation'
import {
@@ -66,6 +67,8 @@ async function submit() {
<template>
<div class="page page-shell auth-page">
<AuthThemeToggle />
<div class="page__scroll flex flex-col justify-center py-6">
<div class="auth-header">
<div class="text-5xl mb-3">🧵</div>
@@ -101,11 +104,16 @@ async function submit() {
<BaseButton block :loading="auth.loading" @click="submit">دریافت کد تأیید</BaseButton>
</div>
<div class="mt-6 w-full max-w-[var(--form-max-width)]">
<p class="m-0 mb-2.5 text-center text-sm text-muted">قبلاً ثبت‌نام کرده‌اید؟</p>
<RouterLink v-slot="{ navigate }" to="/login" custom>
<BaseButton block variant="outline" type="button" @click="navigate">ورود</BaseButton>
</RouterLink>
<div class="mt-6 w-full max-w-[var(--form-max-width)] text-center">
<p class="m-0 text-sm text-muted">
قبلاً ثبت‌نام کرده‌اید؟
<RouterLink
to="/login"
class="ms-1 font-bold text-primary no-underline hover:underline"
>
وارد شوید
</RouterLink>
</p>
</div>
</div>
</div>