Texto Theme Development Guide
Theme File Structure
A Texto theme is a CSS file containing three blocks:
/* Light mode: light values for all variables */
:root {
--background: ...;
--foreground: ...;
/* ... all 33 variables + optional --warning */
}
/* Dark mode: dark values for all variables */
.dark {
--background: ...;
--foreground: ...;
/* ... all 33 variables + optional --warning */
}
/* Editor content area: code/highlight/selection styles */
#writer {
--highlight-color: ...;
--code-editor-theme-light: ...;
/* ... editor-specific variables + custom content styles */
}
Variable Reference
Core Color Variables
33 variables total: 32 standard color variables + --color-scheme. The table below also includes the recommended --warning. Grouped by category.
Surface
| Variable | Purpose | Visual Description |
|---|---|---|
--background |
Deepest app background color | Like paper base color |
--foreground |
Default text color on background | Body, heading, label colors |
--card |
Card component background | Panel base slightly different from background |
--card-foreground |
Text color on card | Text color inside cards |
--popover |
Popover, menu, tooltip background | Floating layer base color |
--popover-foreground |
Text color on popover | Menu item, tooltip text color |
Accents
| Variable | Purpose | Visual Description |
|---|---|---|
--primary |
Primary color for selection, focus, interaction | Most prominent accent color |
--primary-foreground |
Text color on primary background | Text on primary buttons |
--secondary |
Secondary surface color | Panel color slightly different from main background |
--secondary-foreground |
Text color on secondary surface | Text in secondary panels |
--accent |
Highlight/accent for hover, selection styles | Mouse hover, selected item background |
--accent-foreground |
Text color on accent background | Selected item text color |
--breathe-color |
Breathing animation color | Pulse animation color for file modification indicators |
Feedback
| Variable | Purpose | Visual Description |
|---|---|---|
--destructive |
Danger/error/delete operation color | Red tones for error messages, delete buttons |
--warning |
Warning status color (optional, recommended) | Orange/yellow tones for conflicts, warnings |
--muted |
Muted background color | Slightly darker/lighter than background for secondary areas |
--muted-foreground |
Muted text color | For descriptions, hints, placeholders, secondary text |
Boundaries
| Variable | Purpose | Visual Description |
|---|---|---|
--border |
Default border color for all elements | Panel borders, dividers, card strokes |
--input |
Input field border color | Text field, dropdown borders |
--ring |
Focus ring color | Outer glow when clicking inputs or buttons |
Charts
| Variable | Purpose |
|---|---|
--chart-1 |
Chart color 1 |
--chart-2 |
Chart color 2 (also used for title bar "saved" status) |
--chart-3 |
Chart color 3 |
--chart-4 |
Chart color 4 |
--chart-5 |
Chart color 5 |
Sidebar
The sidebar has its own independent set of colors, usually slightly darker (light mode) or slightly brighter (dark mode) than the main palette.
| Variable | Purpose | Visual Description |
|---|---|---|
--sidebar |
Sidebar background color | File tree area base color |
--sidebar-foreground |
Sidebar text color | File name, directory name colors |
--sidebar-primary |
Sidebar primary color | Accent color in sidebar |
--sidebar-primary-foreground |
Text color on sidebar primary | — |
--sidebar-accent |
Sidebar selection/hover background | Selected file, hover item background |
--sidebar-accent-foreground |
Sidebar selected item text color | Selected file text color |
--sidebar-border |
Sidebar border color | Separator between sidebar and main content |
--sidebar-ring |
Sidebar focus ring color | Outer glow when focusing elements in sidebar |
Special Variables
| Variable | Purpose | Value |
|---|---|---|
--color-scheme |
Browser native UI color scheme | light or dark (string, not a color value) |
Controls the styling of scrollbars, form controls, and other system-native elements.
Editor Content Area Variables (defined inside #writer {})
| Variable | Purpose |
|---|---|
--highlight-color |
Background color for text highlight (<mark>) |
--default-selection |
Background color for selected text in editor (optional, uses browser default if not defined) |
--code-editor-theme-light |
Syntax highlighting theme name for code blocks in light mode |
--code-editor-theme-dark |
Syntax highlighting theme name for code blocks in dark mode |
--source-code-theme-light |
Syntax highlighting theme name for source editor in light mode |
--source-code-theme-dark |
Syntax highlighting theme name for source editor in dark mode |
Available values for --code-editor-theme-* and --source-code-theme-* (syntax highlighting theme names):
oneDark materialDark githubDark githubLight
dracula atomone vscodeDark xcodeDark
xcodeLight eclipse sublime basicLight
tokyoNightDay bbedit solarizedLight
Editor Content Area Selectors (defined inside #writer {})
The following selectors can be used to customize the editor content area styles:
#writer h1 /* Level 1 heading */
#writer h2 /* Level 2 heading */
#writer h3 /* Level 3 heading */
#writer h4 /* Level 4 heading */
#writer h5 /* Level 5 heading */
#writer h6 /* Level 6 heading */
#writer p /* Paragraph */
#writer a /* Link */
#writer code /* Inline code */
#writer pre /* Code block */
#writer pre code /* Code inside code block (reset inline code styles) */
#writer blockquote /* Blockquote */
#writer ul /* Unordered list */
#writer ol /* Ordered list */
#writer li /* List item */
#writer ul li::marker /* Unordered list marker color */
#writer ol li::marker /* Ordered list number color */
#writer hr /* Horizontal rule */
#writer table th /* Table header */
#writer table td /* Table cell */
#writer mark /* Highlight mark */
#writer ::selection /* Text selection style */
Color Formats
Theme CSS files can use hex, hsl, or oklch formats:
--primary: #3b82f6;
--primary: hsl(217, 91%, 60%);
--primary: oklch(0.546 0.245 262.881);
However, the visual theme editor only fully supports oklch format. Hex or hsl values will work in CSS, but they won't be displayed in the editor's grouping panel, and editing them through the color picker will automatically convert them to oklch.
OKLCH is recommended. It more closely matches human perception, has better hue consistency, and supports the color-mix() function.
Recommended tool: OKLCH Converter
Color Design Principles
Each background/foreground variable pair must ensure readability:
--background / --foreground Main surface
--card / --card-foreground Card surface
--popover / --popover-foreground Popover
--primary / --primary-foreground Primary accent
--secondary / --secondary-foreground Secondary
--muted / --muted-foreground Muted
--accent / --accent-foreground Interactive highlight
--sidebar / --sidebar-foreground Sidebar
Typical relationship references:
--foregroundon--background: high contrast (e.g. #111 on #fff)--muted-foregroundis lighter than--foreground(e.g. #666 on #fff)--mutedis slightly darker than--background(e.g. #f5f5f5 on #fff)--borderis 10-15% darker than background--primaryis the most prominent color in the app--sidebarseries is usually slightly distinct from the main palette
Highlight Color (mark tag)
--highlight-color defines a default value in the theme, but users can switch between six preset colors in settings. The presets are:
Yellow oklch(0.9 0.15 85 / 0.35)
Green oklch(0.9 0.15 140 / 0.35)
Blue oklch(0.85 0.1 250 / 0.35)
Pink oklch(0.9 0.1 350 / 0.35)
Orange oklch(0.9 0.15 60 / 0.35)
Purple oklch(0.85 0.12 300 / 0.35)
The --highlight-color defined in the theme only applies when the user has not actively switched it.
Custom Theme Variables
You can define theme-specific CSS variables to organize colors:
:root {
--mytheme-code-bg: color-mix(in oklch, var(--primary) 10%, var(--background));
--mytheme-link-color: var(--primary);
--mytheme-blockquote-bg: var(--muted);
}
.dark {
--mytheme-code-bg: color-mix(in oklch, var(--primary) 15%, var(--background));
}
#writer code {
background: var(--mytheme-code-bg);
}
#writer a {
color: var(--mytheme-link-color);
}
Security Restrictions
The following content will be rejected when importing a theme:
| Content | Reason |
|---|---|
url(http or url(https |
External resource references not allowed |
@import |
External stylesheet loading not allowed |
@font-face |
Fonts managed through app settings |
Color Scheme Tips
- Start with
--backgroundand--foreground, establish base and text colors - Set
--primaryand--muted, the two most widely used variables - Use
--muted-foregroundfor secondary text, giving the interface depth - Set
--border, 10-15% darker than background - Give the sidebar its own palette, usually slightly darker for visual distinction
- Tune
--chart-1through--chart-5last, ensure all five are distinguishable - Dark mode: Dark is not the inverse of light. Shift hues (usually toward blue), lower saturation, maintain contrast
Complete Theme Template
/**
* Theme Name
* Brief description
*/
/* ==================== Light Mode ==================== */
:root {
/* ---- Surface ---- */
--background: oklch(1 0 0);
--foreground: oklch(0.25 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.25 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.25 0 0);
/* ---- Accents ---- */
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--breathe-color: oklch(0.646 0.222 41.116);
/* ---- Feedback ---- */
--destructive: oklch(0.577 0.245 27.325);
--warning: oklch(0.621 0.178 26.1);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
/* ---- Boundaries ---- */
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
/* ---- Charts ---- */
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
/* ---- Sidebar ---- */
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.25 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.9 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
/* ---- Special ---- */
--color-scheme: light;
}
/* ==================== Dark Mode ==================== */
.dark {
--background: oklch(0.176 0.014 258.4);
--foreground: oklch(0.943 0.011 243.7);
--card: oklch(0.22 0.016 256.8);
--card-foreground: oklch(0.943 0.011 243.7);
--popover: oklch(0.22 0.016 256.8);
--popover-foreground: oklch(0.943 0.011 243.7);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.176 0.014 258.4);
--secondary: oklch(0.267 0.015 256.8);
--secondary-foreground: oklch(0.943 0.011 243.7);
--accent: oklch(0.267 0.015 256.8);
--accent-foreground: oklch(0.943 0.011 243.7);
--breathe-color: oklch(0.715 0.152 253.3);
--destructive: oklch(0.586 0.201 26.8);
--warning: oklch(0.668 0.164 24.7);
--muted: oklch(0.267 0.015 256.8);
--muted-foreground: oklch(0.662 0.018 250.9);
--border: oklch(0.33 0.015 252.3);
--input: oklch(0.5 0.015 256.8);
--ring: oklch(0.715 0.152 253.3);
--chart-1: oklch(0.715 0.152 253.3);
--chart-2: oklch(0.695 0.181 145.6);
--chart-3: oklch(0.72 0.14 79.9);
--chart-4: oklch(0.73 0.15 34.1);
--chart-5: oklch(0.732 0.167 301.7);
--sidebar: oklch(0.22 0.016 256.8);
--sidebar-foreground: oklch(0.943 0.011 243.7);
--sidebar-primary: oklch(0.715 0.152 253.3);
--sidebar-primary-foreground: oklch(0.943 0.011 243.7);
--sidebar-accent: oklch(0.32 0.015 256.8);
--sidebar-accent-foreground: oklch(0.943 0.011 243.7);
--sidebar-border: oklch(0.33 0.015 252.3);
--sidebar-ring: oklch(0.715 0.152 253.3);
--color-scheme: dark;
}
/* ==================== Editor Content Area ==================== */
#writer {
--highlight-color: oklch(0.9 0.15 85 / 0.35);
--default-selection: oklch(0.6 0.25 255 / 0.3);
--code-editor-theme-light: githubLight;
--code-editor-theme-dark: githubDark;
--source-code-theme-light: githubLight;
--source-code-theme-dark: githubDark;
}
#writer ::selection {
background: var(--default-selection);
}
/* ---- Custom Content Styles ---- */
#writer h1 {
position: relative;
padding-bottom: 0.5em;
border-bottom: 1px solid var(--border);
}
#writer a {
color: var(--primary);
text-decoration: none;
border-bottom: 1px solid color-mix(in oklch, var(--primary) 25%, transparent);
}
#writer code {
padding: 0.2em 0.4em;
background: color-mix(in oklch, var(--foreground) 6%, transparent);
border-radius: 4px;
font-size: 0.85em;
}
#writer blockquote {
border-left: 4px solid var(--border);
padding: 0 1em;
color: var(--muted-foreground);
}
#writer hr {
height: 1px;
background: var(--border);
border: 0;
}
#writer table th {
background: var(--muted);
font-weight: 600;
}
#writer mark {
background: var(--highlight-color);
color: inherit;
}
#writer ul li::marker {
color: var(--primary);
}
#writer ol li::marker {
color: var(--primary);
font-weight: 500;
}
Debugging
- Select "Source Code" mode in the theme editor to edit theme CSS directly
- Changes take effect immediately after saving
- The app ships with three built-in themes (Default in grayscale, Cherry in pink tones, Spring in green tones) for color reference
Exporting and Sharing
Select a theme in the theme editor, click "Export", and save it as a .css file to share with others. They can use the "Import" feature to load it.