Skip to content

themeing

rovr can be themed in two ways, via the config.toml file and styles.tcss file.

the config has a way to define themes using variables

[[custom_theme]]
name = "<name>"
primary = "<color>"
secondary = "<color>"
warning = "<color>"
error = "<color>"
success = "<color>"
accent = "<color>"
foreground = "<color>"
background = "<color>"
surface = "<color>"
panel = "<color>"
is_dark = true
variables = { "<var>" = "<key>" }

you can take a look at the reference in textual, or the table below

namedescription
namethe name of the theme
primarythe primary color, can be considered the branding color.
secondaryan alternative branding color.
warningthe default text color, which should be legible on background, surface, and panel.
errora color used for the background, where there is no content.
successthe default background color of widgets, typically sitting on top of background.
accenta color used to differentiate a part of the ui form the main content.
foregrounda color with alpha that can be used to create layers on a background.
backgroundindicates a warning. typically used as a background color.
surfaceindicates an error. typically used as a background color.
panelused to indicate success. typically used as a background color.
is_darkused sparingly to draw attention and contrasts with primary and secondary
variablescustom variables that are used by textual. variables

styling in textual is handled by tcss files, a simplified version of the web’s css. a reference is available in the textual docs

the dom for the app is currently like this

Vertical(id="root")
HeaderArea(id="headerArea") -> HorizontalGroup
HeaderClock()
Tabline() -> Tabs
TablineTab() -> Tab
HorizontalGroup(id="newTabRight")
NewTabButton() -> Button
Static()
HorizontalScroll(id="menu")
CopyButton() -> Button
CutButton() -> Button
PasteButton() -> Button
NewItemButton() -> Button
RenameItemButton() -> Button
DeleteButton() -> Button
ZipButton() -> Button
UnzipButton() -> Button
VerticalGroup(id="below_menu")
HorizontalGroup()
BackButton() -> Button
ForwardButton() -> Button
UpButton() -> Button
RefreshButton() -> Button
PathInput() -> Input
PathAutoCompleteInput() -> PathAutoComplete
HorizontalGroup(id="main")
VerticalGroup(id="pinned_sidebar_container")
SearchInput() -> Input
PinnedSidebar(id="pinned_sidebar") -> OptionList
PinnedSidebarOption() -> Option
VerticalGroup(id="file_list_container")
SearchInput() -> Input
FileList(id="file_list", class="file-list") -> SelectionList
FileListSelectionWidget() -> Selection
PreviewContainer(id="preview_sidebar") -> Container
Image(id="image_preview", class="inner_preview")
CustomTextArea(id="text_preview") -> TextArea
Static(id="text_preview", class="inner_preview")
FileList(
id="folder_preview",
class="file-list inner_preview"
) -> SelectionList
FileList(id="archive_preview", class="file-list inner_preview") -> SelectionList
FileListSelectionWidget() -> Selection
HorizontalGroup(id="footer")
ProcessContainer() -> VerticalScroll
ProgressBarContainer() -> VerticalGroup
ProgressBar()
Label()
MetadataContainer(id="metadata") -> VerticalScroll
Clipboard(id="clipboard") -> SelectionList
ClipboardSelection() -> Selection

tcss works the same as css, so, if you want to target the FileList inside the #file_list_container you can do

#file_list_container > FileList {
...
}

however, if you took at the dom above, or a truncated dom below

HorizontalGroup(id="main")
VerticalGroup(id="file_list_container")
FileList(id="file_list", class="file-list") -> SelectionList
FileListSelectionWidget() -> Selection

you can notice the SelectionList part. it aims to emphasise that the FileList is based off a SelectionList (which itself is based off OptionList)