mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Combining tab headers and underline bars, no functionality yet
This commit is contained in:
@@ -2,7 +2,9 @@ from rich.console import RenderableType
|
||||
from rich.panel import Panel
|
||||
|
||||
from textual.app import App
|
||||
from textual.renderables._tab_headers import Tab
|
||||
from textual.widget import Widget
|
||||
from textual.widgets.tabs import Tabs
|
||||
|
||||
|
||||
class PanelWidget(Widget):
|
||||
@@ -23,7 +25,16 @@ class BasicApp(App):
|
||||
def on_mount(self):
|
||||
"""Build layout here."""
|
||||
self.mount(
|
||||
header=Widget(),
|
||||
header=Tabs(
|
||||
[
|
||||
Tab("One", active=True),
|
||||
Tab("Two"),
|
||||
Tab("Three"),
|
||||
Tab("Four"),
|
||||
Tab("Five"),
|
||||
Tab("Six"),
|
||||
]
|
||||
),
|
||||
content=PanelWidget(),
|
||||
footer=Widget(),
|
||||
sidebar=Widget(),
|
||||
|
||||
@@ -22,7 +22,7 @@ Widget:hover {
|
||||
#sidebar {
|
||||
text: $primary-style;
|
||||
dock: side;
|
||||
width: 30;
|
||||
width: 24;
|
||||
offset-x: -100%;
|
||||
transition: $animation;
|
||||
border-right: outer $secondary;
|
||||
@@ -34,8 +34,7 @@ Widget:hover {
|
||||
|
||||
#header {
|
||||
text: $text on $primary;
|
||||
height: 3;
|
||||
border-bottom: hkey $secondary;
|
||||
height: 2;
|
||||
}
|
||||
|
||||
#header.-visible {
|
||||
@@ -44,7 +43,6 @@ Widget:hover {
|
||||
|
||||
#content {
|
||||
text: $text on $background;
|
||||
offset-y: -3;
|
||||
}
|
||||
|
||||
#content.-content-visible {
|
||||
@@ -54,7 +52,6 @@ Widget:hover {
|
||||
#footer {
|
||||
opacity: 1;
|
||||
text: $text on $primary;
|
||||
height: 3;
|
||||
border-top: hkey $secondary;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,45 +1,87 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from rich.cells import cell_len
|
||||
from rich.console import Console, ConsoleOptions, RenderResult
|
||||
from rich.padding import Padding
|
||||
from rich.style import Style
|
||||
from rich.text import Text
|
||||
|
||||
from textual import log
|
||||
from textual._loop import loop_first
|
||||
from textual.renderables.opacity import Opacity
|
||||
|
||||
|
||||
class TabHeader:
|
||||
def __init__(self, headers: list[str], *, width: int | None = None):
|
||||
self.headers = headers
|
||||
@dataclass
|
||||
class Tab:
|
||||
title: str
|
||||
active: bool = False
|
||||
key: str | None = None
|
||||
|
||||
def __post_init__(self):
|
||||
if self.key is None:
|
||||
self.key = self.title
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class TabHeadersRenderable:
|
||||
def __init__(
|
||||
self,
|
||||
tabs: list[Tab],
|
||||
*,
|
||||
width: int | None = None,
|
||||
tab_padding: int = 1,
|
||||
):
|
||||
self.tabs = tabs
|
||||
self.width = width
|
||||
self.tab_padding = tab_padding
|
||||
|
||||
def action_highlight(self):
|
||||
log("highlighted!")
|
||||
|
||||
def __rich_console__(
|
||||
self, console: Console, options: ConsoleOptions
|
||||
) -> RenderResult:
|
||||
width = self.width or options.max_width
|
||||
headers = self.headers
|
||||
free_space = width - sum(cell_len(header) for header in headers)
|
||||
space_per_gap = free_space // (len(headers) + 1)
|
||||
tabs = self.tabs
|
||||
|
||||
padding_len = self.tab_padding * len(tabs)
|
||||
total_len = sum(cell_len(header.title) for header in tabs) + padding_len
|
||||
|
||||
free_space = width - total_len
|
||||
space_per_gap = free_space // (len(tabs) + 1)
|
||||
|
||||
gap = Text(" " * space_per_gap, end="")
|
||||
pad = Text(" ", end="")
|
||||
for is_first, header in loop_first(headers):
|
||||
lpad = rpad = Text(" " * self.tab_padding, end="")
|
||||
|
||||
for is_first, tab in loop_first(tabs):
|
||||
if is_first:
|
||||
yield gap
|
||||
yield pad
|
||||
yield Text(header, end="")
|
||||
yield pad
|
||||
yield lpad
|
||||
tab_content = Text(
|
||||
tab.title, end="", style=Style(meta={"@click": "highlight"})
|
||||
)
|
||||
yield tab_content
|
||||
# if tab.active:
|
||||
# yield tab_content
|
||||
# else:
|
||||
# dimmed_tab_content = Opacity(tab_content, opacity=.2)
|
||||
# yield from console.render(dimmed_tab_content)
|
||||
yield rpad
|
||||
yield gap
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
console = Console()
|
||||
|
||||
header = TabHeader(
|
||||
headers=[
|
||||
"One",
|
||||
"Two",
|
||||
"Three",
|
||||
h = TabHeadersRenderable(
|
||||
[
|
||||
Tab("One"),
|
||||
Tab("Two"),
|
||||
Tab("Three"),
|
||||
]
|
||||
)
|
||||
|
||||
console.print(header)
|
||||
console.print(h)
|
||||
|
||||
@@ -3,16 +3,15 @@ from __future__ import annotations
|
||||
from datetime import datetime
|
||||
from logging import getLogger
|
||||
|
||||
from rich.console import Console, ConsoleOptions, RenderableType
|
||||
from rich.console import RenderableType
|
||||
from rich.panel import Panel
|
||||
from rich.repr import rich_repr, Result
|
||||
from rich.repr import Result
|
||||
from rich.style import StyleType
|
||||
from rich.table import Table
|
||||
from rich.text import TextType
|
||||
|
||||
from .. import events
|
||||
from ..widget import Widget
|
||||
from ..reactive import watch, Reactive
|
||||
from ..widget import Widget
|
||||
|
||||
log = getLogger("rich")
|
||||
|
||||
|
||||
@@ -1,5 +1,35 @@
|
||||
from rich.console import Console, ConsoleOptions, RenderableType
|
||||
from __future__ import annotations
|
||||
|
||||
from rich.console import Console, ConsoleOptions, RenderableType, RenderResult
|
||||
from rich.segment import Segment
|
||||
|
||||
from textual import log
|
||||
from textual.renderables._tab_headers import TabHeadersRenderable, Tab
|
||||
from textual.renderables.underline_bar import UnderlineBar
|
||||
from textual.widget import Widget
|
||||
|
||||
|
||||
class Tabs:
|
||||
pass
|
||||
class TabsRenderable:
|
||||
def __init__(self, headers: list[Tab]):
|
||||
self.headers = headers
|
||||
|
||||
def __rich_console__(
|
||||
self, console: Console, options: ConsoleOptions
|
||||
) -> RenderResult:
|
||||
headers = TabHeadersRenderable(tabs=self.headers)
|
||||
underline = UnderlineBar(highlight_range=(19, 26), highlight_style="#95d52a")
|
||||
yield from console.render(headers)
|
||||
yield Segment.line()
|
||||
yield from console.render(underline)
|
||||
|
||||
|
||||
class Tabs(Widget):
|
||||
def __init__(self, headers: list[Tab]):
|
||||
self.headers = headers
|
||||
super().__init__()
|
||||
|
||||
def action_highlight(self, header: str):
|
||||
log(f"action_header_clicked {header}")
|
||||
|
||||
def render(self) -> RenderableType:
|
||||
return TabsRenderable(self.headers)
|
||||
|
||||
Reference in New Issue
Block a user