FontGet Style Guide
April 19, 2026 · View on GitHub
This document defines the styling system and visual hierarchy for FontGet. FontGet uses a theme-based color system that loads colors from YAML theme files, allowing for customization and support for both dark and light modes.
Theme System Overview
FontGet uses a semantic color system where theme files define color keys (primary, secondary, components, etc.) that are mapped to UI styles. This approach provides:
- Consistency: All styles reference theme colors, not hardcoded hex values
- Customization: Users can create custom themes by editing YAML files
- Dark/Light Mode: Themes support both dark and light modes (via theme
styleor separate theme files) - Auto-detection: Terminal theme can be automatically detected
Theme File Structure
Themes are stored in ~/.fontget/themes/ and follow this structure. Each theme file has a single colors block; the top-level style field is optional (e.g. dark or light).
theme_name: "My Theme"
style: dark # optional: "dark" or "light"
colors:
# Required base colors
primary: "#cba6f7" # Main accent – InfoText, PageTitle, CardTitle, Cursor, Spinner, QueryText
secondary: "#94e2d5" # Secondary accent – TableSourceName, FormLabel, CardLabel
components: "#cdd6f4" # Interactive elements – Button, Switch, FormInput
placeholders: "#7f849c" # Muted elements – borders, placeholders, CheckboxUnchecked
base: "#313244" # Backgrounds – selected states (CommandKey uses fixed ANSI 256 grey)
# Required status colors
warning: "#f9e2af"
error: "#e78284"
success: "#a6e3a1"
# Optional component overrides (defaults to base colors above)
overrides:
page_title:
text: "#cba6f7"
button:
foreground: "#cdd6f4"
background: "#313244"
switch:
foreground: "#cdd6f4"
background: "#313244"
checkbox:
unchecked: "#7f849c"
checked: "#cba6f7"
card:
title_text: "#cba6f7"
label: "#94e2d5"
border: "#7f849c"
command_keys:
text: "#7f849c" # optional; CommandKey foreground uses secondary (same as SecondaryText)
table:
header: "#94e2d5"
row: "#cba6f7"
selected: "#cdd6f4"
spinner:
normal: "#cba6f7"
done: "#a6e3a1"
progress_bar:
start: "#cba6f7"
finish: "#eba0ac"
Default Theme
The default theme is Catppuccin, which is embedded in the binary. If no custom theme is specified, this theme is used automatically.
Theme Configuration
Themes are configured in ~/.fontget/config.yaml:
Theme:
Name: "catppuccin" # Theme name (e.g. catppuccin, gruvbox, system)
Use256ColorSpace: false # Set true to downsample theme colors to ANSI 256 for consistent rendering on terminals without true color (e.g. Apple Terminal)
Backward compatibility: Theme: "arasaka" (string) is still supported and is treated as Theme: { Name: "arasaka", Use256ColorSpace: false }.
Theme display options
- Use256ColorSpace (under
Theme:): Whentrue, theme hex colors are downsampled to the nearest ANSI 256-color index before being applied. Use this if your terminal (e.g. Apple Terminal) does not handle 24-bit true color well.
Theme Color Keys and Style Mapping
Theme YAML files use these exact key names under colors. This table shows which UI styles use each theme key:
| Theme Key | Default (Catppuccin) | Used By (Style Names) |
|---|---|---|
| primary | #cba6f7 | InfoText, QueryText, PageTitle (text), CardTitle (text), Cursor, CheckboxChecked, SpinnerColor, progress bar start (default) |
| secondary | #94e2d5 | TableSourceName, FormLabel, CardLabel, CommandKey (text, same as SecondaryText) |
| components | #cdd6f4 | ButtonNormal (fg), FormInput, SwitchNormal (fg), selected-state backgrounds (inverted) for ButtonSelected, SwitchSelected, TableRowSelected |
| placeholders | #7f849c | FormPlaceholder, FormReadOnly, CardBorder, DialogModal (border only), CheckboxUnchecked, SwitchSeparator, RenderSourceTag (built-in tag color) |
| base | #313244 | ButtonSelected (fg), CheckboxItemSelected (bg), SwitchSelected (fg), TableRowSelected (inverted fg/bg) |
| warning | #f9e2af | WarningText |
| error | #e78284 | ErrorText |
| success | #a6e3a1 | SuccessText, SpinnerDoneColor |
Note: Some styles use terminal default colors (no theme color):
Text,TextBold,TableHeader,CommandExample,CardContent– terminal default- These are not affected by theme changes. Command labels use
TextBold(no separateCommandLabelstyle).
Terminal color support: Theme colors are sent as 24-bit hex by default. If a terminal (e.g. Apple Terminal) doesn't handle true color well, enable Theme.Use256ColorSpace in ~/.fontget/config.yaml to downsample theme hex to ANSI 256. See "Theme display options" above.
Style Categories
FontGet uses a clear categorization system for different types of UI elements. Theme key names (e.g. primary, secondary) match the YAML keys in theme files.
1. PAGE STRUCTURE STYLES - Layout hierarchy and page elements
- PageTitle - Main page titles (theme:
primarytext; overridable viaoverrides.page_title)
2. MESSAGE STYLES - User notifications and responses
- Text - Regular text content (terminal default - no theme color)
- InfoText - Informational messages (theme:
primary) - SecondaryText - Secondary informational text (theme:
secondary) - QueryText - User input values e.g. search queries (theme:
primary) - WarningText - Warning messages (theme:
warning) - ErrorText - Error messages (theme:
error) - SuccessText - Success messages (theme:
success) - TextBold - Bold text with terminal default color (use for command labels; no separate CommandLabel style)
3. DATA DISPLAY STYLES - Tables, lists, and data presentation
- TableHeader - Column headers (terminal default - no theme color)
- TableSourceName - Font/source names in tables (theme:
secondary). Used byRenderSourceNameWithTag()for colored source names with tags. For plain source names useText.Render(name) + " " + RenderSourceTag(isBuiltIn). - TableRowSelected - Selected table rows (theme: inverted
components/basefor contrast)
4. FORM STYLES - Input interfaces and forms
- FormLabel - Field labels (theme:
secondary) - FormInput - Input field content (theme:
components) - FormPlaceholder - Placeholder text (theme:
placeholders) - FormReadOnly - Read-only field content (theme:
placeholders)
5. COMMAND STYLES - Interactive elements and controls
- CommandKey - Keyboard shortcuts. Foreground uses secondary (same as SecondaryText). Background uses a fixed ANSI 256-color grey (dark theme → index 236, light theme → index 252) for consistent rendering across terminals.
- CommandExample - Example commands (terminal default - no theme color). For button-like labels use TextBold.
6. CARD STYLES - Card components and layouts
- CardTitle - Card titles integrated into borders (theme:
primarytext; overridable viaoverrides.card.title_text) - CardLabel - Labels within cards (theme:
secondary) - CardContent - Use Text for regular content (terminal default)
- CardBorder - Card border (theme:
placeholders) - DialogModal - Browse font-details modal shell: border uses
placeholders(same as CardBorder); no background on the shell. Inner content follows card patterns: CardTitle, FormLabel, Text, FormatTerminalURL, ButtonGroup. Build withcomponents.RenderDialog
7. BUTTON COMPONENT STYLES
- ButtonNormal - Unselected button text (theme:
components; overridable viaoverrides.button) - ButtonSelected - Selected button (inverted:
basetext oncomponentsbackground)
8. CHECKBOX COMPONENT STYLES
- CheckboxUnchecked - Unchecked checkbox (theme:
placeholders; overridable viaoverrides.checkbox) - CheckboxChecked - Checked checkbox (theme:
primary; overridable viaoverrides.checkbox) - CheckboxItemSelected - Selected checkbox row background (theme:
base) - Cursor - Cursor indicator for lists/checkboxes (theme:
primary)
9. SWITCH COMPONENT STYLES
- SwitchNormal - Unselected switch option (theme:
components; overridable viaoverrides.switch) - SwitchSelected - Selected switch option (inverted:
basetext oncomponentsbackground) - SwitchSeparator - Separator between options (theme:
placeholders)
10. SPINNER COMPONENT
- SpinnerColor - Spinner animation color, hex string (theme:
primary; overridable viaoverrides.spinner) - SpinnerDoneColor - Done checkmark color, hex string (theme:
success; overridable viaoverrides.spinner)
Implementation
Style Initialization
Styles are initialized from the theme system during application startup:
// In cmd/root.go or similar startup code
ui.InitThemeManager() // Loads theme from config
ui.InitStyles() // Applies theme colors to all styles
Style Usage Examples
// Page titles
ui.PageTitle.Render("Font Search Results")
// Status messages
ui.SuccessText.Render("Installed")
ui.WarningText.Render("Skipped")
ui.ErrorText.Render("Failed to install")
// Table content
ui.TableSourceName.Render("Roboto")
ui.TableHeader.Render("Name")
// Form elements
ui.FormLabel.Render("Name:")
ui.FormInput.Render("user input")
ui.FormPlaceholder.Render("Enter font name...")
// Command elements
ui.CommandKey.Render("Enter")
ui.CommandLabel.Render("Submit")
ui.CommandExample.Render("fontget add google.roboto")
// Card elements
ui.CardTitle.Render("Font Details")
ui.CardLabel.Render("Name:")
ui.CardContent.Render("Roboto Mono")
ui.CardBorder.Render("Card content here")
// Browse modal (border shell only; body uses FormLabel / Text / URLs like cards)
components.RenderDialog(title, body, buttons, components.DialogOpts{MaxWidth: 72, MinWidth: 40})
// Source name rendering
ui.RenderSourceNameWithTag("Google Fonts", true) // Colored name with tag
ui.RenderSourceTag(true) // Just the tag: "[Built-in]"
ui.Text.Render("Google Fonts") + " " + ui.RenderSourceTag(true) // Plain name with styled tag
Status Report Styling
Status reports use a specific pattern where only the status word is colored:
// Instead of coloring the entire message
msg := fmt.Sprintf(" - \"%s\" (%s to %s scope)",
fontDisplayName,
ui.SuccessText.Render("Installed"),
scope)
fmt.Println(ui.Text.Render(msg))
This creates:
- Font name and description → Normal text color
- Status word "(Installed)" → Success color (green)
- Status word "(Skipped)" → Warning color (yellow)
- Status word "(Failed)" → Error color (red)
Card Component Styling
Card components use a hierarchical approach with integrated titles:
// Card with integrated title in border
card := components.NewCardWithSections("Font Details", []components.CardSection{
{Label: "Name", Value: "Roboto Mono"},
{Label: "ID", Value: "google.roboto-mono"},
{Label: "Category", Value: "Monospace"},
})
// Custom card with specific padding
customCard := components.Card{
Title: "Test Font",
Content: "Custom content here",
Width: 80,
VerticalPadding: 1, // Top/bottom padding
HorizontalPadding: 2, // Left/right padding
}
This creates:
- Card titles → Integrated into top border with
primarycolor andbasebackground - Card labels →
secondarycolor (e.g. "Name:", "ID:", "Category:") - Card content → Terminal default color for values
- Card borders →
placeholderscolor with rounded corners
Color Hierarchy
Primary Visual Elements
- Page Titles -
primarytext onbasebackground - Card Titles -
primarytext onbasebackground, integrated into borders - Font Names & Labels -
secondaryfor prominent content, form labels, and card labels - Warning Messages -
warningfor warnings and skipped status - Status Words -
success/warning/errorviaSuccessText,WarningText,ErrorText - Primary Text - Terminal default for compatibility
Status Colors
- Success - Use
SuccessText(theme:success) - Warning - Use
WarningText(theme:warning) - Error - Use
ErrorText(theme:error) - Info - Use
InfoText(theme:primary)
Note: The old Feedback* style names (FeedbackText, FeedbackInfo, etc.) are deprecated. Use Text, InfoText, WarningText, ErrorText, SuccessText in new code.
Background Usage
- Page titles, card titles, command keys -
basebackground - Selected rows, checkbox items -
basebackground - Selected buttons/switches -
componentsbackground (inverted) - Regular content - No background (terminal default)
Creating Custom Themes
To create a custom theme:
- Copy the default theme from
internal/ui/themes/catppuccin.yamlorinternal/templates/dark-theme-template.yamlas a starting point. - Save it to
~/.fontget/themes/your-theme.yaml(oryour-theme-theme.yaml). - Edit the colors under the single
colors:block using the key names below.Optionally addoverrides:for component-specific colors. - Update config.yaml to use your theme:
theme: name: "your-theme" mode: "auto" # or "dark" or "light"
Theme Validation
Themes must include all required color keys under colors::
- Base colors:
primary,secondary,components,placeholders,base - Status colors:
warning,error,success
Optional overrides (each defaults to the base color above if omitted):
page_title(text)button(foreground, background)switch(foreground, background)checkbox(unchecked, checked)card(title_text, label, border)command_keys(text)table(header, row, selected)spinner(normal, done)progress_bar(start, finish)
If a theme is missing required keys or fails validation, FontGet falls back to the default Catppuccin theme.
Table Standards
Maximum Table Width
All tables in FontGet are designed to efficiently use standard terminal space:
- Maximum total width: 120 characters (uses full 120-character terminals)
- Column spacing: 1 space between columns
- Separator line: Matches table width exactly
- Space utilization: Maximum readability with full terminal width
Table Column Standards
Different commands use different column structures based on their purpose:
Font Search/Add/Remove Tables (5 columns, 120 chars total)
- Name: 36 characters (font display name - wider for longer names)
- ID: 34 characters (font ID like "nerd.font-name" - much wider)
- License: 12 characters (license type - slightly wider)
- Categories: 16 characters (font categories - wider for multiple)
- Source: 18 characters (source name - wider)
Font List Tables (5 columns, 120 chars total)
- Name: 54 characters (font family name - much wider)
- Style: 22 characters (font style/variant - wider)
- Type: 10 characters (file type)
- Installed: 20 characters (installation date)
- Scope: 10 characters (user/machine)
Sources Management Tables (2 columns, 120 chars total)
- Status: 10 characters (checkbox/status)
- Name: 109 characters (source name with tags - much wider)
Implementation
Use the shared table functions and column constants in internal/ui/tables.go for consistent formatting:
// For font search/add/remove tables
fmt.Printf("%s\n", ui.TableHeader.Render(ui.GetSearchTableHeader()))
fmt.Printf("%s\n", ui.GetTableSeparator())
// For custom tables, use the column constants (e.g. ui.TableColName, ui.TableColID, ui.TableColSource)
fmt.Printf("%-*s %-*s %-*s\n",
ui.TableColName, "Name",
ui.TableColID, "ID",
ui.TableColSource, "Source")
Utility Functions
Source Name Rendering
FontGet provides utility functions for rendering source names with type tags:
-
RenderSourceNameWithTag(name, isBuiltIn)- Renders source name with tag using coloredTableSourceNamestyle- Used in: search, add, and other commands where colored source names are desired
- Example:
ui.RenderSourceNameWithTag("Google Fonts", true)→ "Google Fonts [Built-in]" (name colored, tag styled)
-
RenderSourceTag(isBuiltIn)- Renders just the type tag ([Built-in]or[Custom])- Can be used independently for flexible rendering
- Example:
ui.RenderSourceTag(true)→ "[Built-in]"
-
Plain source names - For uncolored source names with styled tags, combine manually:
- Example:
ui.Text.Render("Google Fonts") + " " + ui.RenderSourceTag(true) - Used in: sources manage command where source names should be plain text
- Example:
Note: The sources manage command uses plain Text style for source names to maintain a cleaner, less colorful appearance, while still showing styled tags.
Usage Guidelines
- Consistency - Use the same style category for similar elements
- Hierarchy - Page titles > Card titles > Font names > Field labels > Regular text
- Status Clarity - Only color status words, not entire messages
- Theme Awareness - Always use theme-aware styles, never hardcode colors
- Accessibility - Ensure sufficient contrast between text and backgrounds in both dark and light modes
- Table Width - Never exceed 120 characters total width for tables
- Card Design - Use integrated titles in borders for better visual hierarchy
- Padding Control - Use vertical and horizontal padding separately for different use cases
- Theme keys - Use theme color keys (
primary,secondary, etc.) in theme YAML; avoid hardcoding hex in code - Terminal Defaults - Use terminal default colors for base text to ensure compatibility
- Source Name Styling - Use
RenderSourceNameWithTag()for colored names, or combineTextwithRenderSourceTag()for plain names
Migration Notes
If you're updating existing code:
- Don't hardcode colors - Use theme-aware styles from the
uipackage - Don't reference specific hex codes - Colors come from theme files (
primary,secondary, etc.) - Use named styles - e.g.
InfoText,SuccessTextinstead of raw colors - Test both modes - Ensure your code works in both dark and light themes
- Check contrast - Verify readability in both theme modes