mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-05-24 18:42:35 +00:00
style(webui): improve typography with Apple-inspired font stack and CJK support
- Add explicit CJK fonts (PingFang SC, Noto Sans SC, Microsoft YaHei) and programmer fonts (JetBrains Mono, Fira Code, Cascadia Code) to Tailwind config - Bump prose base size from prose-sm (14px) to prose-lg (18px) for sharper CJK rendering - Unify user/assistant message font size at 18px with CJK-aware line-height (1.8) - Replace pure black/white foreground with Apple-style warm grays (#1d1d1f / #f5f5f7) - Override Tailwind Typography colors to use design tokens for consistency - Add negative letter-spacing on headings for tighter, more polished look
This commit is contained in:
parent
7527961b19
commit
a7caee1186
@ -26,8 +26,10 @@
|
|||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
color: #0a0a0a;
|
color: #0a0a0a;
|
||||||
font-family:
|
font-family:
|
||||||
ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
|
system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||||
Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
"Helvetica Neue", Arial, "Noto Sans", "Noto Sans SC",
|
||||||
|
"PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
|
||||||
|
sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
html.dark body {
|
html.dark body {
|
||||||
|
|||||||
@ -24,10 +24,10 @@ export default function MarkdownTextRenderer({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"markdown-content prose prose-sm max-w-none dark:prose-invert",
|
"markdown-content prose prose-lg max-w-none dark:prose-invert",
|
||||||
"prose-headings:mt-4 prose-headings:mb-2 prose-headings:font-semibold",
|
"prose-headings:mt-4 prose-headings:mb-2 prose-headings:font-semibold prose-headings:tracking-tight",
|
||||||
"prose-h1:text-lg prose-h2:text-base prose-h3:text-[0.95rem] prose-h4:text-sm",
|
"prose-h1:text-xl prose-h2:text-lg prose-h3:text-base prose-h4:text-sm",
|
||||||
"prose-p:my-2 prose-p:leading-relaxed",
|
"prose-p:my-2",
|
||||||
"prose-ul:my-2 prose-ol:my-2 prose-li:my-0.5",
|
"prose-ul:my-2 prose-ol:my-2 prose-li:my-0.5",
|
||||||
"prose-blockquote:my-3 prose-blockquote:border-l-2 prose-blockquote:font-normal",
|
"prose-blockquote:my-3 prose-blockquote:border-l-2 prose-blockquote:font-normal",
|
||||||
"prose-blockquote:not-italic prose-blockquote:text-foreground/80",
|
"prose-blockquote:not-italic prose-blockquote:text-foreground/80",
|
||||||
@ -38,6 +38,7 @@ export default function MarkdownTextRenderer({
|
|||||||
"prose-table:my-3 prose-th:text-left prose-th:font-medium",
|
"prose-table:my-3 prose-th:text-left prose-th:font-medium",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
|
style={{ lineHeight: "var(--cjk-line-height)" }}
|
||||||
>
|
>
|
||||||
<ReactMarkdown
|
<ReactMarkdown
|
||||||
remarkPlugins={[remarkGfm, remarkMath]}
|
remarkPlugins={[remarkGfm, remarkMath]}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ export function MessageBubble({ message }: MessageBubbleProps) {
|
|||||||
<p
|
<p
|
||||||
className={cn(
|
className={cn(
|
||||||
"ml-auto w-fit rounded-[18px] border border-border/60 bg-secondary/70 px-4 py-2",
|
"ml-auto w-fit rounded-[18px] border border-border/60 bg-secondary/70 px-4 py-2",
|
||||||
"text-right text-sm whitespace-pre-wrap break-words",
|
"text-right text-[18px]/[1.8] whitespace-pre-wrap break-words",
|
||||||
"shadow-[0_10px_24px_-18px_rgba(0,0,0,0.55)]",
|
"shadow-[0_10px_24px_-18px_rgba(0,0,0,0.55)]",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@ -49,7 +49,7 @@ export function MessageBubble({ message }: MessageBubbleProps) {
|
|||||||
|
|
||||||
const empty = message.content.trim().length === 0;
|
const empty = message.content.trim().length === 0;
|
||||||
return (
|
return (
|
||||||
<div className={cn("w-full text-sm leading-relaxed", baseAnim)}>
|
<div className={cn("w-full text-sm", baseAnim)} style={{ lineHeight: "var(--cjk-line-height)" }}>
|
||||||
{empty && message.isStreaming ? (
|
{empty && message.isStreaming ? (
|
||||||
<TypingDots />
|
<TypingDots />
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@ -6,12 +6,12 @@
|
|||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--background: 0 0% 100%;
|
--background: 0 0% 100%;
|
||||||
--foreground: 0 0% 3.9%;
|
--foreground: 240 3% 12%;
|
||||||
--card: 0 0% 100%;
|
--card: 0 0% 100%;
|
||||||
--card-foreground: 0 0% 3.9%;
|
--card-foreground: 240 3% 12%;
|
||||||
--popover: 0 0% 100%;
|
--popover: 0 0% 100%;
|
||||||
--popover-foreground: 0 0% 3.9%;
|
--popover-foreground: 240 3% 12%;
|
||||||
--primary: 0 0% 9%;
|
--primary: 240 4% 16%;
|
||||||
--primary-foreground: 0 0% 98%;
|
--primary-foreground: 0 0% 98%;
|
||||||
--secondary: 0 0% 96.1%;
|
--secondary: 0 0% 96.1%;
|
||||||
--secondary-foreground: 0 0% 9%;
|
--secondary-foreground: 0 0% 9%;
|
||||||
@ -34,12 +34,12 @@
|
|||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--background: 0 0% 10%;
|
--background: 0 0% 10%;
|
||||||
--foreground: 0 0% 98%;
|
--foreground: 240 4% 96%;
|
||||||
--card: 0 0% 12%;
|
--card: 0 0% 12%;
|
||||||
--card-foreground: 0 0% 98%;
|
--card-foreground: 240 4% 96%;
|
||||||
--popover: 0 0% 12%;
|
--popover: 0 0% 12%;
|
||||||
--popover-foreground: 0 0% 98%;
|
--popover-foreground: 240 4% 96%;
|
||||||
--primary: 0 0% 98%;
|
--primary: 240 5% 98%;
|
||||||
--primary-foreground: 0 0% 9%;
|
--primary-foreground: 0 0% 9%;
|
||||||
--secondary: 0 0% 12%;
|
--secondary: 0 0% 12%;
|
||||||
--secondary-foreground: 0 0% 98%;
|
--secondary-foreground: 0 0% 98%;
|
||||||
@ -72,11 +72,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@apply bg-background text-foreground antialiased;
|
@apply bg-background text-foreground font-sans antialiased;
|
||||||
font-family:
|
|
||||||
ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
|
|
||||||
Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
|
|
||||||
"Apple Color Emoji", "Segoe UI Emoji";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
@ -97,6 +93,30 @@
|
|||||||
@apply mb-0;
|
@apply mb-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Override Tailwind Typography's built-in colors with our design tokens
|
||||||
|
so assistant messages use the same --foreground as user messages. */
|
||||||
|
.markdown-content {
|
||||||
|
--tw-prose-body: hsl(var(--foreground));
|
||||||
|
--tw-prose-headings: hsl(var(--foreground));
|
||||||
|
--tw-prose-bold: hsl(var(--foreground));
|
||||||
|
--tw-prose-lead: hsl(var(--foreground));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CJK-friendly line-height: prose paragraphs default to 1.625 which is
|
||||||
|
tight for Chinese/Japanese/Korean characters. Bump to 1.8 for better
|
||||||
|
readability when the browser detects a CJK primary font. */
|
||||||
|
:lang(zh),
|
||||||
|
:lang(zh-CN),
|
||||||
|
:lang(zh-TW),
|
||||||
|
:lang(zh-HK),
|
||||||
|
:lang(ja),
|
||||||
|
:lang(ko) {
|
||||||
|
--cjk-line-height: 1.8;
|
||||||
|
}
|
||||||
|
:root {
|
||||||
|
--cjk-line-height: 1.625;
|
||||||
|
}
|
||||||
|
|
||||||
/* Subtle scrollbar that doesn't fight the dark background. */
|
/* Subtle scrollbar that doesn't fight the dark background. */
|
||||||
.scrollbar-thin {
|
.scrollbar-thin {
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
|
|||||||
@ -14,6 +14,34 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
extend: {
|
extend: {
|
||||||
|
fontFamily: {
|
||||||
|
sans: [
|
||||||
|
"system-ui",
|
||||||
|
"-apple-system",
|
||||||
|
"BlinkMacSystemFont",
|
||||||
|
'"Segoe UI"',
|
||||||
|
"Roboto",
|
||||||
|
'"Helvetica Neue"',
|
||||||
|
"Arial",
|
||||||
|
'"Noto Sans"',
|
||||||
|
'"Noto Sans SC"',
|
||||||
|
'"PingFang SC"',
|
||||||
|
'"Hiragino Sans GB"',
|
||||||
|
'"Microsoft YaHei"',
|
||||||
|
"sans-serif",
|
||||||
|
'"Apple Color Emoji"',
|
||||||
|
'"Segoe UI Emoji"',
|
||||||
|
],
|
||||||
|
mono: [
|
||||||
|
'"JetBrains Mono"',
|
||||||
|
'"Fira Code"',
|
||||||
|
'"Cascadia Code"',
|
||||||
|
'"Source Code Pro"',
|
||||||
|
"Menlo",
|
||||||
|
"Consolas",
|
||||||
|
"monospace",
|
||||||
|
],
|
||||||
|
},
|
||||||
borderRadius: {
|
borderRadius: {
|
||||||
lg: "var(--radius)",
|
lg: "var(--radius)",
|
||||||
md: "calc(var(--radius) - 2px)",
|
md: "calc(var(--radius) - 2px)",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user