blockr.ui::stack_menu_ui()
is a multi-select card-list block picker for stacks. It lives inside the
sidebar primitive and replaces the legacy
selectize-style chooser used by blockr.dock’s add / edit
stack flows. Each card represents a board instance (a block
already on the board) and clicking a card toggles its membership in the
new (or edited) stack. A small panel-level form below the cards carries
the stack-level parameters (name, color, id).
The flow is selected by the target argument, mirroring
block_browser_ui():
target = NULL (default) is the
create flow. The eligible pool is every board block
that is not currently a member of a stack. No card is pre-selected. The
form exposes Stack name (always), Stack color
and Stack id (under an Advanced toggle).
target = "<stack_id>" is the
edit flow. The function looks the stack up via
blockr.core::board_stacks(board)[[target]], augments the
pool with the stack’s current blocks (so the user can deselect them),
pre-selects them, and pre-fills name / color. The stack id is fixed and
not rendered. An unknown id raises a clean error.
The menu publishes the selection set through a Shiny input binding;
the panel-level name / color / id fields are normal Shiny inputs. The
server composes the full spec -
list(blocks, name, color, id) - from both sources, strips
the internal nonce, and hands the spec to
observeEvent().
library(shiny)
library(blockr.ui)
library(blockr.core)
board <- new_board(
blocks = list(
a = new_dataset_block(),
b = new_head_block(),
c = new_subset_block()
)
)
ui <- fluidPage(
sidebar_ui("panel", side = "right", width = "420px"),
actionButton("open_create", "Create stack"),
actionButton("open_edit", "Edit stack s1"),
verbatimTextOutput("spec")
)
server <- function(input, output, session) {
committed <- stack_menu_server("menu")
observeEvent(input$open_create, {
show_sidebar(
"panel",
title = "Create stack",
ui = stack_menu_ui(session$ns("menu"), board)
)
})
observeEvent(input$open_edit, {
show_sidebar(
"panel",
title = "Edit stack s1",
ui = stack_menu_ui(session$ns("menu"), board, target = "s1")
)
})
output$spec <- renderPrint(committed())
}
shinyApp(ui, server)A runnable copy is shipped at:
The stack colour widget is an inline hue / lightness slider + hex
text input shipped by blockr.ui itself - no popover that
escapes the sidebar, no extra dependency. Moving a slider recomputes
HSL -> hex and writes the hex field; typing in the hex
field parses back the other way and repositions the sliders. The hex
<input> is a regular Shiny text input, so the colour
reaches the server through Shiny’s built-in text-input binding without
any custom JS path.