diff --git a/src/components/TabPanel.tsx b/src/components/TabPanel.tsx
index a8e26da..eabebdf 100644
--- a/src/components/TabPanel.tsx
+++ b/src/components/TabPanel.tsx
@@ -19,6 +19,7 @@ import { For } from "solid-js";
import { useTheme } from "@/context/ThemeContext";
import { useNavigation } from "@/context/NavigationContext";
import { useScrollIntoView } from "@/hooks/useScrollIntoView";
+import { useSelectionMarker } from "@/hooks/useSelectionMarker";
import { TABS } from "@/utils/navigation";
import { NF_ICONS, supportsNerdFonts } from "@/utils/nerd-fonts";
@@ -51,6 +52,7 @@ export function TabListPane(props: { muted?: boolean }) {
const nerd = supportsNerdFonts();
const { theme } = useTheme();
const nav = useNavigation();
+ const marker = useSelectionMarker();
const cursor = () => nav.tabCursor();
const activeTab = () => nav.activeTab();
@@ -104,7 +106,7 @@ export function TabListPane(props: { muted?: boolean }) {
}}
>
{/* ── selection marker (j/k cursor) ─────────────────────────── */}
- {isCursor() ? "❯" : " "}
+ {isCursor() ? marker() : " "}
{nerd && (
{TAB_ICON[tab]}
diff --git a/src/hooks/useSelectionMarker.ts b/src/hooks/useSelectionMarker.ts
new file mode 100644
index 0000000..f59ecbd
--- /dev/null
+++ b/src/hooks/useSelectionMarker.ts
@@ -0,0 +1,16 @@
+/**
+ * useSelectionMarker — reactive accessor for the row-selection marker glyph.
+ *
+ * When the `showSelectionMarker` setting is on, the focused row of every list
+ * renders `❯`; when off (the default), it renders a space so column alignment
+ * is preserved. Every list pane in the app reads the marker through this hook
+ * so the setting applies consistently everywhere.
+ */
+
+import { useAppStore } from "@/stores/app";
+
+export function useSelectionMarker(): () => string {
+ const app = useAppStore();
+ return () =>
+ app.state().settings.showSelectionMarker ? "❯" : " ";
+}
diff --git a/src/pages/Discover/DiscoverPage.tsx b/src/pages/Discover/DiscoverPage.tsx
index a090b52..d31bf32 100644
--- a/src/pages/Discover/DiscoverPage.tsx
+++ b/src/pages/Discover/DiscoverPage.tsx
@@ -33,6 +33,7 @@ import { PaneRow } from "@/components/PaneRow";
import { TabListPane } from "@/components/TabPanel";
import { LoadingIndicator } from "@/components/LoadingIndicator";
import { useScrollIntoView } from "@/hooks/useScrollIntoView";
+import { useSelectionMarker } from "@/hooks/useSelectionMarker";
export const DiscoverPaneCount = 1;
@@ -43,6 +44,7 @@ function DiscoverPage() {
const { theme } = useTheme();
const muted = () => theme.muted || theme.text;
const nav = useNavigation();
+ const marker = useSelectionMarker();
const depth = nav.currentDepth;
const focus = (d: number = depth()) => nav.depthFocus(d);
@@ -182,12 +184,11 @@ function DiscoverPage() {
ref={ref}
flexDirection="row"
gap={1}
- paddingLeft={1}
paddingRight={1}
backgroundColor={focusBg(index(), lf(), false)}
>
- {index() === nav.depthFocus(0) ? "❯" : " "}
+ {index() === nav.depthFocus(0) ? marker() : " "}
{nerd && (
@@ -219,7 +220,6 @@ function DiscoverPage() {
ref={ref}
flexDirection="row"
gap={1}
- paddingLeft={1}
paddingRight={1}
backgroundColor={focusBg(index(), lf(), isActive())}
onMouseDown={() => {
@@ -229,7 +229,7 @@ function DiscoverPage() {
}}
>
- {index() === lf() ? "❯" : " "}
+ {index() === lf() ? marker() : " "}
{nerd && (
@@ -268,7 +268,6 @@ function DiscoverPage() {
ref={ref}
flexDirection="column"
gap={0}
- paddingLeft={1}
paddingRight={1}
backgroundColor={focusBg(index(), lf(), isActive())}
onMouseDown={() => {
@@ -278,7 +277,7 @@ function DiscoverPage() {
>
- {index() === lf() ? "❯" : " "}
+ {index() === lf() ? marker() : " "}
{podcast.title}
diff --git a/src/pages/Feed/FeedPage.tsx b/src/pages/Feed/FeedPage.tsx
index a8aaf7b..404ec36 100644
--- a/src/pages/Feed/FeedPage.tsx
+++ b/src/pages/Feed/FeedPage.tsx
@@ -40,6 +40,7 @@ import { LoadingIndicator } from "@/components/LoadingIndicator";
import { PaneRow } from "@/components/PaneRow";
import { TabListPane } from "@/components/TabPanel";
import { useScrollIntoView } from "@/hooks/useScrollIntoView";
+import { useSelectionMarker } from "@/hooks/useSelectionMarker";
export const FeedPaneCount = 1;
@@ -55,6 +56,7 @@ function FeedPage() {
const { theme } = useTheme();
const muted = () => theme.muted || theme.text;
const nav = useNavigation();
+ const marker = useSelectionMarker();
// ── flat episode list (depth 0 — the only depth Feed has) ────────────────
const episodes = createMemo(
@@ -257,7 +259,6 @@ function FeedPage() {
ref={ref}
flexDirection="column"
gap={0}
- paddingLeft={1}
paddingRight={1}
backgroundColor={focusBg(index(), fi(), isActive())}
onMouseDown={() => {
@@ -267,7 +268,7 @@ function FeedPage() {
>
- {index() === fi() ? "❯" : " "}
+ {index() === fi() ? marker() : " "}
{item.episode.episodeNumber
@@ -304,7 +305,6 @@ function FeedPage() {
ref={moreRef}
flexDirection="row"
gap={1}
- paddingLeft={1}
paddingRight={1}
backgroundColor={focusBg(episodes().length, focusedRow(), isActive())}
onMouseDown={() => {
@@ -313,7 +313,7 @@ function FeedPage() {
}}
>
- {focusedOnMore() ? "❯" : " "}
+ {focusedOnMore() ? marker() : " "}
{nerd && (
diff --git a/src/pages/MyShows/MyShowsPage.tsx b/src/pages/MyShows/MyShowsPage.tsx
index 7dd6e1b..a1dac5a 100644
--- a/src/pages/MyShows/MyShowsPage.tsx
+++ b/src/pages/MyShows/MyShowsPage.tsx
@@ -35,6 +35,7 @@ import { LoadingIndicator } from "@/components/LoadingIndicator";
import { PaneRow } from "@/components/PaneRow";
import { TabListPane } from "@/components/TabPanel";
import { useScrollIntoView } from "@/hooks/useScrollIntoView";
+import { useSelectionMarker } from "@/hooks/useSelectionMarker";
export const MyShowsPaneCount = 1;
@@ -47,6 +48,7 @@ export function MyShowsPage() {
const { theme } = useTheme();
const muted = () => theme.muted || theme.text;
const nav = useNavigation();
+ const marker = useSelectionMarker();
const stack = nav.depthStack;
const depth = nav.currentDepth;
@@ -254,12 +256,11 @@ export function MyShowsPage() {
ref={ref}
flexDirection="row"
gap={1}
- paddingLeft={1}
paddingRight={1}
backgroundColor={focusBg(index(), lf(), false)}
>
- {index() === lf() ? "❯" : " "}
+ {index() === lf() ? marker() : " "}
{showTitle(feed)}
({feed.episodes.length})
@@ -299,7 +300,6 @@ export function MyShowsPage() {
ref={ref}
flexDirection="row"
gap={1}
- paddingLeft={1}
paddingRight={1}
backgroundColor={focusBg(index(), lf(), isActive())}
onMouseDown={() => {
@@ -308,7 +308,7 @@ export function MyShowsPage() {
}}
>
- {index() === lf() ? "❯" : " "}
+ {index() === lf() ? marker() : " "}
{showTitle(feed)}
@@ -354,7 +354,6 @@ export function MyShowsPage() {
ref={ref}
flexDirection="column"
gap={0}
- paddingLeft={1}
paddingRight={1}
backgroundColor={focusBg(index(), lf(), isActive())}
onMouseDown={() => {
@@ -364,7 +363,7 @@ export function MyShowsPage() {
>
- {index() === lf() ? "❯" : " "}
+ {index() === lf() ? marker() : " "}
{ep.episodeNumber ? `#${ep.episodeNumber} ` : ""}
diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx
index 5b30d40..e6c1842 100644
--- a/src/pages/Search/SearchPage.tsx
+++ b/src/pages/Search/SearchPage.tsx
@@ -42,6 +42,7 @@ import { PaneRow } from "@/components/PaneRow";
import { TabListPane } from "@/components/TabPanel";
import { LoadingIndicator } from "@/components/LoadingIndicator";
import { useScrollIntoView } from "@/hooks/useScrollIntoView";
+import { useSelectionMarker } from "@/hooks/useSelectionMarker";
export const SearchPaneCount = 1;
@@ -52,6 +53,7 @@ function SearchPage() {
const { theme } = useTheme();
const muted = () => theme.muted || theme.text;
const nav = useNavigation();
+ const marker = useSelectionMarker();
const stack = nav.depthStack;
const depth = nav.currentDepth;
@@ -288,7 +290,6 @@ function SearchPage() {
ref={ref}
flexDirection="row"
gap={1}
- paddingLeft={1}
paddingRight={1}
backgroundColor={
typing()
@@ -311,7 +312,7 @@ function SearchPage() {
: focusFg(index(), lf(), isActive())
}
>
- {index() === lf() && !typing() ? "❯" : " "}
+ {index() === lf() && !typing() ? marker() : " "}
{
@@ -375,7 +375,7 @@ function SearchPage() {
>
- {index() === fi() ? "❯" : " "}
+ {index() === fi() ? marker() : " "}
{result.podcast.title}
diff --git a/src/pages/Settings/PreferencesPanel.tsx b/src/pages/Settings/PreferencesPanel.tsx
index a4e38a2..9528876 100644
--- a/src/pages/Settings/PreferencesPanel.tsx
+++ b/src/pages/Settings/PreferencesPanel.tsx
@@ -20,6 +20,7 @@ import { useFeedStore } from "@/stores/feed";
import { useTheme } from "@/context/ThemeContext";
import { useInputFocusNav } from "@/hooks/useInputFocusNav";
import { useScrollIntoView } from "@/hooks/useScrollIntoView";
+import { useSelectionMarker } from "@/hooks/useSelectionMarker";
import {
NavMode,
useNavigation,
@@ -88,6 +89,18 @@ export function usePreferencesItems(): SettingItem[] {
transparentBackground: !settings().transparentBackground,
}),
},
+ {
+ id: "showSelectionMarker",
+ label: "Selection Marker",
+ kind: "toggle",
+ display: () => (settings().showSelectionMarker ? "On" : "Off"),
+ help: () =>
+ `Show the ❯ marker on the focused row of every list (tabs, shows, episodes, results).\nType: toggle\nDefault: off\nCurrent: ${settings().showSelectionMarker ? "On" : "Off"}\nSpace/Enter to toggle.`,
+ toggle: () =>
+ app.updateSettings({
+ showSelectionMarker: !settings().showSelectionMarker,
+ }),
+ },
{
id: "fontSize",
label: "Font Size",
@@ -427,6 +440,7 @@ function WhitelistEditor() {
const focused = () =>
!nav.inputFocused() && index() === wlCursorClamped();
const ref = useScrollIntoView(focused);
+ const marker = useSelectionMarker();
const bg = () => (focused() ? theme.primary : undefined);
const fg = () => (focused() ? theme.surface : theme.text);
return (
@@ -434,7 +448,6 @@ function WhitelistEditor() {
ref={ref}
flexDirection="row"
gap={1}
- paddingLeft={1}
paddingRight={1}
backgroundColor={bg()}
onMouseDown={() => {
@@ -445,7 +458,7 @@ function WhitelistEditor() {
wlToggle(feed.id);
}}
>
- {focused() ? "❯" : " "}
+ {focused() ? marker() : " "}
{inList(feed.id) ? "●" : "○"}
{feed.customName || feed.podcast.title}
diff --git a/src/pages/Settings/SettingsPage.tsx b/src/pages/Settings/SettingsPage.tsx
index b76b1db..7fd243d 100644
--- a/src/pages/Settings/SettingsPage.tsx
+++ b/src/pages/Settings/SettingsPage.tsx
@@ -38,6 +38,7 @@ import { useDownloadItems } from "./DownloadManager";
import { PaneRow } from "@/components/PaneRow";
import { TabListPane } from "@/components/TabPanel";
import { useScrollIntoView } from "@/hooks/useScrollIntoView";
+import { useSelectionMarker } from "@/hooks/useSelectionMarker";
export const SettingsPaneCount = 1;
@@ -436,17 +437,17 @@ function Row(props: {
? theme.selectedListItemText ?? theme.text
: theme.text;
const ref = useScrollIntoView(() => props.focused);
+ const marker = useSelectionMarker();
return (
- {props.focused ? "❯" : " "}
+ {props.focused ? marker() : " "}
{props.icon && nerd && {props.icon}}
{props.label}
diff --git a/src/stores/app.ts b/src/stores/app.ts
index f56a130..32d1223 100644
--- a/src/stores/app.ts
+++ b/src/stores/app.ts
@@ -30,6 +30,7 @@ const defaultSettings: AppSettings = {
playbackSpeed: 1,
downloadPath: "",
transparentBackground: false,
+ showSelectionMarker: false,
visualizer: defaultVisualizerSettings,
};
diff --git a/src/types/settings.ts b/src/types/settings.ts
index ceae72b..fced4e2 100644
--- a/src/types/settings.ts
+++ b/src/types/settings.ts
@@ -81,6 +81,8 @@ export type AppSettings = {
downloadPath: string;
/** Render the app background transparent (let the terminal's own bg show). */
transparentBackground: boolean;
+ /** Show the `❯` cursor marker on the focused row of every list (default: off). */
+ showSelectionMarker: boolean;
visualizer: VisualizerSettings;
};
diff --git a/src/utils/app-persistence.ts b/src/utils/app-persistence.ts
index a469ea2..bd87ab9 100644
--- a/src/utils/app-persistence.ts
+++ b/src/utils/app-persistence.ts
@@ -33,6 +33,7 @@ const defaultSettings: AppSettings = {
playbackSpeed: 1,
downloadPath: "",
transparentBackground: false,
+ showSelectionMarker: false,
visualizer: defaultVisualizerSettings,
};