Skip to content

Commit

Permalink
Overriding generated theme variables
Browse files Browse the repository at this point in the history
  • Loading branch information
darrenburns committed Oct 17, 2024
1 parent e5d0eab commit 2a13416
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 34 deletions.
1 change: 0 additions & 1 deletion src/textual/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,6 @@ def app(self) -> App[object]:
@property
def match_style(self) -> Style | None:
"""The preferred style to use when highlighting matching portions of the [`match_display`][textual.command.Hit.match_display]."""
print("inside property match_style", self.__match_style)
return self.__match_style

def matcher(self, user_input: str, case_sensitive: bool = False) -> Matcher:
Expand Down
100 changes: 67 additions & 33 deletions src/textual/design.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def __init__(
dark: bool = False,
luminosity_spread: float = 0.15,
text_alpha: float = 0.95,
variables: dict[str, str] | None = None,
):
def parse(color: str | None) -> Color | None:
if color is None:
Expand All @@ -85,6 +86,8 @@ def parse(color: str | None) -> Color | None:
self.dark = dark
self.luminosity_spread = luminosity_spread
self.text_alpha = text_alpha
self.variables = variables or {}
"""Overrides for specific variables."""

@property
def shades(self) -> Iterable[str]:
Expand All @@ -98,6 +101,10 @@ def shades(self) -> Iterable[str]:
else:
yield color

def get_or_default(self, name: str, default: str) -> str:
"""Get the value of a color variable, or the default value if not set."""
return self.variables.get(name, default)

def generate(self) -> dict[str, str]:
"""Generate a mapping of color name on to a CSS color.
Expand Down Expand Up @@ -170,63 +177,90 @@ def luminosity_range(spread: float) -> Iterable[tuple[str, float]]:
# Colors names that have a dark variant
DARK_SHADES = {"primary-background", "secondary-background"}

get = self.get_or_default

for name, color in COLORS:
is_dark_shade = dark and name in DARK_SHADES
spread = luminosity_spread
for shade_name, luminosity_delta in luminosity_range(spread):
key = f"{name}{shade_name}"
if color.ansi is not None:
colors[f"{name}{shade_name}"] = color.hex
colors[key] = color.hex
elif is_dark_shade:
dark_background = background.blend(color, 0.15, alpha=1.0)
shade_color = dark_background.blend(
WHITE, spread + luminosity_delta, alpha=1.0
).clamped
colors[f"{name}{shade_name}"] = shade_color.hex
if key not in self.variables:
shade_color = dark_background.blend(
WHITE, spread + luminosity_delta, alpha=1.0
).clamped
colors[key] = shade_color.hex
else:
colors[key] = self.variables[key]
else:
shade_color = color.lighten(luminosity_delta)
colors[f"{name}{shade_name}"] = shade_color.hex
colors[key] = get(key, color.lighten(luminosity_delta).hex)

if foreground.ansi is None:
colors["text"] = "auto 87%"
colors["text-muted"] = "auto 60%"
colors["text-disabled"] = "auto 38%"
colors["text"] = get("text", "auto 87%")
colors["text-muted"] = get("text-muted", "auto 60%")
colors["text-disabled"] = get("text-disabled", "auto 38%")
else:
colors["text"] = "ansi_default"
colors["text-muted"] = "ansi_default"
colors["text-disabled"] = "ansi_default"

# The cursor color for widgets such as OptionList, DataTable, etc.
colors["block-cursor-foreground"] = colors["text"]
colors["block-cursor-background"] = secondary.hex
colors["block-cursor-text-style"] = "bold"
colors["block-cursor-blurred-foreground"] = colors["text"]
colors["block-cursor-blurred-background"] = secondary.with_alpha(0.3).hex
colors["block-cursor-blurred-text-style"] = ""
colors["block-hover-background"] = boost.with_alpha(0.05).hex
colors["block-cursor-foreground"] = get(
"block-cursor-foreground", colors["text"]
)
colors["block-cursor-background"] = get(
"block-cursor-background", secondary.hex
)
colors["block-cursor-text-style"] = get("block-cursor-text-style", "bold")
colors["block-cursor-blurred-foreground"] = get(
"block-cursor-blurred-foreground", colors["text"]
)
colors["block-cursor-blurred-background"] = get(
"block-cursor-blurred-background", secondary.with_alpha(0.3).hex
)
colors["block-cursor-blurred-text-style"] = get(
"block-cursor-blurred-text-style", "none"
)
colors["block-hover-background"] = get(
"block-hover-background", boost.with_alpha(0.05).hex
)

# The border color for focused widgets which have a border.
colors["border"] = secondary.hex
colors["border-blurred"] = surface.darken(0.025).hex
colors["border"] = get("border", secondary.hex)
colors["border-blurred"] = get("border-blurred", surface.darken(0.025).hex)

# The surface color for builtin focused widgets
colors["surface-active"] = surface.lighten(self.luminosity_spread / 2.5).hex
colors["surface-active"] = get(
"surface-active", surface.lighten(self.luminosity_spread / 2.5).hex
)

# The scrollbar colors
colors["scrollbar"] = panel.hex
colors["scrollbar-hover"] = colors["panel-lighten-1"]
colors["scrollbar-active"] = colors["panel-lighten-2"]
colors["scrollbar-background"] = colors["background-darken-1"]
colors["scrollbar-corner-color"] = colors["background"]
colors["scrollbar-background-hover"] = colors["scrollbar-background"]
colors["scrollbar-background-active"] = colors["scrollbar-background"]
colors["scrollbar"] = get("scrollbar", panel.hex)
colors["scrollbar-hover"] = get("scrollbar-hover", colors["panel-lighten-1"])
colors["scrollbar-active"] = get("scrollbar-active", colors["panel-lighten-2"])
colors["scrollbar-background"] = get(
"scrollbar-background", colors["background-darken-1"]
)
colors["scrollbar-corner-color"] = get(
"scrollbar-corner-color", colors["background"]
)
colors["scrollbar-background-hover"] = get(
"scrollbar-background-hover", colors["scrollbar-background"]
)
colors["scrollbar-background-active"] = get(
"scrollbar-background-active", colors["scrollbar-background"]
)

# Links
colors["link-background"] = "initial"
colors["link-background-hover"] = colors["secondary"]
colors["link-color"] = colors["text"]
colors["link-style"] = "underline"
colors["link-color-hover"] = colors["text"]
colors["link-style-hover"] = "bold not underline"
colors["link-background"] = get("link-background", "initial")
colors["link-background-hover"] = get("link-background-hover", secondary.hex)
colors["link-color"] = get("link-color", colors["text"])
colors["link-style"] = get("link-style", "underline")
colors["link-color-hover"] = get("link-color-hover", colors["text"])
colors["link-style-hover"] = get("link-style-hover", "bold not underline")

return colors

Expand Down
7 changes: 7 additions & 0 deletions src/textual/theme.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class Theme:
dark: bool = False
luminosity_spread: float = 0.15
text_alpha: float = 0.95
variables: dict[str, str] | None = None

def to_color_system(self) -> ColorSystem:
"""
Expand All @@ -57,6 +58,7 @@ def to_color_system(self) -> ColorSystem:
dark=self.dark,
luminosity_spread=self.luminosity_spread,
text_alpha=self.text_alpha,
variables=self.variables,
)


Expand Down Expand Up @@ -94,6 +96,11 @@ def to_color_system(self) -> ColorSystem:
panel="#434C5E", # Nord2 - Polar Night
foreground="#D8DEE9", # Nord4 - Snow Storm
dark=True,
variables={
"block-cursor-background": "#88C0D0",
"block-cursor-foreground": "#2E3440",
"block-cursor-text-style": "bold",
},
),
"gruvbox": Theme(
name="gruvbox",
Expand Down

0 comments on commit 2a13416

Please sign in to comment.