Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:48:15 +08:00
commit b876793d31
10 changed files with 2680 additions and 0 deletions

View File

@@ -0,0 +1,447 @@
# Using brand.yml in R
Guide for using brand.yml in R projects beyond Shiny, including R Markdown documents, theming functions for plots and tables, and programmatic access to brand data.
## Overview
The brand.yml R package provides tools for applying brand styling to R visualizations and documents. These tools work in any R context, including R Markdown documents, Quarto, standalone scripts, and Shiny applications.
## Installation
```r
# Install brand.yml package
install.packages("brand.yml")
```
## R Markdown Integration
Use brand.yml in R Markdown documents (without `runtime: shiny`):
```yaml
---
title: "My Report"
output:
html_document:
theme:
version: 5 # Required for brand.yml
brand: true # Auto-discover _brand.yml
---
```
Or specify a path:
```yaml
---
title: "My Report"
output:
html_document:
theme:
version: 5
brand: "path/to/brand.yml"
---
```
**Important**: Set `version: 5` to use Bootstrap 5, which has the best brand.yml support.
### Other R Markdown Formats
Brand.yml works with various R Markdown output formats:
```yaml
---
title: "Branded Report"
output:
html_document:
theme:
version: 5
brand: _brand.yml
pdf_document: default
---
```
## Programmatic Access
Read and access brand data programmatically in any R script or document:
```r
library(brand.yml)
# Read from default location (_brand.yml in project)
brand <- read_brand_yml()
# Read from specific path
brand <- read_brand_yml("path/to/brand.yml")
# Access brand elements
brand$color$palette$blue # "#447099"
brand$color$primary # blue -> "#447099"
brand$typography$base$family # "Open Sans"
brand$meta$name # "Company Name"
# Access all colors
brand$color$palette # List of all palette colors
brand$color$foreground # Foreground color
brand$color$background # Background color
```
Use programmatically accessed brand data to:
- Display brand colors in custom visualizations
- Show brand logo with correct paths
- Apply brand fonts to custom elements
- Build branded themes dynamically
- Generate branded reports programmatically
## Branded Theming Functions
The brand.yml package includes helper functions to apply brand colors to plots and tables from popular R packages. These functions work in any R context (scripts, R Markdown, Quarto, Shiny).
### theme_brand_ggplot2()
Apply brand colors to ggplot2 visualizations:
```r
library(ggplot2)
library(brand.yml)
# Automatic brand detection
ggplot(mtcars, aes(mpg, hp)) +
geom_point() +
theme_brand_ggplot2()
# Explicit brand file
ggplot(mtcars, aes(mpg, hp)) +
geom_point() +
theme_brand_ggplot2(brand = "_brand.yml")
# Override specific colors
ggplot(mtcars, aes(mpg, hp)) +
geom_point() +
theme_brand_ggplot2(
background = "white",
foreground = "brand-gray",
accent = "brand-blue"
)
```
**Parameters:**
- `brand`: NULL (auto-detect), file path, brand object, or FALSE
- `background`, `foreground`, `accent`: Primary color settings
- `base_size`: Base font size (default: 11)
- Additional parameters for fine-grained control: `title_color`, `line_color`, `rect_fill`, `panel_background_fill`, `panel_grid_major_color`, etc.
### theme_brand_gt()
Apply brand colors to gt tables:
```r
library(gt)
library(brand.yml)
# Create branded table
mtcars |>
head() |>
gt() |>
theme_brand_gt()
# With explicit brand
mtcars |>
head() |>
gt() |>
theme_brand_gt(brand = "_brand.yml")
# Override colors
mtcars |>
head() |>
gt() |>
theme_brand_gt(
background = "white",
foreground = "brand-gray"
)
```
**Parameters:**
- `table`: The gt table object to theme
- `brand`: NULL (auto-detect), file path, brand object, or FALSE
- `background`: Table background color (default: `brand.color.background`)
- `foreground`: Text color (default: `brand.color.foreground`)
### theme_brand_flextable()
Apply brand colors to flextable tables:
```r
library(flextable)
library(brand.yml)
# Create branded flextable
mtcars |>
head() |>
flextable() |>
theme_brand_flextable()
# With explicit brand
mtcars |>
head() |>
flextable() |>
theme_brand_flextable(brand = "_brand.yml")
# Override colors
mtcars |>
head() |>
flextable() |>
theme_brand_flextable(
background = "white",
foreground = "brand-gray"
)
```
**Parameters:**
- `table`: The flextable object to theme
- `brand`: NULL (auto-detect), file path, brand object, or FALSE
- `background`: Table background color (default: `brand.color.background`)
- `foreground`: Text color (default: `brand.color.foreground`)
### theme_brand_plotly()
Apply brand colors to plotly visualizations:
```r
library(plotly)
library(brand.yml)
# Create branded plotly chart
plot_ly(mtcars, x = ~mpg, y = ~hp, type = "scatter", mode = "markers") |>
theme_brand_plotly()
# With explicit brand
plot_ly(mtcars, x = ~mpg, y = ~hp, type = "scatter", mode = "markers") |>
theme_brand_plotly(brand = "_brand.yml")
# Override colors
plot_ly(mtcars, x = ~mpg, y = ~hp, type = "scatter", mode = "markers") |>
theme_brand_plotly(
background = "white",
foreground = "brand-gray",
accent = "brand-blue"
)
```
**Parameters:**
- `plot`: The plotly plot object to theme
- `brand`: NULL (auto-detect), file path, brand object, or FALSE
- `background`: Plot background color (default: `brand.color.background`)
- `foreground`: Text/foreground color (default: `brand.color.foreground`)
- `accent`: Accent/highlight color (default: `brand.color.primary`)
### theme_brand_thematic()
Apply brand colors to base R graphics via thematic:
```r
library(thematic)
library(brand.yml)
# Create theme object
theme <- theme_brand_thematic()
# Use with thematic_with_theme()
thematic::thematic_with_theme(theme, {
plot(mtcars$mpg, mtcars$hp)
})
# Or use with ggplot2
thematic::thematic_with_theme(theme, {
ggplot(mtcars, aes(mpg, hp)) +
geom_point()
})
```
### theme_brand_thematic_on()
Immediately activate brand theming globally for base R graphics:
```r
library(thematic)
library(brand.yml)
# Turn on brand theming globally
theme_brand_thematic_on()
# Now all plots use brand colors
plot(mtcars$mpg, mtcars$hp)
hist(mtcars$mpg)
# Turn off later
thematic::thematic_off()
```
**Parameters (both functions):**
- `brand`: NULL (auto-detect), file path, brand object, or FALSE
- `background`: Background color (default: `brand.color.background`)
- `foreground`: Foreground color (default: `brand.color.foreground`)
- `accent`: Accent color (default: `brand.color.primary`)
- `...`: Additional arguments passed to thematic package
**Difference:**
- `theme_brand_thematic()`: Returns theme object for scoped use
- `theme_brand_thematic_on()`: Immediately applies theme globally
## R Markdown Example
Complete example showing theming functions in R Markdown:
````markdown
---
title: "Branded Report"
output:
html_document:
theme:
version: 5
brand: _brand.yml
---
```{r setup}
library(ggplot2)
library(gt)
library(brand.yml)
```
## Sales Analysis
```{r plot}
ggplot(mtcars, aes(mpg, hp, color = factor(cyl))) +
geom_point(size = 3) +
labs(title = "MPG vs Horsepower", color = "Cylinders") +
theme_brand_ggplot2()
```
## Data Summary
```{r table}
mtcars |>
head(10) |>
gt() |>
theme_brand_gt() |>
tab_header(title = "Motor Trend Car Data")
```
````
## Quarto Integration
Works seamlessly in Quarto documents:
````markdown
---
title: "Branded Analysis"
format:
html:
brand: _brand.yml
---
```{r}
#| label: branded-plot
library(ggplot2)
library(brand.yml)
ggplot(iris, aes(Sepal.Length, Sepal.Width, color = Species)) +
geom_point() +
theme_brand_ggplot2()
```
````
## Script Usage
Use in standalone R scripts:
```r
#!/usr/bin/env Rscript
library(brand.yml)
library(ggplot2)
# Read brand
brand <- read_brand_yml("_brand.yml")
# Create branded plot
p <- ggplot(mtcars, aes(mpg, hp)) +
geom_point(color = brand$color$primary) +
theme_brand_ggplot2()
# Save with brand colors
ggsave("output.png", p, width = 8, height = 6)
```
## Benefits
- **Consistency**: Same brand styling across all R outputs (plots, tables, documents)
- **Automatic detection**: Functions find `_brand.yml` automatically
- **Flexible override**: Easy to customize colors when needed
- **Works everywhere**: R scripts, R Markdown, Quarto, Shiny
## Tips
- **Place `_brand.yml` at project root** for automatic discovery
- **Use `read_brand_yml()`** for programmatic access to brand data
- **Combine theming functions** for cohesive branded reports
- **Set `version: 5`** in R Markdown YAML for Bootstrap 5 support
- **Test theme functions** individually before combining in documents
## Common Patterns
### Branded Report with Multiple Visualizations
```r
library(brand.yml)
library(ggplot2)
library(gt)
# Load brand
brand <- read_brand_yml()
# Create consistent visualizations
plot1 <- ggplot(data1, aes(x, y)) +
geom_point() +
theme_brand_ggplot2()
plot2 <- ggplot(data2, aes(x, y)) +
geom_line() +
theme_brand_ggplot2()
table1 <- data3 |>
gt() |>
theme_brand_gt()
```
### Dynamic Brand Colors
```r
library(brand.yml)
brand <- read_brand_yml()
# Use brand colors in custom visualizations
my_colors <- c(
brand$color$primary,
brand$color$secondary,
brand$color$success
)
# Apply to plot
plot(data, col = my_colors[factor(group)])
```
### Conditional Branding
```r
library(brand.yml)
# Use different brands for different contexts
if (Sys.getenv("BRAND_MODE") == "internal") {
brand <- read_brand_yml("internal-brand.yml")
} else {
brand <- read_brand_yml("external-brand.yml")
}
# Apply to visualizations
theme <- theme_brand_ggplot2(brand = brand)
```

View File

@@ -0,0 +1,408 @@
# brand.yml Specification
Complete specification for creating valid `_brand.yml` files for the brand.yml project.
## File Naming Convention
- **Conventional name**: `_brand.yml` (auto-discovered by Shiny and Quarto)
- **Custom names**: Any `.yml` file (e.g., `my-brand.yml`) requires explicit paths
- **Location**: Typically at project root or in `_brand/` or `brand/` subdirectories
## File Structure
All fields are **optional**. Only include fields directly relevant to the brand.
```yaml
meta: # Company/project identity information
logo: # Logo files and variants
color: # Color palette and semantic colors
typography: # Fonts and text styling
defaults: # Framework-specific customizations
```
## Meta Section
Company or project metadata.
### Simple Format
```yaml
meta:
name: Acme
link: https://acmecorp.com
```
### Extended Format
```yaml
meta:
name:
short: Acme
full: Acme Corporation International
link:
home: https://www.acmecorp.com
docs: https://docs.acmecorp.com
github: https://github.com/acmecorp
bluesky: https://bsky.app/profile/acmecorp.bsky.social
mastodon: https://mastodon.social/@acmecorp
linkedin: https://www.linkedin.com/company/acmecorp
facebook: https://www.facebook.com/acmecorp
twitter: https://twitter.com/acmecorp
```
**Requirements:**
- All links must include `https://` prefix
- Additional custom fields are allowed
## Logo Section
Logo files for different contexts and sizes.
### Structure
```yaml
logo:
images: # Named logo resources (optional)
name: path # Map names to file paths or URLs
small: path # Icon-sized logo (favicons, mobile)
medium: path # Standard logo (headers, navigation)
large: path # Large logo (hero, title slides)
```
### File Paths
- **Local files**: Relative paths from `_brand.yml` location (e.g., `logos/logo.png`)
- **Remote files**: Full URLs with `http://` or `https://`
### Light/Dark Variants
```yaml
logo:
medium:
light: logo-dark.png # For light backgrounds
dark: logo-white.png # For dark backgrounds
```
### With Alt Text
```yaml
logo:
images:
header:
path: logos/header.svg
alt: Company logo
medium: header
```
### Complete Example
```yaml
logo:
images:
header: logos/header-logo.png
header-white: logos/header-logo-white.png
icon: logos/icon.png
full:
path: logos/full-logo.svg
alt: Acme Corporation logo
small: icon
medium:
light: header
dark: header-white
large: full
```
## Color Section
Brand color palette and semantic color assignments.
### Structure
```yaml
color:
palette: # Named brand colors
name: "#hex" # Flat list of color names and hex values
# Semantic theme colors (all optional)
foreground: "#color" # Main text color
background: "#color" # Main background color
primary: "#color" # Links, buttons, primary actions
secondary: "#color" # Lighter text, disabled states
tertiary: "#color" # Hover states, accents
success: "#color" # Positive actions
info: "#color" # Neutral information
warning: "#color" # Cautions
danger: "#color" # Errors, negative actions
light: "#color" # High contrast on dark
dark: "#color" # High contrast on light
```
### Color Palette Best Practices
- Use hex color values: `"#447099"`
- Use descriptive names following Sass conventions: `blue`, `brand-orange`, `success-green`
- Create aliases by referencing other palette colors: `purple: burgundy`
- Include Bootstrap color names when possible: `blue`, `indigo`, `purple`, `pink`, `red`, `orange`, `yellow`, `green`, `teal`, `cyan`, `white`, `black`
- When brands define ranges of shades, choose the midpoint as the primary color
### Referencing Colors
Theme colors can reference palette names:
```yaml
color:
palette:
brand-blue: "#447099"
brand-orange: "#EE6331"
primary: brand-blue # References palette
warning: brand-orange # References palette
```
### Complete Example
```yaml
color:
palette:
white: "#FFFFFF"
black: "#151515"
blue: "#447099"
orange: "#EE6331"
green: "#72994E"
teal: "#419599"
burgundy: "#9A4665"
foreground: black
background: white
primary: blue
success: green
info: teal
warning: orange
danger: burgundy
```
## Typography Section
Font definitions and text element styling.
### Structure
```yaml
typography:
fonts: # Font definitions
- family: Name
source: type # file, google, bunny, or system
# Additional source-specific fields
base: # Body text (optional)
headings: # Heading text (optional)
monospace: # Code text (optional)
monospace-inline: # Inline code (optional)
monospace-block: # Code blocks (optional)
link: # Hyperlinks (optional)
```
### Font Sources
#### Local/Remote Files
```yaml
fonts:
- family: Open Sans
source: file
files:
- path: fonts/OpenSans-Regular.ttf
weight: 400
style: normal
- path: fonts/OpenSans-Bold.ttf
weight: 700
style: normal
- path: https://example.com/fonts/OpenSans-Italic.ttf
weight: 400
style: italic
```
Proprietary fonts, should be downloaded and stored adjacent to the brand.yml file and referenced via relative paths in the `path` field.
#### Google Fonts
```yaml
fonts:
- family: Roboto
source: google
weight: [400, 700] # Optional: specific weights
style: [normal, italic] # Optional: specific styles
display: block # Optional: font-display property
```
Weight options:
- Array of numbers: `[400, 700]`
- Range (variable fonts): `400..900`
- Named weights: `[thin, normal, bold]`
#### Bunny Fonts (GDPR-compliant alternative)
```yaml
fonts:
- family: Inter
source: bunny
weight: [400, 600]
style: [normal, italic]
```
Same syntax as Google Fonts.
### Typographic Elements
All elements support these fields:
- `family`: Font family name (must match a defined font)
- `weight`: `100`-`900` or `thin`, `normal`, `bold`, etc.
- `style`: `normal` or `italic`
- `size`: CSS units (`16px`, `1rem`, `0.9em`)
- `line-height`: Number or CSS unit
- `color`: Hex value or reference to color name
- `background-color`: Hex value or reference to color name
#### Simple Format (String)
```yaml
typography:
base: Open Sans
headings: Roboto
monospace: Fira Code
```
#### Extended Format (Object)
```yaml
typography:
base:
family: Open Sans
weight: 400
size: 16px
line-height: 1.5
headings:
family: Roboto
weight: 600
style: normal
line-height: 1.2
color: "#333333"
monospace:
family: Fira Code
weight: 400
size: 0.9em
monospace-inline:
color: "#7d12ba"
background-color: "#f8f9fa"
monospace-block:
color: foreground
background-color: background
line-height: 1.4
link:
weight: 600
color: primary
decoration: underline
```
**Note**: Base text color uses `color.foreground` by default. Do not specify color in base unless overriding.
### Complete Example
```yaml
typography:
fonts:
- family: Open Sans
source: google
weight: [400, 600, 700]
style: [normal, italic]
- family: Roboto Slab
source: google
weight: [600, 900]
- family: Fira Code
source: bunny
weight: [400, 500]
base:
family: Open Sans
size: 16px
line-height: 1.5
headings:
family: Roboto Slab
weight: 600
monospace: Fira Code
link:
color: primary
weight: 600
```
## Defaults Section
Framework-specific customizations. Use sparingly - only when brand requirements cannot be met through the standard sections above.
### Structure
```yaml
defaults:
bootstrap: # Bootstrap/bslib customizations
functions: # SCSS function declarations (string)
defaults: # Bootstrap variable overrides (mapping)
mixins: # SCSS mixins (string)
rules: # Additional SCSS rules (string)
quarto: # Quarto-specific settings
format: # Format-specific options
shiny: # Shiny-specific settings
theme:
defaults: # Bootstrap variables
rules: # Additional SCSS rules
```
### Example
```yaml
defaults:
bootstrap:
defaults:
navbar-bg: $brand-orange
rules: |
.btn-primary {
border-radius: 0.5rem;
}
shiny:
theme:
defaults:
navbar-padding-y: 1rem
```
**Note**: Colors from `color.palette` are available as Sass variables: `$brand-{color_name}`
## Validation Rules
When creating `_brand.yml` files:
1. **All fields are optional** - only include what's needed
2. **Prefer hex colors** - use `"#447099"` format
3. **Prefer simple syntax** - use strings instead of objects when possible
4. **Follow Sass naming** - color/font names use lowercase and hyphens
5. **Include URLs with protocol** - always use `https://`
6. **Reference before use** - define colors/fonts before referencing them
7. **Keep it concise** - simpler is better
## Complete Minimal Example
```yaml
color:
palette:
blue: "#0066cc"
gray: "#666666"
primary: blue
foreground: gray
background: "#ffffff"
typography:
fonts:
- family: Inter
source: google
weight: [400, 600]
base: Inter
headings:
weight: 600
```
## Complete Comprehensive Example
See the example in the document provided to you (brand-yml.prompt.txt) for a full-featured _brand.yml with all options demonstrated.

View File

@@ -0,0 +1,504 @@
# Using brand.yml with Quarto
Guide for applying brand.yml styling to Quarto documents, presentations, websites, and PDFs.
## Overview
Quarto automatically integrates `_brand.yml` to provide unified visual styling across multiple output formats including HTML, dashboards, RevealJS presentations, and Typst PDFs.
## Quick Start
Place `_brand.yml` at your project root:
```
my-project/
├── _quarto.yml
├── _brand.yml
├── index.qmd
└── ...
```
Quarto automatically discovers and applies `_brand.yml` - no configuration needed.
## Supported Formats
Brand styling automatically applies to:
- **HTML documents** - Web pages, reports
- **HTML dashboards** - Interactive dashboards
- **RevealJS presentations** - Slide decks
- **Typst PDFs** - PDF documents via Typst
- **Websites** - Multi-page Quarto websites
## Document-Level Usage
Specify brand in document frontmatter:
```yaml
---
title: "My Document"
format:
html:
brand: _brand.yml
---
```
Or use default discovery:
```yaml
---
title: "My Document"
format: html
---
```
If `_brand.yml` exists at project root, it's automatically applied.
## Project-Level Usage
Configure in `_quarto.yml`:
```yaml
project:
type: website
brand: _brand.yml
format:
html:
theme: default
```
## Custom Brand File Location
Specify a non-standard path:
```yaml
---
title: "My Document"
format:
html:
brand: branding/company-brand.yml
---
```
Or in project config:
```yaml
project:
brand: path/to/brand.yml
```
## Light/Dark Mode
Specify color variants for light and dark modes:
```yaml
color:
palette:
blue: "#0066cc"
primary:
light: "#0066cc"
dark: "#3399ff"
background:
light: "#ffffff"
dark: "#1a1a1a"
foreground:
light: "#333333"
dark: "#e0e0e0"
```
Any color in `color` or `typography` can have light/dark variants.
## Theme Layering
Control precedence with the `"brand"` keyword:
### Default (Brand Lowest Priority)
```yaml
format:
revealjs:
theme:
- custom.scss
- cosmo
```
Priority: `cosmo` > `custom.scss` > `_brand.yml`
### Brand Highest Priority
```yaml
format:
revealjs:
theme:
- cosmo
- custom.scss
- brand
```
Priority: `_brand.yml` > `custom.scss` > `cosmo`
### Brand in Middle
```yaml
format:
html:
theme:
- cosmo
- brand
- custom.scss
```
Priority: `custom.scss` > `_brand.yml` > `cosmo`
## Accessing Brand Data in Documents
### Shortcodes
Use shortcodes to access brand values (requires Quarto extensions):
```markdown
<!-- Access colors -->
Our primary color is {{{< brand-color primary >}}}.
<!-- Access meta information -->
Welcome to {{{< brand-meta name >}}}.
```
### SCSS Variables
Access brand colors in custom SCSS:
```scss
// Custom SCSS file
.branded-element {
color: $brand-primary;
background: $brand-background;
border-color: $brand-secondary;
}
```
Brand colors are automatically available as Sass variables: `$brand-{color-name}`.
## Typst PDF Support
Brand styling works with Typst PDF output:
```yaml
---
title: "My Document"
format:
typst:
brand: _brand.yml
---
```
### Typst Color Variables
Access colors in Typst templates:
- `brand-color.{name}` - Palette colors (e.g., `brand-color.blue`, `brand-color.primary`)
- `brand-background-color.{name}` - Lighter background variants
### Typst Typography Support
| Element | family | weight | color | background-color | line-height |
|---------|--------|--------|-------|------------------|-------------|
| base | ✓ | ✓ | ✓ | - | ✓ |
| headings | ✓ | ✓ | ✓ | - | ✓ |
| title | ✓ | ✓ | ✓ | - | ✓ |
| monospace-inline | ✓ | ✓ | ✓ | ✓ | - |
| monospace-block | ✓ | ✓ | ✓ | ✓ | ✓ |
| link | - | ✓ | ✓ | ✓ | - |
### Typst Font Handling
Quarto automatically downloads Google Fonts and caches them for Typst. Check fonts:
```bash
quarto typst fonts --ignore-system-fonts --font-path .quarto/typst-font-cache/
```
Disable font fallback in Typst:
```typst
#set text(fallback: false)
```
## Complete Examples
### Simple HTML Document
```yaml
---
title: "Quarterly Report"
format:
html:
toc: true
---
# Executive Summary
Content here uses brand colors and typography automatically.
```
With `_brand.yml` at project root:
```yaml
color:
palette:
blue: "#0066cc"
primary: blue
background: "#ffffff"
typography:
fonts:
- family: Inter
source: google
weight: [400, 600]
base:
family: Inter
size: 16px
headings:
family: Inter
weight: 600
```
### RevealJS Presentation
```yaml
---
title: "Company Overview"
format:
revealjs:
theme:
- default
- brand
logo: logo.png
---
# Introduction
Slides automatically use brand colors and fonts.
```
### Website with Brand
`_quarto.yml`:
```yaml
project:
type: website
brand: _brand.yml
website:
title: "My Company"
navbar:
left:
- href: index.qmd
text: Home
- about.qmd
format:
html:
theme: cosmo
css: styles.css
```
Brand colors and typography apply across all pages.
### Dashboard
```yaml
---
title: "Sales Dashboard"
format:
dashboard:
brand: _brand.yml
theme: default
---
## Row
```{python}
# Dashboard content
```
```
### Typst PDF
```yaml
---
title: "Technical Report"
format:
typst:
brand: _brand.yml
margin:
x: 2cm
y: 2cm
---
# Overview
PDF uses brand colors and fonts via Typst.
```
## Brand Extensions
Create reusable brand packages:
```bash
quarto create extension brand
```
Structure:
```
my-brand-extension/
├── _extension.yml
├── brand.yml
├── logo.png
└── fonts/
└── ...
```
`_extension.yml`:
```yaml
title: Company Brand
author: Your Name
version: 1.0.0
contributes:
brand: brand.yml
```
Install extension in projects:
```bash
quarto add username/my-brand-extension
```
**Requirement**: Brand extensions need `_quarto.yml` project file.
## Sample _brand.yml for Quarto
Minimal example:
```yaml
color:
palette:
brand-blue: "#0066cc"
brand-gray: "#666666"
primary: brand-blue
foreground: brand-gray
background: "#ffffff"
typography:
fonts:
- family: Inter
source: google
weight: [400, 600]
base:
family: Inter
size: 1rem
line-height: 1.6
headings:
family: Inter
weight: 600
line-height: 1.2
```
Complete example with light/dark mode:
```yaml
meta:
name: My Company
link: https://mycompany.com
logo:
small: logo-icon.png
medium:
light: logo-dark.svg
dark: logo-white.svg
color:
palette:
blue: "#0066cc"
navy: "#003366"
gray: "#666666"
light-gray: "#f5f5f5"
primary: blue
secondary: gray
success: "#28a745"
info: blue
warning: "#ffc107"
danger: "#dc3545"
foreground:
light: navy
dark: "#e0e0e0"
background:
light: "#ffffff"
dark: "#1a1a1a"
typography:
fonts:
- family: Inter
source: google
weight: [400, 500, 600, 700]
style: [normal, italic]
- family: Fira Code
source: google
weight: [400, 500]
base:
family: Inter
size: 1rem
line-height: 1.6
headings:
family: Inter
weight: 600
line-height: 1.2
monospace:
family: Fira Code
size: 0.9em
link:
color: primary
weight: 500
```
## Tips
- **Automatic discovery**: Place `_brand.yml` at project root for automatic application
- **Light/dark variants**: Use for websites with theme toggles
- **Layer strategically**: Use `brand` keyword to control theme precedence
- **Test across formats**: Verify brand applies correctly to HTML, PDF, and presentations
- **Extension for reuse**: Create brand extensions for multi-project consistency
- **Version control**: Include `_brand.yml` in git repository
## Troubleshooting
**Brand not applying?**
- Verify file is named `_brand.yml` (with underscore)
- Check file is at project root or specified in `brand:` field
- Ensure `_quarto.yml` exists for project-level branding
- Try explicit path in frontmatter
**Colors not matching?**
- Ensure hex colors have quotes: `"#0066cc"`
- Check color references match palette definitions
- Verify theme layering order
**Fonts not loading?**
- Verify Google Fonts spelling
- Check internet connection (required for Google Fonts)
- For Typst, check font cache: `quarto typst fonts`
- Ensure `source: google` is specified correctly
**Typst-specific issues?**
- Check font cache path: `.quarto/typst-font-cache/`
- Add `#set text(fallback: false)` to debug font issues
- Verify typography properties are supported (see table above)
**Brand extension not working?**
- Ensure `_quarto.yml` exists in project
- Verify extension is installed: `quarto list extensions`
- Check extension contributes brand: look for `contributes.brand` in `_extension.yml`

View File

@@ -0,0 +1,395 @@
# Using brand.yml with Shiny for Python
Guide for applying brand.yml styling to Shiny for Python applications using ui.Theme.
## Overview
Shiny for Python integrates brand.yml through the `ui.Theme.from_brand()` method, which creates custom themes from `_brand.yml` files. This enables consistent branding across Shiny apps with minimal configuration.
## Installation
```bash
# Install Shiny with theme support
pip install "shiny[theme]"
# Or install separately
pip install shiny libsass
# Optional: Install brand_yml for programmatic access
pip install brand_yml
```
## Quick Start
### Automatic Discovery
Place `_brand.yml` at your app directory root:
```
my-app/
├── _brand.yml
├── app.py
└── ...
```
Then use `ui.Theme.from_brand()`:
**Shiny Express:**
```python
from shiny.express import ui
ui.page_opts(theme=ui.Theme.from_brand(__file__))
# ... rest of app
```
**Shiny Core:**
```python
from shiny import App, ui
app_ui = ui.page_fluid(
ui.Theme.from_brand(__file__),
ui.h2("My App"),
# ... rest of UI
)
def server(input, output, session):
pass
app = App(app_ui, server)
```
## ui.Theme.from_brand() Parameters
```python
ui.Theme.from_brand(brand)
```
The `brand` parameter accepts:
### File Path (Most Common)
```python
# Use __file__ for app directory
ui.Theme.from_brand(__file__)
# Explicit file path
ui.Theme.from_brand("path/to/_brand.yml")
# Explicit directory (auto-finds _brand.yml)
ui.Theme.from_brand("branding/")
```
### Brand Object
```python
from brand_yml import Brand
brand = Brand.from_yaml("_brand.yml")
ui.Theme.from_brand(brand)
```
## Search Behavior
When given `__file__` or a directory path, the method searches for `_brand.yml`:
1. In the specified directory
2. In `_brand/` subdirectory
3. In `brand/` subdirectory
4. In parent directories (recursive)
## Complete Examples
### Shiny Express App
```python
from shiny.express import input, render, ui
ui.page_opts(
title="My Dashboard",
theme=ui.Theme.from_brand(__file__)
)
with ui.sidebar():
ui.input_slider("n", "Number of observations", 1, 100, 50)
@render.plot
def histogram():
import matplotlib.pyplot as plt
import numpy as np
data = np.random.randn(input.n())
plt.hist(data, bins=20)
plt.xlabel("Value")
plt.ylabel("Frequency")
```
### Shiny Core App
```python
from shiny import App, render, ui
app_ui = ui.page_sidebar(
ui.sidebar(
ui.input_slider("n", "Number of observations", 1, 100, 50),
),
ui.output_plot("histogram"),
title="My Dashboard",
theme=ui.Theme.from_brand(__file__)
)
def server(input, output, session):
@render.plot
def histogram():
import matplotlib.pyplot as plt
import numpy as np
data = np.random.randn(input.n())
plt.hist(data, bins=20)
plt.xlabel("Value")
plt.ylabel("Frequency")
app = App(app_ui, server)
```
### With Custom Path
```python
from shiny.express import ui
# Shared brand file
ui.page_opts(theme=ui.Theme.from_brand("../shared-branding/_brand.yml"))
# Named brand file
ui.page_opts(theme=ui.Theme.from_brand("company-brand.yml"))
# Directory with _brand.yml inside
ui.page_opts(theme=ui.Theme.from_brand("branding/"))
```
### Multiple Page Types
```python
from shiny import App, ui
# page_fluid
app_ui = ui.page_fluid(
theme=ui.Theme.from_brand(__file__),
# ... content
)
# page_sidebar
app_ui = ui.page_sidebar(
theme=ui.Theme.from_brand(__file__),
ui.sidebar(
# ... sidebar content
),
# ... main content
)
# page_navbar
app_ui = ui.page_navbar(
ui.nav_panel("Tab 1", # ...),
ui.nav_panel("Tab 2", # ...),
title="My App",
theme=ui.Theme.from_brand(__file__)
)
# page_fillable
app_ui = ui.page_fillable(
theme=ui.Theme.from_brand(__file__),
# ... content
)
```
## Combining with Custom Theme Rules
Extend brand.yml themes with custom Sass:
```python
from shiny.express import ui
theme = (
ui.Theme.from_brand(__file__)
.add_rules("""
.custom-card {
border-radius: 0.5rem;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
""")
)
ui.page_opts(theme=theme)
```
Available theme methods (chainable):
- `.add_defaults()` - Override Bootstrap variables
- `.add_functions()` - Add Sass functions
- `.add_mixins()` - Add Sass mixins
- `.add_rules()` - Add CSS rules
- `.add_uses()` - Add Sass declarations
## Programmatic Access with brand_yml
For advanced use cases, access brand data programmatically:
```python
from brand_yml import Brand
# Read brand file
brand = Brand.from_yaml("_brand.yml")
# Or from string
yaml_content = """
color:
palette:
blue: "#0066cc"
primary: blue
"""
brand = Brand.from_yaml_str(yaml_content)
# Access brand elements
brand.meta.name # Organization name
brand.color.palette.blue # "#0066cc"
brand.color.primary # "blue"
brand.typography.base.family # Font family name
# Use in UI
from shiny import ui
app_ui = ui.page_fluid(
theme=ui.Theme.from_brand(brand),
ui.h2(brand.meta.name),
# ... more content
)
```
## Sample _brand.yml for Shiny
Minimal example:
```yaml
color:
palette:
brand-blue: "#0066cc"
brand-gray: "#666666"
primary: brand-blue
foreground: brand-gray
background: "#ffffff"
typography:
fonts:
- family: Inter
source: google
weight: [400, 600]
base:
family: Inter
size: 16px
headings:
family: Inter
weight: 600
```
More complete example:
```yaml
meta:
name: My Company
link: https://mycompany.com
color:
palette:
blue: "#0066cc"
navy: "#003366"
gray: "#666666"
light-gray: "#f5f5f5"
primary: blue
secondary: gray
success: "#28a745"
info: blue
warning: "#ffc107"
danger: "#dc3545"
foreground: navy
background: "#ffffff"
typography:
fonts:
- family: Inter
source: google
weight: [400, 500, 600, 700]
style: [normal, italic]
- family: Fira Code
source: google
weight: [400, 500]
base:
family: Inter
size: 16px
line-height: 1.5
headings:
family: Inter
weight: 600
line-height: 1.2
monospace:
family: Fira Code
size: 14px
```
## Tips
- **Use __file__**: Most reliable way to locate `_brand.yml` in app directory
- **Start simple**: Begin with colors and one font
- **Test paths**: If brand doesn't apply, try explicit paths
- **Version control**: Include `_brand.yml` in git repository
- **Precompile for production**: Use `.to_css()` to avoid runtime Sass compilation
```python
# Development
theme = ui.Theme.from_brand(__file__)
# Production (precompile)
theme_css = ui.Theme.from_brand(__file__).to_css()
# Save to static/theme.css, then reference in production
```
## Troubleshooting
**Theme not applying?**
- Check file is named `_brand.yml` (with underscore)
- Verify `libsass` is installed: `pip install libsass`
- Try explicit path: `ui.Theme.from_brand("path/to/_brand.yml")`
- Check for YAML syntax errors
**Colors not matching?**
- Ensure hex colors have quotes: `"#0066cc"`
- Verify color names match palette definitions
- Check semantic colors reference valid palette names
**Fonts not loading?**
- Verify Google Fonts spelling and availability
- Ensure `source: google` is specified
- Check font family names match exactly
- Internet connection required for Google Fonts
**Import errors?**
- Install theme support: `pip install "shiny[theme]"`
- Or install libsass separately: `pip install libsass`
## Performance Considerations
For production apps with many instances, precompile the theme:
```python
# build_theme.py
from shiny import ui
theme = ui.Theme.from_brand("_brand.yml")
css = theme.to_css()
with open("static/brand-theme.css", "w") as f:
f.write(css)
# Then in app.py, reference the CSS file directly
# This avoids runtime Sass compilation overhead
```

View File

@@ -0,0 +1,378 @@
# Using brand.yml with Shiny for R
Guide for applying brand.yml styling to Shiny applications using the bslib package.
## Overview
The bslib package integrates brand.yml to provide unified visual theming across Shiny applications. Define colors, fonts, and logos once in `_brand.yml`, and bslib automatically applies them to your Shiny app UI.
## Installation
```r
# Install bslib (includes brand.yml support)
install.packages("bslib")
# Optional: Install brand.yml package for theming plots/tables
install.packages("brand.yml")
```
## Quick Start
### Automatic Discovery
Place `_brand.yml` at your app directory root:
```
my-app/
├── _brand.yml
├── app.R
└── ...
```
Then use `bs_theme()` in your app:
```r
library(shiny)
library(bslib)
ui <- page_fluid(
theme = bs_theme(), # Automatically finds _brand.yml
titlePanel("My App"),
# ... rest of UI
)
server <- function(input, output, session) {
# ...
}
shinyApp(ui, server)
```
### Search Paths
bslib automatically searches for `_brand.yml` in this order:
1. Current app directory
2. `_brand/` subdirectory
3. `brand/` subdirectory
4. Parent directories (recursive)
## bs_theme() Brand Parameter
The `brand` parameter controls how branding is applied:
### Automatic (Default)
```r
theme = bs_theme()
```
Searches for `_brand.yml` and applies it if found. No error if file doesn't exist.
### Required Brand
```r
theme = bs_theme(brand = TRUE)
```
Requires `_brand.yml` to exist. Throws error if not found.
### Explicit Path
```r
theme = bs_theme(brand = "path/to/my-brand.yml")
```
Uses specific brand file. Path can be:
- Relative to app directory: `"branding/company-brand.yml"`
- Absolute: `"/Users/name/brands/company.yml"`
- Directory (auto-finds `_brand.yml`): `"branding/"`
### Inline Brand Definition
```r
theme = bs_theme(
brand = list(
color = list(
palette = list(
blue = "#0066cc",
gray = "#666666"
),
primary = "blue",
foreground = "gray"
),
typography = list(
fonts = list(
list(family = "Inter", source = "google", weight = c(400, 600))
),
base = "Inter"
)
)
)
```
### Disable Branding
```r
theme = bs_theme(brand = FALSE)
```
Ignores `_brand.yml` even if it exists.
## Using with page_*() Functions
All bslib page functions support automatic brand discovery:
```r
# page_fluid
ui <- page_fluid(
theme = bs_theme(),
# ... content
)
# page_sidebar
ui <- page_sidebar(
theme = bs_theme(),
sidebar = sidebar(
# ... sidebar content
),
# ... main content
)
# page_navbar
ui <- page_navbar(
theme = bs_theme(),
nav_panel("Tab 1", # ...),
nav_panel("Tab 2", # ...)
)
# page_fillable
ui <- page_fillable(
theme = bs_theme(),
# ... content
)
```
## Branded Plots and Tables in Shiny
Use theming functions from the brand.yml package to style plots and tables within Shiny apps. See `brand-yml-in-r.md` for complete documentation of theming functions.
### Basic Example
```r
library(shiny)
library(bslib)
library(ggplot2)
library(gt)
library(brand.yml)
ui <- page_sidebar(
theme = bs_theme(brand = TRUE),
sidebar = sidebar(
selectInput("dataset", "Dataset:", c("mtcars", "iris"))
),
card(
card_header("Branded Plot"),
plotOutput("plot")
),
card(
card_header("Branded Table"),
gt_output("table")
)
)
server <- function(input, output, session) {
output$plot <- renderPlot({
ggplot(mtcars, aes(mpg, hp)) +
geom_point() +
theme_brand_ggplot2()
})
output$table <- render_gt({
head(mtcars) |>
gt() |>
theme_brand_gt()
})
}
shinyApp(ui, server)
```
**Benefits:**
- Consistent styling across UI, plots, and tables
- Automatic brand detection from `_brand.yml`
- Works with ggplot2, gt, flextable, plotly, and base R graphics
For detailed theming function documentation, see `brand-yml-in-r.md`.
## Complete Shiny Example
```r
library(shiny)
library(bslib)
ui <- page_sidebar(
theme = bs_theme(brand = TRUE), # Require _brand.yml
sidebar = sidebar(
title = "Controls",
selectInput("dataset", "Dataset:",
choices = c("iris", "mtcars")),
numericInput("n", "Number of rows:", 10, min = 1, max = 50)
),
card(
card_header("Data Summary"),
tableOutput("summary")
),
card(
card_header("Data Details"),
verbatimTextOutput("details")
)
)
server <- function(input, output, session) {
dataset <- reactive({
get(input$dataset)
})
output$summary <- renderTable({
head(dataset(), input$n)
})
output$details <- renderPrint({
summary(dataset())
})
}
shinyApp(ui, server)
```
With `_brand.yml`:
```yaml
color:
palette:
brand-blue: "#0066cc"
brand-gray: "#666666"
primary: brand-blue
foreground: brand-gray
background: "#ffffff"
typography:
fonts:
- family: Inter
source: google
weight: [400, 600]
base:
family: Inter
size: 16px
headings:
family: Inter
weight: 600
```
## R Markdown Shiny Documents
Use brand.yml in R Markdown documents with Shiny runtime:
```yaml
---
title: "Interactive Dashboard"
output:
html_document:
theme:
version: 5 # Required for brand.yml
brand: true # Auto-discover _brand.yml
runtime: shiny
---
```
Or specify a path:
```yaml
---
title: "Interactive Dashboard"
output:
html_document:
theme:
version: 5
brand: "path/to/brand.yml"
runtime: shiny
---
```
**Important**: Set `version: 5` to use Bootstrap 5, which has the best brand.yml support.
**Note**: For R Markdown documents without `runtime: shiny`, see `brand-yml-in-r.md`.
## Programmatic Brand Access
For advanced use cases, access brand data programmatically within Shiny:
```r
library(brand.yml)
server <- function(input, output, session) {
# Read brand data
brand <- read_brand_yml()
# Use in custom UI elements
output$brand_info <- renderUI({
div(
style = paste0("color: ", brand$color$primary, ";"),
h3(brand$meta$name),
p("Welcome to our branded app!")
)
})
# Use in plots with custom styling
output$custom_plot <- renderPlot({
plot(mtcars$mpg, mtcars$hp,
col = brand$color$primary,
pch = 19)
})
}
```
For complete documentation on programmatic access and theming functions, see `brand-yml-in-r.md`.
## Tips
- **Start simple**: Begin with colors and one font family
- **Test automatically**: Automatic discovery works well for most cases
- **Use explicit paths**: For shared brand files across multiple apps
- **Version control**: Include `_brand.yml` in your git repository
- **Validate early**: Use `brand = TRUE` during development to catch missing files
- **Combine with theming functions**: Style plots and tables consistently (see `brand-yml-in-r.md`)
## Troubleshooting
**Brand not applying to Shiny UI?**
- Check file is named `_brand.yml` (with underscore)
- Verify file is in app directory or parent directories
- Try explicit path: `bs_theme(brand = "path/to/_brand.yml")`
- Check for YAML syntax errors
**Colors not matching?**
- Verify hex colors have quotes: `"#0066cc"`
- Check color names match palette definitions
- Ensure primary/secondary colors reference valid palette names
**Fonts not loading?**
- Verify Google Fonts spelling and availability
- Check `source: google` is specified correctly
- Ensure font family names match exactly in typography elements
**Plots/tables not branded?**
- Ensure brand.yml package is installed: `install.packages("brand.yml")`
- Use theming functions: `theme_brand_ggplot2()`, `theme_brand_gt()`, etc.
- See `brand-yml-in-r.md` for complete theming documentation
## Related Documentation
- **[brand-yml-in-r.md](brand-yml-in-r.md)**: General R usage, R Markdown integration, theming functions, and programmatic access
- **[brand-yml-spec.md](brand-yml-spec.md)**: Complete brand.yml file specification