"""
A module implementing interfaces for creating tabbed content with bootstrap.
"""
# third-party
from svgen.element import Element
from svgen.element.html import div
# internal
from runtimepy import PKG_NAME
from runtimepy.net.html import create_app_shell
from runtimepy.net.html.bootstrap.elements import (
BOOTSTRAP_BUTTON,
collapse_button,
flex,
toggle_button,
)
[docs]
def create_nav_container(
parent: Element, name: str, item: str, active_tab: bool
) -> Element:
"""Create a navigation container element."""
content = div(id=f"{name}-{item}", role="tabpanel", parent=parent)
content["aria-labelledby"] = f"{name}-{item}-tab"
content.add_class("tab-pane", "fade")
if active_tab:
content.add_class("show", "active")
return content
[docs]
class TabbedContent:
"""A tabbed-content container."""
[docs]
def add_button(self, msg: str, target: str, **kwargs) -> Element:
"""Add a button to the left side button column."""
return collapse_button(
target,
parent=self.button_column,
tooltip=f"{msg}.",
title=f"{msg} button.",
**kwargs,
)
def __init__(self, name: str, parent: Element) -> None:
"""Initialize this instance."""
self.name = name
self.container, self.button_column = create_app_shell(parent, id=name)
# Toggle tabs button.
self.add_button(
"Toggle tabs",
f"#{PKG_NAME}-tabs",
id="tabs-button",
icon="list-task",
)
# Create tab container.
self.tabs = div(id=f"{PKG_NAME}-tabs", parent=self.container)
self.tabs.add_class(
"nav",
"flex-column",
"flex-shrink-0",
"flex-nowrap",
"nav-pills",
"show",
"h-100",
"overflow-y-scroll",
"overscroll-behavior-none",
)
# Create content container.
self.content = div(id=f"{name}-tabContent", parent=self.container)
self.set_scroll(True)
self.active_tab = True
[docs]
def set_scroll(self, scroll: bool) -> None:
"""Set classes on content element."""
self.content["class"] = ""
self.content.add_class("tab-content", "w-100", "h-100")
if scroll:
self.content.add_class("overflow-scroll")
[docs]
def create(self, name: str) -> tuple[Element, Element]:
"""Only the first tab is active."""
container = flex(parent=self.tabs).add_class("border-start")
# Open in new window button.
toggle_button(
container,
id=name,
icon="window-plus",
title=f"Open '{name}' in a new window.",
tabindex="-1",
).add_class("border-bottom", "window-button", "btn-link")
# Navigate to tab button.
button = create_nav_button(
container,
self.name,
name,
self.active_tab,
tabindex="-1",
class_str="border-bottom border-end flex-grow-1",
)
# Add content.
content = create_nav_container(
self.content, self.name, name, self.active_tab
)
if self.active_tab:
self.active_tab = False
return button, content