continued out the reuse
This commit is contained in:
@@ -6,7 +6,11 @@ export function SelectableBox({
|
||||
selected,
|
||||
children,
|
||||
...props
|
||||
}: { selected: () => boolean; children: JSXElement } & BoxOptions) {
|
||||
}: {
|
||||
selected: () => boolean;
|
||||
|
||||
children: JSXElement;
|
||||
} & BoxOptions) {
|
||||
const { theme } = useTheme();
|
||||
|
||||
return (
|
||||
@@ -21,18 +25,54 @@ export function SelectableBox({
|
||||
);
|
||||
}
|
||||
|
||||
enum ColorSet {
|
||||
PRIMARY,
|
||||
SECONDARY,
|
||||
TERTIARY,
|
||||
DEFAULT,
|
||||
}
|
||||
function getTextColor(set: ColorSet, selected: () => boolean) {
|
||||
const { theme } = useTheme();
|
||||
switch (set) {
|
||||
case ColorSet.PRIMARY:
|
||||
return selected() ? theme.textSelectedPrimary : theme.textPrimary;
|
||||
case ColorSet.SECONDARY:
|
||||
return selected() ? theme.textSelectedSecondary : theme.textSecondary;
|
||||
case ColorSet.TERTIARY:
|
||||
return selected() ? theme.textSelectedTertiary : theme.textTertiary;
|
||||
default:
|
||||
return theme.textPrimary;
|
||||
}
|
||||
}
|
||||
|
||||
export function SelectableText({
|
||||
selected,
|
||||
children,
|
||||
primary,
|
||||
secondary,
|
||||
tertiary,
|
||||
...props
|
||||
}: {
|
||||
selected: () => boolean;
|
||||
primary?: boolean;
|
||||
secondary?: boolean;
|
||||
tertiary?: boolean;
|
||||
children: JSXElement;
|
||||
} & TextOptions) {
|
||||
const { theme } = useTheme();
|
||||
|
||||
return (
|
||||
<text fg={selected() ? theme.surface : theme.text} {...props}>
|
||||
<text
|
||||
fg={getTextColor(
|
||||
primary
|
||||
? ColorSet.PRIMARY
|
||||
: secondary
|
||||
? ColorSet.SECONDARY
|
||||
: tertiary
|
||||
? ColorSet.TERTIARY
|
||||
: ColorSet.DEFAULT,
|
||||
selected,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</text>
|
||||
);
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
type TerminalColors,
|
||||
} from "@opentui/core";
|
||||
|
||||
type ThemeResolved = {
|
||||
export type ThemeResolved = {
|
||||
primary: RGBA;
|
||||
secondary: RGBA;
|
||||
accent: RGBA;
|
||||
@@ -32,7 +32,13 @@ type ThemeResolved = {
|
||||
info: RGBA;
|
||||
text: RGBA;
|
||||
textMuted: RGBA;
|
||||
selectedListItemText: RGBA;
|
||||
textPrimary: RGBA;
|
||||
textSecondary: RGBA;
|
||||
textTertiary: RGBA;
|
||||
textSelectedPrimary: RGBA;
|
||||
textSelectedSecondary: RGBA;
|
||||
textSelectedTertiary: RGBA;
|
||||
|
||||
background: RGBA;
|
||||
backgroundPanel: RGBA;
|
||||
backgroundElement: RGBA;
|
||||
@@ -77,6 +83,7 @@ type ThemeResolved = {
|
||||
syntaxPunctuation: RGBA;
|
||||
muted?: RGBA;
|
||||
surface?: RGBA;
|
||||
selectedListItemText?: RGBA;
|
||||
layerBackgrounds?: {
|
||||
layer0: RGBA;
|
||||
layer1: RGBA;
|
||||
|
||||
@@ -29,7 +29,7 @@ export function PodcastCard(props: PodcastCardProps) {
|
||||
onMouseDown={props.onSelect}
|
||||
>
|
||||
<box flexDirection="row" gap={2} alignItems="center">
|
||||
<SelectableText selected={() => props.selected}>
|
||||
<SelectableText selected={() => props.selected} primary>
|
||||
<strong>{props.podcast.title}</strong>
|
||||
</SelectableText>
|
||||
|
||||
@@ -42,7 +42,7 @@ export function PodcastCard(props: PodcastCardProps) {
|
||||
<Show when={props.podcast.author && !props.compact}>
|
||||
<SelectableText
|
||||
selected={() => props.selected}
|
||||
fg={theme.textMuted}
|
||||
tertiary
|
||||
>
|
||||
by {props.podcast.author}
|
||||
</SelectableText>
|
||||
@@ -52,7 +52,7 @@ export function PodcastCard(props: PodcastCardProps) {
|
||||
<Show when={props.podcast.description && !props.compact}>
|
||||
<SelectableText
|
||||
selected={() => props.selected}
|
||||
fg={theme.text}
|
||||
tertiary
|
||||
>
|
||||
{props.podcast.description!.length > 80
|
||||
? props.podcast.description!.slice(0, 80) + "..."
|
||||
|
||||
@@ -54,26 +54,26 @@ export function FeedItem(props: FeedItemProps) {
|
||||
>
|
||||
<SelectableText
|
||||
selected={() => props.isSelected}
|
||||
fg={theme.primary}
|
||||
primary
|
||||
>
|
||||
{props.isSelected ? ">" : " "}
|
||||
</SelectableText>
|
||||
<SelectableText
|
||||
selected={() => props.isSelected}
|
||||
fg={visibilityColor()}
|
||||
tertiary
|
||||
>
|
||||
{visibilityIcon()}
|
||||
</SelectableText>
|
||||
<SelectableText
|
||||
selected={() => props.isSelected}
|
||||
fg={theme.text}
|
||||
primary
|
||||
>
|
||||
{props.feed.customName || props.feed.podcast.title}
|
||||
</SelectableText>
|
||||
{props.showEpisodeCount && (
|
||||
<SelectableText
|
||||
selected={() => props.isSelected}
|
||||
fg={theme.textMuted}
|
||||
tertiary
|
||||
>
|
||||
({episodeCount()})
|
||||
</SelectableText>
|
||||
@@ -95,25 +95,25 @@ export function FeedItem(props: FeedItemProps) {
|
||||
<box flexDirection="row" gap={1}>
|
||||
<SelectableText
|
||||
selected={() => props.isSelected}
|
||||
fg={theme.primary}
|
||||
primary
|
||||
>
|
||||
{props.isSelected ? ">" : " "}
|
||||
</SelectableText>
|
||||
<SelectableText
|
||||
selected={() => props.isSelected}
|
||||
fg={visibilityColor()}
|
||||
tertiary
|
||||
>
|
||||
{visibilityIcon()}
|
||||
</SelectableText>
|
||||
<SelectableText
|
||||
selected={() => props.isSelected}
|
||||
fg={theme.warning}
|
||||
secondary
|
||||
>
|
||||
{pinnedIndicator()}
|
||||
</SelectableText>
|
||||
<SelectableText
|
||||
selected={() => props.isSelected}
|
||||
fg={theme.text}
|
||||
primary
|
||||
>
|
||||
<strong>{props.feed.customName || props.feed.podcast.title}</strong>
|
||||
</SelectableText>
|
||||
@@ -123,7 +123,7 @@ export function FeedItem(props: FeedItemProps) {
|
||||
{props.showEpisodeCount && (
|
||||
<SelectableText
|
||||
selected={() => props.isSelected}
|
||||
fg={theme.textMuted}
|
||||
tertiary
|
||||
>
|
||||
{episodeCount()} episodes ({unplayedCount()} new)
|
||||
</SelectableText>
|
||||
@@ -131,7 +131,7 @@ export function FeedItem(props: FeedItemProps) {
|
||||
{props.showLastUpdated && (
|
||||
<SelectableText
|
||||
selected={() => props.isSelected}
|
||||
fg={theme.textMuted}
|
||||
tertiary
|
||||
>
|
||||
Updated: {formatDate(props.feed.lastUpdated)}
|
||||
</SelectableText>
|
||||
@@ -143,7 +143,7 @@ export function FeedItem(props: FeedItemProps) {
|
||||
selected={() => props.isSelected}
|
||||
paddingLeft={4}
|
||||
paddingTop={0}
|
||||
fg={theme.textMuted}
|
||||
tertiary
|
||||
>
|
||||
{props.feed.podcast.description.slice(0, 60)}
|
||||
{props.feed.podcast.description.length > 60 ? "..." : ""}
|
||||
|
||||
@@ -81,7 +81,7 @@ export function FeedPage(props: PageProps) {
|
||||
{([date, episode], groupIndex) => (
|
||||
<>
|
||||
<box flexDirection="column" gap={0} paddingLeft={1} paddingRight={1} paddingTop={1} paddingBottom={1}>
|
||||
<text fg={theme.primary}>{date}</text>
|
||||
<SelectableText selected={() => false} primary>{date}</SelectableText>
|
||||
</box>
|
||||
<SelectableBox
|
||||
selected={() => groupIndex() === selectedIndex()}
|
||||
@@ -93,23 +93,25 @@ export function FeedPage(props: PageProps) {
|
||||
paddingBottom={0}
|
||||
onMouseDown={() => setSelectedIndex(groupIndex())}
|
||||
>
|
||||
<SelectableText selected={() => groupIndex() === selectedIndex()}>
|
||||
<SelectableText selected={() => groupIndex() === selectedIndex()} primary>
|
||||
{groupIndex() === selectedIndex() ? ">" : " "}
|
||||
</SelectableText>
|
||||
<SelectableText
|
||||
selected={() => groupIndex() === selectedIndex()}
|
||||
fg={theme.text}
|
||||
primary
|
||||
>
|
||||
{episode.episode.title}
|
||||
</SelectableText>
|
||||
<box flexDirection="row" gap={2} paddingLeft={2}>
|
||||
<text fg={theme.primary}>{episode.feed.podcast.title}</text>
|
||||
<text fg={theme.textMuted}>
|
||||
<SelectableText selected={() => groupIndex() === selectedIndex()} primary>
|
||||
{episode.feed.podcast.title}
|
||||
</SelectableText>
|
||||
<SelectableText selected={() => groupIndex() === selectedIndex()} tertiary>
|
||||
{formatDate(episode.episode.pubDate)}
|
||||
</text>
|
||||
<text fg={theme.textMuted}>
|
||||
</SelectableText>
|
||||
<SelectableText selected={() => groupIndex() === selectedIndex()} tertiary>
|
||||
{formatDuration(episode.episode.duration)}
|
||||
</text>
|
||||
</SelectableText>
|
||||
</box>
|
||||
</SelectableBox>
|
||||
</>
|
||||
|
||||
@@ -30,7 +30,7 @@ export function ResultCard(props: ResultCardProps) {
|
||||
<box flexDirection="row" gap={2} alignItems="center">
|
||||
<SelectableText
|
||||
selected={() => props.selected}
|
||||
fg={theme.primary}
|
||||
primary
|
||||
>
|
||||
<strong>{podcast().title}</strong>
|
||||
</SelectableText>
|
||||
|
||||
@@ -16,10 +16,18 @@ export const BASE_THEME_COLORS: ThemeColors = {
|
||||
secondary: "#a9b1d6",
|
||||
accent: "#f6c177",
|
||||
text: "#e6edf3",
|
||||
textPrimary: "#e6edf3",
|
||||
textSecondary: "#a9b1d6",
|
||||
textTertiary: "#7d8590",
|
||||
textSelectedPrimary: "#1b1f27",
|
||||
textSelectedSecondary: "#e6edf3",
|
||||
textSelectedTertiary: "#a9b1d6",
|
||||
muted: "#7d8590",
|
||||
warning: "#f0b429",
|
||||
error: "#f47067",
|
||||
success: "#3fb950",
|
||||
_hasSelectedListItemText: true,
|
||||
thinkingOpacity: 0.5,
|
||||
}
|
||||
|
||||
// Base layer backgrounds
|
||||
@@ -61,6 +69,12 @@ export const THEMES_DESKTOP: DesktopTheme = {
|
||||
secondary: "#cba6f7",
|
||||
accent: "#f9e2af",
|
||||
text: "#cdd6f4",
|
||||
textPrimary: "#cdd6f4",
|
||||
textSecondary: "#cba6f7",
|
||||
textTertiary: "#7f849c",
|
||||
textSelectedPrimary: "#1e1e2e",
|
||||
textSelectedSecondary: "#cdd6f4",
|
||||
textSelectedTertiary: "#cba6f7",
|
||||
muted: "#7f849c",
|
||||
warning: "#fab387",
|
||||
error: "#f38ba8",
|
||||
@@ -82,6 +96,12 @@ export const THEMES_DESKTOP: DesktopTheme = {
|
||||
secondary: "#83a598",
|
||||
accent: "#fe8019",
|
||||
text: "#ebdbb2",
|
||||
textPrimary: "#ebdbb2",
|
||||
textSecondary: "#83a598",
|
||||
textTertiary: "#928374",
|
||||
textSelectedPrimary: "#282828",
|
||||
textSelectedSecondary: "#ebdbb2",
|
||||
textSelectedTertiary: "#83a598",
|
||||
muted: "#928374",
|
||||
warning: "#fabd2f",
|
||||
error: "#fb4934",
|
||||
@@ -103,6 +123,12 @@ export const THEMES_DESKTOP: DesktopTheme = {
|
||||
secondary: "#bb9af7",
|
||||
accent: "#e0af68",
|
||||
text: "#c0caf5",
|
||||
textPrimary: "#c0caf5",
|
||||
textSecondary: "#bb9af7",
|
||||
textTertiary: "#565f89",
|
||||
textSelectedPrimary: "#1a1b26",
|
||||
textSelectedSecondary: "#c0caf5",
|
||||
textSelectedTertiary: "#bb9af7",
|
||||
muted: "#565f89",
|
||||
warning: "#e0af68",
|
||||
error: "#f7768e",
|
||||
@@ -124,6 +150,12 @@ export const THEMES_DESKTOP: DesktopTheme = {
|
||||
secondary: "#81a1c1",
|
||||
accent: "#ebcb8b",
|
||||
text: "#eceff4",
|
||||
textPrimary: "#eceff4",
|
||||
textSecondary: "#81a1c1",
|
||||
textTertiary: "#4c566a",
|
||||
textSelectedPrimary: "#2e3440",
|
||||
textSelectedSecondary: "#eceff4",
|
||||
textSelectedTertiary: "#81a1c1",
|
||||
muted: "#4c566a",
|
||||
warning: "#ebcb8b",
|
||||
error: "#bf616a",
|
||||
|
||||
@@ -23,11 +23,20 @@ export type ThemeColors = {
|
||||
secondary: ColorValue;
|
||||
accent: ColorValue;
|
||||
text: ColorValue;
|
||||
textPrimary?: ColorValue;
|
||||
textSecondary?: ColorValue;
|
||||
textTertiary?: ColorValue;
|
||||
textSelectedPrimary?: ColorValue;
|
||||
textSelectedSecondary?: ColorValue;
|
||||
textSelectedTertiary?: ColorValue;
|
||||
muted: ColorValue;
|
||||
warning: ColorValue;
|
||||
error: ColorValue;
|
||||
success: ColorValue;
|
||||
layerBackgrounds?: LayerBackgrounds;
|
||||
_hasSelectedListItemText?: boolean;
|
||||
thinkingOpacity?: number;
|
||||
selectedListItemText?: ColorValue;
|
||||
};
|
||||
|
||||
export type ThemeVariant = {
|
||||
|
||||
@@ -23,4 +23,10 @@ export type ThemeJson = {
|
||||
export type ThemeColors = Record<string, RGBA> & {
|
||||
_hasSelectedListItemText: boolean
|
||||
thinkingOpacity: number
|
||||
textPrimary?: ColorValue
|
||||
textSecondary?: ColorValue
|
||||
textTertiary?: ColorValue
|
||||
textSelectedPrimary?: ColorValue
|
||||
textSelectedSecondary?: ColorValue
|
||||
textSelectedTertiary?: ColorValue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user