Skip to content

Instantly share code, notes, and snippets.

@gadenbuie
Last active July 13, 2023 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gadenbuie/53fdd9cc4beed95314dd889b9aab7b0b to your computer and use it in GitHub Desktop.
Save gadenbuie/53fdd9cc4beed95314dd889b9aab7b0b to your computer and use it in GitHub Desktop.
bslib function prefixes
library(tidyverse)

bsf <- pkgnet::FunctionReporter$new()
bsf$set_package("bslib")
bsf$calculate_default_measures()
bslib_fns <-
  bsf$nodes |>
  as_tibble() |>
  filter(!str_detect(node, "^[.%]")) |>
  filter(isExported) |>
  select(node, isExported, betweenness) |>
  separate(node, c("prefix", "rest"), sep = "_", extra = "merge", fill = "right", remove = FALSE)
bslib_fns |>
  count(prefix, sort = TRUE) |>
  print(n = 25)
#> # A tibble: 27 × 2
#>    prefix          n
#>    <chr>       <int>
#>  1 bs             36
#>  2 nav            14
#>  3 accordion       8
#>  4 card            7
#>  5 navs            7
#>  6 navset          7
#>  7 page            7
#>  8 is              4
#>  9 as              3
#> 10 layout          3
#> 11 bootstrap       2
#> 12 showcase        2
#> 13 sidebar         2
#> 14 theme           2
#> 15 as.card         1
#> 16 bootswatch      1
#> 17 breakpoints     1
#> 18 builtin         1
#> 19 input           1
#> 20 is.card         1
#> 21 precompiled     1
#> 22 remove          1
#> 23 run             1
#> 24 update          1
#> 25 value           1
#> # ℹ 2 more rows
bslib_fns |>
  filter(prefix %in% c("bs", "accordion", "card", "nav", "navset", "page", "layout", "input", "update")) |>
  (\(x) split(x, x$prefix))()
#> $accordion
#> # A tibble: 8 × 5
#>   node                   prefix    rest         isExported betweenness
#>   <chr>                  <chr>     <chr>        <lgl>            <dbl>
#> 1 accordion              accordion <NA>         TRUE               190
#> 2 accordion_panel        accordion panel        TRUE                 0
#> 3 accordion_panel_close  accordion panel_close  TRUE                 0
#> 4 accordion_panel_insert accordion panel_insert TRUE                 0
#> 5 accordion_panel_open   accordion panel_open   TRUE                 0
#> 6 accordion_panel_remove accordion panel_remove TRUE                 0
#> 7 accordion_panel_set    accordion panel_set    TRUE                 0
#> 8 accordion_panel_update accordion panel_update TRUE                 0
#>
#> $bs
#> # A tibble: 36 × 5
#>    node                prefix rest             isExported betweenness
#>    <chr>               <chr>  <chr>            <lgl>            <dbl>
#>  1 bs_add_declarations bs     add_declarations TRUE              0
#>  2 bs_add_functions    bs     add_functions    TRUE              0
#>  3 bs_add_mixins       bs     add_mixins       TRUE              0
#>  4 bs_add_rules        bs     add_rules        TRUE              1
#>  5 bs_add_variables    bs     add_variables    TRUE            139.
#>  6 bs_bundle           bs     bundle           TRUE             18.5
#>  7 bs_current_theme    bs     current_theme    TRUE             52.5
#>  8 bs_dependency       bs     dependency       TRUE              0
#>  9 bs_dependency_defer bs     dependency_defer TRUE             43
#> 10 bs_get_contrast     bs     get_contrast     TRUE              5.23
#> # ℹ 26 more rows
#>
#> $card
#> # A tibble: 7 × 5
#>   node           prefix rest      isExported betweenness
#>   <chr>          <chr>  <chr>     <lgl>            <dbl>
#> 1 card           card   <NA>      TRUE           129
#> 2 card_body      card   body      TRUE            21
#> 3 card_body_fill card   body_fill TRUE             0
#> 4 card_footer    card   footer    TRUE             0.333
#> 5 card_header    card   header    TRUE             0.833
#> 6 card_image     card   image     TRUE             0
#> 7 card_title     card   title     TRUE             0
#>
#> $input
#> # A tibble: 1 × 5
#>   node         prefix rest   isExported betweenness
#>   <chr>        <chr>  <chr>  <lgl>            <dbl>
#> 1 input_switch input  switch TRUE                 0
#>
#> $layout
#> # A tibble: 3 × 5
#>   node               prefix rest        isExported betweenness
#>   <chr>              <chr>  <chr>       <lgl>            <dbl>
#> 1 layout_column_wrap layout column_wrap TRUE               93
#> 2 layout_columns     layout columns     TRUE                0
#> 3 layout_sidebar     layout sidebar     TRUE              217.
#>
#> $nav
#> # A tibble: 14 × 5
#>    node             prefix rest         isExported betweenness
#>    <chr>            <chr>  <chr>        <lgl>            <dbl>
#>  1 nav              nav    <NA>         TRUE                 0
#>  2 nav_append       nav    append       TRUE                 0
#>  3 nav_content      nav    content      TRUE                 0
#>  4 nav_hide         nav    hide         TRUE                 0
#>  5 nav_insert       nav    insert       TRUE                 0
#>  6 nav_item         nav    item         TRUE                 0
#>  7 nav_menu         nav    menu         TRUE                 0
#>  8 nav_panel        nav    panel        TRUE                 0
#>  9 nav_panel_hidden nav    panel_hidden TRUE                 0
#> 10 nav_prepend      nav    prepend      TRUE                 0
#> 11 nav_remove       nav    remove       TRUE                 0
#> 12 nav_select       nav    select       TRUE                 0
#> 13 nav_show         nav    show         TRUE                 0
#> 14 nav_spacer       nav    spacer       TRUE                 0
#>
#> $navset
#> # A tibble: 7 × 5
#>   node             prefix rest      isExported betweenness
#>   <chr>            <chr>  <chr>     <lgl>            <dbl>
#> 1 navset_bar       navset bar       TRUE               0
#> 2 navset_card_pill navset card_pill TRUE               0
#> 3 navset_card_tab  navset card_tab  TRUE               0
#> 4 navset_hidden    navset hidden    TRUE               0
#> 5 navset_pill      navset pill      TRUE              18.5
#> 6 navset_pill_list navset pill_list TRUE               0
#> 7 navset_tab       navset tab       TRUE              18.5
#>
#> $page
#> # A tibble: 7 × 5
#>   node          prefix rest     isExported betweenness
#>   <chr>         <chr>  <chr>    <lgl>            <dbl>
#> 1 page          page   <NA>     TRUE                30
#> 2 page_fill     page   fill     TRUE                 0
#> 3 page_fillable page   fillable TRUE                12
#> 4 page_fixed    page   fixed    TRUE                 0
#> 5 page_fluid    page   fluid    TRUE                 0
#> 6 page_navbar   page   navbar   TRUE                 0
#> 7 page_sidebar  page   sidebar  TRUE                 0
#>
#> $update
#> # A tibble: 1 × 5
#>   node          prefix rest   isExported betweenness
#>   <chr>         <chr>  <chr>  <lgl>            <dbl>
#> 1 update_switch update switch TRUE                 0

In general, I think things input_{type} pairs well with update_{type} and similarly output_{type} with render_{type}. I'm very tempted to say that we should have update_accordion_panel() but I probably also would have gone with accordion_panel_update() back when there weren't any update_ functions at all. That said, maybe we'd have an alias? I think it's really helpful to be able to type out update_ and hit tab and see the things you can update. I think that for UI elements, prefixing within the component type makes sense, but once you've built out the UI, then the code lives in a different context.

I'm actually starting to talk myself into a few more things, like toggle_, insert_ and remove_ prefixes:

  • toggle_sidebar() instead of sidebar_toggle() (the second one kinda sounds like a noun and not a verb)
  • toggle_accordion_panel() instead of accordion_panel_set()
  • toggle_switch() (keeping update_switch())
  • update_accordion_panel()
  • update_accordion()
    • maybe we don't need this one, but one thing it might do is open/close more than one panel at a time
  • insert_accordion_panel() , remove_accordion_panel()

Quick thoughts behind those prefixes:

  • update_*() changes the properties of the thing, like state, labels, styles, titles, etc
  • toggle_*() is used for binary state only — open/closed, on/off, active/inactive — by default flips state but can force a particular state
  • insert_*() and remove_*() for adding and removing UI elements
  • input_* , output_*, render_*, standard shiny stuff
  • page_* and layout_* for layouts
  • navset_* and nav_* for navs and content toggles

This has some reach into nav land, too:

  • insert_nav() or insert_nav_panel() would consume nav_append(), nav_prepend() and nav_insert()
  • update_nav_panel() would handle nav_hide() and nav_show()
  • update_navset() would handle nav_select() (or maybe it'd be toggle_nav_panel())

Thinking about nav_hide() and nav_show() brought up that toggle_* would only be used for binary state that's reported back to the server. iotw, we wouldn't use toggle_nav_panel() to hide/show the nav because that's not the dominant state of the nav panel. We might also choose not to use toggle_nav_panel() to activate the nav panel because there's no clear opposite (how do you "unactivate" a nav panel?)

I think the key for me is the distinction between contexts. When you're writing your UI you're in a "what else goes in an accordion" mind frame. You want to type accordion and hit tab to see the other things you can include there. When you're in your server logic, you're in a different head space. You're thinking about the verb first... "okay so when this input value changes, I want to... update... my accordion"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment