feat: complete SSR CRM and refine auth UI
This commit is contained in:
@@ -25,17 +25,17 @@ component SignIn {
|
||||
class = ""
|
||||
}
|
||||
view {
|
||||
<section {...attrs} data-wrnexus-runtime="auth" data-auth-sign-in data-mfa-href='{mfaHref}' class='w-full max-w-md rounded-[var(--wrn-radius-lg)] border border-[var(--wrn-color-border)] bg-[var(--wrn-color-surface)] p-6 text-[var(--wrn-color-text)] shadow-[var(--wrn-shadow-2)] {class}'>
|
||||
<header class="mb-6 space-y-1.5">
|
||||
<section {...attrs} data-wrnexus-runtime="auth" data-auth-sign-in data-mfa-href='{mfaHref}' class='wrn-auth-sign-in w-full max-w-md rounded-[var(--wrn-radius-lg)] border border-[var(--wrn-color-border)] bg-[var(--wrn-color-surface)] p-6 text-[var(--wrn-color-text)] shadow-[var(--wrn-shadow-2)] {class}'>
|
||||
<header class="wrn-auth-sign-in__header mb-6 space-y-1.5">
|
||||
<h1 class="m-0 text-2xl font-semibold tracking-tight">{title}</h1>
|
||||
<p class="m-0 text-sm text-[var(--wrn-color-muted)]">{description}</p>
|
||||
</header>
|
||||
<form method="post" action='{action}' data-schema='{schema}' data-redirect='{redirect}' novalidate class="space-y-4">
|
||||
<form method="post" action='{action}' data-schema='{schema}' data-redirect='{redirect}' novalidate class="wrn-auth-sign-in__form">
|
||||
<input type="hidden" name="returnTo" value='{returnTo}' />
|
||||
<input type="hidden" name="deviceFingerprint" value="" />
|
||||
<input type="hidden" name="deviceName" value="" />
|
||||
<Input id="auth-sign-in-identifier" name="identifier" type="text" label="{identifierLabel}" autocomplete="username webauthn" placeholder="{identifierPlaceholder}" icon="icon-[lucide--at-sign]" color="{color}" size="{size}" />
|
||||
<div class="space-y-1.5">
|
||||
<div>
|
||||
<TogglePassword
|
||||
label="{passwordLabel}"
|
||||
cornerHint="Forgot password?"
|
||||
@@ -48,9 +48,7 @@ component SignIn {
|
||||
size="{size}"
|
||||
/>
|
||||
</div>
|
||||
{#if showRemember}
|
||||
<Checkbox id="auth-sign-in-remember" name="rememberDevice" label="Trust this device" color="{color}" size="{size}" />
|
||||
{/if}
|
||||
{#if showRemember}<div class="wrn-auth-sign-in__remember"><Checkbox id="auth-sign-in-remember" name="rememberDevice" label="Trust this device" color="{color}" size="{size}" /></div>{/if}
|
||||
<slot></slot>
|
||||
<p data-error="_form" role="alert" class="m-0 hidden rounded-[var(--wrn-radius-sm)] bg-[color-mix(in_srgb,var(--wrn-color-danger)_10%,transparent)] p-3 text-sm text-[var(--wrn-color-danger)]"></p>
|
||||
<Button type="submit" label="{submitLabel}" variant="solid" color="{color}" size="{size}" fullWidth="true" />
|
||||
@@ -64,4 +62,18 @@ component SignIn {
|
||||
{/if}
|
||||
</section>
|
||||
}
|
||||
|
||||
style {
|
||||
.wrn-auth-sign-in__header { margin-bottom: 1.5rem; }
|
||||
.wrn-auth-sign-in__header h1 { font-size: 1.75rem; line-height: 1.15; }
|
||||
.wrn-auth-sign-in__header p { margin-top: 0.35rem; font-size: 0.9375rem; line-height: 1.5; }
|
||||
.wrn-auth-sign-in__form { display: grid; gap: 1.15rem; }
|
||||
.wrn-auth-sign-in__form > * { margin: 0 !important; }
|
||||
.wrn-auth-sign-in__remember { margin-top: -0.25rem !important; }
|
||||
.wrn-auth-sign-in__form .wrn-next__field-heading label,
|
||||
.wrn-auth-sign-in__form .wrn-next__password-heading { font-size: 0.875rem; font-weight: 650; }
|
||||
.wrn-auth-sign-in__form .wrn-next__field-control > input { min-height: 3rem; font-size: 0.875rem; }
|
||||
.wrn-auth-sign-in__form [data-error]:empty { display: none; }
|
||||
.wrn-auth-sign-in__form .wrn-action[data-full-width="true"] { margin-top: 0.15rem !important; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ component SignUp {
|
||||
<section
|
||||
{...attrs}
|
||||
data-wrnexus-runtime="auth"
|
||||
class='w-full max-w-lg rounded-[var(--wrn-radius-lg)] border border-[var(--wrn-color-border)] bg-[var(--wrn-color-surface)] p-6 text-[var(--wrn-color-text)] shadow-[var(--wrn-shadow-2)] {class}'
|
||||
class='wrn-auth-sign-up w-full max-w-lg rounded-[var(--wrn-radius-lg)] border border-[var(--wrn-color-border)] bg-[var(--wrn-color-surface)] p-6 text-[var(--wrn-color-text)] shadow-[var(--wrn-shadow-2)] {class}'
|
||||
>
|
||||
<header
|
||||
class="mb-6 space-y-1.5"
|
||||
@@ -50,7 +50,7 @@ component SignUp {
|
||||
data-schema='{schema}'
|
||||
data-redirect='{redirect}'
|
||||
novalidate
|
||||
class="grid gap-4 sm:grid-cols-2"
|
||||
class="wrn-auth-sign-up__form"
|
||||
>
|
||||
<Input
|
||||
id="auth-sign-up-name"
|
||||
@@ -61,7 +61,6 @@ component SignUp {
|
||||
icon="icon-[lucide--user]"
|
||||
color="{color}"
|
||||
size="{size}"
|
||||
class="sm:col-span-2"
|
||||
/>
|
||||
|
||||
<Input
|
||||
@@ -100,7 +99,6 @@ component SignUp {
|
||||
icon="icon-[lucide--circle-user-round]"
|
||||
color="{color}"
|
||||
size="{size}"
|
||||
class="sm:col-span-2"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -176,15 +174,7 @@ component SignUp {
|
||||
>
|
||||
</p>
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
label="{submitLabel}"
|
||||
variant="solid"
|
||||
color="{color}"
|
||||
size="{size}"
|
||||
fullWidth="true"
|
||||
class="wrn-auth-sign-up__wide sm:col-span-2"
|
||||
/>
|
||||
<div class="wrn-auth-sign-up__submit"><Button type="submit" label="{submitLabel}" variant="solid" color="{color}" size="{size}" fullWidth="true" /></div>
|
||||
</form>
|
||||
|
||||
<p
|
||||
@@ -196,9 +186,19 @@ component SignUp {
|
||||
}
|
||||
|
||||
style {
|
||||
.wrn-auth-sign-up > header { margin-bottom: 1.5rem; }
|
||||
.wrn-auth-sign-up > header h1 { font-size: 1.75rem; line-height: 1.15; letter-spacing: -0.025em; }
|
||||
.wrn-auth-sign-up > header p { margin-top: 0.35rem; font-size: 0.9375rem; line-height: 1.5; }
|
||||
.wrn-auth-sign-up__form { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.15rem; }
|
||||
.wrn-auth-sign-up__form .wrn-next__field-heading label,
|
||||
.wrn-auth-sign-up__form .wrn-next--strong-password > label { font-size: 0.875rem; font-weight: 650; }
|
||||
.wrn-auth-sign-up__form .wrn-next__field-control > input { min-height: 3rem; font-size: 0.875rem; }
|
||||
.wrn-auth-sign-up__form [data-error]:empty { display: none; }
|
||||
.wrn-auth-sign-up__wide {
|
||||
grid-column: 1 / -1;
|
||||
min-width: 0;
|
||||
}
|
||||
.wrn-auth-sign-up__submit { width: 100%; margin-top: 0.25rem; }
|
||||
.wrn-auth-sign-up__submit .wrn-btn { min-height: 3rem; font-size: 0.9375rem; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@wrnexus/auth",
|
||||
"version": "0.8.12",
|
||||
"version": "0.8.13",
|
||||
"description": "Complete authentication, account security, MFA, passkeys, recovery, devices, risk, and audit system for WRNexusJS.",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@@ -72,6 +72,17 @@ test("account forms use the dedicated password components", () => {
|
||||
expect(signUp).not.toContain('id="auth-sign-up-password"');
|
||||
});
|
||||
|
||||
test("account forms own consistent spacing and full-width submit layout", () => {
|
||||
const signIn = readFileSync(join(directory, "SignIn.wrn"), "utf8");
|
||||
const signUp = readFileSync(join(directory, "SignUp.wrn"), "utf8");
|
||||
|
||||
expect(signIn).toContain("wrn-auth-sign-in__form");
|
||||
expect(signIn).toContain("wrn-auth-sign-in__remember");
|
||||
expect(signUp).toContain("wrn-auth-sign-up__form");
|
||||
expect(signUp).toContain("wrn-auth-sign-up__submit");
|
||||
expect(signUp).toContain("grid-template-columns: minmax(0, 1fr)");
|
||||
});
|
||||
|
||||
test("authentication journeys use themed UI form controls", () => {
|
||||
const expected = {
|
||||
"SignIn.wrn": ["<Input", "<TogglePassword", "<Checkbox", "<Button"],
|
||||
|
||||
Reference in New Issue
Block a user