Skip to contents

Build a small immutable record describing one border line — width, style, and colour. A brdr() value is the stroke you hand to the preset() rules knob (one entry per rule name, e.g. rules = list(midrule = brdr(width = 0.75))) or to style()'s border arguments (style(border_top = brdr(...), .at = cells_table(side = "rows"))). Successive preset() calls layer cleanly, so a one-off override composes onto a house-style template without disturbing the other rules.

Usage

brdr(width = "thin", style = "solid", color = "ink")

is_brdr(x)

Arguments

width

Stroke width. <numeric(1) | character(1)>: default "thin"*. Either a numeric in points (>= 0) or one of the four named keywords ("hairline", "thin", "medium", "thick"`).

style

Line style. <character(1)>: default "solid"*. One of "solid", "dashed", "dotted", "double", "dashdot", "none"`.

color

Stroke colour. <character(1)>: default "currentColor"*. Hex ("#RRGGBB"), CSS colour name, or "currentColor"` to inherit the surrounding text colour.

x

Any R object — tested by is_brdr() for membership in the tabular_brdr S3 class.

Value

A tabular_brdr S3 object — a length-3 named list suitable for preset(rules = list(<rule> = .)) or style(border_* = .).

Details

Surface. A single tabular_brdr value is a length-3 named list with class "tabular_brdr": list(style, width, color). The shape is identical to the bare triple style()'s per-side scalars accept, so the resolver in R/borders.R can ingest either form transparently. Construct with brdr(); test with is_brdr().

Width keywords. width accepts either a numeric in points (typical clinical values: 0.25, 0.5, 1, 1.5) or one of the four named keywords:

keywordpoints
"hairline"0.25
"thin"0.5
"medium"1
"thick"1.5

Keywords resolve to numeric points immediately; the constructed value carries a numeric width. Numeric inputs pass through unchanged after a non-negative check.

Style enum. style is one of "solid" (default), "dashed", "dotted", "double", "dashdot", "none". "none" is the explicit clear-this-rule sentinel: setting a rule to brdr(style = "none") (or the bare string "none") in preset()(rules = list(...)) suppresses the baseline rule that backend would otherwise draw.

Color. Hex ("#212529"), CSS colour name ("black", "slategray"), the "ink" token (default; resolves to the primary rule ink #212529, decoupled from the surrounding text colour so a recoloured header keeps a neutral rule), or "currentColor" (inherit the surrounding text colour per backend convention — w:color="auto" in DOCX, the document text colour in RTF, the CSS currentColor keyword in HTML).

See also

Where to attach: preset()'s rules knob (one brdr() per rule name) and style()'s border_* arguments.

Per-cell predicates: style() accepts the same per-side border_<side>_{style,width,color} triples without going through brdr().

Resolver internals: tabular_classes (style_node's 12 border scalars).

Examples

# ---- Example 1: A house-style rule set ----
#
# The `rules` knob takes one brdr() value per rule name. Here a
# thick column-label divider (midrule), a hairline dotted rule
# between body rows (rowrule), and the muted spanner rule dropped.
# Unlisted rules keep their booktabs defaults.
demo_n <- stats::setNames(cdisc_saf_n$n, cdisc_saf_n$arm_short)
tabular(
  cdisc_saf_ae,
  titles = c(
    "Table 14.3.1",
    "Overall Summary of Adverse Events",
    "Safety Population"
  ),
  footnotes = "Subjects counted once per category."
) |>
  cols(
    stat_label = col_spec(label = "Category"),
    placebo    = col_spec(label = "Placebo\nN={demo_n['placebo']}"),
    drug_50    = col_spec(label = "Drug 50\nN={demo_n['drug_50']}"),
    drug_100   = col_spec(label = "Drug 100\nN={demo_n['drug_100']}"),
    Total      = col_spec(label = "Total\nN={demo_n['Total']}")
  ) |>
  preset(
    rules = list(
      midrule  = brdr(width = "thick"),
      rowrule  = brdr(width = "hairline", style = "dotted"),
      spanrule = "none"
    )
  )

 

Table 14.3.1

Overall Summary of Adverse Events

Safety Population

 

CategoryPlacebo
N=86
Drug 50
N=96
Drug 100
N=72
Total
N=254
Any TEAE65 (75.6)84 (87.5)68 (94.4)217 (85.4)
Any Serious AE (SAE)0 (0.0)2 (2.1)1 (1.4)3 (1.2)
Any AE Related to Study Drug43 (50.0)77 (80.2)64 (88.9)184 (72.4)
Any AE Leading to Death2 (2.3)1 (1.0)0 (0.0)3 (1.2)
Any AE Recovered / Resolved47 (54.7)61 (63.5)49 (68.1)157 (61.8)
  Maximum severity: Mild36 (41.9)21 (21.9)20 (27.8)77 (30.3)
  Maximum severity: Moderate24 (27.9)47 (49.0)40 (55.6)111 (43.7)
  Maximum severity: Severe5 (5.8)16 (16.7)8 (11.1)29 (11.4)

Subjects counted once per category.

# ---- Example 2: Wrap a custom style into a reusable function ---- # # The recommended way to share a rule style across many tables is to # wrap the `preset()` call in a small function. A later `preset()` / # `style()` call layers a one-off override cleanly on top. custom_style <- function(spec) { spec |> preset( rules = list( toprule = brdr(width = "thin", color = "#212529"), midrule = brdr(width = "thin", color = "#212529"), bottomrule = brdr(width = "thin", color = "#212529") ) ) } tabular(cdisc_saf_n) |> custom_style() |> preset(rules = list(rowrule = brdr("hairline", "dashed")))
armarm_shortn
Placeboplacebo86
Xanomeline Low Dosedrug_5096
Xanomeline High Dosedrug_10072
TotalTotal254
# ---- Example 3: Width keyword vs numeric, every style enum value ---- # # Width accepts both the four named keywords and a bare numeric # in points; style accepts six enum values. Use `is_brdr()` to # confirm the constructor returned a valid `tabular_brdr` rather # than a fallback list. for (w in c("hairline", "thin", "medium", "thick")) { cat(w, "=", brdr(width = w)$width, "pt\n") } #> hairline = 0.25 pt #> thin = 0.5 pt #> medium = 1 pt #> thick = 1.5 pt is_brdr(brdr(width = 0.75)) #> [1] TRUE lapply( c("solid", "dashed", "dotted", "double", "dashdot", "none"), function(s) brdr(style = s) ) #> [[1]] #> <tabular_brdr> 0.5pt solid ink #> #> [[2]] #> <tabular_brdr> 0.5pt dashed ink #> #> [[3]] #> <tabular_brdr> 0.5pt dotted ink #> #> [[4]] #> <tabular_brdr> 0.5pt double ink #> #> [[5]] #> <tabular_brdr> 0.5pt dashdot ink #> #> [[6]] #> <tabular_brdr> 0.5pt none ink #> # ---- Example 4: A full grid via the body-edge style() path ---- # # The `rules` knob covers the named booktabs anatomy; for the body # outer frame and inter-column separators, hand brdr() to # `style(.at = cells_table(side = ...))`. Here a medium outer frame # plus hairline column separators on a demographics table. tabular(cdisc_saf_demo, titles = "Demographics with a full grid") |> cols( variable = col_spec(usage = "group", label = "Characteristic"), stat_label = col_spec(label = "Statistic"), placebo = col_spec(label = "Placebo", align = "decimal"), drug_50 = col_spec(label = "Drug 50", align = "decimal"), drug_100 = col_spec(label = "Drug 100", align = "decimal"), Total = col_spec(label = "Total", align = "decimal") ) |> style(border = brdr(width = "medium"), .at = cells_table(side = "outer")) |> style(border_left = brdr("hairline"), .at = cells_table(side = "cols"))

 

Demographics with a full grid

 

StatisticPlaceboDrug 50Drug 100Total
Age (years)
n86         96         72         254         
Mean (SD)75.2 (8.59)76.0 (8.11)73.8 (7.94) 75.1 (8.25)
Median76.0       78.0       75.5        77.0       
Q1, Q369.2, 81.8 71.0, 82.0 70.5, 79.0  70.0, 81.0 
Min, Max52  , 89   51  , 88   56  , 88    51  , 89   
 
Sex, n (%)
F53 (61.6)  55 (57.3)  35 (48.6)  143 (56.3)  
M33 (38.4)  41 (42.7)  37 (51.4)  111 (43.7)  
 
Race, n (%)
WHITE78 (90.7)  90 (93.8)  62 (86.1)  230 (90.6)  
BLACK OR AFRICAN AMERICAN 8 ( 9.3)   6 ( 6.2)   9 (12.5)   23 ( 9.1)  
ASIAN 0          0          0           0         
AMERICAN INDIAN OR ALASKA NATIVE 0          0          1 ( 1.4)    1 ( 0.4)