--- title: "The stack menu" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{The stack menu} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include=FALSE} knitr::opts_chunk$set(eval = FALSE, comment = "#>") ``` `blockr.ui::stack_menu_ui()` is a multi-select card-list block picker for stacks. It lives inside the [sidebar primitive](sidebar.html) 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). ## Create vs edit The flow is selected by the `target` argument, mirroring [`block_browser_ui()`](block-browser.html): * `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 = ""` 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. ## Commit contract 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()`. ## Minimal example ```{r} 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: ```{r} system.file("examples", "stack-menu", "app.R", package = "blockr.ui") ``` ## Colour picker 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 `` 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.