Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions apps/community/app/(board)/member/[id]/reputation/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Metadata } from 'next'
import { notFound } from 'next/navigation'

import { TextLink } from '@meith/ui'
import { PageTitle, TextLink } from '@meith/ui'

import { RateMemberForm, WithdrawRatingForm } from '@/components/account/reputation-forms'
import { BoardNotice } from '@/components/shell/board-notice'
Expand Down Expand Up @@ -92,9 +92,7 @@ export default async function ReputationPage({
)}

<div className="flex flex-col gap-1">
<h1 className="font-heading text-2xl font-semibold">
{profile.username}&rsquo;s reputation
</h1>
<PageTitle>{profile.username}&rsquo;s reputation</PageTitle>
<p className="text-sm text-muted-foreground">
{reputationLabel(view.summary, translator)}
</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Metadata } from 'next'
import { notFound, redirect } from 'next/navigation'

import { pluginPagePath } from '@meith/plugin-kit'
import { PageTitle } from '@meith/ui'

import { boardUrl } from '@/server/board-url'
import { getActor } from '@/server/context'
Expand Down Expand Up @@ -59,7 +60,7 @@ export default async function PluginBoardPage({
tabIndex={-1}
className="mx-auto flex w-full max-w-4xl flex-col gap-6 px-6 py-8 flex-1"
>
<h1 className="font-heading text-2xl font-semibold">{result.title}</h1>
<PageTitle>{result.title}</PageTitle>
{result.node === null ? (
<p className="rounded-lg border border-border p-4 text-sm text-muted-foreground">
{(await getTranslator()).t('board.plugin.failed')}
Expand Down
3 changes: 2 additions & 1 deletion apps/community/app/(board)/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
type SearchFormModel,
slotCopy,
} from '@meith/theme-kit'
import { PageTitle } from '@meith/ui'

import { SearchOffNotice } from '@/components/board/search-off-notice'
import { getContainer } from '@/server/container'
Expand Down Expand Up @@ -126,7 +127,7 @@ async function Page({ children }: { children: React.ReactNode }) {
tabIndex={-1}
className="mx-auto flex w-full max-w-3xl flex-col gap-6 px-6 py-8 flex-1"
>
<h1 className="font-heading text-2xl font-semibold">{translator.t('board.search.title')}</h1>
<PageTitle>{translator.t('board.search.title')}</PageTitle>
{children}
</main>
)
Expand Down
4 changes: 2 additions & 2 deletions apps/community/app/(board)/unsubscribe/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Metadata } from 'next'

import { env } from '@meith/core'
import { readUnsubscribeToken } from '@meith/subscriptions'
import { TextLink } from '@meith/ui'
import { PageTitle, TextLink } from '@meith/ui'

import { UnsubscribeConfirmForm } from '@/components/account/subscription-forms'
import { BoardNotice } from '@/components/shell/board-notice'
Expand Down Expand Up @@ -30,7 +30,7 @@ export default async function UnsubscribePage({
return (
<main id="board-content" tabIndex={-1} className="flex-1">
<div className="mx-auto flex w-full max-w-xl flex-col gap-6 px-6 py-10">
<h1 className="font-heading text-2xl font-semibold">{translator.t('page.unsubscribe')}</h1>
<PageTitle>{translator.t('page.unsubscribe')}</PageTitle>

{done !== null ? (
<>
Expand Down
10 changes: 9 additions & 1 deletion apps/community/app/admin/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import type { Metadata } from 'next'
import { notFound } from 'next/navigation'

import { ADMIN_IDLE_MINUTES } from '@meith/admin'
import { NavigationDrawerTrigger } from '@meith/ui'

import {
AdminSecondFactorForm,
AdminSignInForm,
AdminSignOutForm,
} from '@/components/admin/admin-forms'
import { AdminNav } from '@/components/admin/admin-nav'
import { NavDisclosureEnhancer } from '@/components/shell/nav-disclosure-enhancer'
import { PanelShell } from '@/components/shell/panel-shell'
import { askForPassword, pendingAdminSecondFactor, resolveAdmin } from '@/server/admin'
import { getActor } from '@/server/context'
Expand Down Expand Up @@ -66,6 +68,7 @@ export default async function AdminLayout({ children }: { children: React.ReactN

return (
<div className="min-h-screen bg-background text-foreground">
<NavDisclosureEnhancer />
<a
href="#board-content"
className="sr-only focus-visible:not-sr-only focus-visible:absolute focus-visible:top-4 focus-visible:left-4 focus-visible:z-50 focus-visible:inline-flex focus-visible:h-9 focus-visible:items-center focus-visible:rounded-md focus-visible:border focus-visible:border-border focus-visible:bg-card focus-visible:px-3 focus-visible:text-sm focus-visible:font-medium focus-visible:text-foreground focus-visible:shadow-lg"
Expand All @@ -74,7 +77,7 @@ export default async function AdminLayout({ children }: { children: React.ReactN
</a>

<header className="sticky top-0 z-30 border-b border-border bg-card/95 backdrop-blur supports-[backdrop-filter]:bg-card/85">
<div className="mx-auto flex h-14 w-full max-w-6xl items-center gap-x-3 px-4 sm:gap-x-4 sm:px-6">
<div className="mx-auto flex h-14 w-full max-w-7xl items-center gap-x-3 px-4 sm:gap-x-4 sm:px-6">
<a
href="/admin"
className="flex min-w-0 items-center gap-2.5 font-heading text-base font-semibold whitespace-nowrap text-foreground sm:text-lg"
Expand All @@ -100,6 +103,11 @@ export default async function AdminLayout({ children }: { children: React.ReactN
</a>
<div className="ml-auto flex shrink-0 items-center gap-3 text-sm whitespace-nowrap sm:gap-4">
<AdminSignOutForm copy={adminFormsCopy(t)} />
<NavigationDrawerTrigger
target="panel-admincp-navigation"
label={t.t('default.panelNav.open')}
className="lg:hidden"
/>
</div>
</div>
</header>
Expand Down
4 changes: 1 addition & 3 deletions apps/community/app/admin/plugins/[key]/[[...path]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,7 @@ export default async function AdminPluginPage({
{rendered.node === null ? (
<p className={PANEL_NOTE}>{t.t('adminPluginDetail.pluginPageError')}</p>
) : (
<section className="rounded-xl border border-border bg-surface p-4">
{rendered.node}
</section>
<section className="min-w-0">{rendered.node}</section>
)}
</PanelPage>
)
Expand Down
6 changes: 2 additions & 4 deletions apps/community/app/install/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
warnings,
} from '@meith/install'
import { isUsableOrigin, MAIL_PRESETS, normaliseOrigin } from '@meith/settings'
import { Alert, AlertDescription, AlertTitle, Disclosure } from '@meith/ui'
import { Alert, AlertDescription, AlertTitle, Disclosure, PageTitle } from '@meith/ui'

import { InstallForm } from '@/components/install/install-form'
import { InstallRestoreForm } from '@/components/install/restore-form'
Expand Down Expand Up @@ -88,9 +88,7 @@ export default async function InstallPage() {
return (
<main className="mx-auto flex w-full max-w-2xl flex-col gap-8 px-6 py-12">
<header className="flex flex-col gap-2">
<h1 className="font-heading text-2xl font-semibold tracking-tight text-foreground">
{t.t('page.install-this-board')}
</h1>
<PageTitle>{t.t('page.install-this-board')}</PageTitle>
<p className="text-sm text-muted-foreground">{t.t('page.this-page-works-once-when')}</p>
</header>

Expand Down
2 changes: 2 additions & 0 deletions apps/community/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { env } from '@meith/core'
import { currentRequestId } from '@meith/core/logger'
import { localeDirection, SOURCE_LOCALE } from '@meith/i18n'
import { resolveBoardUrl } from '@meith/settings'
import { NavTabsEnhancer } from '@meith/ui/nav-tabs-enhancer'

import { CopyProvider } from '@/components/shell/copy'
import { CrashNoticeProvider } from '@/components/shell/crash-notice'
Expand Down Expand Up @@ -108,6 +109,7 @@ export default async function RootLayout({
<ServiceWorkerRegistrar />
</head>
<body className="font-sans antialiased">
<NavTabsEnhancer />
<DemoBanner />
<CrashNoticeProvider
notice={notice}
Expand Down
4 changes: 2 additions & 2 deletions apps/community/src/components/account/active-sessions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

import { useActionState } from 'react'

import { buttonVariants } from '@meith/ui'
import { buttonVariants, surfaceVariants } from '@meith/ui'

import { EMPTY_STATE } from '@/server/auth-form-state'
import { revokeOtherSessionsAction, revokeSessionAction } from '@/server/session-actions'

import { FormError, PendingButton } from '../auth/form-controls'
import { type Copy, fromCopy } from '../shell/copy'

const CARD = 'flex flex-col gap-4 rounded-lg border border-border bg-card p-5'
const CARD = surfaceVariants({ padded: true })

const ROW =
'flex flex-wrap items-center justify-between gap-3 rounded-md border border-border px-3 py-2'
Expand Down
5 changes: 3 additions & 2 deletions apps/community/src/components/account/avatar-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
import { useActionState } from 'react'

import { AVATAR_BOX } from '@meith/avatars/limits'
import { surfaceVariants } from '@meith/ui'

import { EMPTY_STATE } from '@/server/auth-form-state'
import { removeAvatarAction, saveAvatarAction } from '@/server/usercp-actions'

import { FormError, SubmitButton } from '../auth/form-controls'
import { type Copy, fromCopy } from '../shell/copy'

const CARD = 'flex flex-col gap-3 rounded-lg border border-border bg-card p-4'
const CARD = surfaceVariants({ padded: true })

export function AvatarForm({
currentUrl,
Expand Down Expand Up @@ -86,7 +87,7 @@ export function AvatarForm({

<form action={save} className={CARD} noValidate>
<FormError message={saveState.error} />
<label className="flex flex-col gap-1 text-sm">
<label className="flex min-w-0 flex-col gap-2 text-sm">
<span className="font-medium">{fromCopy(copy, 'accountForm.avatar.choose')}</span>
<input
type="file"
Expand Down
10 changes: 5 additions & 5 deletions apps/community/src/components/account/feed-token.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@

import { useActionState } from 'react'

import { buttonVariants, surfaceVariants } from '@meith/ui'

import { EMPTY_STATE } from '@/server/auth-form-state'
import { regenerateFeedTokenAction, revokeFeedTokenAction } from '@/server/feed-token-actions'

import { FormError, PendingButton } from '../auth/form-controls'
import { type Copy, fromCopy } from '../shell/copy'

const CARD = 'flex flex-col gap-4 rounded-lg border border-border bg-card p-5'
const CARD = surfaceVariants({ padded: true })

const BUTTON =
'inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring'
const BUTTON = buttonVariants({ variant: 'primary', size: 'default' })

const GHOST_BUTTON =
'inline-flex h-9 items-center justify-center rounded-md border border-border bg-background px-4 text-sm font-medium transition-opacity hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring'
const GHOST_BUTTON = buttonVariants({ variant: 'outline', size: 'default' })

const REVEAL_CODE = 'block overflow-x-auto rounded-sm bg-card px-2 py-1 font-mono text-xs'

Expand Down
10 changes: 4 additions & 6 deletions apps/community/src/components/account/notification-forms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { useActionState } from 'react'

import { textLinkVariants } from '@meith/ui'
import { buttonVariants, controlVariants, textLinkVariants } from '@meith/ui'

import { EMPTY_STATE } from '@/server/auth-form-state'
import {
Expand All @@ -16,8 +16,7 @@ import { saveBoardDigestCadenceAction } from '@/server/usercp-actions'
import { FormError, PendingButton } from '../auth/form-controls'
import { type Copy, fromCopy } from '../shell/copy'

const BUTTON =
'inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring'
const BUTTON = buttonVariants({ variant: 'primary', size: 'default' })

const LINK_BUTTON = `${textLinkVariants({ size: 'sm' })} focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring`

Expand Down Expand Up @@ -203,8 +202,7 @@ export function AnnouncementsOptInForm({ optedIn, copy }: { optedIn: boolean; co
)
}

const FIELD =
'w-full max-w-xs rounded-md border border-input bg-card px-3 py-2 text-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring'
const FIELD = controlVariants()

export function BoardDigestCadenceForm({ cadence, copy }: { cadence: string; copy: Copy }) {
const [state, action] = useActionState(saveBoardDigestCadenceAction, EMPTY_STATE)
Expand All @@ -216,7 +214,7 @@ export function BoardDigestCadenceForm({ cadence, copy }: { cadence: string; cop
>
<FormError message={state.error} />

<label className="flex flex-col gap-1 text-sm">
<label className="flex min-w-0 flex-col gap-2 text-sm">
<span className="font-medium">{fromCopy(copy, 'accountForm.boardDigest.legend')}</span>
<span className="text-xs text-muted-foreground">
{fromCopy(copy, 'accountForm.boardDigest.description')}
Expand Down
5 changes: 3 additions & 2 deletions apps/community/src/components/account/push-device-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

import { useCallback, useEffect, useState } from 'react'

import { buttonVariants } from '@meith/ui'

import { subscribeToPushAction, unsubscribeFromPushAction } from '@/server/push-actions'

import { FormError, FormNotice } from '../auth/form-controls'
import { type Copy, fromCopy } from '../shell/copy'

const BUTTON =
'inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring disabled:opacity-60'
const BUTTON = buttonVariants({ variant: 'primary', size: 'default' })

type Status = 'checking' | 'unsupported' | 'blocked' | 'off' | 'on' | 'working'

Expand Down
9 changes: 5 additions & 4 deletions apps/community/src/components/account/reputation-forms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@

import { useActionState } from 'react'

import { controlVariants, surfaceVariants } from '@meith/ui'

import { EMPTY_STATE } from '@/server/auth-form-state'
import { rateMemberAction, withdrawRatingAction } from '@/server/reputation-actions'

import { FormError, PendingButton } from '../auth/form-controls'
import { type Copy, fromCopy } from '../shell/copy'

const FIELD =
'w-full rounded-md border border-input bg-card px-3 py-2 text-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring'
const FIELD = controlVariants()

const CARD = 'flex flex-col gap-3 rounded-lg border border-border bg-card p-5'
const CARD = surfaceVariants({ padded: true })

const CHOICE =
'inline-flex h-9 items-center justify-center rounded-md border border-border px-4 text-sm font-medium hover:bg-muted focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring'
Expand Down Expand Up @@ -52,7 +53,7 @@ export function RateMemberForm({
: fromCopy(copy, 'accountForm.rate.changeTitle')}
</h2>

<label className="flex flex-col gap-1 text-sm">
<label className="flex min-w-0 flex-col gap-2 text-sm">
<span className="font-medium">
{commentRequired
? fromCopy(copy, 'accountForm.rate.why')
Expand Down
4 changes: 2 additions & 2 deletions apps/community/src/components/account/sign-in-methods.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

import { useActionState } from 'react'

import { buttonVariants } from '@meith/ui'
import { buttonVariants, surfaceVariants } from '@meith/ui'

import { EMPTY_STATE } from '@/server/auth-form-state'
import { removePasskeyAction, unlinkIdentityAction } from '@/server/federation-actions'

import { FormError, PendingButton } from '../auth/form-controls'
import { type Copy, fromCopy } from '../shell/copy'

const CARD = 'flex flex-col gap-4 rounded-lg border border-border bg-card p-5'
const CARD = surfaceVariants({ padded: true })

const ROW =
'flex flex-wrap items-center justify-between gap-3 rounded-md border border-border px-3 py-2'
Expand Down
14 changes: 6 additions & 8 deletions apps/community/src/components/account/subscription-forms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import { useActionState, useEffect, useState } from 'react'

import { buttonVariants, controlVariants } from '@meith/ui'

import { EMPTY_STATE } from '@/server/auth-form-state'
import {
subscribeAction,
Expand All @@ -13,17 +15,13 @@ import { FormError, PendingButton } from '../auth/form-controls'
import { ProgressiveMarker } from '../content/progressive-marker'
import { type Copy, fromCopy } from '../shell/copy'

const BUTTON =
'inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring'
const BUTTON = buttonVariants({ variant: 'primary', size: 'default' })

const QUIET_BUTTON =
'inline-flex h-9 items-center justify-center rounded-md border border-border px-3 text-sm font-medium transition-colors hover:bg-muted focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring'
const QUIET_BUTTON = buttonVariants({ variant: 'outline', size: 'default' })

const GHOST_BUTTON =
'inline-flex h-9 items-center justify-center rounded-md px-3 text-sm font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring'
const GHOST_BUTTON = buttonVariants({ variant: 'ghost', size: 'default' })

const FIELD =
'rounded-md border border-border bg-background px-2 py-1 text-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring'
const FIELD = controlVariants({ size: 'sm', className: 'w-auto max-w-full' })

export interface ModeOption {
readonly value: string
Expand Down
7 changes: 3 additions & 4 deletions apps/community/src/components/account/two-factor-forms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { useActionState } from 'react'

import { buttonVariants } from '@meith/ui'
import { buttonVariants, surfaceVariants } from '@meith/ui'

import { EMPTY_STATE, type FormState } from '@/server/auth-form-state'
import {
Expand All @@ -18,10 +18,9 @@ import { Field, FormError, PendingButton } from '../auth/form-controls'
import { OtpField, otpRecoveryFromCopy } from '../auth/otp-field'
import { type Copy, fromCopy } from '../shell/copy'

const CARD = 'flex flex-col gap-4 rounded-lg border border-border bg-card p-5'
const CARD = surfaceVariants({ padded: true })

const BUTTON =
'inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring'
const BUTTON = buttonVariants({ variant: 'primary', size: 'default' })

function RecoveryCodes({ state, copy }: { readonly state: FormState; readonly copy: Copy }) {
const codes = state.values?.[RECOVERY_CODES_FIELD]
Expand Down
Loading