Skip to content

Commit 4ddf0f5

Browse files
committed
refactor: Use add methods for brand Sass inclusion
Removes the `_insert_sass()` method to use standard `ui.Theme()` methods
1 parent 39e6390 commit 4ddf0f5

File tree

2 files changed

+52
-70
lines changed

2 files changed

+52
-70
lines changed

shiny/ui/_theme_brand.py

Lines changed: 47 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ def __init__(
5252
mixins: Any = None,
5353
rules: Any = None,
5454
):
55-
5655
# TODO: Remove `path` and handle in try/except block in caller
5756
self._path = path
5857
self.version = version
@@ -183,7 +182,6 @@ def __init__(
183182
*,
184183
include_paths: Optional[str | Path | list[str | Path]] = None,
185184
):
186-
187185
name = self._get_theme_name(brand)
188186
brand_bootstrap = BrandBootstrapConfig.from_brand(brand)
189187

@@ -208,17 +206,25 @@ def __init__(
208206

209207
brand_typography_defaults = ThemeBrand._prepare_typography_vars(brand)
210208

211-
brand_bootstrap_defaults = (
212-
"\n".join(Theme._combine_args_kwargs(kwargs=brand_bootstrap.defaults))
213-
if brand_bootstrap.defaults
214-
else ""
215-
)
209+
# Defaults ----
210+
# Final order is reverse-insertion:
211+
# * brand.color.palette
212+
# * brand.defaults (Brand-defined Bootstrap defaults)
213+
# * brand.color
214+
# * brand.typography
215+
216+
self._add_defaults_hdr("typography", **brand_typography_defaults)
217+
self._add_defaults_hdr("color", **brand_color_defaults)
218+
219+
if brand_bootstrap.defaults:
220+
self._add_defaults_hdr("defaults (bootstrap)", **(brand_bootstrap.defaults))
221+
222+
self._add_defaults_hdr("color.palette", **brand_color_palette_defaults)
216223

217-
self._insert_sass("brand.color.palette:defaults", brand_color_palette_defaults)
218-
self._insert_sass("brand.defaults:defaults", brand_bootstrap_defaults)
219-
self._insert_sass("brand.color:defaults", brand_color_defaults)
220-
self._insert_sass("brand.typography:defaults", brand_typography_defaults)
221-
self._insert_sass("brand.color.palette:rules", brand_color_palette_rules)
224+
# Rules ----
225+
self.add_rules(*brand_color_palette_rules)
226+
227+
# Bootstrap extras: functions, mixins, rules (defaults handled above)
222228
self._add_brand_bootstrap_other(brand_bootstrap)
223229

224230
def _get_theme_name(self, brand: "Brand") -> str:
@@ -227,39 +233,18 @@ def _get_theme_name(self, brand: "Brand") -> str:
227233

228234
return brand.meta.name.short or brand.meta.name.full or "brand"
229235

230-
def _insert_sass(self, name: str, code: str):
231-
name_parts = name.split(":")
232-
if len(name_parts) != 2:
233-
raise ValueError(
234-
f"Invalid name format. Expected 'name:layer', got '{name}'"
235-
)
236-
237-
layer = name_parts[1]
238-
layer_attr = f"_{layer}"
239-
if not hasattr(self, layer_attr):
240-
raise ValueError(f"Invalid layer: {layer}")
241-
242-
layer_content = getattr(self, layer_attr)
243-
insert_marker = f"/*-- insert({name}) --*/"
244-
245-
new_layer_content = [
246-
chunk.replace(insert_marker, code) for chunk in layer_content
247-
]
248-
249-
setattr(self, layer_attr, new_layer_content)
250-
251236
@staticmethod
252237
def _prepare_color_vars(
253238
brand: "Brand",
254-
) -> tuple[str, str, str]:
239+
) -> tuple[dict[str, YamlScalarType], dict[str, YamlScalarType], list[str]]:
255240
"""
256241
Colors: Create a dictionaries of Sass and CSS variables
257242
"""
258243
if not brand.color:
259-
return "", "", ""
244+
return {}, {}, []
260245

261-
defaults_dict: dict[str, str | float | int | bool | None] = {}
262-
palette_defaults_dict: dict[str, str | float | int | bool | None] = {}
246+
defaults_dict: dict[str, YamlScalarType] = {}
247+
palette_defaults_dict: dict[str, YamlScalarType] = {}
263248
palette_css_vars: list[str] = []
264249

265250
for thm_name, thm_color in brand.color.to_dict(include="theme").items():
@@ -289,34 +274,21 @@ def _prepare_color_vars(
289274
# => CSS var: `--brand-{name}: {value}`
290275
palette_css_vars.append(f" --brand-{pal_name}: {pal_color};")
291276

292-
palette_defaults = [
293-
"",
294-
"// *---- brand.color.palette ----* //",
295-
*Theme._combine_args_kwargs(kwargs=palette_defaults_dict, is_default=True),
296-
]
297-
298-
defaults = [
299-
"",
300-
"// *---- brand.color ----* //",
301-
*Theme._combine_args_kwargs(kwargs=defaults_dict, is_default=True),
302-
]
303-
304277
palette_rules = [
305-
"",
306278
"// *---- brand.color.palette ----* //",
307279
":root {",
308280
*palette_css_vars,
309281
"}",
310282
]
311283

312284
return (
313-
"\n".join(palette_defaults), # brand.color.palette:defaults
314-
"\n".join(defaults), # brand.color:defaults
315-
"\n".join(palette_rules), # brand.color.palette:rules
285+
palette_defaults_dict, # brand.color.palette:defaults
286+
defaults_dict, # brand.color:defaults
287+
palette_rules, # brand.color.palette:rules
316288
)
317289

318290
@staticmethod
319-
def _prepare_typography_vars(brand: "Brand") -> str:
291+
def _prepare_typography_vars(brand: "Brand") -> dict[str, YamlScalarType]:
320292
"""
321293
Typography: Create a list of brand Sass variables
322294
@@ -329,10 +301,10 @@ def _prepare_typography_vars(brand: "Brand") -> str:
329301
$brand_typography_base_line-height: 1.25;
330302
```
331303
"""
332-
mapped: dict[str, str | float | int | bool | None] = {}
304+
mapped: dict[str, YamlScalarType] = {}
333305

334306
if not brand.typography:
335-
return ""
307+
return {}
336308

337309
brand_typography = brand.typography.model_dump(
338310
exclude={"fonts"},
@@ -347,21 +319,31 @@ def _prepare_typography_vars(brand: "Brand") -> str:
347319
typo_sass_var = f"brand_typography_{field}_{prop_key}"
348320
mapped[typo_sass_var] = prop_value
349321

350-
ret = [
351-
"",
352-
"// *---- brand.typography ----* //",
353-
*Theme._combine_args_kwargs(kwargs=mapped, is_default=True),
354-
]
322+
return mapped
355323

356-
return "\n".join(ret)
324+
def _add_defaults_hdr(self, header: str, **kwargs: YamlScalarType):
325+
self.add_defaults(**kwargs)
326+
self.add_defaults(f"\n// *---- brand: {header} ----* //")
357327

358328
def _add_brand_bootstrap_other(self, bootstrap: BrandBootstrapConfig):
359329
if bootstrap.functions:
360-
self.add_functions(bootstrap.functions)
330+
self.add_functions(
331+
*[
332+
"// *---- brand.defaults: bootstrap.functions ----* //",
333+
bootstrap.functions,
334+
]
335+
)
361336
if bootstrap.mixins:
362-
self.add_mixins(bootstrap.mixins)
337+
self.add_mixins(
338+
*[
339+
"// *---- brand.defaults: bootstrap.mixins ----* //",
340+
bootstrap.mixins,
341+
]
342+
)
363343
if bootstrap.rules:
364-
self.add_rules(bootstrap.rules)
344+
self.add_rules(
345+
*["// *---- brand.defaults: bootstrap.rules ----* //", bootstrap.rules]
346+
)
365347

366348
def _html_dependencies(self) -> list[HTMLDependency]:
367349
theme_deps = super()._html_dependencies()

shiny/www/py-shiny/brand/_brand-yml.scss

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@
2222

2323
/*-- scss:defaults --*/
2424

25-
/*-- insert(brand.color.palette:defaults) --*/
26-
/*-- insert(brand.defaults:defaults) --*/
27-
/*-- insert(brand.color:defaults) --*/
28-
/*-- insert(brand.typography:defaults) --*/
25+
// Sass variables from `brand` will be inserted (above) here in this order:
26+
// * brand.color.palette
27+
// * brand.defaults
28+
// * brand.color
29+
// * brand.typography
2930

3031
//*-- brand: initial defaults --*//
3132
$brand_color_foreground: null !default;
@@ -166,7 +167,6 @@ $link-bg: null !default;
166167
$link-weight: null !default;
167168

168169
/*-- scss:rules --*/
169-
/*-- insert(brand.color.palette:rules) --*/
170170

171171
// *---- brand: brand rules to augment Bootstrap rules ----* //
172172
// https://github.com/twbs/bootstrap/blob/5c2f2e7e/scss/_root.scss#L82

0 commit comments

Comments
 (0)