Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions chartlets.js/CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## Version 0.1.8 (in development)

* Fixed handling of `style` prop in `Tabs` component and added prop
`iconPosition`. (#135)
Comment thread
clarasb marked this conversation as resolved.
Outdated

## Version 0.1.7 (from 2025/12/03)

* Updated dependencies
Expand Down
1,448 changes: 763 additions & 685 deletions chartlets.js/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion chartlets.js/packages/demo/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "chartlets-demo",
"version": "0.1.8.dev0",
"version": "0.1.8-dev.0",
"description": "Demonstrator for the Chartlets framework.",
"type": "module",
"files": [
Expand Down
2 changes: 1 addition & 1 deletion chartlets.js/packages/lib/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "chartlets",
"version": "0.1.8.dev0",
"version": "0.1.8-dev.0",
"description": "An experimental library for integrating interactive charts into existing JavaScript applications.",
"type": "module",
"files": [
Expand Down
12 changes: 8 additions & 4 deletions chartlets.js/packages/lib/src/plugins/mui/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import { Box } from "@/plugins/mui/Box";
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" | undefined;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we have undefined here?
Also, in the API docs https://mui.com/material-ui/api/tab/, the default is set to top. If you change that to undefined, does it affect it in any way?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, undefined shouldn't be here. I removed it.

disabled?: boolean;
children?: ComponentProps[];
}
Expand Down Expand Up @@ -44,21 +45,23 @@ export function Tabs({
}
};
return (
<MuiBox sx={{ width: "100%" }}>
<MuiBox sx={{ width: "100%" }} style={style}>
<MuiBox sx={{ borderBottom: 1, borderColor: "divider" }}>
<MuiTabs id={id} style={style} value={value} onChange={handleChange}>
<MuiTabs id={id} value={value} onChange={handleChange}>
{tabItems?.map((tab, index) => {
const tabState = isComponentState(tab)
? (tab as TabState)
: undefined;
return (
<MuiTab
key={index}
style={tabState?.style}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we apply the same style to both the Tab button and body, was this a design decision? or does it needs discussion?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, this enables a user to apply styling to the entire Tab component (Button in the header + body).

Before this change it was only possible to change the styling of the button and the user had no styling control over the content (body) of the Tab (see #135).

However, this desicion was not discussed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@b-yogesh is right, using the same style for both cannot be right.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I applied your change requests. Now, the style of the Tab component gets applied only to the Tab button, the styling of the Tab content needs to be managed by the children of the Tab component.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you share a screenshot of this new demo looks like with the style-specific children in Tab content?

label={tabState ? tabState.label : isString(tab) ? tab : ""}
icon={
tabState &&
tabState.icon && <MuiIcon>{tabState.icon}</MuiIcon>
}
iconPosition={tabState?.iconPosition}
disabled={disabled || (tabState && tabState.disabled)}
/>
);
Expand All @@ -70,10 +73,11 @@ export function Tabs({
return (
value === index && (
<Box
style={tabState?.style}
key={index}
type={type}
onChange={onChange}
children={tabState?.children ?? undefined}
children={tabState?.children}
/>
)
);
Expand Down
6 changes: 4 additions & 2 deletions chartlets.py/CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## Version 0.1.8 (in development)

* Added `iconPosition` to `Tabs` Component. (#135)
Comment thread
clarasb marked this conversation as resolved.
Outdated

## Version 0.1.7 (from 2025/12/03)

* Updated dependencies
Expand All @@ -11,10 +13,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)
Expand Down
6 changes: 6 additions & 0 deletions chartlets.py/chartlets/components/tabs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,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."""

Expand Down
94 changes: 77 additions & 17 deletions chartlets.py/demo/my_extension/my_panel_8.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,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
Expand Down Expand Up @@ -37,25 +44,57 @@ 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": "250px", "margin": "30px"},
)

info_text = Typography(
id="info_text", children=["This is a text."], style={"color": "pink"}
)

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=[info_text])
tab3 = Tab(
id="tab3",
label="Tab 3",
children=[chart],
style={
"color": "darkseagreen",
"backgroundColor": "darkgreen",
"padding": "1px",
},
)

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={
Expand All @@ -64,6 +103,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!",
)