From 98165f71b0e1e032c25b96a16f70e0e26151a97a Mon Sep 17 00:00:00 2001 From: Nils Schneider Date: Thu, 13 Nov 2025 12:40:38 +0100 Subject: [PATCH] links --- frontend/src/login/LoginView.tsx | 35 +++++++++---- frontend/src/sidebar/Sidebar.tsx | 35 +++++++++++++ frontend/src/sidebar/SidebarContext.tsx | 2 +- frontend/src/styles/auth/login.css | 55 ++++++++++++++++---- frontend/src/styles/base/theme.css | 2 +- frontend/src/styles/detail/detail-panels.css | 2 +- frontend/src/styles/sidebar/sidebar.css | 42 +++++++++++++-- frontend/src/ui/icons.tsx | 30 +++++++++++ 8 files changed, 177 insertions(+), 26 deletions(-) diff --git a/frontend/src/login/LoginView.tsx b/frontend/src/login/LoginView.tsx index 8ee4d1b..6ee1b44 100644 --- a/frontend/src/login/LoginView.tsx +++ b/frontend/src/login/LoginView.tsx @@ -1,5 +1,7 @@ import React, { useEffect, useState } from 'react'; +const loginLogoSrc = new URL('../assets/logo.webp', import.meta.url).toString(); + interface StatusBannerProps { status?: { message: string; variant: string } | null; } @@ -80,13 +82,26 @@ const LoginView: React.FC = ({ return (
-
-

Papercrate

- {hasTenantSelection ? ( -
-

Select a tenant to finish signing in.

-
- {tenantSelection?.tenants?.map((tenant) => ( +
+
+
+ Papercrate logo +

Papercrate

+
+ +
+ {hasTenantSelection ? ( +
+

Select a tenant to finish signing in.

+
+ {tenantSelection?.tenants?.map((tenant) => ( ) : null} - )} - + )} + +
+
); }; diff --git a/frontend/src/sidebar/Sidebar.tsx b/frontend/src/sidebar/Sidebar.tsx index d0def8e..4b9e7fd 100644 --- a/frontend/src/sidebar/Sidebar.tsx +++ b/frontend/src/sidebar/Sidebar.tsx @@ -19,6 +19,9 @@ import { DesktopIcon, UploadIcon, LogoIcon, + GithubIcon, + MatrixIcon, + WorldIcon, } from '../ui/icons'; import PanelHeader from '../ui/PanelHeader'; import useFloatingMenu from '../ui/useFloatingMenu'; @@ -980,6 +983,38 @@ const Sidebar: React.FC = ({
+ ); }; diff --git a/frontend/src/sidebar/SidebarContext.tsx b/frontend/src/sidebar/SidebarContext.tsx index 54965b3..f0c0da3 100644 --- a/frontend/src/sidebar/SidebarContext.tsx +++ b/frontend/src/sidebar/SidebarContext.tsx @@ -32,7 +32,7 @@ const SIDEBAR_COLLAPSE_STORAGE_KEY = 'papercrate_sidebar_collapsed'; const SidebarContext = createContext(null); const THEME_STORAGE_KEY = 'papercrate_theme_settings'; -const DEFAULT_NEUTRAL_HUE = 145; +const DEFAULT_NEUTRAL_HUE = 35; const DEFAULT_NEUTRAL_CHROMA = 0.1; const DEFAULT_NEUTRAL_CONTRAST = 0.3; const DEFAULT_THEME_MODE = 'system'; diff --git a/frontend/src/styles/auth/login.css b/frontend/src/styles/auth/login.css index 10feb02..25bae47 100644 --- a/frontend/src/styles/auth/login.css +++ b/frontend/src/styles/auth/login.css @@ -1,14 +1,57 @@ + .login-screen { min-height: 100vh; min-height: 100dvh; height: 100%; - display: flex; - align-items: center; - justify-content: center; background: var(--bg); padding: 2rem; } +.login-screen__inner { + min-height: calc(100vh - 4rem); + min-height: calc(100dvh - 4rem); + max-width: 24rem; + margin: 0 auto; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 1.75rem; +} + +.login-screen__content { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + gap: 1.75rem; +} + +.login-screen__brand { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.65rem; + text-align: center; +} + +.login-screen__brand img { + width: 5.5rem; + height: 5.5rem; + border-radius: 1rem; + border: none; + background: transparent; + padding: 0; + box-shadow: none; +} + +.login-screen__brand h1 { + margin: 0; + font-size: 2.35rem; + font-weight: 600; + letter-spacing: 0.02em; +} + .login-card { width: min(340px, 100%); background: var(--surface); @@ -20,12 +63,6 @@ gap: 1rem; } -.login-card h1 { - margin: 0; - font-size: 1.6rem; - font-weight: 600; -} - .login-card p { margin: 0; color: var(--muted); diff --git a/frontend/src/styles/base/theme.css b/frontend/src/styles/base/theme.css index 0ef0e77..d3307cf 100644 --- a/frontend/src/styles/base/theme.css +++ b/frontend/src/styles/base/theme.css @@ -1,7 +1,7 @@ :root { color-scheme: light dark; - --neutral-hue: 145deg; + --neutral-hue: 35deg; --surface-hue-shift: 6deg; --foreground-hue-offset: 20deg; --accent-hue-offset: 0deg; diff --git a/frontend/src/styles/detail/detail-panels.css b/frontend/src/styles/detail/detail-panels.css index 6aaebdc..0f51420 100644 --- a/frontend/src/styles/detail/detail-panels.css +++ b/frontend/src/styles/detail/detail-panels.css @@ -7,7 +7,7 @@ min-height: 100dvh; height: 100%; height: 100%; - background: var(--bg); + background: var(--surface); box-shadow: 0 0 24px var(--shadow-soft); border-left: 1px solid var(--border); display: flex; diff --git a/frontend/src/styles/sidebar/sidebar.css b/frontend/src/styles/sidebar/sidebar.css index 839a1b8..5e0f092 100644 --- a/frontend/src/styles/sidebar/sidebar.css +++ b/frontend/src/styles/sidebar/sidebar.css @@ -189,13 +189,45 @@ } .sidebar__footer { - margin-top: auto; - padding: 0.75rem 1rem 1rem; - border-top: 1px solid var(--border); + border-top: 1px solid var(--border-muted, var(--border)); background: var(--surface-subtle); + padding: 0.6rem 0.85rem; display: flex; - flex-direction: column; - gap: 0.75rem; + gap: 0.35rem; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + color: var(--muted); +} + +.sidebar__footer-link { + display: inline-flex; + flex: 1 1 0; + align-items: center; + justify-content: center; + gap: 0.25rem; + font-size: 0.83rem; + color: inherit; + text-decoration: none; + padding: 0.2rem 0.35rem; + border-radius: 999px; + transition: + color 0.12s ease, + background-color 0.12s ease; +} + +.sidebar__footer-link:visited { + color: inherit; +} + +.sidebar__footer-link:hover, +.sidebar__footer-link:focus-visible { + color: var(--sidebar-fg, var(--fg)); + background-color: color-mix(in srgb, var(--surface-overlay) 20%, transparent); +} + +.sidebar__footer-link .icon { + flex-shrink: 0; } .sidebar__title { diff --git a/frontend/src/ui/icons.tsx b/frontend/src/ui/icons.tsx index 85dc09c..afe9547 100644 --- a/frontend/src/ui/icons.tsx +++ b/frontend/src/ui/icons.tsx @@ -48,6 +48,9 @@ import { IconSortDescendingLetters, IconFileInfo, IconAlertTriangle, + IconBrandGithub, + IconBrandMatrix, + IconWorld, } from '@tabler/icons-react'; import FolderSvg from '../assets/folder.svg'; const logoWebp = new URL('../assets/logo.webp', import.meta.url).toString(); @@ -146,6 +149,33 @@ export const IconZoomInArea: TablerIconComponent = ({ className, size = '1em', s /> ); +export const GithubIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => ( + +); + +export const MatrixIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => ( + +); + +export const WorldIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => ( + +); + export const ViewListIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (