Upgrade to Tailwind 4
This commit is contained in:
parent
d17dc81720
commit
7ab319142f
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -9,6 +9,7 @@
|
|||||||
"camelcase",
|
"camelcase",
|
||||||
"cloudflarestorage",
|
"cloudflarestorage",
|
||||||
"cmdk",
|
"cmdk",
|
||||||
|
"Consolas",
|
||||||
"CredentialsSignin",
|
"CredentialsSignin",
|
||||||
"datetime",
|
"datetime",
|
||||||
"Eterna",
|
"Eterna",
|
||||||
|
|||||||
@ -48,6 +48,7 @@
|
|||||||
"@next/bundle-analyzer": "15.1.6",
|
"@next/bundle-analyzer": "15.1.6",
|
||||||
"@tailwindcss/container-queries": "^0.1.1",
|
"@tailwindcss/container-queries": "^0.1.1",
|
||||||
"@tailwindcss/forms": "^0.5.10",
|
"@tailwindcss/forms": "^0.5.10",
|
||||||
|
"@tailwindcss/postcss": "^4.0.5",
|
||||||
"@testing-library/dom": "^10.4.0",
|
"@testing-library/dom": "^10.4.0",
|
||||||
"@testing-library/jest-dom": "^6.6.3",
|
"@testing-library/jest-dom": "^6.6.3",
|
||||||
"@testing-library/react": "^16.2.0",
|
"@testing-library/react": "^16.2.0",
|
||||||
@ -57,7 +58,6 @@
|
|||||||
"@types/react": "19.0.8",
|
"@types/react": "19.0.8",
|
||||||
"@types/react-dom": "19.0.3",
|
"@types/react-dom": "19.0.3",
|
||||||
"@types/sanitize-html": "^2.13.0",
|
"@types/sanitize-html": "^2.13.0",
|
||||||
"autoprefixer": "10.4.20",
|
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cross-fetch": "^4.1.0",
|
"cross-fetch": "^4.1.0",
|
||||||
"eslint": "9.20.0",
|
"eslint": "9.20.0",
|
||||||
@ -65,7 +65,7 @@
|
|||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"jest-environment-jsdom": "^29.7.0",
|
"jest-environment-jsdom": "^29.7.0",
|
||||||
"postcss": "8.5.1",
|
"postcss": "8.5.1",
|
||||||
"tailwindcss": "3.4.17",
|
"tailwindcss": "4.0.5",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"typescript": "5.7.3"
|
"typescript": "5.7.3"
|
||||||
}
|
}
|
||||||
|
|||||||
837
pnpm-lock.yaml
generated
837
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: {
|
plugins: {
|
||||||
tailwindcss: {},
|
'@tailwindcss/postcss': {},
|
||||||
autoprefixer: {},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -105,7 +105,7 @@ export default function AdminAddAllUploads({
|
|||||||
<div className="w-full space-y-4 py-1">
|
<div className="w-full space-y-4 py-1">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
'flex-grow',
|
'grow',
|
||||||
tagErrorMessage ? 'text-error' : 'text-main',
|
tagErrorMessage ? 'text-error' : 'text-main',
|
||||||
)}>
|
)}>
|
||||||
{showTags
|
{showTags
|
||||||
|
|||||||
@ -156,11 +156,11 @@ export default function AdminBatchEditPanelClient({
|
|||||||
color="gray"
|
color="gray"
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'min-h-[3.5rem]',
|
'min-h-[3.5rem]',
|
||||||
'backdrop-blur-lg !border-transparent',
|
'backdrop-blur-lg border-transparent!',
|
||||||
'!text-gray-900 dark:!text-gray-100',
|
'text-gray-900! dark:text-gray-100!',
|
||||||
'!bg-gray-100/90 dark:!bg-gray-900/70',
|
'bg-gray-100/90! dark:bg-gray-900/70!',
|
||||||
// Override default <Note /> content spacing
|
// Override default <Note /> content spacing
|
||||||
'[&>*>*:first-child]:gap-1.5 [&>*>*:first-child]:sm:gap-2.5',
|
'[&>*>*:first-child]:gap-1.5 sm:[&>*>*:first-child]:gap-2.5',
|
||||||
)}
|
)}
|
||||||
padding={isInTagMode ? 'tight-cta-right-left' : 'tight-cta-right'}
|
padding={isInTagMode ? 'tight-cta-right-left' : 'tight-cta-right'}
|
||||||
cta={<div className="flex items-center gap-1.5 sm:gap-2.5">
|
cta={<div className="flex items-center gap-1.5 sm:gap-2.5">
|
||||||
|
|||||||
@ -67,7 +67,7 @@ export default function AdminNavClient({
|
|||||||
)}>
|
)}>
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
'flex gap-0.5 md:gap-1.5 -mx-1',
|
'flex gap-0.5 md:gap-1.5 -mx-1',
|
||||||
'flex-grow overflow-x-auto',
|
'grow overflow-x-auto',
|
||||||
)}>
|
)}>
|
||||||
{items.map(({ label, href, count }) =>
|
{items.map(({ label, href, count }) =>
|
||||||
<LinkWithStatus
|
<LinkWithStatus
|
||||||
@ -101,7 +101,7 @@ export default function AdminNavClient({
|
|||||||
</LinkWithLoader>
|
</LinkWithLoader>
|
||||||
</div>
|
</div>
|
||||||
{shouldShowBanner &&
|
{shouldShowBanner &&
|
||||||
<Note icon={<FaRegClock className="flex-shrink-0" />}>
|
<Note icon={<FaRegClock className="shrink-0" />}>
|
||||||
Photo updates detected—they may take several minutes to show up
|
Photo updates detected—they may take several minutes to show up
|
||||||
for visitors
|
for visitors
|
||||||
</Note>}
|
</Note>}
|
||||||
|
|||||||
@ -42,7 +42,7 @@ export default function AdminPhotosClient({
|
|||||||
return (
|
return (
|
||||||
<SiteGrid
|
<SiteGrid
|
||||||
contentMain={
|
contentMain={
|
||||||
<div className="space-y-4">
|
<div>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className="grow min-w-0">
|
<div className="grow min-w-0">
|
||||||
<PhotoUpload
|
<PhotoUpload
|
||||||
|
|||||||
@ -79,7 +79,7 @@ export default function AdminPhotosTable({
|
|||||||
</span>
|
</span>
|
||||||
{photo.priorityOrder !== null &&
|
{photo.priorityOrder !== null &&
|
||||||
<span className={clsx(
|
<span className={clsx(
|
||||||
'text-xs leading-none px-1.5 py-1 rounded-sm',
|
'text-xs leading-none px-1.5 py-1 rounded-xs',
|
||||||
'dark:text-gray-300',
|
'dark:text-gray-300',
|
||||||
'bg-gray-100 dark:bg-gray-800',
|
'bg-gray-100 dark:bg-gray-800',
|
||||||
)}>
|
)}>
|
||||||
|
|||||||
@ -35,6 +35,6 @@ export default function AdminTagBadge({
|
|||||||
return (
|
return (
|
||||||
hideBadge
|
hideBadge
|
||||||
? renderBadgeContent()
|
? renderBadgeContent()
|
||||||
: <Badge className="!py-[3px]">{renderBadgeContent()}</Badge>
|
: <Badge className="py-[3px]!">{renderBadgeContent()}</Badge>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -14,11 +14,11 @@ export default function DeleteButton({
|
|||||||
icon={<BiTrash size={16} />}
|
icon={<BiTrash size={16} />}
|
||||||
spinnerColor="text"
|
spinnerColor="text"
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'!text-red-500 dark:!text-red-600',
|
'text-red-500! dark:text-red-600!',
|
||||||
'active:!bg-red-100/50 active:dark:!bg-red-950/50',
|
'active:bg-red-100/50! dark:active:bg-red-950/50!',
|
||||||
'disabled:!bg-red-100/50 disabled:dark:!bg-red-950/50',
|
'disabled:bg-red-100/50! dark:disabled:bg-red-950/50!',
|
||||||
'!border-red-200 hover:!border-red-300',
|
'border-red-200! hover:border-red-300!',
|
||||||
'dark:!border-red-900/75 dark:hover:!border-red-900',
|
'dark:border-red-900/75! dark:hover:border-red-900!',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -35,11 +35,11 @@ export default function DeleteFormButton (
|
|||||||
spinnerColor="text"
|
spinnerColor="text"
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
'!text-red-500 dark:!text-red-600',
|
'text-red-500! dark:text-red-600!',
|
||||||
'active:!bg-red-100/50 active:dark:!bg-red-950/50',
|
'active:bg-red-100/50! dark:active:bg-red-950/50!',
|
||||||
'disabled:!bg-red-100/50 disabled:dark:!bg-red-950/50',
|
'disabled:bg-red-100/50! dark:disabled:bg-red-950/50!',
|
||||||
'!border-red-200 hover:!border-red-300',
|
'border-red-200! hover:border-red-300!',
|
||||||
'dark:!border-red-900/75 dark:hover:!border-red-900',
|
'dark:border-red-900/75! dark:hover:border-red-900!',
|
||||||
)}
|
)}
|
||||||
onFormSubmit={onFormSubmit}
|
onFormSubmit={onFormSubmit}
|
||||||
/>;
|
/>;
|
||||||
|
|||||||
@ -49,7 +49,7 @@ export default function GitHubForkStatusBadgeClient({
|
|||||||
'border transition-colors',
|
'border transition-colors',
|
||||||
'select-none',
|
'select-none',
|
||||||
'pl-[4.5px] pr-2.5 py-[3px]',
|
'pl-[4.5px] pr-2.5 py-[3px]',
|
||||||
'rounded-full shadow-sm',
|
'rounded-full shadow-xs',
|
||||||
classNameForStyle(),
|
classNameForStyle(),
|
||||||
)}>
|
)}>
|
||||||
{!label
|
{!label
|
||||||
|
|||||||
@ -43,7 +43,7 @@ export default function ComponentsPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
'flex gap-1',
|
'flex gap-1',
|
||||||
'[&>*]:inline-flex [&>*]:gap-1 [&_input]:-translate-y-0.5',
|
'*:inline-flex *:gap-1 [&_input]:-translate-y-0.5',
|
||||||
)}>
|
)}>
|
||||||
<FieldSetWithStatus
|
<FieldSetWithStatus
|
||||||
id="grid"
|
id="grid"
|
||||||
@ -62,7 +62,7 @@ export default function ComponentsPage() {
|
|||||||
</div>
|
</div>
|
||||||
</h1>
|
</h1>
|
||||||
<DivDebugBaselineGrid className="flex gap-8">
|
<DivDebugBaselineGrid className="flex gap-8">
|
||||||
<div className="[&>*]:flex">
|
<div className="*:flex">
|
||||||
<div>
|
<div>
|
||||||
<LabeledIcon
|
<LabeledIcon
|
||||||
icon={<FaCamera size={12} />}
|
icon={<FaCamera size={12} />}
|
||||||
@ -229,8 +229,8 @@ export default function ComponentsPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
debugComponents && '[&>*]:bg-gray-300 [&>*]:dark:bg-gray-700',
|
debugComponents && '*:bg-gray-300 dark:*:bg-gray-700',
|
||||||
'[&>*]:flex',
|
'*:flex',
|
||||||
)}>
|
)}>
|
||||||
{DEBUG_LINES.map((_, i) =>
|
{DEBUG_LINES.map((_, i) =>
|
||||||
<div key={i}>
|
<div key={i}>
|
||||||
@ -239,8 +239,8 @@ export default function ComponentsPage() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
debugComponents && '[&>*]:bg-gray-300 [&>*]:dark:bg-gray-700',
|
debugComponents && '*:bg-gray-300 dark:*:bg-gray-700',
|
||||||
'[&>*]:flex',
|
'*:flex',
|
||||||
)}>
|
)}>
|
||||||
{DEBUG_LINES.map((_, i) =>
|
{DEBUG_LINES.map((_, i) =>
|
||||||
<PhotoCamera
|
<PhotoCamera
|
||||||
|
|||||||
@ -39,7 +39,7 @@ export default function FilmPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
'absolute top-0 left-[-2px] right-0 bottom-0',
|
'absolute top-0 left-[-2px] right-0 bottom-0',
|
||||||
'bg-gradient-to-t',
|
'bg-linear-to-t',
|
||||||
'from-white to-[rgba(255,255,255,0.5)]',
|
'from-white to-[rgba(255,255,255,0.5)]',
|
||||||
'dark:from-black dark:to-[rgba(0,0,0,0.5)]',
|
'dark:from-black dark:to-[rgba(0,0,0,0.5)]',
|
||||||
)} />
|
)} />
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { Analytics } from '@vercel/analytics/react';
|
import { Analytics } from '@vercel/analytics/react';
|
||||||
import { SpeedInsights } from '@vercel/speed-insights/react';
|
import { SpeedInsights } from '@vercel/speed-insights/react';
|
||||||
import { clsx } from 'clsx/lite';
|
import { clsx } from 'clsx/lite';
|
||||||
import { IBM_Plex_Mono } from 'next/font/google';
|
|
||||||
import {
|
import {
|
||||||
BASE_URL,
|
BASE_URL,
|
||||||
DEFAULT_THEME,
|
DEFAULT_THEME,
|
||||||
@ -25,12 +24,6 @@ import '../site/globals.css';
|
|||||||
import '../site/sonner.css';
|
import '../site/sonner.css';
|
||||||
import '../site/viewerjs.css';
|
import '../site/viewerjs.css';
|
||||||
|
|
||||||
const ibmPlexMono = IBM_Plex_Mono({
|
|
||||||
subsets: ['latin'],
|
|
||||||
weight: ['400', '500', '700'],
|
|
||||||
variable: '--font-ibm-plex-mono',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: SITE_TITLE,
|
title: SITE_TITLE,
|
||||||
description: SITE_DESCRIPTION,
|
description: SITE_DESCRIPTION,
|
||||||
@ -79,7 +72,7 @@ export default function RootLayout({
|
|||||||
// Suppress hydration errors due to next-themes behavior
|
// Suppress hydration errors due to next-themes behavior
|
||||||
suppressHydrationWarning
|
suppressHydrationWarning
|
||||||
>
|
>
|
||||||
<body className={ibmPlexMono.variable}>
|
<body>
|
||||||
<AppStateProvider>
|
<AppStateProvider>
|
||||||
<SwrConfigClient>
|
<SwrConfigClient>
|
||||||
<ThemeProvider
|
<ThemeProvider
|
||||||
|
|||||||
@ -35,7 +35,7 @@ function AdminChildPage({
|
|||||||
)}>
|
)}>
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
'flex items-center gap-x-1.5 sm:gap-x-3 gap-y-1',
|
'flex items-center gap-x-1.5 sm:gap-x-3 gap-y-1',
|
||||||
'flex-grow',
|
'grow',
|
||||||
breadcrumbEllipsis ? 'min-w-0' : 'flex-wrap',
|
breadcrumbEllipsis ? 'min-w-0' : 'flex-wrap',
|
||||||
)}>
|
)}>
|
||||||
{backPath &&
|
{backPath &&
|
||||||
|
|||||||
@ -53,7 +53,7 @@ export default function Badge({
|
|||||||
<span className={clsx(
|
<span className={clsx(
|
||||||
'max-w-full inline-flex',
|
'max-w-full inline-flex',
|
||||||
// Truncate 1 + 2 levels deep
|
// Truncate 1 + 2 levels deep
|
||||||
'truncate [&>*]:truncate',
|
'truncate *:truncate',
|
||||||
dimContent && 'opacity-50',
|
dimContent && 'opacity-50',
|
||||||
)}>
|
)}>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@ -33,7 +33,7 @@ export default function ChecklistRow({
|
|||||||
: optional ? 'optional' : 'missing'}
|
: optional ? 'optional' : 'missing'}
|
||||||
loading={isPending}
|
loading={isPending}
|
||||||
/>
|
/>
|
||||||
<div className="flex flex-col min-w-0 flex-grow">
|
<div className="flex flex-col min-w-0 grow">
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
'flex flex-wrap items-center gap-2 pb-0.5',
|
'flex flex-wrap items-center gap-2 pb-0.5',
|
||||||
'font-bold dark:text-gray-300',
|
'font-bold dark:text-gray-300',
|
||||||
|
|||||||
@ -79,7 +79,7 @@ export default function ImageInput({
|
|||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
id={INPUT_ID}
|
id={INPUT_ID}
|
||||||
type="file"
|
type="file"
|
||||||
className="!hidden"
|
className="hidden!"
|
||||||
accept={ACCEPTED_PHOTO_FILE_TYPES.join(',')}
|
accept={ACCEPTED_PHOTO_FILE_TYPES.join(',')}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
multiple
|
multiple
|
||||||
|
|||||||
@ -60,7 +60,7 @@ export default function OGTile({
|
|||||||
className={clsx(
|
className={clsx(
|
||||||
'group',
|
'group',
|
||||||
'block w-full rounded-md overflow-hidden',
|
'block w-full rounded-md overflow-hidden',
|
||||||
'border shadow-sm',
|
'border shadow-xs',
|
||||||
'border-gray-200 dark:border-gray-800',
|
'border-gray-200 dark:border-gray-800',
|
||||||
riseOnHover && 'hover:-translate-y-1.5 transition-transform',
|
riseOnHover && 'hover:-translate-y-1.5 transition-transform',
|
||||||
)}
|
)}
|
||||||
@ -78,7 +78,7 @@ export default function OGTile({
|
|||||||
</div>}
|
</div>}
|
||||||
{loadingState === 'failed' &&
|
{loadingState === 'failed' &&
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
'absolute top-0 left-0 right-0 bottom-0 z-[11]',
|
'absolute top-0 left-0 right-0 bottom-0 z-11',
|
||||||
'flex items-center justify-center',
|
'flex items-center justify-center',
|
||||||
'text-red-400',
|
'text-red-400',
|
||||||
)}>
|
)}>
|
||||||
@ -121,8 +121,8 @@ export default function OGTile({
|
|||||||
'h-full flex flex-col gap-0.5 p-3',
|
'h-full flex flex-col gap-0.5 p-3',
|
||||||
'font-sans leading-tight',
|
'font-sans leading-tight',
|
||||||
'bg-gray-50 dark:bg-gray-900/50',
|
'bg-gray-50 dark:bg-gray-900/50',
|
||||||
'group-active:bg-gray-50 group-active:dark:bg-gray-900/50',
|
'group-active:bg-gray-50 dark:group-active:bg-gray-900/50',
|
||||||
'group-hover:bg-gray-100 group-hover:dark:bg-gray-900/70',
|
'group-hover:bg-gray-100 dark:group-hover:bg-gray-900/70',
|
||||||
'border-t border-gray-200 dark:border-gray-800',
|
'border-t border-gray-200 dark:border-gray-800',
|
||||||
)}>
|
)}>
|
||||||
<div className="text-gray-800 dark:text-white font-medium">
|
<div className="text-gray-800 dark:text-white font-medium">
|
||||||
|
|||||||
@ -17,7 +17,7 @@ export default function SelectTileOverlay({
|
|||||||
return (
|
return (
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
'absolute w-full h-full cursor-pointer',
|
'absolute w-full h-full cursor-pointer',
|
||||||
'active:bg-gray-950/40 active:dark:bg-gray-950/60',
|
'active:bg-gray-950/40 dark:active:bg-gray-950/60',
|
||||||
isPerformingSelectEdit && 'pointer-events-none',
|
isPerformingSelectEdit && 'pointer-events-none',
|
||||||
)}>
|
)}>
|
||||||
{/* Admin Select Border */}
|
{/* Admin Select Border */}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export default function Switcher({
|
|||||||
type === 'regular'
|
type === 'regular'
|
||||||
? 'border-gray-300 dark:border-gray-800'
|
? 'border-gray-300 dark:border-gray-800'
|
||||||
: 'border-transparent',
|
: 'border-transparent',
|
||||||
type === 'regular' && 'shadow-sm',
|
type === 'regular' && 'shadow-xs',
|
||||||
)}>
|
)}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -33,7 +33,7 @@ export default function SwitcherItem({
|
|||||||
? 'text-black dark:text-white'
|
? 'text-black dark:text-white'
|
||||||
: 'text-gray-400 dark:text-gray-600',
|
: 'text-gray-400 dark:text-gray-600',
|
||||||
active
|
active
|
||||||
? 'hover:text-black hover:dark:text-white'
|
? 'hover:text-black dark:hover:text-white'
|
||||||
: 'hover:text-gray-700 dark:hover:text-gray-400',
|
: 'hover:text-gray-700 dark:hover:text-gray-400',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -225,7 +225,7 @@ export default function TagInput({
|
|||||||
aria-controls={ARIA_ID_TAG_CONTROL}
|
aria-controls={ARIA_ID_TAG_CONTROL}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
'w-full control !px-2 !py-2',
|
'w-full control px-2! py-2!',
|
||||||
'outline-1 outline-blue-600',
|
'outline-1 outline-blue-600',
|
||||||
'group-focus-within:outline group-active:outline',
|
'group-focus-within:outline group-active:outline',
|
||||||
'inline-flex flex-wrap items-center gap-2',
|
'inline-flex flex-wrap items-center gap-2',
|
||||||
@ -247,7 +247,7 @@ export default function TagInput({
|
|||||||
'px-1.5 py-0.5',
|
'px-1.5 py-0.5',
|
||||||
'bg-gray-200/60 dark:bg-gray-800',
|
'bg-gray-200/60 dark:bg-gray-800',
|
||||||
'active:bg-gray-200 dark:active:bg-gray-900',
|
'active:bg-gray-200 dark:active:bg-gray-900',
|
||||||
'rounded-sm',
|
'rounded-xs',
|
||||||
)}
|
)}
|
||||||
onClick={() => removeOption(option)}
|
onClick={() => removeOption(option)}
|
||||||
>
|
>
|
||||||
@ -258,8 +258,8 @@ export default function TagInput({
|
|||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
type="text"
|
type="text"
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'grow !min-w-0 !p-0 -my-2 text-xl',
|
'grow min-w-0! p-0! -my-2 text-xl',
|
||||||
'!border-none !ring-transparent',
|
'border-none! ring-transparent!',
|
||||||
'placeholder:text-dim placeholder:text-[14px]',
|
'placeholder:text-dim placeholder:text-[14px]',
|
||||||
'placeholder:translate-x-[2px]',
|
'placeholder:translate-x-[2px]',
|
||||||
'placeholder:translate-y-[-1.5px]',
|
'placeholder:translate-y-[-1.5px]',
|
||||||
@ -287,7 +287,7 @@ export default function TagInput({
|
|||||||
role="listbox"
|
role="listbox"
|
||||||
ref={optionsRef}
|
ref={optionsRef}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'control absolute top-0 mt-3 w-full z-10 !px-1.5 !py-1.5',
|
'control absolute top-0 mt-3 w-full z-10 px-1.5! py-1.5!',
|
||||||
'max-h-[8rem] overflow-y-auto',
|
'max-h-[8rem] overflow-y-auto',
|
||||||
'flex flex-col gap-y-1',
|
'flex flex-col gap-y-1',
|
||||||
'text-xl shadow-lg dark:shadow-xl',
|
'text-xl shadow-lg dark:shadow-xl',
|
||||||
@ -310,13 +310,13 @@ export default function TagInput({
|
|||||||
'text-base',
|
'text-base',
|
||||||
'group flex items-center gap-1',
|
'group flex items-center gap-1',
|
||||||
'cursor-pointer select-none',
|
'cursor-pointer select-none',
|
||||||
'px-1.5 py-1 rounded-sm',
|
'px-1.5 py-1 rounded-xs',
|
||||||
'hover:bg-gray-100 dark:hover:bg-gray-800',
|
'hover:bg-gray-100 dark:hover:bg-gray-800',
|
||||||
'active:bg-gray-50 dark:active:bg-gray-900',
|
'active:bg-gray-50 dark:active:bg-gray-900',
|
||||||
'focus:bg-gray-100 dark:focus:bg-gray-800',
|
'focus:bg-gray-100 dark:focus:bg-gray-800',
|
||||||
index === 0 && selectedOptionIndex === undefined &&
|
index === 0 && selectedOptionIndex === undefined &&
|
||||||
'bg-gray-100 dark:bg-gray-800',
|
'bg-gray-100 dark:bg-gray-800',
|
||||||
'outline-none',
|
'outline-hidden',
|
||||||
)}
|
)}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
addOptions([value]);
|
addOptions([value]);
|
||||||
|
|||||||
@ -377,13 +377,13 @@ export default function CommandKClient({
|
|||||||
<Command.Input
|
<Command.Input
|
||||||
onChangeCapture={(e) => setQueryLive(e.currentTarget.value)}
|
onChangeCapture={(e) => setQueryLive(e.currentTarget.value)}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'w-full !min-w-0',
|
'w-full min-w-0!',
|
||||||
'focus:ring-0',
|
'focus:ring-0',
|
||||||
isPlaceholderVisible || isLoading && '!pr-8',
|
isPlaceholderVisible || isLoading && 'pr-8!',
|
||||||
'!border-gray-200 dark:!border-gray-800',
|
'border-gray-200! dark:border-gray-800!',
|
||||||
'focus:border-gray-200 focus:dark:border-gray-800',
|
'focus:border-gray-200 dark:focus:border-gray-800',
|
||||||
'placeholder:text-gray-400/80',
|
'placeholder:text-gray-400/80',
|
||||||
'placeholder:dark:text-gray-700',
|
'dark:placeholder:text-gray-700',
|
||||||
isPending && 'opacity-20',
|
isPending && 'opacity-20',
|
||||||
)}
|
)}
|
||||||
placeholder="Search photos, views, settings ..."
|
placeholder="Search photos, views, settings ..."
|
||||||
|
|||||||
@ -32,13 +32,13 @@ export default function CommandKItem({
|
|||||||
'px-2',
|
'px-2',
|
||||||
accessory ? 'py-2' : 'py-1',
|
accessory ? 'py-2' : 'py-1',
|
||||||
'rounded-md cursor-pointer tracking-wide',
|
'rounded-md cursor-pointer tracking-wide',
|
||||||
'active:!bg-gray-200/75 active:dark:!bg-gray-800/55',
|
'active:bg-gray-200/75! dark:active:bg-gray-800/55!',
|
||||||
...loading
|
...loading
|
||||||
? [
|
? [
|
||||||
'data-[selected=true]:dark:bg-gray-900/50',
|
'dark:data-[selected=true]:bg-gray-900/50',
|
||||||
'data-[selected=true]:bg-gray-100/50',
|
'data-[selected=true]:bg-gray-100/50',
|
||||||
] : [
|
] : [
|
||||||
'data-[selected=true]:dark:bg-gray-900/75',
|
'dark:data-[selected=true]:bg-gray-900/75',
|
||||||
'data-[selected=true]:bg-gray-100',
|
'data-[selected=true]:bg-gray-100',
|
||||||
],
|
],
|
||||||
disabled && 'opacity-15',
|
disabled && 'opacity-15',
|
||||||
|
|||||||
@ -21,9 +21,9 @@ export default function MoreMenu({
|
|||||||
<button
|
<button
|
||||||
className={clsx(
|
className={clsx(
|
||||||
buttonClassName,
|
buttonClassName,
|
||||||
'p-1 min-h-0 border-none shadow-none hover:outline-none',
|
'p-1 min-h-0 border-none shadow-none hover:outline-hidden',
|
||||||
'hover:bg-gray-100 active:bg-gray-100',
|
'hover:bg-gray-100 active:bg-gray-100',
|
||||||
'hover:dark:bg-gray-800/75 active:dark:bg-gray-900',
|
'dark:hover:bg-gray-800/75 dark:active:bg-gray-900',
|
||||||
'text-dim',
|
'text-dim',
|
||||||
)}
|
)}
|
||||||
aria-label={ariaLabel}
|
aria-label={ariaLabel}
|
||||||
|
|||||||
@ -36,9 +36,9 @@ export default function MoreMenuItem({
|
|||||||
className={clsx(
|
className={clsx(
|
||||||
'flex items-center h-8',
|
'flex items-center h-8',
|
||||||
'px-2 py-1.5 rounded-[3px]',
|
'px-2 py-1.5 rounded-[3px]',
|
||||||
'select-none hover:outline-none',
|
'select-none hover:outline-hidden',
|
||||||
'hover:bg-gray-50 active:bg-gray-100',
|
'hover:bg-gray-50 active:bg-gray-100',
|
||||||
'hover:dark:bg-gray-900/75 active:dark:bg-gray-900',
|
'dark:hover:bg-gray-900/75 dark:active:bg-gray-900',
|
||||||
'whitespace-nowrap',
|
'whitespace-nowrap',
|
||||||
isLoading
|
isLoading
|
||||||
? 'cursor-not-allowed opacity-50'
|
? 'cursor-not-allowed opacity-50'
|
||||||
|
|||||||
@ -96,7 +96,7 @@ export default function EntityLink({
|
|||||||
{renderLabel()}
|
{renderLabel()}
|
||||||
</Badge>
|
</Badge>
|
||||||
: <span className={clsx(
|
: <span className={clsx(
|
||||||
truncate && 'inline-flex max-w-full [&>*]:truncate',
|
truncate && 'inline-flex max-w-full *:truncate',
|
||||||
)}>
|
)}>
|
||||||
{renderLabel()}
|
{renderLabel()}
|
||||||
</span>}
|
</span>}
|
||||||
|
|||||||
@ -44,10 +44,11 @@ export default function LoaderButton(props: {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
|
'font-mono',
|
||||||
...(styleAs !== 'button'
|
...(styleAs !== 'button'
|
||||||
? [
|
? [
|
||||||
'link h-4 active:text-medium',
|
'link h-4 active:text-medium',
|
||||||
'disabled:!bg-transparent',
|
'disabled:bg-transparent!',
|
||||||
]
|
]
|
||||||
: ['h-9']
|
: ['h-9']
|
||||||
),
|
),
|
||||||
@ -55,7 +56,7 @@ export default function LoaderButton(props: {
|
|||||||
styleAs === 'link-without-hover' && 'hover:text-main',
|
styleAs === 'link-without-hover' && 'hover:text-main',
|
||||||
'inline-flex items-center gap-2 self-start whitespace-nowrap',
|
'inline-flex items-center gap-2 self-start whitespace-nowrap',
|
||||||
primary && 'primary',
|
primary && 'primary',
|
||||||
hideFocusOutline && 'focus:outline-none',
|
hideFocusOutline && 'focus:outline-hidden',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
disabled={isLoading || disabled}
|
disabled={isLoading || disabled}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export default function MenuSurface({
|
|||||||
className={clsx(
|
className={clsx(
|
||||||
'component-surface',
|
'component-surface',
|
||||||
'px-2 py-1.5 max-w-[14rem]',
|
'px-2 py-1.5 max-w-[14rem]',
|
||||||
'shadow-sm',
|
'shadow-xs',
|
||||||
'text-[0.8rem] leading-tight',
|
'text-[0.8rem] leading-tight',
|
||||||
'text-balance text-center',
|
'text-balance text-center',
|
||||||
className,
|
className,
|
||||||
|
|||||||
@ -36,8 +36,8 @@ export default function PhotoGridPage({
|
|||||||
className={clsx(
|
className={clsx(
|
||||||
'absolute left-0 right-0',
|
'absolute left-0 right-0',
|
||||||
side === 'top'
|
side === 'top'
|
||||||
? 'top-0 bg-gradient-to-b from-white dark:from-black'
|
? 'top-0 bg-linear-to-b from-white dark:from-black'
|
||||||
: 'bottom-0 bg-gradient-to-t from-white dark:from-black',
|
: 'bottom-0 bg-linear-to-t from-white dark:from-black',
|
||||||
'h-6 z-10 pointer-events-none',
|
'h-6 z-10 pointer-events-none',
|
||||||
)}
|
)}
|
||||||
/>;
|
/>;
|
||||||
|
|||||||
@ -131,7 +131,7 @@ export default function PhotoLarge({
|
|||||||
const renderPhotoLink = () =>
|
const renderPhotoLink = () =>
|
||||||
<PhotoLink
|
<PhotoLink
|
||||||
photo={photo}
|
photo={photo}
|
||||||
className="font-bold uppercase flex-grow"
|
className="font-bold uppercase grow"
|
||||||
prefetch={prefetch}
|
prefetch={prefetch}
|
||||||
/>;
|
/>;
|
||||||
|
|
||||||
@ -171,7 +171,7 @@ export default function PhotoLarge({
|
|||||||
</div>;
|
</div>;
|
||||||
|
|
||||||
const largePhotoContainerClassName = clsx(arePhotosMatted &&
|
const largePhotoContainerClassName = clsx(arePhotosMatted &&
|
||||||
'flex items-center justify-center aspect-[3/2] bg-gray-100',
|
'flex items-center justify-center aspect-3/2 bg-gray-100',
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -54,7 +54,7 @@ export default function PhotoMedium({
|
|||||||
{isLoading &&
|
{isLoading &&
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
'absolute inset-0 flex items-center justify-center',
|
'absolute inset-0 flex items-center justify-center',
|
||||||
'text-white bg-black/25 backdrop-blur-sm',
|
'text-white bg-black/25 backdrop-blur-xs',
|
||||||
'animate-fade-in',
|
'animate-fade-in',
|
||||||
'z-10',
|
'z-10',
|
||||||
)}>
|
)}>
|
||||||
|
|||||||
@ -388,7 +388,7 @@ export default function PhotoForm({
|
|||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
'absolute -top-16 -left-2 right-0 bottom-0 -z-10',
|
'absolute -top-16 -left-2 right-0 bottom-0 -z-10',
|
||||||
'pointer-events-none',
|
'pointer-events-none',
|
||||||
'bg-gradient-to-t',
|
'bg-linear-to-t',
|
||||||
'from-white/90 from-60%',
|
'from-white/90 from-60%',
|
||||||
'dark:from-black/90 dark:from-50%',
|
'dark:from-black/90 dark:from-50%',
|
||||||
)} />
|
)} />
|
||||||
|
|||||||
@ -64,7 +64,7 @@ export default function ShareModal({
|
|||||||
'text-2xl leading-snug',
|
'text-2xl leading-snug',
|
||||||
)}>
|
)}>
|
||||||
<TbPhotoShare size={22} className="hidden xs:block" />
|
<TbPhotoShare size={22} className="hidden xs:block" />
|
||||||
<div className="flex-grow">
|
<div className="grow">
|
||||||
{title}
|
{title}
|
||||||
</div>
|
</div>
|
||||||
</div>}
|
</div>}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ export default function Footer() {
|
|||||||
'flex items-center gap-1',
|
'flex items-center gap-1',
|
||||||
'text-dim min-h-10',
|
'text-dim min-h-10',
|
||||||
)}>
|
)}>
|
||||||
<div className="flex gap-x-3 xs:gap-x-4 flex-grow flex-wrap">
|
<div className="flex gap-x-3 xs:gap-x-4 grow flex-wrap">
|
||||||
{isPathAdmin(pathname)
|
{isPathAdmin(pathname)
|
||||||
? <>
|
? <>
|
||||||
{userEmail === undefined &&
|
{userEmail === undefined &&
|
||||||
|
|||||||
@ -76,7 +76,7 @@ export default function Nav({
|
|||||||
showAdmin={isUserSignedIn}
|
showAdmin={isUserSignedIn}
|
||||||
/>
|
/>
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
'flex-grow text-right min-w-0',
|
'grow text-right min-w-0',
|
||||||
'hidden xs:block',
|
'hidden xs:block',
|
||||||
'translate-y-[-1px]',
|
'translate-y-[-1px]',
|
||||||
)}>
|
)}>
|
||||||
|
|||||||
@ -1,6 +1,179 @@
|
|||||||
@tailwind base;
|
@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;700&display=swap");
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
@import 'tailwindcss';
|
||||||
|
|
||||||
|
@custom-variant dark (&:where(.dark, .dark *));
|
||||||
|
|
||||||
|
@theme {
|
||||||
|
--font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
|
||||||
|
|
||||||
|
--breakpoint-xs: 390px;
|
||||||
|
--breakpoint-3xl: 1640px;
|
||||||
|
|
||||||
|
--text-xs: 0.75rem;
|
||||||
|
--text-xs--line-height: 1rem;
|
||||||
|
--text-sm: 0.84375rem;
|
||||||
|
--text-sm--line-height: 1.1875rem;
|
||||||
|
--text-base: 0.875rem;
|
||||||
|
--text-base--line-height: 1.25rem;
|
||||||
|
--text-lg: 1rem;
|
||||||
|
--text-lg--line-height: 1.25rem;
|
||||||
|
--text-xl: 1.125rem;
|
||||||
|
--text-xl--line-height: 1.25rem;
|
||||||
|
--text-2xl: 1.25rem;
|
||||||
|
--text-2xl--line-height: 1.25rem;
|
||||||
|
--text-3xl: 1.5rem;
|
||||||
|
--text-3xl--line-height: 1.5rem;
|
||||||
|
|
||||||
|
--animate-fade-in: fade-in 0.5s linear both running;
|
||||||
|
@keyframes fade-in {
|
||||||
|
0% { opacity: 0; }
|
||||||
|
100% { opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
--animate-fade-in-from-top: fade-in-from-top 0.25s ease-in-out;
|
||||||
|
@keyframes fade-in-from-top {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--animate-fade-in-from-bottom: fade-in-from-bottom 0.25s ease-in-out;
|
||||||
|
@keyframes fade-in-from-bottom {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(10px);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--animate-rotate-pulse: rotate-pulse 0.75s linear infinite normal both running;
|
||||||
|
@keyframes rotate-pulse {
|
||||||
|
0% { transform: rotate(0deg) scale(1) }
|
||||||
|
50% { transform: rotate(180deg) scale(0.8) }
|
||||||
|
100% { transform: rotate(360deg) scale(1) }
|
||||||
|
}
|
||||||
|
|
||||||
|
--animate-hover-drift: hover-drift 8s linear infinite;
|
||||||
|
@keyframes hover-drift {
|
||||||
|
0% { transform: translate(0, 0) }
|
||||||
|
20% { transform: translate(1px, -2px) }
|
||||||
|
40% { transform: translate(1px, 1.5px) }
|
||||||
|
60% { transform: translate(-1px, 2px) }
|
||||||
|
80% { transform: translate(-1.5px, -1.75px) }
|
||||||
|
100% { transform: translate(0, 0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
--animate-hover-wobble: hover-wobble 6s linear infinite normal both running;
|
||||||
|
@keyframes hover-wobble {
|
||||||
|
0% { transform: rotate(0deg) }
|
||||||
|
20% { transform: rotate(3.5deg) }
|
||||||
|
40% { transform: rotate(-2deg) }
|
||||||
|
60% { transform: rotate(2.5deg) }
|
||||||
|
80% { transform: rotate(-2.5deg) }
|
||||||
|
100% { transform: rotate(0deg) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text */
|
||||||
|
@utility text-main {
|
||||||
|
@apply
|
||||||
|
text-gray-900 dark:text-gray-100
|
||||||
|
}
|
||||||
|
@utility text-invert {
|
||||||
|
@apply
|
||||||
|
text-white dark:text-black
|
||||||
|
}
|
||||||
|
@utility text-medium {
|
||||||
|
@apply
|
||||||
|
text-gray-500 dark:text-gray-400
|
||||||
|
}
|
||||||
|
@utility text-dim {
|
||||||
|
@apply
|
||||||
|
text-gray-400 dark:text-gray-500
|
||||||
|
}
|
||||||
|
@utility text-extra-dim {
|
||||||
|
@apply
|
||||||
|
text-gray-400/80 dark:text-gray-400/50
|
||||||
|
}
|
||||||
|
@utility text-extra-extra-dim {
|
||||||
|
@apply
|
||||||
|
text-gray-200 dark:text-gray-800
|
||||||
|
}
|
||||||
|
@utility text-icon {
|
||||||
|
@apply
|
||||||
|
text-gray-800 dark:text-gray-200
|
||||||
|
}
|
||||||
|
@utility text-error {
|
||||||
|
@apply
|
||||||
|
text-red-500 dark:text-red-400
|
||||||
|
}
|
||||||
|
/* Border */
|
||||||
|
@utility border-main {
|
||||||
|
@apply border-gray-200 dark:border-gray-700
|
||||||
|
}
|
||||||
|
@utility border-subtle {
|
||||||
|
@apply
|
||||||
|
border border-gray-200 dark:border-gray-800
|
||||||
|
}
|
||||||
|
/* Background */
|
||||||
|
@utility bg-main {
|
||||||
|
@apply
|
||||||
|
bg-white dark:bg-black
|
||||||
|
}
|
||||||
|
@utility bg-dim {
|
||||||
|
@apply
|
||||||
|
bg-gray-100 dark:bg-gray-900/75
|
||||||
|
}
|
||||||
|
@utility bg-content {
|
||||||
|
@apply
|
||||||
|
bg-white border-gray-200
|
||||||
|
dark:bg-black dark:border-gray-800
|
||||||
|
}
|
||||||
|
@utility bg-invert {
|
||||||
|
@apply
|
||||||
|
bg-gray-900 dark:bg-gray-100
|
||||||
|
}
|
||||||
|
/* Baseline Grid */
|
||||||
|
@utility space-y-baseline {
|
||||||
|
@apply
|
||||||
|
space-y-[1.1875rem] md:space-y-[1.25rem]
|
||||||
|
}
|
||||||
|
@utility gap-y-baseline {
|
||||||
|
@apply
|
||||||
|
gap-y-[1.1875rem] md:gap-y-[1.25rem]
|
||||||
|
}
|
||||||
|
@utility gap-baseline {
|
||||||
|
@apply
|
||||||
|
gap-[1.1875rem] md:gap-[1.25rem]
|
||||||
|
}
|
||||||
|
@utility h-baseline {
|
||||||
|
@apply
|
||||||
|
h-[1.1875rem] md:h-[1.25rem]
|
||||||
|
}
|
||||||
|
@utility max-h-baseline {
|
||||||
|
@apply
|
||||||
|
max-h-[1.1875rem] md:max-h-[1.25rem]
|
||||||
|
}
|
||||||
|
@utility -mt-baseline {
|
||||||
|
@apply
|
||||||
|
-mt-[1.1875rem] md:-mt-[1.25rem]
|
||||||
|
}
|
||||||
|
@utility bg-baseline-grid {
|
||||||
|
@apply
|
||||||
|
bg-[repeating-linear-gradient(to_bottom,#eee,#eee_1px,transparent_1px,transparent_1.1875rem)]
|
||||||
|
md:bg-[repeating-linear-gradient(to_bottom,#eee,#eee_1px,transparent_1px,transparent_1.25rem)]
|
||||||
|
dark:bg-[repeating-linear-gradient(to_bottom,#222,#222_1px,transparent_1px,transparent_1.1875rem)]
|
||||||
|
dark:md:bg-[repeating-linear-gradient(to_bottom,#222,#222_1px,transparent_1px,transparent_1.25rem)]
|
||||||
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
/* Core */
|
/* Core */
|
||||||
@ -56,7 +229,7 @@
|
|||||||
file:border-solid file:border
|
file:border-solid file:border
|
||||||
file:border-gray-200 dark:file:border-gray-700
|
file:border-gray-200 dark:file:border-gray-700
|
||||||
file:cursor-pointer
|
file:cursor-pointer
|
||||||
file:shadow-sm
|
file:shadow-xs
|
||||||
file:active:bg-gray-100
|
file:active:bg-gray-100
|
||||||
file:disabled:bg-gray-100
|
file:disabled:bg-gray-100
|
||||||
file:hover:border-gray-300 file:dark:hover:border-gray-600
|
file:hover:border-gray-300 file:dark:hover:border-gray-600
|
||||||
@ -80,7 +253,7 @@
|
|||||||
inline-flex gap-2 items-center
|
inline-flex gap-2 items-center
|
||||||
px-3
|
px-3
|
||||||
text-base
|
text-base
|
||||||
shadow-sm
|
shadow-xs
|
||||||
active:bg-gray-100 dark:active:bg-gray-900
|
active:bg-gray-100 dark:active:bg-gray-900
|
||||||
hover:border-gray-300 dark:hover:border-gray-600
|
hover:border-gray-300 dark:hover:border-gray-600
|
||||||
disabled:cursor-not-allowed
|
disabled:cursor-not-allowed
|
||||||
@ -127,95 +300,4 @@
|
|||||||
bg-content border border-main
|
bg-content border border-main
|
||||||
rounded-lg
|
rounded-lg
|
||||||
}
|
}
|
||||||
/* Utilities: Text */
|
|
||||||
.text-main {
|
|
||||||
@apply
|
|
||||||
text-gray-900 dark:text-gray-100
|
|
||||||
}
|
|
||||||
.text-invert {
|
|
||||||
@apply
|
|
||||||
text-white dark:text-black
|
|
||||||
}
|
|
||||||
.text-medium {
|
|
||||||
@apply
|
|
||||||
text-gray-500 dark:text-gray-400
|
|
||||||
}
|
|
||||||
.text-dim {
|
|
||||||
@apply
|
|
||||||
text-gray-400 dark:text-gray-500
|
|
||||||
}
|
|
||||||
.text-extra-dim {
|
|
||||||
@apply
|
|
||||||
text-gray-400/80 dark:text-gray-400/50
|
|
||||||
}
|
|
||||||
.text-extra-extra-dim {
|
|
||||||
@apply
|
|
||||||
text-gray-200 dark:text-gray-800
|
|
||||||
}
|
|
||||||
.text-icon {
|
|
||||||
@apply
|
|
||||||
text-gray-800 dark:text-gray-200
|
|
||||||
}
|
|
||||||
.text-error {
|
|
||||||
@apply
|
|
||||||
text-red-500 dark:text-red-400
|
|
||||||
}
|
|
||||||
/* Utilities: Border */
|
|
||||||
.border-main {
|
|
||||||
@apply border-gray-200 dark:border-gray-700
|
|
||||||
}
|
|
||||||
.border-subtle {
|
|
||||||
@apply
|
|
||||||
border border-gray-200 dark:border-gray-800
|
|
||||||
}
|
|
||||||
/* Utilities: Background */
|
|
||||||
.bg-main {
|
|
||||||
@apply
|
|
||||||
bg-white dark:bg-black
|
|
||||||
}
|
|
||||||
.bg-dim {
|
|
||||||
@apply
|
|
||||||
bg-gray-100 dark:bg-gray-900/75
|
|
||||||
}
|
|
||||||
.bg-content {
|
|
||||||
@apply
|
|
||||||
bg-white border-gray-200
|
|
||||||
dark:bg-black dark:border-gray-800
|
|
||||||
}
|
|
||||||
.bg-invert {
|
|
||||||
@apply
|
|
||||||
bg-gray-900 dark:bg-gray-100
|
|
||||||
}
|
|
||||||
/* Utilities: Baseline Grid */
|
|
||||||
.space-y-baseline {
|
|
||||||
@apply
|
|
||||||
space-y-[1.1875rem] md:space-y-[1.25rem]
|
|
||||||
}
|
|
||||||
.gap-y-baseline {
|
|
||||||
@apply
|
|
||||||
gap-y-[1.1875rem] md:gap-y-[1.25rem]
|
|
||||||
}
|
|
||||||
.gap-baseline {
|
|
||||||
@apply
|
|
||||||
gap-[1.1875rem] md:gap-[1.25rem]
|
|
||||||
}
|
|
||||||
.h-baseline {
|
|
||||||
@apply
|
|
||||||
h-[1.1875rem] md:h-[1.25rem]
|
|
||||||
}
|
|
||||||
.max-h-baseline {
|
|
||||||
@apply
|
|
||||||
max-h-[1.1875rem] md:max-h-[1.25rem]
|
|
||||||
}
|
|
||||||
.-mt-baseline {
|
|
||||||
@apply
|
|
||||||
-mt-[1.1875rem] md:-mt-[1.25rem]
|
|
||||||
}
|
|
||||||
.bg-baseline-grid {
|
|
||||||
@apply
|
|
||||||
bg-[repeating-linear-gradient(to_bottom,#eee,#eee_1px,transparent_1px,transparent_1.1875rem)]
|
|
||||||
md:bg-[repeating-linear-gradient(to_bottom,#eee,#eee_1px,transparent_1px,transparent_1.25rem)]
|
|
||||||
dark:bg-[repeating-linear-gradient(to_bottom,#222,#222_1px,transparent_1px,transparent_1.1875rem)]
|
|
||||||
dark:md:bg-[repeating-linear-gradient(to_bottom,#222,#222_1px,transparent_1px,transparent_1.25rem)]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,98 +0,0 @@
|
|||||||
const defaultTheme = require('tailwindcss/defaultTheme');
|
|
||||||
|
|
||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
module.exports = {
|
|
||||||
content: [
|
|
||||||
'./src/**/*.{js,ts,jsx,tsx,mdx}',
|
|
||||||
],
|
|
||||||
darkMode: 'class',
|
|
||||||
theme: {
|
|
||||||
screens: {
|
|
||||||
'xs': '390px',
|
|
||||||
...defaultTheme.screens,
|
|
||||||
'3xl': '1640px',
|
|
||||||
},
|
|
||||||
fontSize: {
|
|
||||||
'xs': ['0.75rem', '1rem'], // 12px on 16px
|
|
||||||
'sm': ['0.84375rem', '1.1875rem'], // 13.5px on 19px [Default: mobile]
|
|
||||||
'base': ['0.875rem', '1.25rem'], // 14px on 20px [Default: desktop]
|
|
||||||
'lg': ['1rem', '1.25rem'], // 16px on 20px
|
|
||||||
'xl': ['1.125rem', '1.25rem'], // 18px on 20px
|
|
||||||
'2xl': ['1.25rem', '1.25rem'], // 20px on 20px
|
|
||||||
'3xl': ['1.5rem', '1.5rem'], // 24px on 24px
|
|
||||||
},
|
|
||||||
extend: {
|
|
||||||
fontFamily: {
|
|
||||||
'mono': ['var(--font-ibm-plex-mono)', ...defaultTheme.fontFamily.mono],
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
'rotate-pulse':
|
|
||||||
'rotate-pulse 0.75s linear infinite normal both running',
|
|
||||||
'fade-in':
|
|
||||||
'fade-in 0.5s linear both running',
|
|
||||||
'fade-in-from-top':
|
|
||||||
'fade-in-from-top 0.25s ease-in-out',
|
|
||||||
'fade-in-from-bottom':
|
|
||||||
'fade-in-from-bottom 0.25s ease-in-out',
|
|
||||||
'hover-drift':
|
|
||||||
'hover-drift 8s linear infinite',
|
|
||||||
'hover-wobble':
|
|
||||||
'hover-wobble 6s linear infinite normal both running',
|
|
||||||
},
|
|
||||||
keyframes: {
|
|
||||||
'fade-in': {
|
|
||||||
'0%': { opacity: '0' },
|
|
||||||
'100%': { opacity: '1' },
|
|
||||||
},
|
|
||||||
'fade-in-from-top': {
|
|
||||||
'0%': {
|
|
||||||
opacity: '0',
|
|
||||||
transform: 'translateY(-10px)',
|
|
||||||
},
|
|
||||||
'100%': {
|
|
||||||
opacity: '1',
|
|
||||||
transform: 'translateY(0)',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'fade-in-from-bottom': {
|
|
||||||
'0%': {
|
|
||||||
opacity: '0',
|
|
||||||
transform: 'translateY(10px)',
|
|
||||||
},
|
|
||||||
'100%': {
|
|
||||||
opacity: '1',
|
|
||||||
transform: 'translateY(0)',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'rotate-pulse': {
|
|
||||||
'0%': { transform: 'rotate(0deg) scale(1)' },
|
|
||||||
'50%': { transform: 'rotate(180deg) scale(0.8)' },
|
|
||||||
'100%': { transform: 'rotate(360deg) scale(1)' },
|
|
||||||
},
|
|
||||||
'hover-drift': {
|
|
||||||
'0%': { transform: 'translate(0, 0)' },
|
|
||||||
'20%': { transform: 'translate(1px, -2px)' },
|
|
||||||
'40%': { transform: 'translate(1px, 1.5px)' },
|
|
||||||
'60%': { transform: 'translate(-1px, 2px)' },
|
|
||||||
'80%': { transform: 'translate(-1.5px, -1.75px)' },
|
|
||||||
'100%': { transform: 'translate(0, 0)' },
|
|
||||||
},
|
|
||||||
'hover-wobble': {
|
|
||||||
'0%': { transform: 'rotate(0deg)' },
|
|
||||||
'20%': { transform: 'rotate(3.5deg)' },
|
|
||||||
'40%': { transform: 'rotate(-2deg)' },
|
|
||||||
'60%': { transform: 'rotate(2.5deg)' },
|
|
||||||
'80%': { transform: 'rotate(-2.5deg)' },
|
|
||||||
'100%': { transform: 'rotate(0deg)' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
future: {
|
|
||||||
hoverOnlyWhenSupported: true,
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
require('@tailwindcss/forms'),
|
|
||||||
require('@tailwindcss/container-queries'),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
Loading…
Reference in New Issue
Block a user