Skip to content

Commit

Permalink
Merge pull request #242 from posit-dev/fix-transparent-color
Browse files Browse the repository at this point in the history
Allow the 'transparent' color (and others) to be used in tab_options(table_background_color == <color>) (supersedes previous PR)
  • Loading branch information
machow committed Mar 15, 2024
2 parents 420d5f2 + 7b9fded commit 84eb813
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 58 deletions.
35 changes: 12 additions & 23 deletions great_tables/_data_color/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,8 +414,6 @@ def _html_color(colors: List[str], alpha: Optional[Union[int, float]] = None) ->
all_hex_colors = all(_is_hex_col(colors=colors))

if not all_hex_colors:
# Ensure that all color names are in the set of X11/R color names or CSS color names
_check_named_colors(colors=colors)

# Translate named colors to hexadecimal values
colors = _color_name_to_hex(colors=colors)
Expand Down Expand Up @@ -502,31 +500,22 @@ def _float_to_hex(x: float) -> str:
def _color_name_to_hex(colors: List[str]) -> List[str]:
# If any of the colors are in the color_name_dict, then replace them with the
# corresponding hexadecimal value
i = 0
while i < len(colors):
color = colors[i]
if color.lower() in COLOR_NAME_TO_HEX:
colors[i] = COLOR_NAME_TO_HEX[color.lower()]
i += 1

return colors


def _check_named_colors(colors: Union[str, List[str]]) -> None:
# Ensure that all incoming color names are set in lowercase letters since CSS color names
# are often shown with uppercase letters and X11/R color names are always shown with lowercase
if isinstance(colors, str):
colors = [colors]

valid_color_names = _color_name_list()
hex_colors: List[str] = []

for color in colors:
if not _is_hex_col(colors=[color]) and color not in valid_color_names:
raise ValueError(
f"Invalid color name provided ({color}). Please ensure that all color names are valid."
)

return
if _is_hex_col([color])[0]:
hex_colors.append(color)
else:
try:
hex_colors.append(COLOR_NAME_TO_HEX[color.lower()])
except KeyError:
raise ValueError(
f"Invalid color name provided ({color}). Please ensure that all colors are valid CSS3 or X11 color names."
)

return hex_colors


def _color_name_list() -> List[str]:
Expand Down
34 changes: 22 additions & 12 deletions great_tables/_scss.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import pkg_resources
import re
import webcolors as wc

from dataclasses import fields
from functools import partial
Expand All @@ -11,6 +10,7 @@

from ._gt_data import GTData
from ._utils import _as_css_font_family_attr, _unique_set
from ._data_color.base import _html_color, _ideal_fgnd_color

DEFAULTS_TABLE_BACKGROUND = (
"heading_background_color",
Expand Down Expand Up @@ -39,20 +39,30 @@
)


def font_color(color: str, table_font_color: str, table_font_color_light: str):
if color.startswith("#"):
rgb = wc.hex_to_rgb(color)
elif color.startswith("rgb") and "%" in color:
# TODO: rgb_percent_to_rgb() expects a tuple
raise NotImplementedError()
rgb = wc.rgb_percent_to_rgb(color)
else:
rgb = wc.name_to_rgb(color)
def font_color(color: str, table_font_color: str, table_font_color_light: str) -> str:

if (rgb.red * 0.299 + rgb.green * 0.587 + rgb.blue * 0.114) > 186:
if color == "transparent":
# With the `transparent` color, the font color should have the same value
# as the `table_font_color` option since the background will be transparent
return table_font_color
if color in ["currentcolor", "currentColor"]:
# With two variations of `currentColor` value, normalize to `currentcolor`
return "currentcolor"
if color in ["inherit", "initial", "unset"]:
# For the other valid CSS color attribute values, we should pass them through
return color

# Normalize the color to a hexadecimal value
color_normalized = _html_color(colors=[color])

# Determine the ideal font color given the different background colors
ideal_font_color = _ideal_fgnd_color(
bgnd_color=color_normalized[0],
light=table_font_color,
dark=table_font_color_light,
)

return table_font_color_light
return ideal_font_color


def css_add(value: str | int, amount: int):
Expand Down
20 changes: 10 additions & 10 deletions tests/__snapshots__/test_options.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
line-height: normal;
margin-left: 10px;
margin-right: 10px;
color: lightred;
color: #000000;
font-size: 12px;
font-weight: bold;
font-style: bold;
Expand All @@ -57,7 +57,7 @@
}

#abc .gt_title {
color: lightred;
color: #000000;
font-size: 12px;
font-weight: bold;
padding-top: 5px;
Expand All @@ -69,7 +69,7 @@
}

#abc .gt_subtitle {
color: lightred;
color: #000000;
font-size: 12px;
font-weight: bold;
padding-top: 4px;
Expand Down Expand Up @@ -114,7 +114,7 @@
}

#abc .gt_col_heading {
color: lightred;
color: #000000;
background-color: red;
font-size: 12px;
font-weight: bold;
Expand All @@ -134,7 +134,7 @@
}

#abc .gt_column_spanner_outer {
color: lightred;
color: #000000;
background-color: red;
font-size: 12px;
font-weight: bold;
Expand Down Expand Up @@ -174,7 +174,7 @@
padding-bottom: 5px;
padding-left: 5px;
padding-right: 5px;
color: lightred;
color: #000000;
background-color: red;
font-size: 12px;
font-weight: bold;
Expand All @@ -197,7 +197,7 @@

#abc .gt_empty_group_heading {
padding: 0.5px;
color: lightred;
color: #000000;
background-color: red;
font-size: 12px;
font-weight: bold;
Expand Down Expand Up @@ -238,7 +238,7 @@
}

#abc .gt_stub {
color: lightred;
color: #000000;
background-color: red;
font-size: 12px;
font-weight: bold;
Expand All @@ -251,7 +251,7 @@
}

#abc .gt_stub_row_group {
color: lightred;
color: #000000;
background-color: red;
font-size: 12px;
font-weight: bold;
Expand Down Expand Up @@ -282,7 +282,7 @@
}

#abc .gt_sourcenotes {
color: lightred;
color: #000000;
background-color: red;
border-bottom-style: solid;
border-bottom-width: 5px;
Expand Down
7 changes: 4 additions & 3 deletions tests/data_color/test_data_color_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pandas as pd
import numpy as np
import pytest
from great_tables._data_color.base import (
_ideal_fgnd_color,
_get_wcag_contrast_ratio,
Expand Down Expand Up @@ -318,10 +319,10 @@ def test_color_name_to_hex():

# Test case 6: Colors with invalid names
colors = ["#FF0000", "green", "invalid"]
try:
with pytest.raises(ValueError) as e:
_color_name_to_hex(colors)
except ValueError as e:
assert str(e) == "Invalid color name provided (invalid)."

assert "Invalid color name provided (invalid)" in e.value.args[0]


def test_is_short_hex_valid_short_hex():
Expand Down
13 changes: 7 additions & 6 deletions tests/test_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ def test_options_no_mutate():
css_length_val_margin = "10px"
css_length_val_small = "5px"
css_font_size_val = "12px"
css_font_color_val = "#000000"
css_font_color_val_light = "#FFFFFF"
css_color_val = "red"
css_color_val_light = "lightred"
css_style_val = "solid"
css_font_family_list = ["Arial", "Helvetica", "sans-serif"]
css_font_weight_val = "bold"
Expand Down Expand Up @@ -62,13 +63,13 @@ def gt_tbl():
table_layout="auto",
table_margin_left=css_length_val_margin,
table_margin_right=css_length_val_margin,
table_background_color=css_color_val,
table_background_color="red",
table_font_names=css_font_family_list,
table_font_size=css_font_size_val,
table_font_weight=css_font_weight_val,
table_font_style=css_font_weight_val,
table_font_color=css_color_val,
table_font_color_light=css_color_val_light,
table_font_color=css_font_color_val,
table_font_color_light=css_font_color_val_light,
table_border_top_style=css_style_val,
table_border_top_width=css_length_val_small,
table_border_top_color=css_color_val,
Expand Down Expand Up @@ -191,8 +192,8 @@ def test_options_all_available(gt_tbl: GT):
assert gt_tbl._options.table_font_size.value == css_font_size_val
assert gt_tbl._options.table_font_weight.value == css_font_weight_val
assert gt_tbl._options.table_font_style.value == css_font_weight_val
assert gt_tbl._options.table_font_color.value == css_color_val
assert gt_tbl._options.table_font_color_light.value == css_color_val_light
assert gt_tbl._options.table_font_color.value == css_font_color_val
assert gt_tbl._options.table_font_color_light.value == css_font_color_val_light
assert gt_tbl._options.table_border_top_style.value == css_style_val
assert gt_tbl._options.table_border_top_width.value == css_length_val_small
assert gt_tbl._options.table_border_top_color.value == css_color_val
Expand Down
13 changes: 9 additions & 4 deletions tests/test_scss.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@
@pytest.mark.parametrize(
"src,dst",
[
("#FFFFFF", "dark"),
("#000000", "light"),
("white", "dark"),
("#FFFFFF", "#000000"),
("#000000", "#FFFFFF"),
("white", "#000000"),
("black", "#FFFFFF"),
("silver", "#000000"),
("transparent", "#000000"),
("currentcolor", "currentcolor"),
("currentColor", "currentcolor"),
],
)
def test_font_color(src, dst):
res = font_color(src, "dark", "light")
res = font_color(src, "#000000", "#FFFFFF")
assert res == dst


Expand Down

0 comments on commit 84eb813

Please sign in to comment.