Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .markdownlint.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
},
"MD033": false,
"MD041": false,
"MD046": false
"MD046": false,
"MD060": false
}
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,33 @@ More help: [Troubleshooting Guide](https://moneyflow.dev/reference/troubleshooti

---

## Themes

moneyflow includes multiple color themes for different aesthetic preferences:

- **default** - Original moneyflow dark theme
- **berg** - Orange on black (inspired by Bloomberg Terminal) - nostalgic 1980s financial terminal aesthetic
- **nord** - Nord (arctic blue tones) - popular among developers for eye-friendly cool colors
- **gruvbox** - Gruvbox (retro warm colors) - vintage aesthetic beloved by vim users
- **dracula** - Dracula (modern purple) - vibrant high-contrast dark theme
- **solarized-dark** - Solarized Dark (precision colors) - scientifically designed for reduced eye strain
- **monokai** - Monokai (Sublime Text classic) - the iconic editor theme

### Configuring Themes

Set your preferred theme in `~/.moneyflow/config.yaml`:

```yaml
version: 1

settings:
theme: berg # or nord, gruvbox, dracula, solarized-dark, monokai
```

Restart moneyflow for the theme to take effect.

---

## Documentation

**Full documentation available at [moneyflow.dev](https://moneyflow.dev)**
Expand Down
13 changes: 13 additions & 0 deletions config.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@

version: 1

# General settings
settings:
# Theme: Color scheme for the TUI
# Available themes:
# - default: Original moneyflow dark theme
# - berg: Orange on black (inspired by Bloomberg Terminal)
# - nord: Nord (arctic blue tones)
# - gruvbox: Gruvbox (retro warm colors)
# - dracula: Dracula (modern purple)
# - solarized-dark: Solarized Dark (precision colors)
# - monokai: Monokai (Sublime Text classic)
theme: default

# Category customization
# Built-in defaults are chosen to ease integration with Monarch Money but work
# well for most personal finance platforms.
Expand Down
89 changes: 89 additions & 0 deletions docs/config/themes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Themes

moneyflow includes 7 color themes to customize the TUI appearance.

## Available Themes

### Default

Original moneyflow look and feel using Textual's built-in dark theme colors.

![Default Theme](../assets/screenshots/theme-default.svg)

### Berg

Warm amber aesthetic inspired by classic 1980s financial terminals. Muted earth tones for comfortable extended viewing.

![Berg Theme](../assets/screenshots/theme-berg.svg)

### Nord

Arctic blue palette popular among developers. Cool tones designed for eye-friendly extended sessions.

![Nord Theme](../assets/screenshots/theme-nord.svg)

### Gruvbox

Retro warm color scheme with vintage appeal. Beloved by terminal enthusiasts for its comfortable warm tones.

![Gruvbox Theme](../assets/screenshots/theme-gruvbox.svg)

### Dracula

Modern dark theme with purple accents. Popular across editors and terminals.

![Dracula Theme](../assets/screenshots/theme-dracula.svg)

### Monokai

Classic Sublime Text color scheme with vibrant syntax highlighting and warm earth tones.

![Monokai Theme](../assets/screenshots/theme-monokai.svg)

### Solarized Dark

Scientifically designed precision color scheme by Ethan Schoonover. Optimized to reduce eye strain.

![Solarized Dark Theme](../assets/screenshots/theme-solarized-dark.svg)

## Configuration

### Set Default Theme

Create or edit `~/.moneyflow/config.yaml`:

```yaml
version: 1

settings:
theme: berg # or nord, gruvbox, dracula, solarized-dark, monokai, default
```

Restart moneyflow for the theme to take effect.

### Temporary Override

Use the `--theme` option to temporarily try a different theme without changing your config:

```bash
# Try the berg theme
moneyflow --theme berg

# Use nord theme for this session only
moneyflow --mtd --theme nord

# Test dracula theme
moneyflow --demo --theme dracula
```

The override only applies to the current session and doesn't modify `config.yaml`.

### Invalid Theme Names

If you specify an invalid theme, moneyflow will show an error with the list of available themes:

```bash
$ moneyflow --theme foobar
Error: Invalid value for '--theme': 'foobar' is not one of
'default', 'berg', 'nord', 'gruvbox', 'dracula', 'solarized-dark', 'monokai'.
```
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ nav:
- YNAB: guide/ynab.md
- Amazon Mode: guide/amazon-mode.md
- Configuration:
- Themes: config/themes.md
- Categories: categories.md
- Caching: config/caching.md
- Advanced Options: config/advanced.md
Expand Down
32 changes: 27 additions & 5 deletions moneyflow/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
from .screens.transaction_detail_screen import TransactionDetailScreen
from .state import AppState, ViewMode
from .textual_view import TextualViewPresenter
from .theme_manager import get_theme_css_paths, load_theme_from_config
from .version import get_version
from .widgets.help_screen import HelpScreen


Expand Down Expand Up @@ -112,9 +114,9 @@ class MoneyflowApp(App):
while keeping complex logic fully tested.
"""

# Use Path object to properly resolve CSS file location
# __file__ is moneyflow/app.py, so parent/styles/moneyflow.tcss is correct
CSS_PATH = str(Path(__file__).parent / "styles" / "moneyflow.tcss")
# CSS_PATH will be set dynamically based on theme configuration
# This is set in __init__ to allow theme selection from config
CSS_PATH = None

BINDINGS = [
# View mode
Expand Down Expand Up @@ -183,7 +185,22 @@ def __init__(
config_dir: Optional[str] = None,
profile_dir: Optional[Path] = None,
backend_type: Optional[str] = None,
theme_override: Optional[str] = None,
):
# Load theme before calling super().__init__() so CSS is ready
# config_dir may be None (defaults to ~/.moneyflow)
# theme_override takes precedence over config file
theme_name = load_theme_from_config(config_dir, theme_override=theme_override)
css_paths = get_theme_css_paths(theme_name)

# Set CSS_PATH on the class before super().__init__()
# Textual will load these CSS files during initialization
# Convert to List[str | PurePath] for Textual's type requirements
from pathlib import PurePath
from typing import List, cast

MoneyflowApp.CSS_PATH = cast(List[str | PurePath], css_paths)

super().__init__()
self.demo_mode = demo_mode
self.start_year = start_year
Expand All @@ -203,10 +220,12 @@ def __init__(
elif demo_mode:
# Default to 3 years of data (2023-2025) for showcasing multi-year TIME views
self.backend = DemoBackend(start_year=start_year or 2023, years=3)
self.title = "moneyflow [DEMO MODE]"
version = get_version()
self.title = f"moneyflow [{version}] [DEMO MODE]"
else:
# Backend will be set in initialize_data() based on credentials
self.title = "moneyflow"
version = get_version()
self.title = f"moneyflow [{version}]"

self.data_manager: Optional[DataManager] = None
self.state = AppState()
Expand Down Expand Up @@ -2169,6 +2188,7 @@ def launch_monarch_mode(
refresh: bool = False,
demo: bool = False,
config_dir: Optional[str] = None,
theme: Optional[str] = None,
) -> None:
"""
Launch moneyflow with default backend (Monarch Money).
Expand All @@ -2181,6 +2201,7 @@ def launch_monarch_mode(
refresh: Force refresh from API, skip cache
demo: Run in demo mode with sample data
config_dir: Config directory (None = ~/.moneyflow)
theme: Override theme (temporary, doesn't modify config.yaml)
"""
from datetime import date as date_type

Expand Down Expand Up @@ -2211,6 +2232,7 @@ def launch_monarch_mode(
cache_path=cache,
force_refresh=refresh,
config_dir=config_dir,
theme_override=theme,
)
app.run()
except Exception:
Expand Down
11 changes: 10 additions & 1 deletion moneyflow/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,16 @@ def _get_amazon_backend_with_profile_support(db_path=None, config_dir=None):
default=None,
help="Config directory (default: ~/.moneyflow). Useful for testing with isolated configs.",
)
@click.option(
"--theme",
type=click.Choice(
["default", "berg", "nord", "gruvbox", "dracula", "solarized-dark", "monokai"]
),
default=None,
help="Override theme for this session",
)
@click.pass_context
def cli(ctx, year, since, mtd, no_cache, refresh, demo, config_dir):
def cli(ctx, year, since, mtd, no_cache, refresh, demo, config_dir, theme):
"""moneyflow - Terminal UI for personal finance management.

Run with no arguments to launch the default backend (Monarch Money).
Expand Down Expand Up @@ -130,6 +138,7 @@ def cli(ctx, year, since, mtd, no_cache, refresh, demo, config_dir):
refresh=refresh,
demo=demo,
config_dir=config_dir,
theme=theme,
)


Expand Down
6 changes: 3 additions & 3 deletions moneyflow/styles/moneyflow.tcss
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Screen {

#status-bar {
height: 1;
background: $panel;
background: $panel-bg;
padding: 0 1;
dock: top;
}
Expand Down Expand Up @@ -68,7 +68,7 @@ DataTable > .datatable--even-row {
}

DataTable > .datatable--odd-row {
background: $panel;
background: $panel-bg;
}

/* Right-align amount and total columns for proper decimal alignment */
Expand All @@ -82,7 +82,7 @@ DataTable > .datatable--cell-key-total {

#action-bar {
height: 1;
background: $panel;
background: $panel-bg;
padding: 0 1;
dock: bottom;
}
Expand Down
Loading