1
0
mirror of https://github.com/pocket-id/pocket-id.git synced 2026-02-04 13:21:45 +00:00

feat: minor redesign of auth pages

This commit is contained in:
Elias Schneider
2025-12-22 21:36:23 +01:00
parent 59ca6b26ac
commit 08e4ffeb60
7 changed files with 30 additions and 30 deletions

View File

@@ -4,7 +4,7 @@ Pocket ID is a simple OIDC provider that allows users to authenticate with their
→ Try out the [Demo](https://demo.pocket-id.org) → Try out the [Demo](https://demo.pocket-id.org)
<img src="https://github.com/user-attachments/assets/96ac549d-b897-404a-8811-f42b16ea58e2" width="1200"/> <img src="https://github.com/user-attachments/assets/1e99ba44-76da-4b47-9b8a-dbe9b7f84512" width="1200"/>
The goal of Pocket ID is to be a simple and easy-to-use. There are other self-hosted OIDC providers like [Keycloak](https://www.keycloak.org/) or [ORY Hydra](https://www.ory.sh/hydra/) but they are often too complex for simple use cases. The goal of Pocket ID is to be a simple and easy-to-use. There are other self-hosted OIDC providers like [Keycloak](https://www.keycloak.org/) or [ORY Hydra](https://www.ory.sh/hydra/) but they are often too complex for simple use cases.

View File

@@ -24,7 +24,8 @@ func initApplicationImages(ctx context.Context, fileStorage storage.FileStorage)
// Previous versions of images // Previous versions of images
// If these are found, they are deleted // If these are found, they are deleted
legacyImageHashes := imageHashMap{ legacyImageHashes := imageHashMap{
"background.jpg": mustDecodeHex("138d510030ed845d1d74de34658acabff562d306476454369a60ab8ade31933f"), "background.jpg": mustDecodeHex("138d510030ed845d1d74de34658acabff562d306476454369a60ab8ade31933f"),
"background.webp": mustDecodeHex("3fc436a66d6b872b01d96a4e75046c46b5c3e2daccd51e98ecdf98fd445599ab"),
} }
sourceFiles, err := resources.FS.ReadDir("images") sourceFiles, err := resources.FS.ReadDir("images")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 291 KiB

After

Width:  |  Height:  |  Size: 221 KiB

View File

@@ -232,22 +232,19 @@
} }
} }
@keyframes slide-bg-container { @keyframes bg-zoom {
0% { 0% {
left: 0; transform: scale(1.3);
} }
100% { 100% {
left: 650px; transform: scale(1);
} }
} }
.animate-slide-bg-container { .animate-bg-zoom {
position: absolute; transform-origin: center;
top: 0; will-change: transform;
bottom: 0; animation: bg-zoom 0.7s cubic-bezier(0.25, 0.1, 0.25, 1) forwards;
left: 0;
right: 0;
animation: slide-bg-container 0.6s cubic-bezier(0.33, 1, 0.68, 1) forwards;
} }
@keyframes delayed-fade { @keyframes delayed-fade {

View File

@@ -19,7 +19,7 @@
); );
</script> </script>
<div class=" w-full {isAuthPage ? 'absolute top-0 z-10 mt-4' : 'border-b'}"> <div class=" w-full {isAuthPage ? 'absolute top-0 z-10 mt-3 lg:mt-8 pr-2 lg:pr-3' : 'border-b'}">
<div <div
class="{!isAuthPage class="{!isAuthPage
? 'max-w-[1640px]' ? 'max-w-[1640px]'

View File

@@ -48,20 +48,16 @@
{#if isDesktop.current} {#if isDesktop.current}
<div class="h-screen items-center overflow-hidden text-center"> <div class="h-screen items-center overflow-hidden text-center">
<div <div
class="relative z-10 flex h-full w-[650px] p-16 {cn( class="relative z-10 flex h-full w-[650px] 2xl:w-[800px] p-16 {cn(
showAlternativeSignInMethodButton && 'pb-0', showAlternativeSignInMethodButton && 'pb-0'
animate && 'animate-delayed-fade'
)}" )}"
> >
<div class="flex h-full w-full flex-col overflow-hidden"> <div class="flex h-full w-full flex-col overflow-hidden">
<div class="relative flex flex-grow flex-col items-center justify-center overflow-auto"> <div class="relative flex grow flex-col items-center justify-center overflow-auto">
{@render children()} {@render children()}
</div> </div>
{#if showAlternativeSignInMethodButton} {#if showAlternativeSignInMethodButton}
<div <div class="mb-4 flex items-center justify-center">
class="mb-4 flex items-center justify-center"
style={animate ? 'animation-delay: 500ms;' : ''}
>
<a <a
href={alternativeSignInButton.href} href={alternativeSignInButton.href}
class="text-muted-foreground text-xs transition-colors hover:underline" class="text-muted-foreground text-xs transition-colors hover:underline"
@@ -73,13 +69,13 @@
</div> </div>
</div> </div>
<!-- Background image with slide animation --> <!-- Background image -->
<div class="{cn(animate && 'animate-slide-bg-container')} absolute top-0 right-0 bottom-0 z-0"> <div class="absolute top-0 right-0 left-500px bottom-0 z-0 overflow-hidden rounded-[40px] m-6">
<img <img
src={cachedBackgroundImage.getUrl()} src={cachedBackgroundImage.getUrl()}
class="h-screen rounded-l-[60px] object-cover {animate class="{cn(
? 'w-full' animate && 'animate-bg-zoom'
: 'w-[calc(100vw-650px)]'}" )} h-screen object-cover w-[calc(100vw-650px)] 2xl:w-[calc(100vw-800px)]"
alt={m.login_background()} alt={m.login_background()}
/> />
</div> </div>
@@ -89,7 +85,7 @@
class="flex h-screen items-center justify-center bg-cover bg-center text-center" class="flex h-screen items-center justify-center bg-cover bg-center text-center"
style="background-image: url({cachedBackgroundImage.getUrl()});" style="background-image: url({cachedBackgroundImage.getUrl()});"
> >
<Card.Root class="mx-3 w-full max-w-md" style={animate ? 'animation-delay: 200ms;' : ''}> <Card.Root class="mx-3 w-full max-w-md">
<Card.CardContent <Card.CardContent
class="px-4 py-10 sm:p-10 {showAlternativeSignInMethodButton ? 'pb-3 sm:pb-3' : ''}" class="px-4 py-10 sm:p-10 {showAlternativeSignInMethodButton ? 'pb-3 sm:pb-3' : ''}"
> >

View File

@@ -9,6 +9,7 @@
import { getWebauthnErrorMessage } from '$lib/utils/error-util'; import { getWebauthnErrorMessage } from '$lib/utils/error-util';
import { startAuthentication } from '@simplewebauthn/browser'; import { startAuthentication } from '@simplewebauthn/browser';
import { fade } from 'svelte/transition'; import { fade } from 'svelte/transition';
import { cn } from 'tailwind-variants';
import LoginLogoErrorSuccessIndicator from './components/login-logo-error-success-indicator.svelte'; import LoginLogoErrorSuccessIndicator from './components/login-logo-error-success-indicator.svelte';
let { data } = $props(); let { data } = $props();
@@ -55,13 +56,18 @@
{m.authenticate_with_passkey_to_access_account()} {m.authenticate_with_passkey_to_access_account()}
</p> </p>
{/if} {/if}
<div class="mt-10 flex justify-center gap-3"> <div class="mt-10 flex justify-center gap-3 w-full max-w-[450px]">
{#if $appConfigStore.allowUserSignups === 'open'} {#if $appConfigStore.allowUserSignups === 'open'}
<Button variant="secondary" href="/signup"> <Button class="w-[50%]" variant="secondary" href="/signup">
{m.signup()} {m.signup()}
</Button> </Button>
{/if} {/if}
<Button {isLoading} onclick={authenticate} autofocus={true}> <Button
class={cn($appConfigStore.allowUserSignups === 'open' && 'w-[50%]')}
{isLoading}
onclick={authenticate}
autofocus={true}
>
{error ? m.try_again() : m.authenticate()} {error ? m.try_again() : m.authenticate()}
</Button> </Button>
</div> </div>