Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ Returns a `PivotTableResult` dict containing the current `config` state and opti
| `filters` | `dict[str, dict[str, list[Any]]] \| None` | `None` | Initial user-facing dimension filters stored in the frontend config. Maps field name to `{"include": [...]}` or `{"exclude": [...]}`. Values are matched using **resolved-value semantics** (same as the interactive header-menu filter): for dates compare at the effective grain (e.g. `"2023 Q1"`), for null buckets use the display string (e.g. `"(empty)"`). Any filter key not already in `filter_fields` or the current `rows`/`columns` layout is automatically added to `filter_fields` so there is never a hidden active filter. Use `source_filters` for server-only filters that should not be exposed to the user. |
| `filter_fields` | `list[str] \| None` | `None` | Ordered list of dimension fields to place in the Filters zone. Fields appear as interactive chips in the FilterBar (when sections are expanded) and in the Settings panel's Filters zone. A field can be in both `rows`/`columns` and `filter_fields` simultaneously (dual-role). |
| `show_sections` | `bool \| None` | `True` | Whether the toolbar sections (Rows, Columns, Values cards and FilterBar) are expanded. `False` collapses them into a compact single-line summary that still shows active-filter count. Users can toggle interactively with the collapse/expand button. |
| `show_toolbar` | `bool` | `True` | Whether to render the interactive toolbar. Set to `False` to hide the Rows, Columns, Values, Filters, and toolbar controls while keeping the pivot table visible. |
| `source_filters` | `dict[str, dict[str, list[Any]]] \| None` | `None` | Server-only report-level filters applied before any pivot processing. `include` takes precedence over `exclude`. `None` matches null-like values, `""` matches only literal empty strings, and no type coercion is performed. |
| `member_groups` | `list[MemberGroup] \| None` | `None` | *(0.6.0+)* Custom dimension-value groupings. Each entry combines one or more raw dimension members into a single named group that is shown in the pivot instead of the individual members. See [Custom Member Grouping](#custom-member-grouping-060). |

Expand Down
11 changes: 11 additions & 0 deletions streamlit_pivot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ class PivotConfig(TypedDict, total=False):
filters: dict[str, dict[str, list[Any]]]
filter_fields: list[str]
show_sections: bool
show_toolbar: bool
top_n_filters: list[TopNFilterFull]
value_filters: list[ValueFilterFull]
values_axis: str
Expand Down Expand Up @@ -3276,6 +3277,7 @@ def _default_config(
filters: dict[str, dict[str, list[Any]]] | None = None,
filter_fields: list[str] | None = None,
show_sections: bool | None = None,
show_toolbar: bool = True,
top_n_filters: list[TopNFilterFull] | None = None,
value_filters: list[ValueFilterFull] | None = None,
values_axis: Literal["columns", "rows"] = "columns",
Expand Down Expand Up @@ -3391,6 +3393,8 @@ def _default_config(
cfg["filter_fields"] = effective_filter_fields
if show_sections is not None:
cfg["show_sections"] = show_sections
if not show_toolbar:
cfg["show_toolbar"] = False
if top_n_filters:
cfg["top_n_filters"] = top_n_filters
if value_filters:
Expand Down Expand Up @@ -3552,6 +3556,7 @@ def st_pivot_table(
filters: dict[str, dict[str, list[Any]]] | None = None,
filter_fields: list[str] | None = None,
show_sections: bool | None = None,
show_toolbar: bool = True,
# 0.5.0: analytical filtering
top_n_filters: list[TopNFilterFull] | None = None,
value_filters: list[ValueFilterFull] | None = None,
Expand Down Expand Up @@ -3676,6 +3681,9 @@ def st_pivot_table(
toggle the state interactively with the collapse/expand button in the
toolbar. Pass ``False`` to start in the compact view when screen
real-estate is limited.
show_toolbar : bool
Whether to render the interactive toolbar. Defaults to ``True``. Pass
``False`` to hide the toolbar while keeping the pivot table visible.
null_handling : str or dict[str, str] or None
How to treat null/NaN values. Global mode ("exclude", "zero",
"separate") or per-field dict mapping column names to modes.
Expand Down Expand Up @@ -4059,6 +4067,8 @@ def st_pivot_table(
raise TypeError(
f"show_sections must be a bool or None, got {type(show_sections).__name__}"
)
if not isinstance(show_toolbar, bool):
raise TypeError(f"show_toolbar must be a bool, got {type(show_toolbar).__name__}")

if not isinstance(collapse_row_groups, bool):
raise TypeError(
Expand Down Expand Up @@ -4878,6 +4888,7 @@ def _validate_single_sort_cfg(sc: dict, param_name: str) -> None:
filters=filters,
filter_fields=filter_fields,
show_sections=show_sections,
show_toolbar=show_toolbar,
top_n_filters=top_n_filters,
value_filters=value_filters,
values_axis=values_axis,
Expand Down
18 changes: 18 additions & 0 deletions streamlit_pivot/frontend/src/PivotRoot.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,24 @@ describe("PivotRoot - FilterBar rendering", () => {
await flush();
expect(screen.queryByTestId("filter-bar")).not.toBeInTheDocument();
});

it("does not render the toolbar when show_toolbar=false", async () => {
const props = makeBaseProps({
config: makeConfig({
rows: ["region"],
columns: [],
values: ["revenue"],
filter_fields: ["category"],
show_toolbar: false,
}),
dataframe: makeSimpleDataframe(),
original_column_types: {},
});
render(<PivotRoot {...props} />);
await flush();
expect(screen.queryByTestId("filter-bar")).not.toBeInTheDocument();
expect(screen.queryByTestId("pivot-toolbar")).not.toBeInTheDocument();
});
});

describe("PivotRoot - handleRemoveFilterField", () => {
Expand Down
3 changes: 2 additions & 1 deletion streamlit_pivot/frontend/src/PivotRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1098,7 +1098,7 @@ const PivotRoot: FC<PivotRootProps> = ({
>
<WarningBanner messages={allWarnings} />

{currentConfig.interactive && (
{currentConfig.interactive && currentConfig.show_toolbar !== false && (
<Toolbar
instanceKey={instanceKey}
config={currentConfig}
Expand Down Expand Up @@ -1130,6 +1130,7 @@ const PivotRoot: FC<PivotRootProps> = ({
{((currentConfig.filter_fields?.length ?? 0) > 0 ||
Object.keys(currentConfig.filters ?? {}).length > 0 ||
(currentConfig.member_groups?.length ?? 0) > 0) &&
currentConfig.show_toolbar !== false &&
currentConfig.show_sections !== false &&
pivotData && (
<FilterBar
Expand Down
16 changes: 16 additions & 0 deletions streamlit_pivot/frontend/src/config/Toolbar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3164,6 +3164,22 @@ describe("validatePivotConfigV1 - filter_fields and show_sections", () => {
expect(result.show_sections).toBe(false);
});

it("passes through show_toolbar=false", () => {
const raw = {
version: 1,
rows: [],
columns: [],
values: [],
aggregation: {},
show_totals: false,
empty_cell_value: "",
interactive: true,
show_toolbar: false,
};
const result = validatePivotConfigV1(raw);
expect(result.show_toolbar).toBe(false);
});

it("strips empty filter_fields (not stored when empty)", () => {
const raw = {
version: 1,
Expand Down
4 changes: 4 additions & 0 deletions streamlit_pivot/frontend/src/engine/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ export interface PivotConfigV1 {
/** Whether the toolbar sections (Rows/Columns/Values cards + FilterBar) are expanded.
* Defaults to true (expanded). Set to false to collapse to a compact one-line summary. */
show_sections?: boolean;
/** Whether to render the toolbar at all. */
show_toolbar?: boolean;
/**
* 0.5.0: Top N / Bottom N filters applied to row or column dimension members.
* Evaluated per-parent after member (include/exclude) filters.
Expand Down Expand Up @@ -1771,6 +1773,8 @@ export function validatePivotConfigV1(obj: unknown): PivotConfigV1 {
result.filter_fields = o.filter_fields as string[];
if (typeof o.show_sections === "boolean")
result.show_sections = o.show_sections;
if (typeof o.show_toolbar === "boolean")
result.show_toolbar = o.show_toolbar;

// top_n_filters and value_filters: structural checks only here (types, enum values).
// Semantic validation (field/by references against declared dims/measures) is done
Expand Down
42 changes: 42 additions & 0 deletions tests/test_filter_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,48 @@ def test_show_sections_invalid_type_raises(sample_df, pivot_module, mount_record
)


# ---------------------------------------------------------------------------
# show_toolbar — toolbar visibility
# ---------------------------------------------------------------------------


def test_show_toolbar_false_passes_through(sample_df, pivot_module, mount_recorder):
calls = mount_recorder()
pivot_module.st_pivot_table(
sample_df,
key="pivot",
rows=["Region"],
values=["Revenue"],
show_toolbar=False,
)
cfg = calls[0]["default"]["config"]
assert cfg["show_toolbar"] is False


def test_show_toolbar_default_is_omitted(sample_df, pivot_module, mount_recorder):
calls = mount_recorder()
pivot_module.st_pivot_table(
sample_df,
key="pivot",
rows=["Region"],
values=["Revenue"],
)
cfg = calls[0]["default"]["config"]
assert "show_toolbar" not in cfg


def test_show_toolbar_invalid_type_raises(sample_df, pivot_module, mount_recorder):
mount_recorder()
with pytest.raises(TypeError, match="show_toolbar must be a bool"):
pivot_module.st_pivot_table(
sample_df,
key="pivot",
rows=["Region"],
values=["Revenue"],
show_toolbar="yes",
)


# ---------------------------------------------------------------------------
# Interaction: filters are applied to source data in client_only mode
# ---------------------------------------------------------------------------
Expand Down