mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-02-04 09:51:46 +00:00
feat: minor redesign of auth pages
This commit is contained in:
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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 |
@@ -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 {
|
||||||
|
|||||||
@@ -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]'
|
||||||
|
|||||||
@@ -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' : ''}"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user