fix: font loading and chat scrolling issues

- fix: Replace corrupted Merriweather fonts with valid WOFF2 files from @fontsource
- fix: Use CSS @font-face instead of next/font/local for Merriweather (Next.js 16 compatibility)
- fix: Add smart scroll detection to ChatWindow (respects manual scrolling)
- feat: Update app title to "Brachnha Insight"
- feat: Update app description

Co-Authored-By: Claude (glm-4.7) <noreply@anthropic.com>
This commit is contained in:
Max
2026-01-27 13:58:05 +07:00
parent 02ac9762e4
commit 250832da37
7 changed files with 73 additions and 19 deletions

Binary file not shown.

36
src/app/fonts.css Normal file
View File

@@ -0,0 +1,36 @@
/* Merriweather Font Faces */
@font-face {
font-family: 'Merriweather';
src: url('/fonts/Merriweather-Light.woff2') format('woff2');
font-weight: 300;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Merriweather';
src: url('/fonts/Merriweather-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Merriweather';
src: url('/fonts/Merriweather-Bold.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Merriweather';
src: url('/fonts/Merriweather-Black.woff2') format('woff2');
font-weight: 900;
font-style: normal;
font-display: swap;
}
:root {
--font-merriweather: 'Merriweather', serif;
}

View File

@@ -1,6 +1,7 @@
import type { Metadata } from "next";
import localFont from "next/font/local";
import "./globals.css";
import "./fonts.css";
import { OfflineIndicator } from "../components/features/common";
import { InstallPrompt } from "../components/features/pwa/install-prompt";
import { ThemeProvider } from "@/components/theme-provider";
@@ -11,20 +12,9 @@ const inter = localFont({
display: "swap",
});
const merriweather = localFont({
src: [
{ path: "../../public/fonts/Merriweather-Light.woff2", weight: "300", style: "normal" },
{ path: "../../public/fonts/Merriweather-Regular.woff2", weight: "400", style: "normal" },
{ path: "../../public/fonts/Merriweather-Bold.woff2", weight: "700", style: "normal" },
{ path: "../../public/fonts/Merriweather-Black.woff2", weight: "900", style: "normal" },
],
variable: "--font-merriweather",
display: "swap",
});
export const metadata: Metadata = {
title: "Test01 - Local-First Venting",
description: "Transform your struggles into personal branding content with AI-powered journaling",
title: "Brachnha Insight",
description: "Transform what in your mind into a powerful notes",
// Story 3.4: PWA metadata
manifest: "/manifest.webmanifest", // Next.js 14+ convention
themeColor: "#64748B",
@@ -52,7 +42,7 @@ export default function RootLayout({
return (
<html lang="en" suppressHydrationWarning>
<body
className={`${inter.variable} ${merriweather.variable} font-sans antialiased`}
className={`${inter.variable} font-sans antialiased`}
>
<ThemeProvider
attribute="class"

View File

@@ -1,6 +1,6 @@
"use client";
import { useEffect, useRef } from 'react';
import { useEffect, useRef, useState } from 'react';
import { ChatBubble } from './chat-bubble';
import { TypingIndicator } from './typing-indicator';
import { useChatStore } from '@/store/use-chat';
@@ -9,11 +9,39 @@ import { BookOpen, Sparkles } from 'lucide-react';
export function ChatWindow() {
const { messages, isTyping } = useChatStore();
const bottomRef = useRef<HTMLDivElement>(null);
const containerRef = useRef<HTMLDivElement>(null);
const [isUserScrolling, setIsUserScrolling] = useState(false);
// Auto-scroll to bottom
// Auto-scroll to bottom only when new messages arrive
useEffect(() => {
if (!isUserScrolling) {
bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages, isTyping]);
}
}, [messages.length, isUserScrolling]);
// Detect when user is manually scrolling
useEffect(() => {
const container = containerRef.current;
if (!container) return;
const handleScroll = () => {
const { scrollTop, scrollHeight, clientHeight } = container;
const isAtBottom = scrollHeight - scrollTop - clientHeight < 100;
// If user scrolls up from bottom, disable auto-scroll
if (!isAtBottom && !isUserScrolling) {
setIsUserScrolling(true);
}
// If user scrolls back near bottom, re-enable auto-scroll
if (isAtBottom && isUserScrolling) {
setIsUserScrolling(false);
}
};
container.addEventListener('scroll', handleScroll);
return () => container.removeEventListener('scroll', handleScroll);
}, [isUserScrolling]);
if (!messages || messages.length === 0) {
return (
@@ -38,7 +66,7 @@ export function ChatWindow() {
}
return (
<div className="h-full flex-1 overflow-y-auto px-4 py-6 scroll-smooth">
<div ref={containerRef} className="h-full flex-1 overflow-y-auto px-4 py-6 scroll-smooth">
<div className="max-w-3xl mx-auto space-y-4">
{messages.map((msg) => (
<ChatBubble key={msg.id} role={msg.role} content={msg.content} />