Open corey-dawson opened 3 months ago
Good news! You can do this manually as of #1475 . That PR will be released in the v1.0.0 release shortly.
Type information for each StyleInfo
item in styles=
for render.DataGrid
and render.DataTable
objects being returned in a @render.data_frame
output function:
StyleInfoBody = TypedDict(
"StyleInfoBody",
{
"location": Required[Literal["body"]],
"rows": NotRequired[Union[int, ListOrTuple[int], ListOrTuple[bool], None]],
"cols": NotRequired[
Union[str, int, ListOrTuple[str], ListOrTuple[int], ListOrTuple[bool], None]
],
"style": NotRequired[Union[Dict[str, Jsonifiable], None]],
"class": NotRequired[Union[str, None]],
},
)
StyleInfo = StyleInfoBody
Example
import pandas as pd
from shiny.express import render
df_styles = [
{
"location": "body",
"rows": [2, 4],
"cols": [2, 4],
"style": {
"background-color": "coral",
},
}
]
n = 6
df = pd.DataFrame(
{
"a": range(n),
"b": range(n, n * 2),
"c": range(n * 2, n * 3),
"d": range(n * 3, n * 4),
"e": range(n * 4, n * 5),
}
)
@render.data_frame
def my_df():
return render.DataGrid(
df,
styles=df_styles,
)
We are continuing to explore using great_tables
as a way to set the styles and formatting of the cells. But for the v1 release, we ran into more problems than we were willing to let slide. However, integrating great_tables
is still my end goal as its API to define lazy expressions that can create conditional formatting is very convenient!
For now, you'll need to define the style information yourself. 🫤 But at least it can be defined! 🥳
(Leaving issue open as conditional styling has not be implemented. Only cell styling.)
This is great and a very good solution for the 1.0. Thank you. Can styles manage also columns width? Or will it be addressed in a different way?
Yes! ... a pleasant surprise!
import pandas as pd
from shiny.express import render
df_styles = [
{
"location": "body",
"rows": [2, 4],
"cols": [2, 4],
"style": {
"background-color": "coral",
"width": "300px",
"height": "100px",
},
}
]
n = 6
df = pd.DataFrame(
{
"a": range(n),
"b": range(n, n * 2),
"c": range(n * 2, n * 3),
"d": range(n * 3, n * 4),
"e": range(n * 4, n * 5),
}
)
@render.data_frame
def my_df():
return render.DataGrid(
df,
styles=df_styles,
)
Maybe I miss something, but if we wanted to style 14 and 28 how is it done (ie both rows and both columns but not combinatorial)? Two dictionaries in the styles array?
if we wanted to style 14 and 28 how is it done (ie both rows and both columns but not combinatorial)? Two dictionaries in the styles array?
If rows
is missing, or None
, then the corresponding style
or class
values will be applied to all rows. Same goes for cols
. If cols
is missing or None
, then the style
or class
values will be applied to all columns.
If both rows
and cols
are supplied, then the combination of all rows
and cols
values will be made and their corresponding style
or class
values will be applied. If no rows
or cols
are supplied, then it will be applied to every cell.
Obviously it is nice to have multiple style definitions for different locations, so multiple StyleInfo
objects can be supplied to the styles=
parameter.
Updating the example above...
import pandas as pd
from shiny.express import render
df_styles = [
{
"location": "body",
"style": {
"background-color": "lightblue",
"border": "transparent",
"color": "transparent",
},
},
{
"location": "body",
"rows": [2],
"cols": [2],
"style": {
"background-color": "yellow",
"width": "100px",
"height": "75px",
},
},
{
"location": "body",
"cols": [1, 3, 5, 7],
"style": {
"background-color": "yellow",
},
},
{
"location": "body",
"rows": [3],
"cols": [7],
"style": {
"background-color": "lightblue",
},
},
]
n = 5
df = pd.DataFrame(
{
"a": range(n),
"b": range(n, n * 2),
"c": range(n * 2, n * 3),
"d": range(n * 3, n * 4),
"e": range(n * 4, n * 5),
"f": range(n * 5, n * 6),
"g": range(n * 6, n * 7),
"h": range(n * 7, n * 8),
"i": range(n * 8, n * 9),
}
)
@render.data_frame
def my_df():
return render.DataGrid(
df,
styles=df_styles,
)
Thanks. Really looking forward to this!
Amazing! Thank you.
How do I apply styles to table column headers?
@slackmodel Currently there is no support for conditional styling for table headers.
However you can do regular css styling that applies to them.
Right now, there doesn't seem to be any options for conditionally coloring rows and cells in dataframe outputs (datagrid and datatable). This is especially important for analytical dashboards and data. Requesting a new feature or any recommendations on how to achieve conditional coloring in Python Shiny's current state