tipitaka / DESIGN.md
dhammawatthumpra's picture
fix: guard PyThaiNLP auto-correction with similarity check
0d73e33
|
Raw
History Blame Contribute Delete
23.1 kB
metadata
name: พระไตรปิฎก มจร.  Tipitaka Reader
description: >-
  Digital reader for the MCU Pali Tipitaka canon with full-text search and AI
  assistance
colors:
  primary: '#c8860a'
  primary-deep: '#9a6307'
  primary-light: '#e8b84a'
  indigo-bg: '#1a1a2e'
  indigo-deep: '#0f0f1e'
  indigo-surface: '#222242'
  neutral-cream: '#fdfaf5'
  neutral-cream-dark: '#f5edd8'
  neutral-paper: '#faf7f2'
  neutral-warm-white: '#f8f6f0'
  text-dark: '#1a1a1a'
  text-soft: '#555555'
  text-muted: '#888888'
  text-light: '#e0e0e0'
  border-light: '#e0d0b0'
  border-dark: '#3a3a5e'
  highlight-bg: '#fff3cd'
  success-bg: '#e8f5e9'
  info-bg: '#e3f2fd'
typography:
  display:
    fontFamily: Sarabun, 'Noto Serif Thai', 'Noto Sans Thai Looped', sans-serif
    fontSize: clamp(1.2rem, 2vw, 1.6rem)
    fontWeight: 700
    lineHeight: 1.3
    letterSpacing: 0.02em
  body:
    fontFamily: Sarabun, 'Noto Serif Thai', 'Noto Sans Thai Looped', sans-serif
    fontSize: 17px
    fontWeight: 400
    lineHeight: 2.1
    letterSpacing: normal
  label:
    fontFamily: Sarabun, 'Noto Sans Thai Looped', sans-serif
    fontSize: 0.82em
    fontWeight: 600
    lineHeight: 1.4
    letterSpacing: 0.04em
rounded:
  sm: 4px
  md: 6px
  lg: 8px
  xl: 12px
spacing:
  xs: 4px
  sm: 8px
  md: 16px
  lg: 24px
  xl: 32px
components:
  button-primary:
    backgroundColor: '{colors.primary}'
    textColor: '{colors.neutral-warm-white}'
    rounded: '{rounded.md}'
    padding: 10px 20px
  button-secondary:
    backgroundColor: transparent
    textColor: '{colors.text-light}'
    rounded: '{rounded.md}'
    padding: 10px 20px
  button-secondary-hover:
    backgroundColor: '{colors.indigo-surface}'
    textColor: '{colors.primary}'
    rounded: '{rounded.md}'
  card:
    backgroundColor: '{colors.neutral-cream}'
    textColor: '{colors.text-dark}'
    rounded: '{rounded.md}'
    padding: 8px 12px
  reader-panel:
    backgroundColor: '{colors.neutral-cream}'
    textColor: '{colors.text-dark}'
    rounded: '{rounded.lg}'
    padding: 24px 32px
    maxWidth: 70ch
    lineHeight: 2.1
  page-marker:
    textAlign: center
    textColor: '{colors.text-muted}'
    fontSize: 0.82em
    margin: 32px 0
    letterSpacing: 0.04em
  nav-drawer:
    width: 320px
    widthMobile: 100%
    backgroundColor: '{colors.indigo-bg}'
    tabs:
      - toc
      - search
      - overview
    animation: slide-in from left
  ai-fab:
    size: 56px
    shape: circle
    position: fixed bottom-24px right-24px
    backgroundColor: '{colors.primary}'
    iconColor: '{colors.neutral-warm-white}'
    hoverScale: 1.05
    activeScale: 0.95
  ai-popup:
    width: 420px
    maxHeight: 70vh
    position: fixed above ai-fab
    bottomOffset: 96px
    rightOffset: 24px
    draggable: true
    minimizable: true
    backgroundColor: '{colors.neutral-paper}'
    rounded: '{rounded.lg}'
  ai-message-user:
    backgroundColor: '{colors.info-bg}'
    textColor: '{colors.text-dark}'
    rounded: '{rounded.xl}'
    padding: 8px 12px
  ai-message-assistant:
    backgroundColor: '{colors.success-bg}'
    textColor: '{colors.text-dark}'
    rounded: '{rounded.xl}'
    padding: 8px 12px
  right-toolbar:
    width: 44px
    position: fixed right-0
    backgroundColor: '{colors.indigo-surface}'
    buttonSize: 44px
    iconColorRest: '{colors.text-muted}'
    iconColorActive: '{colors.primary}'
    dividerColor: '{colors.border-dark}'
    opacityScrolling: 0.2
    opacityRest: 1
    scrollStopDelay: 1.5s
    hoverZone: 60px
themes:
  dark:
    description: Default  Indigo Midnight shell, Parchment reader
    shell: '{colors.indigo-bg}'
    nav: '{colors.indigo-bg}'
    reader: '{colors.neutral-cream}'
    ai-panel: '{colors.indigo-deep}'
  light:
    description: Warm white shell, paper reader
    shell: '{colors.neutral-warm-white}'
    nav: '{colors.neutral-cream-dark}'
    reader: '{colors.neutral-paper}'
    ai-panel: '{colors.neutral-cream-dark}'
  classic:
    description: Parchment throughout  closest to printed scripture
    shell: '{colors.neutral-cream-dark}'
    nav: '{colors.neutral-cream}'
    reader: '{colors.neutral-cream}'
    ai-panel: '{colors.neutral-paper}'

Design System: พระไตรปิฎก มจร. — Tipitaka Reader

1. Overview

Creative North Star: "The Dhamma Light" (แสงแห่งธรรม)

A digital scripture reader that feels like light illuminating ancient wisdom. The interface is a quiet chamber — indigo walls, warm golden accents, and cream-paper reading surfaces. Every design decision bends toward one purpose: making the sacred text the most prominent thing on screen.

This system explicitly rejects:

  • SaaS dashboard aesthetics (cards with badges, data-heavy chrome, progress bars)
  • AI-first UIs where the chatbot dominates the experience
  • Dark mode as a gamer-aesthetic choice (dark surfaces exist but are subdued, not dramatic)
  • Anything that competes with readability — animated backgrounds, neon accents, decorative floating elements

The app has two modes of being: reading (the user is deep in text — controls fade, AI is closed) and exploring (the user is searching or browsing — panels open, navigation is present). The design prioritizes the reading state.

Key Characteristics

  • Tonal layering, not shadows. Depth is conveyed through shifts in background lightness, not drop shadows. The reader surface is the lightest layer; navigation panels are progressively darker.
  • Typography-led hierarchy. Scale and weight contrast carry the information architecture. Color is supplementary, not structural.
  • Generous rhythm. Line height, padding, and margins are spacious — this is text meant for slow, contemplative reading, not rapid scanning.
  • The accent is earned. Gold appears on interactive elements, highlights, and active states — never as decoration. Its rarity signals "this is actionable."

2. Colors: The Indigo & Gold Palette

The palette pairs a deep indigo architecture (nav, sidebar, backgrounds) with warm cream for reading surfaces and gold for interaction. The contrast between cool indigo and warm cream+gold creates a serene, focused atmosphere.

Primary

  • Dhamma Gold (#c8860a / oklch(0.62 0.12 68)): The sole accent color. Used for active states, hover borders, icons, highlight markers, and page pills. Never applied to more than 10% of any surface. Its golden warmth echoes the ink of illuminated manuscripts.

Neutral

  • Indigo Midnight (#1a1a2e / oklch(0.18 0.04 280)): App shell and navigation background. A very dark blue-black that reads as black but has subtle cool character.
  • Indigo Void (#0f0f1e / oklch(0.12 0.03 280)): The deepest layer — AI panel, footer areas. Conveys depth below the navigation layer.
  • Indigo Surface (#222242 / oklch(0.22 0.05 280)): Hover state for navigation items, secondary card backgrounds.
  • Parchment Cream (#fdfaf5 / oklch(0.96 0.01 75)): The reading surface. Warm off-white reminiscent of aged paper. Used for reader panel and cards in classic/light mode.
  • Cream Dark (#f5edd8 / oklch(0.93 0.02 75)): Hover state for reading-surface items. Also used for active result cards.
  • Warm Paper (#faf7f2 / oklch(0.95 0.01 75)): Alternative reading background, slightly cooler than Parchment Cream. Used for AI panel and secondary surfaces.

Semantic

  • Text Dark (#1a1a1a): Primary body text on light surfaces.
  • Text Soft (#555555): Secondary text, section headers.
  • Text Muted (#888888): Metadata, timestamps, page numbers.
  • Text Light (#e0e0e0): Text on dark surfaces.
  • Border Cream (#e0d0b0): Borders on light/classic surfaces.
  • Border Indigo (#3a3a5e): Borders on dark surfaces.
  • Highlight Yellow (#fff3cd): Search result highlighting in text.
  • Message User Blue (#e3f2fd): User chat bubble background.
  • Message Assistant Green (#e8f5e9): AI chat bubble background.

Named Rules

The Gold Rarity Rule. Gold appears on ≤5% of any given screen. Its role is signal, not ornament. If an element is not interactive or active, it should not be gold.

The Parchment Priority Rule. The reader surface is always the lightest element on screen, regardless of theme. Even in dark mode, the reader background lifts by one tonal step.

3. Typography

Display & Body Font: Sarabun (with 'Noto Serif Thai', 'Noto Sans Thai Looped' fallback)

Sarabun is a modern Thai sans-serif with excellent readability at body sizes. Its open counters and generous ascenders accommodate Thai tone marks and Pali diacritics without crowding. The font is native to the Thai web ecosystem (Google Fonts) and renders reliably across platforms.

Character: Warm, legible, undistracting. Sarabun at 17px with 2.1 line-height creates a rhythm that matches the cadence of Pali chanting — spacious enough for the eye to rest between lines.

Hierarchy

  • Display (700, clamp(1.2rem, 2vw, 1.6rem), 1.3): Volume titles, section headings in the TOC. Large enough to anchor a panel, never dramatic.
  • Headline (600, 1.2rem, 1.4): Panel headers ("ผลการค้นหา", "เลือกเล่มที่ต้องการอ่าน").
  • Title (600, 1rem, 1.4): Card titles, result headers.
  • Body (400, 17px / 1rem, 2.1): The primary reading size. Capped at 70ch max-width on the reader panel. Line height of 2.1 is deliberate — Thai script needs vertical breathing room for tone marks above and below characters.
  • Label (600, 0.82em, 1.4, 0.04em letter-spacing): Metadata, page numbers, section references. Uppercase in Thai context via CSS text-transform.

Named Rules

The Sarabun Solitude Rule. No secondary font. Sarabun serves every role from display to label. Mixing fonts would add visual chatter to a system whose job is to disappear.

4. Elevation

The system uses tonal layering exclusively — depth is conveyed by varying background lightness, never by box shadows. This is deliberate: shadows create the illusion of floating cards, which contradicts the manuscript-like reading experience. Instead, surfaces feel like stacked paper.

The z-order from deepest to lightest:

  1. AI panel / background chrome — darkest indigo (#0f0f1e)
  2. Sidebar / navigation — dark indigo (#1a1a2e)
  3. Card / hover surfaces — indigo surface (#222242) on dark; cream dark (#f5edd8) on light
  4. Reader panel — lightest cream (#fdfaf5) — always the brightest surface

Named Rules

The Flat-By-Default Rule. Every surface is flat at rest. Tonal shifts appear only in response to state — hover, active, focus. No card shadows, no floating elements, no elevated buttons.

5. Components

Buttons

  • Shape: Rounded rectangle with 6px radius. Consistent across all variants.
  • Primary: Gold fill (#c8860a), white text. Used for the primary action on any panel — "ค้นหา", "ส่งคำถาม". Hover: deeper gold (#9a6307). Height: 44px minimum.
  • Secondary: Transparent fill, border matching current theme's border color. Used for navigation, toggle, and utility actions. Hover: gold border + indigo surface background. Active: translateY(-1px) micro-motion.
  • Icon-only: Transparent, same geometry. Used in sidebar icon mode. Active variant uses gold border.
  • Ghost (TOC/List items): Full-width, text-align left, transparent. Hover: gold text + tinted background.

Cards (Search Results / TOC)

  • Shape: 6px radius, 1px border matching theme border color. Left border is not used as accent (avoiding side-stripe anti-pattern per design law).
  • Resting: Transparent or panel-matching background. Text at body weight.
  • Active: Gold border + lighter background tint. No shadow.
  • Internal spacing: 8px top/bottom, 12px left/right.

Reader Panel

  • Shape: 8px radius, no border (breathes within its column). Background is always the lightest surface on screen.
  • Header: Section title + volume/page pill in gold. Separated from text by a thin border.
  • Typography: 17px body, 2.1 line-height, 70ch max-width. Content is left-aligned (Thai/Pali reads left-to-right).
  • Search highlighting: mark element with highlight yellow background + gold underline.

AI Chat Panel (inside AIPopup)

  • Container: 8px radius popup, floating above the FAB — never a permanent column.
  • User message bubble: Light blue (#e3f2fd) background, 12px radius (bottom-right corner flattened to 4px).
  • Assistant message bubble: Light green (#e8f5e9) background, 12px radius (bottom-left corner flattened to 4px).
  • Thinking indicator: Italic, muted text above assistant messages when in reasoner mode.
  • Input: Full-width text input with 44px height, gold focus ring.

Right Reading Toolbar

Vertical strip fixed to the right edge of the viewport. The sole home for all reading-flow controls. Never in the NavDrawer — these need to be reachable without opening a panel.

Layout (top to bottom):

┌────────┐
│ หน้า N │  ← page pill (current page, tappable to jump)
│  / 532 │  ← total pages, muted
├────────┤
│   ^    │  ← previous page
│   v    │  ← next page
├────────┤
│   ↑    │  ← scroll to top
│  A+    │  ← increase font size
│  A−    │  ← decrease font size
│  ☀/🌙 │  ← cycle theme (dark → light → classic)
└────────┘
  • Width: 44px. Each button is 44 × 44px (touch minimum).
  • Background: Indigo Surface (#222242) in dark theme — one step lighter than the shell, reads as a contained strip.
  • Dividers: 1px border-dark (#3a3a5e) between groups. No divider between A+ and A−.
  • Icon color: Text Muted (#888888) at rest; Dhamma Gold (#c8860a) on hover/active.
  • Page pill: Gold text on dark surface. Tapping opens an inline number input for direct page jump (no modal).
  • Auto-hide: Fades to 20% opacity when the user is actively scrolling. Returns to full opacity on scroll-stop (1.5s) or when cursor enters the 60px right edge zone.
  • No shadow. Sits flush against the right viewport edge — tonal contrast with the reader panel is sufficient separation.
  • Theme toggle icon: Changes to reflect current theme — ☀ (dark), 🌙 (light), 📜 (classic).

Page Marker (Continuous Scroll Divider)

Appears between pages in the continuous scroll reading experience. It is purely informational — never a control.

  • Layout: Centered, full reader-column width.
  • Text: "— หน้า N —" in Text Muted (#888888), label scale (0.82em), 0.04em letter-spacing.
  • Margin: 32px top and bottom — generous breathing room signals a boundary without breaking rhythm.
  • No border, no rule. The text alone is sufficient. A horizontal rule would add visual weight where only a pause is needed.

NavDrawer (Navigation Sidebar)

Three tabs: TOC (table of contents), Search, Overview. Slides in from the left.

  • Width: 320px on desktop; 100% viewport width on mobile with an overlay backdrop.
  • Background: Indigo Midnight (#1a1a2e) in dark/default theme — one tonal step lighter than the app shell.
  • Tabs: Full-width tab strip at top, gold underline on active tab. No icon-only tab bar — labels are always visible.
  • Behavior: On desktop, the drawer can push the reader or overlay it (user preference). On mobile, always overlays with a semi-transparent backdrop.
  • Close target: The backdrop itself is tappable to close on mobile; a ✕ button is present at top-right for keyboard users.

AI Floating Action Button (FAB)

The sole entry point to the AI assistant. Presence at bottom-right is persistent when AI is closed; it disappears when the popup is open (replaced by the popup's close control).

  • Size: 56 × 56px circle. Minimum touch target met without padding hacks.
  • Background: Dhamma Gold (#c8860a). This is the only gold surface in the UI — it earns its prominence.
  • Icon: Lotus or spark glyph in warm white. No text label (position and color are sufficient affordance).
  • Hover: scale(1.05), color deepens to #9a6307. Ease-out-quart, 150ms.
  • Active: scale(0.95), 80ms. Communicates physical press.
  • Unread indicator: 8px dot in amber at top-right of button. Only when the AI has a response the user hasn't seen.
  • No shadow. Tonal layering rule applies — the gold surface against the indigo background creates sufficient contrast without elevation.

AI Popup

Opens above the FAB. Draggable by its title bar. Never full-screen on desktop.

  • Default position: bottom: 96px; right: 24px (24px gap above FAB).
  • Size: 420px wide, max-height 70vh. On mobile: 100vw − 16px margin each side, anchored to bottom.
  • Draggable: Title bar drag handle (cursor: grab). Constrained to viewport bounds.
  • States: Open (full), Minimized (title bar only, ~48px tall), Closed (FAB only).
  • Background: Warm Paper (#faf7f2) — lighter than indigo shell, slightly darker than reader panel. Reads as a floating layer without a shadow.
  • Title bar: "✨ ผู้ช่วยธรรมะ" left-aligned, minimize (—) and close (✕) right-aligned.
  • Quick Actions: Shown on first open, before any message. Four preset buttons in a 2×2 grid: อธิบายให้เข้าใจง่าย, สรุปใจความสำคัญ, วิเคราะห์หลักธรรม, ประยุกต์ใช้ในชีวิต. Plus a free-text input below.
  • Mode toggle: fast / reasoner — compact toggle in title bar area. Not prominent; scholars who need it will find it.

Highlight / Mark

  • Shape: 3px radius, no padding for inline highlights.
  • Color: Highlight yellow (#fff3cd) background in light mode, amber-gold (#4a3c10) in dark mode.
  • Weight: Bolded to distinguish from surrounding text.
  • Animation: Subtle pulse-in on appearance (400ms ease-out-quart).

6. Themes

Three named themes. Dark is the default — the physical scene is a scholar at a desk in a dim monastery library, warm lamp to the right, the screen the primary light source.

Token Dark (default) Light Classic
Shell Indigo Midnight #1a1a2e Warm White #f8f6f0 Cream Dark #f5edd8
NavDrawer Indigo Midnight #1a1a2e Cream Dark #f5edd8 Parchment Cream #fdfaf5
Reader Parchment Cream #fdfaf5 Warm Paper #faf7f2 Parchment Cream #fdfaf5
AI Panel Indigo Void #0f0f1e Cream Dark #f5edd8 Warm Paper #faf7f2
Body text Text Dark #1a1a1a Text Dark #1a1a1a Text Dark #1a1a1a
Nav text Text Light #e0e0e0 Text Dark #1a1a1a Text Soft #555555

Switching: Via the theme toggle button (☀/🌙/📜) in the Right Reading Toolbar — bottom of the toolbar strip, always visible.

7. Do's and Don'ts

Do Don't
Use gold sparingly — only for interactive/active elements Add gold borders to every card "for consistency"
Keep the reader panel as the lightest surface Use shadows to elevate the reader above the background
Let typography carry the hierarchy Rely on color alone to distinguish headings from body
Use generous line height (2.1) for Thai/Pali text Squeeze text to fit more content on screen
Close AI panel when not in active use Let the AI panel dominate the layout
Use tonal layering to indicate depth Add drop shadows anywhere
Keep navigation compact and predictable Add animations that delay reading
Show the page number prominently in gold Hide navigation controls in hamburger menus
Test every color combination at WCAG AA Assume dark theme text on dark backgrounds is readable
Prefer inline/panel alternatives to modals Use modals for search results or text selection

8. Animation & Motion

All animations serve function — they orient the user or confirm an action. No animation exists for decoration.

Global: Respect prefers-reduced-motion: reduce — all animations collapse to instant state changes.

Easing & Duration Tokens

Token Value Usage
ease-standard cubic-bezier(0.4, 0, 0.2, 1) Most transitions (panels, opacity)
ease-out-quart cubic-bezier(0.25, 1, 0.5, 1) Elements entering view (drawer, popup)
ease-in-quart cubic-bezier(0.5, 0, 0.75, 0) Elements exiting view
duration-fast 150ms Micro-interactions (hover, active)
duration-normal 250ms Panel transitions, state changes
duration-slow 400ms Large-area transitions (drawer, popup)

Component Animations

Component Trigger Animation Duration Easing
NavDrawer Open translateX(-100%) → translateX(0) duration-slow ease-out-quart
NavDrawer Close translateX(0) → translateX(-100%) duration-normal ease-in-quart
NavDrawer backdrop Open opacity: 0 → 0.5 duration-slow ease-standard
AI FAB Hover scale(1) → scale(1.05), color deepens duration-fast ease-out-quart
AI FAB Active scale(1) → scale(0.95) 80ms ease-standard
AI FAB Unread pulse Subtle ring pulse (opacity 0.4→0→0.4) 2000ms loop ease-standard
AI Popup Open opacity: 0, translateY(16px) → opacity: 1, translateY(0) duration-slow ease-out-quart
AI Popup Close opacity: 1 → 0, translateY(0) → translateY(8px) duration-normal ease-in-quart
Search results Appear Stagger children: opacity: 0 → 1, delay 50ms × index (max 8 items) duration-normal ease-out-quart
Highlight mark Appear Background pulse-in (0→100% opacity) duration-slow ease-out-quart
Page marker Enter viewport No animation — static text, appears naturally via scroll
Right Toolbar Scroll start opacity: 1 → 0.2 duration-normal ease-standard
Right Toolbar Scroll stop (1.5s) opacity: 0.2 → 1 duration-normal ease-standard
Theme switch Toggle Cross-fade backgrounds: opacity swap duration-slow ease-standard
Loading skeleton Pulse Background shimmer left→right 1500ms loop ease-standard

Named Rules

The No-Bounce Rule. No spring or bounce physics anywhere. The aesthetic is calm, not playful — overshooting motion contradicts the contemplative reading environment.

The Stagger Cap Rule. List animations stagger at most 8 items (8 × 50ms = 400ms max). Beyond 8, remaining items appear instantly. Long stagger chains feel sluggish.