Skip to content

Commit 4679ff1

Browse files
authored
Merge pull request #74 from posit-dev/feat-gt-add-divider
feat: `gt_add_divider()`
2 parents 4677b24 + c04ef69 commit 4679ff1

File tree

5 files changed

+198
-7
lines changed

5 files changed

+198
-7
lines changed

docs/_quarto.yml

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ quartodoc:
3838

3939
sections:
4040
- title: Plotting
41-
desc: "" # TODO: add desc
41+
desc: >
42+
Functions to create various types of visualizations, such as bars, dots,
43+
and win/loss charts, directly within columns of your existing `GT` objects.
4244
contents:
4345
- gt_plt_bar
4446
- gt_plt_bar_stack
@@ -48,14 +50,19 @@ quartodoc:
4850
- gt_plt_winloss
4951

5052
- title: Colors
51-
desc: "" # TODO: add desc
53+
# TODO: revisit desc
54+
desc: >
55+
Functions to apply color-based formatting, highlight specific columns, or create colorful
56+
styles with palettes that are easy on the eye.
5257
contents:
5358
- gt_color_box
5459
- gt_highlight_cols
5560
- gt_hulk_col_numeric
5661

5762
- title: Themes
58-
desc: Functions to generate themes.
63+
desc: >
64+
Predefined themes to style `GT` objects, inspired by popular design styles such as ESPN,
65+
The Guardian, and Excel.
5966
contents:
6067
- gt_theme_538
6168
- gt_theme_dark
@@ -67,16 +74,23 @@ quartodoc:
6774
- gt_theme_pff
6875

6976
- title: Icons and Images
70-
desc: "" # TODO: add desc
77+
# TODO: revisit desc
78+
desc: >
79+
Functions to enhance `GT` objects by adding icons, ratings, or images to cells
80+
or headers alike.
7181
contents:
7282
- fa_icon_repeat
7383
- gt_fa_rating
7484
- img_header
7585

76-
- title: HTML and Formatting
77-
desc: "" # TODO: add desc
86+
- title: Utilities
87+
# TODO: revisit desc
88+
desc: >
89+
Helper functions to extend `GT` functionality, including HTML features
90+
and formatting tools.
7891
contents:
7992
- fmt_pct_extra
93+
- gt_add_divider
8094
- gt_hyperlink
8195
- with_tooltip
8296

docs/styles.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
--bs-body-bg: white;
33
}
44

5-
.sidebar {
5+
.sidebar-navigation {
66
background-color: white !important;
77
}
88

gt_extras/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
from .images import img_header
3131

32+
from .styling import gt_add_divider
33+
3234

3335
__all__ = [
3436
"gt_theme_538",
@@ -54,4 +56,5 @@
5456
"with_tooltip",
5557
"fmt_pct_extra",
5658
"img_header",
59+
"gt_add_divider",
5760
]

gt_extras/styling.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
from __future__ import annotations
2+
from typing import Literal
3+
4+
from great_tables import GT, style, loc
5+
from great_tables._tbl_data import SelectExpr
6+
7+
8+
__all__ = ["gt_add_divider"]
9+
10+
11+
def gt_add_divider(
12+
gt: GT,
13+
columns: SelectExpr,
14+
sides: (
15+
Literal["right", "left", "top", "bottom", "all"]
16+
| list[Literal["right", "left", "top", "bottom", "all"]]
17+
) = "right",
18+
color: str = "grey",
19+
divider_style: Literal["solid", "dashed", "dotted", "hidden", "double"] = "solid",
20+
weight: int = 2,
21+
include_labels: bool = True,
22+
) -> GT:
23+
"""
24+
Add dividers to specified columns in a GT table.
25+
26+
The `gt_add_divider()` function takes an existing `GT` object and adds dividers to the specified
27+
columns. Dividers can be applied to one or more sides of the cells, with customizable color,
28+
style, and weight. Optionally, dividers can also be applied to column labels.
29+
30+
Parameters
31+
----------
32+
gt
33+
A `GT` object to modify.
34+
35+
columns
36+
The columns to which dividers should be applied.
37+
38+
sides
39+
The sides of the cells where dividers should be added. Options include `"right"`, `"left"`,
40+
`"top"`, `"bottom"`, or `"all"`. A list of sides can also be provided to apply dividers to
41+
multiple sides.
42+
43+
color
44+
The color of the dividers.
45+
46+
divider_style
47+
The style of the dividers. Options include `"solid"`, `"dashed"`, `"dotted"`, `"hidden"`,
48+
and `"double"`.
49+
50+
weight
51+
The thickness of the dividers in pixels.
52+
53+
include_labels
54+
Whether to include dividers in the column labels. If `True`, dividers will be applied to
55+
both the body and the column labels. If `False`, dividers will only be applied to the body.
56+
57+
Returns
58+
-------
59+
GT
60+
A `GT` object with dividers added to the specified columns.
61+
62+
Examples
63+
--------
64+
```{python}
65+
import pandas as pd
66+
from great_tables import GT
67+
from great_tables.data import peeps
68+
import gt_extras as gte
69+
70+
peeps_mini = peeps.head(6)
71+
72+
gt = (
73+
GT(peeps_mini)
74+
.cols_hide([
75+
"name_family", "postcode", "country", "country_code",
76+
"dob", "gender", "state_prov", "email_addr",
77+
])
78+
.tab_spanner("Location", ["address", "city"])
79+
.tab_spanner("Body Measurements", ["height_cm", "weight_kg"])
80+
)
81+
82+
gt.pipe(
83+
gte.gt_add_divider,
84+
columns="name_given",
85+
color="#FFB90F",
86+
divider_style="double",
87+
weight=8,
88+
).pipe(
89+
gte.gt_add_divider,
90+
columns="phone_number",
91+
color="purple",
92+
sides=["right", "left"],
93+
weight=5,
94+
)
95+
```
96+
"""
97+
98+
locations = [loc.body(columns=columns)]
99+
100+
if include_labels:
101+
locations.append(loc.column_labels(columns=columns))
102+
103+
res = gt.tab_style(
104+
style=style.borders(
105+
sides=sides,
106+
color=color,
107+
weight=weight,
108+
style=divider_style,
109+
),
110+
locations=locations,
111+
)
112+
113+
return res

gt_extras/tests/test_styling.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import pytest
2+
import pandas as pd
3+
from great_tables import GT
4+
5+
from gt_extras.styling import gt_add_divider
6+
7+
8+
@pytest.fixture
9+
def sample_gt():
10+
sample_df = pd.DataFrame({"A": [1, 2], "B": [3, 4], "C": [5, 6]})
11+
return GT(sample_df)
12+
13+
14+
def test_gt_add_divider_basic(sample_gt):
15+
html = gt_add_divider(sample_gt, columns="A").as_raw_html()
16+
17+
assert html.count("border-right:") == 3
18+
assert html.count("2px solid grey") == 3
19+
20+
21+
def test_gt_add_divider_multiple_columns(sample_gt):
22+
html = gt_add_divider(sample_gt, columns=["A", "B"]).as_raw_html()
23+
24+
assert html.count("border-right: 2px solid grey") == 2 * 3
25+
26+
27+
def test_gt_add_divider_custom_sides(sample_gt):
28+
html = gt_add_divider(sample_gt, columns="A", sides="left").as_raw_html()
29+
30+
assert html.count("border-left:") == 3
31+
assert "border-right:" not in html
32+
33+
34+
def test_gt_add_divider_custom_color_and_style(sample_gt):
35+
res = gt_add_divider(sample_gt, columns="A", color="blue", divider_style="dashed")
36+
html = res.as_raw_html()
37+
38+
assert "border-right: 2px dashed blue;" in html
39+
assert "grey" not in html
40+
41+
42+
def test_gt_add_divider_custom_weight(sample_gt):
43+
html = gt_add_divider(sample_gt, columns="A", weight=5).as_raw_html()
44+
45+
assert "border-right: 5px solid grey;" in html
46+
assert "2px solid grey" not in html
47+
48+
49+
def test_gt_add_divider_exclude_labels(sample_gt):
50+
html = gt_add_divider(sample_gt, columns="A", include_labels=False).as_raw_html()
51+
52+
assert html.count("border-right:") == 2
53+
54+
55+
def test_gt_add_divider_multiple_sides(sample_gt):
56+
html = gt_add_divider(sample_gt, columns="A", sides=["top", "bottom"]).as_raw_html()
57+
58+
assert "border-top:" in html
59+
assert "border-bottom:" in html
60+
assert "border-right:" not in html
61+
assert "border-left:" not in html

0 commit comments

Comments
 (0)