Skip to content
Merged
41 changes: 38 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,39 @@
This is the source of the R-ArcGIS Bridge package clacite which provides bindings to Esri Calcite Design System components.
- This is the source of the R-ArcGIS Bridge package {clacite} which provides bindings to Esri Calcite Design System components.
- The components were originally automatically generated by data-raw/generate-component-new.R
- The auto-generated shiny bindings are created via inst/www/calcite-bindings.js
- We are in the process of re-writing them manually.

The components are automatically generated by data-raw/generate-component-new.R
The shiny bindings are created via inst/www/calcite-bindings.js
## Creating new components

When creating a new component:

- remind me to remove the component from R/components-generated.R
- remind me to remove the binding from inst/www/calcite-bindings.js
- create a new binding inst/www/calcite-{component}.js
- add the binding using `htmltools::htmlDependency()`


R/action.R example:
```
action_binding <- htmltools::htmlDependency(
name = "calcite-action-binding",
version = calcite_version(),
src = c(file = system.file("www", package = "calcite")),
script = "calcite-action.js"
)
```

- Component properties (except read-only) must be arguments
- Component slots must be arguments
- Ignore all deprecated properties and slots
- Bindings must register each event

- New components must have a `inst/examples/calcite-{component}.R` file based on calcite JS examples
- The example should always use `verbatimTextOutput()` to show how components change


## Etiquette

- Never run R code, ask me to.
- Use `compact()` to remove NULL elements from a list
- Use `rlang::arg_match()` to validate input string values
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: calcite
Title: Bindings to the Calcite Design System 'JavaScript' Component
Library
Version: 0.1.2
Version: 0.1.2.9000
Authors@R:
person("Josiah", "Parry", , "josiah.parry@gmail.com", role = c("aut", "cre"),
comment = c(ORCID = "0000-0001-9910-865X"))
Expand All @@ -19,4 +19,4 @@ Imports:
Encoding: UTF-8
Language: en
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.2
RoxygenNote: 7.3.3
5 changes: 3 additions & 2 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,6 @@ export(calcite_tabs)
export(calcite_text_area)
export(calcite_tile)
export(calcite_tile_group)
export(calcite_tile_select)
export(calcite_tile_select_group)
export(calcite_time_picker)
export(calcite_tip)
export(calcite_tip_group)
Expand All @@ -97,4 +95,7 @@ export(calcite_tooltip)
export(calcite_tree)
export(calcite_tree_item)
export(calcite_version)
export(page_actionbar)
export(page_navbar)
export(page_sidebar)
export(update_calcite)
14 changes: 14 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# calcite (development version)

- adds experimental page layous: `page_navbar()`, `page_sidebar()`, `page_actionbar()`
- manually implements numerous components for improved shiny integration and documentation clarity:
- `calcite_action()`
- `calcite_block()`
- `calcite_date_picker()`
- `calcite_tile()`
- `calcite_tile_group()`
- `calcite_slider()`
- `calcite_segmented_control_item()`
- `calcite_notice()`
- `calcite_panel()`

# calcite 0.1.2

- `calcite_button()` click handler can be tracked via `input$your_button$clicked`
Expand Down
93 changes: 93 additions & 0 deletions R/action-group.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#' Create a Calcite Action Group Component
#'
#' Groups multiple action components together with consistent layout and spacing.
#' Action groups can be used within action bars to organize related actions.
#'
#' @param ... Child `calcite_action()` components or other content
#' @param id Optional ID for the action group
#' @param layout Layout style: "vertical", "horizontal", or "grid"
#' @param columns Number of columns when layout is "grid" (1-6)
#' @param scale Size of the group: "s" (small), "m" (medium), or "l" (large)
#' @param expanded Whether the group is expanded
#' @param label Accessibility label for the group
#' @param slot Optional slot name (e.g., "bottom-actions" for action bars)
#'
#' @export
#' @return An object of class `calcite_component`
#' @references [Official Documentation](https://developers.arcgis.com/calcite-design-system/components/action-group/)
#' @examples
#' # Basic action group with vertical layout
#' calcite_action_group(
#' calcite_action(text = "Add", icon = "plus"),
#' calcite_action(text = "Edit", icon = "pencil"),
#' calcite_action(text = "Delete", icon = "trash")
#' )
#'
#' # Horizontal group with custom scale
#' calcite_action_group(
#' layout = "horizontal",
#' scale = "l",
#' calcite_action(text = "Save", icon = "save"),
#' calcite_action(text = "Cancel", icon = "x")
#' )
#'
#' # Grid layout with 2 columns
#' calcite_action_group(
#' layout = "grid",
#' columns = 2,
#' calcite_action(text = "A", icon = "letter-a"),
#' calcite_action(text = "B", icon = "letter-b"),
#' calcite_action(text = "C", icon = "letter-c"),
#' calcite_action(text = "D", icon = "letter-d")
#' )
calcite_action_group <- function(
...,
id = NULL,
layout = NULL,
columns = NULL,
scale = NULL,
expanded = NULL,
label = NULL,
slot = NULL
) {
# Validate layout if provided
if (!is.null(layout)) {
layout <- match.arg(layout, c("vertical", "horizontal", "grid"))
}

# Validate scale if provided
if (!is.null(scale)) {
scale <- match.arg(scale, c("s", "m", "l"))
}

# Validate columns if provided
if (!is.null(columns)) {
if (!is.numeric(columns) || columns < 1 || columns > 6) {
stop("columns must be a number between 1 and 6")
}
}

# Build attributes list
attribs <- compact(list(
id = id,
layout = layout,
columns = columns,
scale = scale,
expanded = expanded,
label = label,
slot = slot
))

# Build the tag
res <- htmltools::tag(
"calcite-action-group",
c(
attribs,
rlang::dots_list(...),
list(calcite_dependency(), calcite_bindings())
)
)

class(res) <- c("calcite_component", class(res))
res
}
175 changes: 175 additions & 0 deletions R/action.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
#' Create a Calcite Action Component
#'
#' Creates an action button that can be used within action bars and action groups.
#' Actions provide a compact way to trigger operations with icon-based buttons.
#'
#' @param text Text label for the action (required, also used for accessibility)
#' @param icon Icon name from the Calcite icon set
#' @param id Optional ID for the action (required for Shiny reactivity)
#' @param active Whether the action is highlighted/selected
#' @param disabled Whether the action is disabled
#' @param indicator Whether to show a visual indicator (e.g., notification badge)
#' @param text_enabled Whether to display the text label alongside the icon
#' @param scale Size of the action: "s" (small), "m" (medium), or "l" (large)
#' @param alignment Text alignment: "start", "center", or "end"
#' @param appearance Visual style: "solid" or "transparent"
#' @param loading Whether to show a loading indicator
#' @param label Custom accessibility label (defaults to `text` if not provided)
#' @param ... Additional attributes passed to the component
#'
#' @details
#' ## Shiny Integration
#'
#' When used in a Shiny app, `calcite_action()` returns a reactive list containing
#' all component properties. You can observe the entire component state or watch
#' individual properties:
#'
#' **Available properties:**
#' - `$clicked` - Boolean that toggles on each click (use this to detect clicks)
#' - `$active` - Whether the action is currently active/highlighted
#' - `$disabled` - Whether the action is disabled
#' - `$icon` - The icon name
#' - `$text` - The text label
#' - `$indicator` - Whether an indicator is shown
#' - `$alignment`, `$appearance`, `$scale`, etc. - Other component properties
#'
#' **Usage in server:**
#' ```r
#' # Watch for any change to the action (including clicks)
#' observeEvent(input$my_action, {
#' print("Action changed!")
#' })
#'
#' # Watch only the clicked state
#' observeEvent(input$my_action$clicked, {
#' print("Action was clicked!")
#' })
#'
#' # Access specific properties
#' observeEvent(input$my_action, {
#' is_active <- input$my_action$active
#' click_state <- input$my_action$clicked
#' })
#' ```
#'
#' @export
#' @return An object of class `calcite_component`
#' @references [Official Documentation](https://developers.arcgis.com/calcite-design-system/components/action/)
#' @examples
#' # Basic action with icon
#' calcite_action(
#' text = "Layers",
#' icon = "layers",
#' id = "layers-action"
#' )
#'
#' # Active action with text label
#' calcite_action(
#' text = "Settings",
#' icon = "gear",
#' active = TRUE,
#' text_enabled = TRUE
#' )
#'
#' # Action with indicator
#' calcite_action(
#' text = "Notifications",
#' icon = "bell",
#' indicator = TRUE
#' )
#'
#' # Shiny example
#' if (interactive()) {
#' library(shiny)
#'
#' ui <- calcite_shell(
#' calcite_action(
#' id = "my_action",
#' text = "Click me",
#' icon = "check",
#' text_enabled = TRUE
#' ),
#' verbatimTextOutput("status")
#' )
#'
#' server <- function(input, output, session) {
#' # Respond to clicks
#' observeEvent(input$my_action$clicked, {
#' message("Action clicked! State: ", input$my_action$clicked)
#' })
#'
#' # Display all properties
#' output$status <- renderPrint({
#' input$my_action
#' })
#' }
#'
#' shinyApp(ui, server)
#' }
calcite_action <- function(
text,
icon = NULL,
id = NULL,
active = NULL,
disabled = NULL,
indicator = NULL,
text_enabled = NULL,
scale = NULL,
alignment = NULL,
appearance = NULL,
loading = NULL,
label = NULL,
...
) {
if (!is.null(scale)) {
scale <- match.arg(scale, c("s", "m", "l"))
}

if (!is.null(alignment)) {
alignment <- match.arg(alignment, c("start", "center", "end"))
}

if (!is.null(appearance)) {
appearance <- match.arg(appearance, c("solid", "transparent"))
}

attribs <- compact(list(
id = id,
text = text,
icon = icon,
active = active,
disabled = disabled,
indicator = indicator,
`text-enabled` = text_enabled,
scale = scale,
alignment = alignment,
appearance = appearance,
loading = loading,
label = label
))

extra_attribs <- rlang::dots_list(...)

all_attribs <- c(
attribs,
extra_attribs[!names(extra_attribs) %in% names(attribs)]
)

action_binding <- htmltools::htmlDependency(
name = "calcite-action-binding",
version = calcite_version(),
src = c(file = system.file("www", package = "calcite")),
script = "calcite-action.js"
)

res <- htmltools::tag(
"calcite-action",
c(
all_attribs,
list(calcite_dependency(), action_binding)
)
)

class(res) <- c("calcite_component", class(res))
res
}
Loading
Loading