Skip to content

Commit 2938a0a

Browse files
committed
Separates out the inline CSS on elements and attempts to re-use existing bootstrap styling set via pkgdown
1 parent 7580cf2 commit 2938a0a

File tree

2 files changed

+207
-25
lines changed

2 files changed

+207
-25
lines changed

R/examplesWebR.R

Lines changed: 177 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#' \section{WebR}{
3131
#' \ifelse{html}{
3232
#' \out{
33-
#' <a href="webR_URL">\U0001F310 View in webR REPL</a>
33+
#' <div class="rocleteer-webr-container">...</div>
3434
#' }
3535
#' }{
3636
#' \ifelse{latex}{
@@ -56,6 +56,32 @@
5656
#' - **LaTeX/PDF**: Plain URL link to webR session
5757
#' - **Other formats**: Informational message about limited support
5858
#'
59+
#' @section Styling and Theming:
60+
#'
61+
#' The webR Section HTML output uses Bootstrap-compatible CSS classes and custom
62+
#' properties to link themeing to pkgdown's existing CSS themes. The styles
63+
#' follow the CSS custom properties pattern:
64+
#'
65+
#' - Private variables (`--_*`): Used internally
66+
#' - Public variables (`--rocleteer-webr-*`): For user customization
67+
#' - Bootstrap variables (`--bs-*`): Used as fallbacks
68+
#'
69+
#' Main CSS classes are:
70+
#'
71+
#' - `.rocleteer-webr-container`: Main container
72+
#' - `.rocleteer-webr-warning`: Experimental feature warning
73+
#' - `.rocleteer-webr-btn`, `.rocleteer-webr-btn-primary`, etc.: Button styling
74+
#'
75+
#' To customize appearance in pkgdown sites, override CSS custom properties by
76+
#' including into a file:
77+
#'
78+
#' ```css
79+
#' .rocleteer-webr-container {
80+
#' --rocleteer-webr-container-bg: #f0f8ff;
81+
#' --rocleteer-webr-btn-primary-bg: #1976d2;
82+
#' }
83+
#' ```
84+
#'
5985
#' @section Parameters:
6086
#'
6187
#' The tag supports optional parameters (these override global `DESCRIPTION` config):
@@ -326,7 +352,7 @@ encode_webr_code <- function(code, filename = "example.R", autorun = FALSE) {
326352
if (!requireNamespace("base64enc", quietly = TRUE)) {
327353
stop("Package 'base64enc' is required for @examplesWebR tag")
328354
}
329-
355+
330356
# Create the share item structure exactly as webR expects
331357
share_item <- list(
332358
list(
@@ -519,6 +545,132 @@ parse_webr_params <- function(tag_line, global_config = list()) {
519545
return(params)
520546
}
521547

548+
#' Generate Rocleteer webR CSS styles
549+
#'
550+
#' Create the complete CSS for webR components as an inline style block
551+
#'
552+
#' @return
553+
#' HTML string with complete CSS styles
554+
#'
555+
#' @noRd
556+
webr_inline_css <- function() {
557+
paste0(
558+
'<style id="rocleteer-webr-styles">',
559+
'/* WebR Interactive Examples CSS - rocleteer package */',
560+
'.rocleteer-webr-container {',
561+
' --_container-bg: var(--rocleteer-webr-container-bg, var(--bs-light, #f8f9fa));',
562+
' --_container-border: var(--rocleteer-webr-container-border, var(--bs-border-color, #dee2e6));',
563+
' --_container-border-radius: var(--rocleteer-webr-container-border-radius, var(--bs-border-radius, 8px));',
564+
' --_warning-bg: var(--rocleteer-webr-warning-bg, var(--bs-info-bg-subtle, #e7f3ff));',
565+
' --_warning-border: var(--rocleteer-webr-warning-border, var(--bs-info-border-subtle, #b3d9ff));',
566+
' --_warning-text: var(--rocleteer-webr-warning-text, var(--bs-info-text-emphasis, #0c5aa6));',
567+
' --_btn-primary-bg: var(--rocleteer-webr-btn-primary-bg, var(--bs-primary, #007bff));',
568+
' --_btn-primary-hover: var(--rocleteer-webr-btn-primary-hover, var(--bs-primary-hover, #0056b3));',
569+
' --_btn-success-bg: var(--rocleteer-webr-btn-success-bg, var(--bs-success, #28a745));',
570+
' --_btn-success-hover: var(--rocleteer-webr-btn-success-hover, var(--bs-success-hover, #1e7e34));',
571+
' --_btn-secondary-bg: var(--rocleteer-webr-btn-secondary-bg, var(--bs-secondary, #6c757d));',
572+
' --_btn-secondary-hover: var(--rocleteer-webr-btn-secondary-hover, var(--bs-secondary-hover, #545b62));',
573+
' --_text-color: var(--rocleteer-webr-text-color, var(--bs-body-color, #333));',
574+
' --_text-emphasis: var(--rocleteer-webr-text-emphasis, var(--bs-emphasis-color, #000));',
575+
' --_container-padding: var(--rocleteer-webr-container-padding, 16px);',
576+
' --_container-margin: var(--rocleteer-webr-container-margin, 16px 0);',
577+
' --_btn-padding: var(--rocleteer-webr-btn-padding, 12px 20px);',
578+
' --_btn-margin: var(--rocleteer-webr-btn-margin, 0 8px 0 0);',
579+
' --_font-size: var(--rocleteer-webr-font-size, var(--bs-body-font-size, 14px));',
580+
' --_font-weight-bold: var(--rocleteer-webr-font-weight-bold, var(--bs-font-weight-bold, 700));',
581+
' border: 1px solid var(--_container-border);',
582+
' border-radius: var(--_container-border-radius);',
583+
' padding: var(--_container-padding);',
584+
' margin: var(--_container-margin);',
585+
' background-color: var(--_container-bg);',
586+
' color: var(--_text-color);',
587+
' font-size: var(--_font-size);',
588+
'}',
589+
'.rocleteer-webr-warning {',
590+
' background-color: var(--_warning-bg);',
591+
' border: 1px solid var(--_warning-border);',
592+
' border-radius: var(--bs-border-radius, 4px);',
593+
' padding: 12px;',
594+
' margin-bottom: 16px;',
595+
' color: var(--_warning-text);',
596+
' font-size: var(--_font-size);',
597+
'}',
598+
'.rocleteer-webr-warning strong {',
599+
' font-weight: var(--_font-weight-bold);',
600+
'}',
601+
'.rocleteer-webr-btn {',
602+
' display: inline-block;',
603+
' padding: var(--_btn-padding);',
604+
' margin: var(--_btn-margin);',
605+
' border: none;',
606+
' border-radius: var(--bs-border-radius, 4px);',
607+
' cursor: pointer;',
608+
' text-decoration: none;',
609+
' font-size: var(--_font-size);',
610+
' color: white;',
611+
' transition: background-color 0.15s ease-in-out;',
612+
'}',
613+
'.rocleteer-webr-btn-primary {',
614+
' background-color: var(--_btn-primary-bg);',
615+
'}',
616+
'.rocleteer-webr-btn-primary:hover {',
617+
' background-color: var(--_btn-primary-hover);',
618+
' color: white;',
619+
' text-decoration: none;',
620+
'}',
621+
'.rocleteer-webr-btn-success {',
622+
' background-color: var(--_btn-success-bg);',
623+
'}',
624+
'.rocleteer-webr-btn-success:hover {',
625+
' background-color: var(--_btn-success-hover);',
626+
'}',
627+
'.rocleteer-webr-btn-secondary {',
628+
' background-color: var(--_btn-secondary-bg);',
629+
'}',
630+
'.rocleteer-webr-btn-secondary:hover {',
631+
' background-color: var(--_btn-secondary-hover);',
632+
'}',
633+
'.rocleteer-webr-initial-text {',
634+
' margin: 8px 0;',
635+
' font-weight: var(--_font-weight-bold);',
636+
' color: var(--_text-emphasis);',
637+
'}',
638+
'.rocleteer-webr-iframe-container {',
639+
' display: none;',
640+
'}',
641+
'.rocleteer-webr-iframe-controls {',
642+
' margin-bottom: 12px;',
643+
'}',
644+
'.rocleteer-webr-iframe-controls .rocleteer-webr-btn {',
645+
' padding: 8px 16px;',
646+
' font-size: var(--_font-size);',
647+
'}',
648+
'.rocleteer-webr-iframe {',
649+
' width: 100\\%;',
650+
' border: 1px solid var(--_container-border);',
651+
' border-radius: var(--bs-border-radius, 4px);',
652+
'}',
653+
'@media (max-width: 576px) {',
654+
' .rocleteer-webr-container {',
655+
' --_container-padding: 12px;',
656+
' --_btn-padding: 10px 16px;',
657+
' --_font-size: 13px;',
658+
' }',
659+
' .rocleteer-webr-btn {',
660+
' display: block;',
661+
' margin: 4px 0;',
662+
' text-align: center;',
663+
' }',
664+
' .rocleteer-webr-iframe-controls .rocleteer-webr-btn {',
665+
' display: inline-block;',
666+
' margin: 0 4px 0 0;',
667+
' }',
668+
'}',
669+
'</style>',
670+
collapse = "\n"
671+
)
672+
}
673+
522674
#' Generate webR warning HTML
523675
#'
524676
#' Create standardized warning message for webR examples
@@ -529,7 +681,7 @@ parse_webr_params <- function(tag_line, global_config = list()) {
529681
#' @noRd
530682
webr_experimental_warning <- function() {
531683
paste0(
532-
'<div class="webr-warning" style="background-color: #e7f3ff; border: 1px solid #b3d9ff; border-radius: 4px; padding: 12px; margin-bottom: 16px; font-size: 14px; color: #0c5aa6;">',
684+
'<div class="rocleteer-webr-warning">',
533685
'<strong>\U0001F9EA Experimental:</strong> Interactive webR examples are a new feature. ',
534686
'Loading may take a moment, and the package version might differ from this documentation.',
535687
'</div>'
@@ -590,15 +742,17 @@ webr_repl_href <- function(encoded_code, version = "latest", mode = "", channel
590742
webr_repl_link <- function(encoded_code, version = "latest", mode = "", channel = "") {
591743
url <- webr_repl_href(encoded_code, version, mode, channel)
592744
html <- paste0(
593-
'<div class="webr-container" style="border: 1px solid #ddd; border-radius: 8px; padding: 16px; margin: 16px 0; background-color: #f8f9fa;">',
745+
# Include CSS
746+
# TODO: Figure out how to include it once? Post parser re-write?
747+
webr_inline_css(),
748+
749+
'<div class="rocleteer-webr-container">',
594750

595751
# Warning message
596752
webr_experimental_warning(),
597753

598754
# Link button
599-
'<p><a href="', url, '" target="_blank" ',
600-
'style="background-color: #007bff; color: white; padding: 12px 20px; ',
601-
'text-decoration: none; border-radius: 4px; font-size: 14px; display: inline-block;">',
755+
'<p><a href="', url, '" target="_blank" class="rocleteer-webr-btn rocleteer-webr-btn-primary">',
602756
'\U0001F310 View in webR REPL</a></p>',
603757

604758
'</div>'
@@ -622,43 +776,42 @@ webr_repl_link <- function(encoded_code, version = "latest", mode = "", channel
622776
#' @noRd
623777
webr_repl_iframe <- function(encoded_code, version = "latest", height = 300, mode = "", channel = "") {
624778
url <- webr_repl_href(encoded_code, version, mode, channel)
625-
779+
626780
# Create an ID for this iframe (based on the encoded code)
627781
hashed_id <- abs(sum(utf8ToInt(substr(encoded_code, 1, 10))))
628782
iframe_id <- paste0("webr_iframe_", hashed_id)
629783

630784
html <- paste0(
631-
'<div class="webr-container" style="border: 1px solid #ddd; border-radius: 8px; padding: 16px; margin: 16px 0; background-color: #f8f9fa;">',
785+
# Include CSS
786+
webr_inline_css(),
787+
788+
'<div class="rocleteer-webr-container">',
632789

633790
# Warning message
634791
webr_experimental_warning(),
635792

636793
# Initial buttons (before iframe loads)
637-
'<div id="', iframe_id, '_initial" class="webr-initial">',
638-
'<p style="margin: 8px 0; font-weight: bold; color: #333;">Interactive Example Available</p>',
794+
'<div id="', iframe_id, '_initial" class="rocleteer-webr-initial">',
795+
'<p class="rocleteer-webr-initial-text">Interactive Example Available</p>',
639796
'<button onclick="loadWebRIframe(\'', iframe_id, '\', \'', url, '\', ', height, ')" ',
640-
'style="background-color: #28a745; color: white; padding: 12px 20px; border: none; border-radius: 4px; ',
641-
'cursor: pointer; font-size: 14px; margin-right: 8px;">',
797+
'class="rocleteer-webr-btn rocleteer-webr-btn-success rocleteer-webr-btn-try">',
642798
'\U0001F680 Try it in your browser</button>',
643799
'<button onclick="window.open(\'', url, '\', \'_blank\')" ',
644-
'style="background-color: #007bff; color: white; padding: 12px 20px; border: none; border-radius: 4px; ',
645-
'cursor: pointer; font-size: 14px;">',
800+
'class="rocleteer-webr-btn rocleteer-webr-btn-primary rocleteer-webr-btn-open">',
646801
'\U0001F310 Open in Tab</button>',
647802
'</div>',
648803

649804
# Iframe container (hidden initially)
650-
'<div id="', iframe_id, '_container" class="webr-iframe-container" style="display: none;">',
651-
'<div style="margin-bottom: 12px;">',
805+
'<div id="', iframe_id, '_container" class="rocleteer-webr-iframe-container">',
806+
'<div class="rocleteer-webr-iframe-controls">',
652807
'<button onclick="hideWebRIframe(\'', iframe_id, '\')" ',
653-
'style="background-color: #6c757d; color: white; padding: 8px 16px; border: none; border-radius: 4px; ',
654-
'cursor: pointer; font-size: 14px; margin-right: 8px;">',
808+
'class="rocleteer-webr-btn rocleteer-webr-btn-secondary rocleteer-webr-btn-back">',
655809
'\U0001F519 Go back</button>',
656810
'<button onclick="window.open(\'', url, '\', \'_blank\')" ',
657-
'style="background-color: #007bff; color: white; padding: 8px 16px; border: none; border-radius: 4px; ',
658-
'cursor: pointer; font-size: 14px;">',
811+
'class="rocleteer-webr-btn rocleteer-webr-btn-primary rocleteer-webr-btn-open">',
659812
'\U0001F310 Open in Tab</button>',
660813
'</div>',
661-
'<div id="', iframe_id, '_content"></div>',
814+
'<div id="', iframe_id, '_content" class="rocleteer-webr-iframe-content"></div>',
662815
'</div>',
663816

664817
'</div>',
@@ -669,8 +822,8 @@ webr_repl_iframe <- function(encoded_code, version = "latest", height = 300, mod
669822
' document.getElementById(id + "_initial").style.display = "none";',
670823
' document.getElementById(id + "_container").style.display = "block";',
671824
' document.getElementById(id + "_content").innerHTML = ',
672-
' \'<iframe src="\' + url + \'" width="100\\%" height="\' + height + \'px" \' +',
673-
' \'style="border: 1px solid #ddd; border-radius: 4px;" title="webR REPL"></iframe>\';',
825+
' \'<iframe src="\' + url + \'" class="rocleteer-webr-iframe" height="\' + height + \'px" \' +',
826+
' \'title="webR REPL"></iframe>\';',
674827
'}',
675828
'function hideWebRIframe(id) {',
676829
' document.getElementById(id + "_initial").style.display = "block";',

man/tag-examplesWebR.Rd

Lines changed: 30 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)