refactor: update color documentation and enhance ErrorElement component

- Revised color documentation to streamline usage of Apple UIKit colors with Tailwind CSS, emphasizing the correct prefixes for different color categories.
- Refactored the ErrorElement component to improve layout and user experience, including a more structured error display and action buttons for reloading and going back.
- Removed unused translation imports and adjusted the error message presentation for clarity.

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei
2025-07-15 00:19:46 +08:00
parent 988846c46a
commit da487a3000
2 changed files with 102 additions and 213 deletions

View File

@@ -1,191 +1,26 @@
---
description:
globs: apps/**/*
description: write a component
alwaysApply: false
---
# UIKit Colors for Tailwind CSS
You should use @https://github.com/Innei/apple-uikit-colors/blob/main/packages/uikit-colors/macos.ts TailwindCSS atom classname.
## System Colors
red
orange
yellow
green
mint
teal
cyan
blue
indigo
purple
pink
brown
gray
Use Apple UIKit color system with Tailwind classes. **Important**: Always use the correct Tailwind prefix for each color category:
## Fill Colors
fill
fill-secondary
fill-tertiary
fill-quaternary
fill-quinary
fill-vibrant
fill-vibrant-secondary
fill-vibrant-tertiary
fill-vibrant-quaternary
fill-vibrant-quinary
**System Colors**: `text-red`, `bg-red`, `border-red` (same for `orange`, `yellow`, `green`, `mint`, `teal`, `cyan`, `blue`, `indigo`, `purple`, `pink`, `brown`, `gray`)
## Text Colors
text
text-secondary
text-tertiary
text-quaternary
text-quinary
text-vibrant
text-vibrant-secondary
text-vibrant-tertiary
text-vibrant-quaternary
text-vibrant-quinary
**Fill Colors**:
## Material Colors
material-ultra-thick
material-thick
material-medium
material-thin
material-ultra-thin
material-opaque
- Background: `bg-fill`, `bg-fill-secondary`, `bg-fill-tertiary`, `bg-fill-quaternary`, `bg-fill-quinary`, `bg-fill-vibrant`, `bg-fill-vibrant-secondary`, `bg-fill-vibrant-tertiary`, `bg-fill-vibrant-quaternary`, `bg-fill-vibrant-quinary`
- Border: `border-fill`, `border-fill-secondary`, etc.
## Control Colors
control-enabled
control-disabled
**Text Colors**: `text-text`, `text-text-secondary`, `text-text-tertiary`, `text-text-quaternary`, `text-text-quinary`, `text-text-vibrant`, `text-text-vibrant-secondary`, `text-text-vibrant-tertiary`, `text-text-vibrant-quaternary`, `text-text-vibrant-quinary`
## Interface Colors
menu
popover
titlebar
sidebar
selection-focused
selection-focused-fill
selection-unfocused
selection-unfocused-fill
header-view
tooltip
under-window-background
**Material Colors**: `bg-material-ultra-thick`, `bg-material-thick`, `bg-material-medium`, `bg-material-thin`, `bg-material-ultra-thin`, `bg-material-opaque`
**Control Colors**: `bg-control-enabled`, `bg-control-disabled`
## Applied Colors
All above tailwind atom will match this colors.
**Interface Colors**: `bg-menu`, `bg-popover`, `bg-titlebar`, `bg-sidebar`, `bg-selection-focused`, `bg-selection-focused-fill`, `bg-selection-unfocused`, `bg-selection-unfocused-fill`, `bg-header-view`, `bg-tooltip`, `bg-under-window-background`
```css
@media (prefers-color-scheme: light) {
html {
--color-red: 255 69 58;
--color-orange: 255 149 0;
--color-yellow: 255 204 0;
--color-green: 40 205 65;
--color-mint: 0 199 190;
--color-teal: 89 173 196;
--color-cyan: 85 190 240;
--color-blue: 0 122 255;
--color-indigo: 88 86 214;
--color-purple: 175 82 222;
--color-pink: 255 45 85;
--color-brown: 162 132 94;
--color-gray: 142 142 147;
--color-fill: 0 0 0 / 0.1;
--color-fillSecondary: 0 0 0 / 0.08;
--color-fillTertiary: 0 0 0 / 0.05;
--color-fillQuaternary: 0 0 0 / 0.03;
--color-fillQuinary: 0 0 0 / 0.02;
--color-fillVibrant: 217 217 217;
--color-fillVibrantSecondary: 230 230 230;
--color-fillVibrantTertiary: 242 242 242;
--color-fillVibrantQuaternary: 247 247 247;
--color-fillVibrantQuinary: 251 251 251;
--color-text: 0 0 0 / 0.85;
--color-textSecondary: 0 0 0 / 0.5;
--color-textTertiary: 0 0 0 / 0.25;
--color-textQuaternary: 0 0 0 / 0.1;
--color-textQuinary: 0 0 0 / 0.05;
--color-textVibrant: 76 76 76;
--color-textVibrantSecondary: 128 128 128;
--color-textVibrantTertiary: 191 191 191;
--color-textVibrantQuaternary: 230 230 230;
--color-textVibrantQuinary: 242 242 242;
--color-materialUltraThick: 246 246 246 / 0.84;
--color-materialThick: 246 246 246 / 0.72;
--color-materialMedium: 246 246 246 / 0.6;
--color-materialThin: 246 246 246 / 0.48;
--color-materialUltraThin: 246 246 246 / 0.36;
--color-materialOpaque: 246 246 246;
--color-controlEnabled: 251 251 251;
--color-controlDisabled: 243 243 243;
--color-menu: 40 40 40 / 0.58;
--color-popover: 0 0 0 / 0.28;
--color-titlebar: 234 234 234 / 0.8;
--color-sidebar: 234 234 234 / 0.84;
--color-selectionFocused: 10 130 255 / 0.75;
--color-selectionFocusedFill: 10 130 255;
--color-selectionUnfocused: 0 0 0 / 0.1;
--color-selectionUnfocusedFill: 246 246 246 / 0.84;
--color-headerView: 255 255 255 / 0.8;
--color-tooltip: 246 246 246 / 0.6;
--color-underWindowBackground: 246 246 246 / 0.84;
}
}
@media (prefers-color-scheme: dark) {
html {
--color-red: 255 69 58;
--color-orange: 255 159 10;
--color-yellow: 255 214 10;
--color-green: 50 215 75;
--color-mint: 106 196 220;
--color-teal: 106 196 220;
--color-cyan: 90 200 245;
--color-blue: 10 132 255;
--color-indigo: 94 92 230;
--color-purple: 191 90 242;
--color-pink: 255 55 95;
--color-brown: 172 142 104;
--color-gray: 152 152 157;
--color-fill: 255 255 255 / 0.1;
--color-fillSecondary: 255 255 255 / 0.08;
--color-fillTertiary: 255 255 255 / 0.05;
--color-fillQuaternary: 255 255 255 / 0.03;
--color-fillQuinary: 255 255 255 / 0.02;
--color-fillVibrant: 36 36 36;
--color-fillVibrantSecondary: 20 20 20;
--color-fillVibrantTertiary: 13 13 13;
--color-fillVibrantQuaternary: 9 9 9;
--color-fillVibrantQuinary: 7 7 7;
--color-text: 255 255 255 / 0.85;
--color-textSecondary: 255 255 255 / 0.5;
--color-textTertiary: 255 255 255 / 0.25;
--color-textQuaternary: 255 255 255 / 0.1;
--color-textQuinary: 255 255 255 / 0.05;
--color-textVibrant: 229 229 229;
--color-textVibrantSecondary: 124 124 124;
--color-textVibrantTertiary: 65 65 65;
--color-textVibrantQuaternary: 35 35 35;
--color-textVibrantQuinary: 17 17 17;
--color-materialUltraThick: 40 40 40 / 0.84;
--color-materialThick: 40 40 40 / 0.72;
--color-materialMedium: 40 40 40 / 0.6;
--color-materialThin: 40 40 40 / 0.48;
--color-materialUltraThin: 40 40 40 / 0.36;
--color-materialOpaque: 40 40 40;
--color-controlEnabled: 255 255 255 / 0.2;
--color-controlDisabled: 255 255 255 / 0.1;
--color-menu: 246 246 246 / 0.72;
--color-popover: 246 246 246 / 0.6;
--color-titlebar: 60 60 60 / 0.8;
--color-sidebar: 0 0 0 / 0.45;
--color-selectionFocused: 10 130 255 / 0.75;
--color-selectionFocusedFill: 10 130 255;
--color-selectionUnfocused: 255 255 255 / 0.1;
--color-selectionUnfocusedFill: 40 40 40 / 0.65;
--color-headerView: 30 30 30 / 0.8;
--color-tooltip: 0 0 0 / 0.35;
--color-underWindowBackground: 0 0 0 / 0.45;
}
}
```
These colors automatically adapt to light/dark mode following Apple's design system. Remember to use the appropriate prefix (`text-`, `bg-`, `border-`) based on the CSS property you're styling.

View File

@@ -1,6 +1,5 @@
import { repository } from '@pkg'
import { useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { isRouteErrorResponse, useRouteError } from 'react-router'
import { attachOpenInEditor } from '~/lib/dev'
@@ -8,7 +7,6 @@ import { attachOpenInEditor } from '~/lib/dev'
import { Button } from '../ui/button'
export function ErrorElement() {
const { t } = useTranslation()
const error = useRouteError()
const message = isRouteErrorResponse(error)
? `${error.status} ${error.statusText}`
@@ -34,43 +32,99 @@ export function ErrorElement() {
}
return (
<div className="m-auto flex min-h-full max-w-prose flex-col p-8 pt-12 select-text">
<div className="fixed inset-x-0 top-0 h-12" />
<div className="flex flex-col items-center justify-center">
<i className="i-mingcute-bug-fill size-12 text-red-400" />
<h2 className="mt-12 text-2xl select-text">{t('error.title')}</h2>
</div>
<h3 className="text-xl select-text">{message}</h3>
{import.meta.env.DEV && stack ? (
<div className="mt-4 cursor-text overflow-auto rounded-md bg-red-50 p-4 text-left font-mono text-sm whitespace-pre text-red-600">
{attachOpenInEditor(stack)}
<div className="flex min-h-screen flex-col">
{/* Header spacer */}
<div className="h-16" />
{/* Main content */}
<div className="flex flex-1 items-center justify-center px-6">
<div className="w-full max-w-lg">
{/* Error icon and status */}
<div className="mb-8 text-center">
<div className="bg-background-secondary mb-4 inline-flex h-16 w-16 items-center justify-center rounded-full">
<svg
className="text-red h-8 w-8"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z"
/>
</svg>
</div>
<h1 className="text-text mb-2 text-3xl font-medium">
Something went wrong
</h1>
<p className="text-text-secondary text-lg">
We encountered an unexpected error
</p>
</div>
{/* Error message */}
<div className="bg-material-medium border-fill-tertiary mb-6 rounded-lg border p-4">
<p className="text-text-secondary font-mono text-sm break-words">
{message}
</p>
</div>
{/* Stack trace in development */}
{import.meta.env.DEV && stack && (
<div className="mb-6">
<div className="bg-material-medium border-fill-tertiary overflow-auto rounded-lg border p-4">
<pre className="text-red font-mono text-xs break-words whitespace-pre-wrap">
{attachOpenInEditor(stack)}
</pre>
</div>
</div>
)}
{/* Action buttons */}
<div className="mb-8 flex flex-col gap-3 sm:flex-row">
<Button
onClick={() => (window.location.href = '/')}
className="bg-material-opaque text-text-vibrant hover:bg-control-enabled/90 h-10 flex-1 border-0 font-medium transition-colors"
>
Reload Application
</Button>
<Button
onClick={() => window.history.back()}
className="bg-material-thin text-text border-fill-tertiary hover:bg-fill-tertiary h-10 flex-1 border font-medium transition-colors"
>
Go Back
</Button>
</div>
{/* Help text */}
<div className="text-center">
<p className="text-text-secondary mb-3 text-sm">
If this problem persists, please report it to our team.
</p>
<a
href={`${repository.url}/issues/new?title=${encodeURIComponent(
`Error: ${message}`,
)}&body=${encodeURIComponent(
`### Error\n\n${message}\n\n### Stack\n\n\`\`\`\n${stack}\n\`\`\``,
)}&label=bug`}
target="_blank"
rel="noreferrer"
className="text-text-secondary hover:text-text inline-flex items-center text-sm transition-colors"
>
<svg
className="mr-2 h-4 w-4"
fill="currentColor"
viewBox="0 0 24 24"
>
<path d="M12 0C5.374 0 0 5.373 0 12 0 17.302 3.438 21.8 8.207 23.387c.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z" />
</svg>
Report on GitHub
</a>
</div>
</div>
) : null}
<p className="my-8">{t('error.temporary.description')}</p>
<div className="center gap-4">
<Button onClick={() => (window.location.href = '/')}>
{t('error.reload')}
</Button>
</div>
<p className="mt-8">
{t('error.feedback')}
<a
className="text-accent ml-2 cursor-pointer duration-200"
href={`${repository.url}/issues/new?title=${encodeURIComponent(
`Error: ${message}`,
)}&body=${encodeURIComponent(
`### Error\n\n${message}\n\n### Stack\n\n\`\`\`\n${stack}\n\`\`\``,
)}&label=bug`}
target="_blank"
rel="noreferrer"
>
{t('error.submit.issue')}
</a>
</p>
<div className="grow" />
</div>
)
}