diff --git a/chartlets.js/CHANGES.md b/chartlets.js/CHANGES.md index cab1a85..229c788 100644 --- a/chartlets.js/CHANGES.md +++ b/chartlets.js/CHANGES.md @@ -9,6 +9,9 @@ * Added icon support for `Button`, `IconButton` and `Tabs` components. (#124). +* Fixed handling of `style` prop in `Tabs` component and added prop + `iconPosition`. (#135, #136) + ## Version 0.1.7 (from 2025/12/03) * Updated dependencies diff --git a/chartlets.js/packages/lib/src/plugins/mui/Tabs.tsx b/chartlets.js/packages/lib/src/plugins/mui/Tabs.tsx index 1a9c288..fc2b26c 100644 --- a/chartlets.js/packages/lib/src/plugins/mui/Tabs.tsx +++ b/chartlets.js/packages/lib/src/plugins/mui/Tabs.tsx @@ -15,10 +15,11 @@ import { Icon } from "./Icon"; import { isString } from "@/utils/isString"; import { isComponentState } from "@/types/state/component"; -interface TabState { +interface TabState extends ComponentState { type: "Tab"; label?: string; icon?: string; + iconPosition?: "bottom" | "end" | "start" | "top"; disabled?: boolean; children?: ComponentProps[]; } @@ -50,9 +51,9 @@ export function Tabs({ } }; return ( - + - + {tabItems?.map((tab, index) => { const tabState = isComponentState(tab) ? (tab as TabState) @@ -60,10 +61,12 @@ export function Tabs({ return ( } + iconPosition={tabState?.iconPosition} disabled={disabled || (tabState && tabState.disabled)} /> ); @@ -78,7 +81,7 @@ export function Tabs({ key={index} type={type} onChange={onChange} - children={tabState?.children ?? undefined} + children={tabState?.children} /> ) ); diff --git a/chartlets.py/CHANGES.md b/chartlets.py/CHANGES.md index f318520..9ba3d0b 100644 --- a/chartlets.py/CHANGES.md +++ b/chartlets.py/CHANGES.md @@ -3,6 +3,8 @@ * Added `size` and removed `variant` property from `IconButton` component to align with component in chartlets.js. (#124) +* Added `iconPosition` to `Tabs` Component. (#135, #136) + ## Version 0.1.7 (from 2025/12/03) * Updated dependencies @@ -14,10 +16,10 @@ ## Version 0.1.5 (from 2025/03/21) -* Add `multiple` property for `Select` component to enable the +* Added `multiple` property for `Select` component to enable the selection of multiple elements. -* Add support for `Python 3.13` +* Added support for `Python 3.13` ## Version 0.1.4 (from 2025/03/06) diff --git a/chartlets.py/chartlets/components/tabs.py b/chartlets.py/chartlets/components/tabs.py index b470b17..a211aaa 100644 --- a/chartlets.py/chartlets/components/tabs.py +++ b/chartlets.py/chartlets/components/tabs.py @@ -16,6 +16,12 @@ class Tab(Component): icon: str | None = None """The tab icon's name.""" + iconPosition: str | None = None + """ The position of the icon relative to the label. + One of "bottom" | "end" | "start" | "top". + Defaults to "top". + """ + label: str | None = None """The tab label.""" diff --git a/chartlets.py/demo/my_extension/my_panel_8.py b/chartlets.py/demo/my_extension/my_panel_8.py index b3d28cc..4fa7172 100644 --- a/chartlets.py/demo/my_extension/my_panel_8.py +++ b/chartlets.py/demo/my_extension/my_panel_8.py @@ -5,8 +5,15 @@ import altair as alt from chartlets import Component, Input, State, Output -from chartlets.components import (Tabs, Tab, Typography, Box, - VegaChart, Table) +from chartlets.components import ( + Tabs, + Tab, + Typography, + Box, + VegaChart, + Table, + Button, +) from chartlets.components.table import TableColumn, TableRow from server.context import Context @@ -41,25 +48,48 @@ def render_panel( ["3", "Peter", "Jones", 40], ] - table = Table(id="table", rows=rows, columns=columns, hover=True) + open_button = Button( + id="open_button", text="Show component!", style={"margin": "20px"} + ) + + table = Table( + id="table", + rows=rows, + columns=columns, + hover=True, + style={"width": "100%", "padding": "2px"}, + ) - info_text = Typography(id="info_text", children=["This is a text."]) chart = VegaChart( - id="chart", chart=( - alt.Chart(dataset) - .mark_bar() - .encode( - x=alt.X("x:N", title="x"), - y=alt.Y("a:Q", title="a")) - .properties(width=290, height=300, title="Vega charts") - ), style={"flexGrow": 1} + id="chart", + chart=( + alt.Chart(dataset) + .mark_bar() + .encode(x=alt.X("x:N", title="x"), y=alt.Y("a:Q", title="a")) + .properties(width=290, height=300, title="Vega charts") + ), + style={"flexGrow": 1, "margin": "10px"}, ) - tab1 = Tab(id = "tab1", label="Tab 1", children=[table]) - tab2 = Tab(id = "tab2", label="Tab 2", children=[info_text]) - tab3 = Tab(id="tab3", label="Tab 3", children=[chart]) + tab1 = Tab( + id="tab1", + label="Tab 1", + children=[table], + style={"backgroundColor": "darkblue", "padding": "1px"}, + ) + tab2 = Tab(id="tab2", label="Tab 2", children=["This is a text."], disabled=True) + tab3 = Tab( + id="tab3", + label="Tab 3", + children=[chart], + ) - tabs = Tabs(id = "tabs", value = 0, children=[tab1,tab2,tab3]) + tabs = Tabs( + id="tabs", + value=0, + children=[tab1, tab2, tab3], + style={"visibility": "hidden"}, + ) return Box( style={ @@ -68,6 +98,27 @@ def render_panel( "width": "100%", "height": "100%", }, - children=[ tabs ], + children=[open_button, tabs], ) + +# noinspection PyUnusedLocal +@panel.callback( + Input("open_button", "clicked"), + Input("tabs", "style"), + Output("tabs", "style"), + Output("open_button", "text"), +) +def tabs_on_open(ctx: Context, button, style) -> tuple[dict, str]: + visibility = style["visibility"] + + if visibility == "hidden": + return ( + {**style, "visibility": "visible"}, + "Hide component!", + ) + else: + return ( + {**style, "visibility": "hidden"}, + "Show component!", + )