Skip to content

Commit 6973fc0

Browse files
fix(tabs): Added function to generate tabs_hidden variables
1 parent c7ee38d commit 6973fc0

2 files changed

Lines changed: 82 additions & 0 deletions

File tree

python/src/numerous/widgets/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from .base.string import String as String
3636
from .base.table import Table as Table
3737
from .base.tabs import Tabs as Tabs
38+
from .base.tabs import create_tabs_with_visibility as create_tabs_with_visibility
3839
from .base.task import Task as Task
3940
from .base.timer import Timer as Timer
4041
from .base.toggle_button import ToggleButton as ToggleButton

python/src/numerous/widgets/base/tabs.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
"""Module providing a tabs widget for the numerous library."""
22

3+
import re
4+
from typing import Any, NamedTuple
5+
36
import anywidget
47
import traitlets
58

@@ -56,3 +59,81 @@ def __init__(
5659
def selected_value(self) -> str:
5760
"""Returns the currently selected tab."""
5861
return str(self.active_tab)
62+
63+
64+
class TabsWithVisibility(NamedTuple):
65+
"""Container for a Tabs widget and its visibility controllers."""
66+
67+
tabs: Tabs
68+
visibility: list[bool]
69+
70+
71+
def _sanitize_id(name: str) -> str:
72+
"""
73+
Sanitize a name for use in widget IDs.
74+
75+
Args:
76+
name: The name to sanitize
77+
78+
Returns:
79+
Sanitized name: lowercase, spaces to underscore, \
80+
only alphanumeric and underscore
81+
82+
"""
83+
# Convert to lowercase
84+
name = name.lower()
85+
# Replace spaces and hyphens with underscore
86+
name = re.sub(r"[\s-]+", "_", name)
87+
# Remove any characters that aren't alphanumeric or underscore
88+
return re.sub(r"[^\w]", "", name)
89+
90+
91+
def create_tabs_with_visibility(
92+
tabs: list[str],
93+
widget_id: str,
94+
label: str = "",
95+
tooltip: str | None = None,
96+
default: str | None = None,
97+
) -> dict[str, Tabs]:
98+
r"""
99+
Create a Tabs widget with associated visibility booleans.
100+
101+
Args:
102+
tabs: List of tab names
103+
widget_id: Unique identifier for this tab group
104+
label: Label for the tabs widget
105+
tooltip: Optional tooltip text
106+
default: Default active tab (defaults to first tab if None)
107+
108+
Returns:
109+
Dictionary containing the tabs widget and
110+
\visibility booleans keyed by widget_id:
111+
- {widget_id}: Tabs widget
112+
- {widget_id}_{tab_name}: bool indicating if tab should be hidden
113+
114+
"""
115+
# Sanitize widget_id
116+
widget_id = _sanitize_id(widget_id)
117+
118+
# Create the tabs widget
119+
tabs_widget = Tabs(tabs=tabs, label=label, tooltip=tooltip, default=default)
120+
121+
# Create result dictionary with tabs widget
122+
result = {widget_id: tabs_widget}
123+
124+
# Create visibility booleans for each tab
125+
visibility_states = [tab != tabs_widget.active_tab for tab in tabs_widget.tabs]
126+
127+
# Add visibility states to result with sanitized widget_id keys
128+
for tab, hidden in zip(tabs_widget.tabs, visibility_states, strict=False):
129+
result[f"{widget_id}_{_sanitize_id(tab)}"] = hidden
130+
131+
# Set up visibility changes on tab changes
132+
def on_tab_change(event: Any) -> None: # noqa: ANN401
133+
for tab in tabs_widget.tabs:
134+
key = f"{widget_id}_{_sanitize_id(tab)}"
135+
result[key] = tab != event.new
136+
137+
tabs_widget.observe(on_tab_change, names="active_tab")
138+
139+
return result

0 commit comments

Comments
 (0)