feat(web): add sticky header

pull/715/head
Travis Fischer 2025-06-17 04:46:51 +07:00
rodzic 2bca04d5a6
commit 85ac47783d
7 zmienionych plików z 259 dodań i 134 usunięć

Wyświetl plik

@ -0,0 +1,86 @@
import { cn } from '@/lib/utils'
import styles from './styles.module.css'
export default function AboutPage() {
return (
<>
<section>
<h1>About</h1>
<div className={cn('prose dark:prose-invert', styles.markdown)}>
<h2>Our Mission</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
<b>Ut enim ad minim veniam</b>, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat.
</p>
<h2>Our Story</h2>
<p>
Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur.
<em>Excepteur sint occaecat cupidatat non proident</em>, sunt in
culpa qui officia deserunt mollit anim id est laborum.
</p>
<h2>Our Values</h2>
<p>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem
accusantium doloremque laudantium, totam rem aperiam, eaque ipsa
quae ab illo inventore veritatis et quasi architecto beatae vitae
dicta sunt explicabo.
</p>
<h2>Our Team</h2>
<p>
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut
fugit, sed quia consequuntur magni dolores eos qui ratione
voluptatem sequi nesciunt.
</p>
<h2>Our Technology</h2>
<p>
At vero eos et accusamus et iusto odio dignissimos ducimus qui
blanditiis praesentium voluptatum deleniti atque corrupti quos
dolores et quas molestias <b>excepturi sint occaecati</b> cupiditate
non provident.
</p>
<h2>Our Impact</h2>
<p>
Similique sunt in culpa qui officia deserunt mollitia animi, id est
laborum et dolorum fuga.
<em>Et harum quidem rerum facilis est et expedita distinctio</em>.
Nam libero tempore, cum soluta nobis est eligendi optio.
</p>
<h2>Our Future</h2>
<p>
Temporibus autem quibusdam et aut officiis debitis aut rerum
necessitatibus saepe eveniet ut et voluptates repudiandae sint et
molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente
delectus.
</p>
<h2>Our Community</h2>
<p>
Ut aut reiciendis voluptatibus maiores alias consequatur aut
perferendis doloribus asperiores repellat. Sed ut perspiciatis unde
omnis iste natus error sit voluptatem accusantium doloremque
laudantium.
</p>
<h2>Our Commitment</h2>
<p>
Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse
quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat
quo voluptas nulla pariatur?{' '}
<b>Excepteur sint occaecat cupidatat non proident</b>.
</p>
</div>
</section>
</>
)
}

Wyświetl plik

@ -0,0 +1,142 @@
.markdown {
width: 100%;
max-width: 100%;
line-height: 1.6;
display: flex;
flex-direction: column;
align-items: center;
}
.markdown > * {
margin-bottom: 1em;
width: 100%;
max-width: 830px;
}
.markdown > *:first-child {
margin-top: 0 !important;
}
.markdown img {
display: inline-block;
max-width: 100%;
margin: 0;
}
.markdown a:not(:has(img)) {
display: inline-block;
text-decoration: none;
font-weight: inherit;
line-height: 1.3;
position: relative;
transition: unset;
opacity: 1;
color: unset;
padding-bottom: 0.1rem;
border-color: var(--border);
border-bottom-width: 0.135rem;
background: transparent;
background-origin: border-box;
background-repeat: no-repeat;
background-position: 50% 100%;
background-size: 0 0.135rem;
}
.markdown a:hover:not(:has(img)),
.markdown a:focus:not(:has(img)) {
color: var(--tw-prose-links);
text-decoration: none;
border-bottom-color: transparent;
background-image: linear-gradient(90.68deg, #b439df 0.26%, #e5337e 102.37%);
background-repeat: no-repeat;
background-position: 0 100%;
background-size: 100% 0.135rem;
transition-property: background-position, background-size;
transition-duration: 300ms;
}
.markdown :where(ul):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
margin-top: 1em;
}
.markdown p + ul,
.markdown p + ol,
.markdown h1 + ul,
.markdown h2 + ul,
.markdown h3 + ul,
.markdown h4 + ul,
.markdown h5 + ul,
.markdown h6 + ul,
.markdown h1 + ol,
.markdown h2 + ol,
.markdown h3 + ol,
.markdown h4 + ol,
.markdown h5 + ol,
.markdown h6 + ol {
margin-top: 0;
}
.markdown p {
margin-top: 0;
margin-bottom: 1em;
}
.markdown li a {
margin: 0;
}
.markdown li:first-child {
margin-top: 0;
}
.markdown li:last-child {
margin-bottom: 0;
}
.markdown h1,
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
margin-top: 1.5em;
margin-bottom: 0.5em;
font-weight: 600;
line-height: 1.25;
}
.markdown h1 {
font-size: 2em;
}
.markdown h2 {
font-size: 1.5em;
}
.markdown h3 {
font-size: 1.25em;
}
.markdown h4 {
font-size: 1em;
}
.markdown h5 {
font-size: 1em;
font-weight: 700;
}
.markdown h6 {
font-size: 1em;
font-weight: 500;
}
@media (max-width: 800px) {
.markdown img {
display: block;
text-align: center;
margin: 0 auto;
}
}

Wyświetl plik

@ -1,129 +0,0 @@
'use client'
import type {
PasswordChangeError,
PasswordChangeState
} from '@agentic/openauth/provider/password'
import { useState } from 'react'
import { authCopy } from '@/lib/auth-copy'
export default function ForgotPasswordPage() {
// TODO
const [error] = useState<PasswordChangeError | undefined>(undefined)
const [state] = useState<PasswordChangeState>({
type: 'start',
redirect: '/' // TODO
})
const [form] = useState<FormData | undefined>(undefined)
const passwordError = [
'invalid_password',
'password_mismatch',
'validation_error'
].includes(error?.type || '')
return (
<>
<section>
<h1 className='my-0! text-center text-balance leading-snug md:leading-none'>
{authCopy.change_prompt}
</h1>
<form data-component='form' method='post'>
{/* <FormAlert
message={
error?.type
? error.type === 'validation_error'
? (error.message ?? authCopy?.[`error_${error.type}`])
: authCopy?.[`error_${error.type}`]
: undefined
}
/> */}
{state.type === 'start' && (
<>
<input type='hidden' name='action' value='code' />
<input
data-component='input'
autoFocus
type='email'
name='email'
required
value={form?.get('email')?.toString()}
placeholder={authCopy.input_email}
/>
</>
)}
{state.type === 'code' && (
<>
<input type='hidden' name='action' value='verify' />
<input
data-component='input'
autoFocus
name='code'
minLength={6}
maxLength={6}
required
placeholder={authCopy.input_code}
autoComplete='one-time-code'
/>
</>
)}
{state.type === 'update' && (
<>
<input type='hidden' name='action' value='update' />
<input
data-component='input'
autoFocus
type='password'
name='password'
placeholder={authCopy.input_password}
required
value={!passwordError ? form?.get('password')?.toString() : ''}
autoComplete='new-password'
/>
<input
data-component='input'
type='password'
name='repeat'
required
value={!passwordError ? form?.get('password')?.toString() : ''}
placeholder={authCopy.input_repeat}
autoComplete='new-password'
/>
</>
)}
<button data-component='button'>{authCopy.button_continue}</button>
</form>
{state.type === 'code' && (
<form method='post'>
<input type='hidden' name='action' value='code' />
<input type='hidden' name='email' value={state.email} />
{state.type === 'code' && (
<div data-component='form-footer'>
<span>
{authCopy.code_return}{' '}
<a data-component='link' href='/login'>
{authCopy.login.toLowerCase()}
</a>
</span>
<button data-component='link'>{authCopy.code_resend}</button>
</div>
)}
</form>
)}
</section>
</>
)
}

Wyświetl plik

@ -135,7 +135,7 @@ body {
html,
body {
max-width: 100vw;
overflow-x: hidden;
height: 100%;
}
a {

Wyświetl plik

@ -107,13 +107,13 @@ export default function LoginPage() {
<div className='flex items-center'>
<Label htmlFor={field.name}>Password</Label>
<a
{/* <a
href='/forgot-password'
className='ml-auto text-xs underline-offset-4 hover:underline'
tabIndex={-1}
>
Forgot your password?
</a>
</a> */}
</div>
<Input

Wyświetl plik

@ -1,9 +1,10 @@
.root {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
width: 100%;
min-height: 100vh;
}
.main {

Wyświetl plik

@ -1,5 +1,18 @@
.header {
position: sticky;
top: 0;
left: 0;
z-index: 200;
width: 100%;
max-width: 100vw;
overflow: hidden;
height: 55px;
min-height: 55px;
background: hsla(0, 0%, 100%, 0.8);
backdrop-filter: saturate(180%) blur(16px);
display: flex;
flex-direction: column;
align-items: center;
@ -7,8 +20,20 @@
line-height: 1;
}
:global(.dark) .header {
background: transparent;
box-shadow: inset 0 -1px 0 0 rgba(0, 0, 0, 0.1);
backdrop-filter: saturate(180%) blur(20px);
}
/* Workaround for Firefox not supporting backdrop-filter yet */
@-moz-document url-prefix() {
:global(.dark) .header {
background: hsla(203, 8%, 20%, 0.8);
}
}
.headerContent {
pointer-events: auto;
align-self: center;
width: 100%;
max-width: 1200px;