Skip to content

feat: respect terminal background theme#27

Merged
emarkou merged 8 commits into
mainfrom
feat/respect-terminal-theme
May 13, 2026
Merged

feat: respect terminal background theme#27
emarkou merged 8 commits into
mainfrom
feat/respect-terminal-theme

Conversation

@emarkou

@emarkou emarkou commented May 13, 2026

Copy link
Copy Markdown
Owner

Summary

  • Remove background: $surface from Screen, FeedList, FeedList ListItem, and all modal containers — terminal background now shows through
  • Replace hardcoded color: #ff6600 on LoadingIndicator with $accent design token
  • Source badge colors (HN orange, lobste.rs red, GitHub green) unchanged — those are semantic, not theme colors

Test plan

  • Launch devskim with a dark terminal theme — background should be terminal color, not Textual's surface
  • Launch with a light terminal theme — same
  • Loading spinner should pick up theme accent color
  • Split view / comment / content modals show terminal background through their panels
  • All 167 tests pass, ruff + mypy clean

Summary by CodeRabbit

  • New Features

    • Added a configurable theme option (auto/light/dark) to control app appearance.
  • Style

    • Switched modal, screen, and list backgrounds to transparent for cleaner integration.
    • Loading indicator now uses the app accent color for consistent theming.
    • Refined feed list and list-item visuals while preserving highlights and spacing.

Review Change Stack

Remove hardcoded `background: $surface` from Screen, FeedList, and modal
containers so the user's terminal theme shows through. Replace the
hardcoded HN-orange LoadingIndicator color with `$accent` design token.
@coderabbitai

coderabbitai Bot commented May 13, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Add theme config option ("auto" default); add an OSC 11 terminal probe used when theme == "auto" to decide dark mode; compute and set DevSkimApp.dark from config/probe; replace $surface backgrounds with transparent across several widgets; use $accent for the loading indicator.

Changes

Theme and UI updates

Layer / File(s) Summary
Config: theme option
devskim/config.py
Add theme: str = "auto" to Config, include a commented theme = "auto" line in DEFAULT_CONFIG, and read theme from the TOML in load_config().
Terminal OSC11 probe & app wiring
devskim/app.py
Add OS/TTY imports and _terminal_is_dark() to query OSC 11 on interactive TTYs; compute self._initial_dark from config.theme (use probe when "auto", otherwise config.theme != "light"); set self.dark in on_mount; change LoadingIndicator color from #ff6600 to $accent.
FeedList and ListItem backgrounds
devskim/widgets/feed.py
FeedList container and FeedList ListItem backgrounds changed from $surface to transparent; container height and item height/padding preserved; highlights keep $primary-darken-2.
ContentModal background
devskim/widgets/content_modal.py
ContentModal CSS background changed from $surface to transparent.
CommentsModal background
devskim/widgets/comments_modal.py
CommentsModal > Vertical background changed from $surface to transparent.
PostSplitModal background
devskim/widgets/post_split_modal.py
PostSplitModal > Vertical background changed from $surface to transparent.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I peeked at the terminal, dusk or dawn,
Let surfaces vanish so pixels move on,
The spinner now hums with the theme's bright accent,
Config whispers "auto" and the app gets consent,
A little hop, a lighter UI—happy rabbit!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: respect terminal background theme' accurately summarizes the main change: implementing terminal background theme detection and adapting the UI to respect it.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/respect-terminal-theme

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented May 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 82.60870% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.67%. Comparing base (3dca523) to head (1f2cbbf).

Files with missing lines Patch % Lines
devskim/app.py 82.22% 8 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #27      +/-   ##
==========================================
+ Coverage   70.99%   73.67%   +2.68%     
==========================================
  Files          18       18              
  Lines        1010     1056      +46     
==========================================
+ Hits          717      778      +61     
+ Misses        293      278      -15     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
devskim/config.py (1)

95-95: ⚡ Quick win

Normalize and validate theme input before storing it.

Line 95 currently stringifies any value and accepts unknown themes silently. Consider lowercasing and allowlisting ("dark" | "light") so typos/config mistakes don’t get ignored.

Proposed patch
-        theme=str(raw.get("theme", "dark")),
+        theme=(
+            (theme := str(raw.get("theme", "dark")).strip().lower())
+            if (theme := str(raw.get("theme", "dark")).strip().lower()) in {"dark", "light"}
+            else "dark"
+        ),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@devskim/config.py` at line 95, Normalize and validate the theme value
returned from raw.get before storing it: instead of blindly stringifying
raw.get("theme", "dark"), read it, lower-case it (e.g. theme_raw =
raw.get("theme", "dark")), check against an allowlist {"dark", "light"}, and
then assign the validated value (fallback to "dark" if not allowed); if you have
a logger available emit a warning for unknown values. Update the expression at
the site where theme=str(raw.get("theme", "dark")) is set (devskim/config.py) to
perform this normalization and validation so only "dark" or "light" are stored.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@devskim/config.py`:
- Line 95: Normalize and validate the theme value returned from raw.get before
storing it: instead of blindly stringifying raw.get("theme", "dark"), read it,
lower-case it (e.g. theme_raw = raw.get("theme", "dark")), check against an
allowlist {"dark", "light"}, and then assign the validated value (fallback to
"dark" if not allowed); if you have a logger available emit a warning for
unknown values. Update the expression at the site where
theme=str(raw.get("theme", "dark")) is set (devskim/config.py) to perform this
normalization and validation so only "dark" or "light" are stored.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: aac79cdc-e7a6-4159-b6d4-51707195d93f

📥 Commits

Reviewing files that changed from the base of the PR and between 19f2e03 and fa914e8.

📒 Files selected for processing (6)
  • devskim/app.py
  • devskim/config.py
  • devskim/widgets/comments_modal.py
  • devskim/widgets/content_modal.py
  • devskim/widgets/feed.py
  • devskim/widgets/post_split_modal.py
💤 Files with no reviewable changes (4)
  • devskim/widgets/content_modal.py
  • devskim/widgets/comments_modal.py
  • devskim/widgets/feed.py
  • devskim/widgets/post_split_modal.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • devskim/app.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@devskim/app.py`:
- Around line 5-10: Unconditional POSIX imports (termios, tty) cause ImportError
on Windows and _terminal_is_dark() also consumes sys.stdin when called in
DevSkimApp.__init__; remove the top-level imports of termios and tty and move
them into _terminal_is_dark() behind a platform guard (e.g., check os.name or
sys.platform) so they are only imported on POSIX, and change DevSkimApp.__init__
to not call _terminal_is_dark() synchronously (delay the call until after
Textual has initialized or use a non-blocking/platform-safe fallback) so stdin
isn't read during initialization; update any references to _terminal_is_dark()
accordingly.
- Around line 35-52: The current startup probe uses sys.stdin (fd from
sys.stdin.fileno()) and tty.setraw(), which consumes the app's input; instead
open the controlling TTY returned by os.ctermid() and perform the raw-mode probe
on that separate file descriptor: call os.ctermid(), open that path (os.open) to
get a new fd, call termios.tcgetattr/tty.setraw on that fd (saving/restoring
attrs), write the OSC 11 probe to that fd and read from it with select/os.read,
then restore termios attributes and close the fd; remove use of
sys.stdin.fileno() for the probe so Textual's stdin is not modified.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 288e6fff-ab17-481b-addd-a4f8c39dd55d

📥 Commits

Reviewing files that changed from the base of the PR and between fa914e8 and 9e03f5b.

📒 Files selected for processing (2)
  • devskim/app.py
  • devskim/config.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • devskim/config.py

Comment thread devskim/app.py Outdated
Comment thread devskim/app.py Outdated
@emarkou emarkou merged commit 05fd3fd into main May 13, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant