---
title: "Getting Started with glasstabs"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Getting Started with glasstabs}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(eval = FALSE)
```

## What is glasstabs?

glasstabs provides animated Shiny widgets for tab navigation and
selection controls:

- **Tabs**: a glass-morphism tab navigation bar with a sliding halo,
  spring easing, and a luminous transfer trace between tabs
- **Multi-select filter**: a dropdown filter with animated checkboxes,
  live search, tag-pill display, and three checkbox styles
- **Single-select dropdown**: an animated single-select input with
  optional search and clear support

All widgets work in plain `fluidPage()` and in bs4Dash. They can be used
together or independently.
---

## Installation

```{r install}
# From CRAN 
install.packages("glasstabs")

# From GitHub
pak::pak("YOUR_GITHUB_USERNAME/glasstabs")

# From source
devtools::install_local("path/to/glasstabs")
```

---

## The one rule: call `useGlassTabs()` once

Every glasstabs app needs exactly one call to `useGlassTabs()` somewhere in
the UI. It injects the CSS and JavaScript as a proper `htmltools` dependency.

```{r use}
library(shiny)
library(glasstabs)

ui <- fluidPage(
  useGlassTabs(),   # <-- this is all you need
  # ... rest of your UI
)
```

---

## Tab widget in 3 minutes

### Step 1 — define your tabs

Each `glassTabPanel()` takes a unique `value`, a display `label`, and any UI
content:

```{r tab-panels}
glassTabPanel("overview", "Overview", selected = TRUE,
  h3("Welcome"),
  p("This is the overview pane.")
)
```

### Step 2 — assemble with `glassTabsUI()`

Pass your panels to `glassTabsUI()` along with a namespace `id`:

```{r tabs-ui}
ui <- fluidPage(
  useGlassTabs(),
  glassTabsUI("nav",
    glassTabPanel("overview", "Overview", selected = TRUE,
      shiny::h3("Welcome"),
      shiny::p("Start here.")
    ),
    glassTabPanel("analysis", "Analysis",
      shiny::h3("Analysis"),
      shiny::p("Your charts go here.")
    ),
    glassTabPanel("settings", "Settings",
      shiny::h3("Settings"),
      shiny::p("Configuration options.")
    )
  )
)
```

### Step 3 — read the active tab in the server

The active tab value is pushed to Shiny automatically on every click:

```{r tabs-server}
server <- function(input, output, session) {
  observe({
    req(input[["nav-active_tab"]])
    message("User is on: ", input[["nav-active_tab"]])
  })
}

shinyApp(ui, server)
```

---

## Multi-select filter

### Step 1 — define choices and place the widget

```{r ms-basic}
choices <- c(Alpha = "alpha", Beta = "beta", Gamma = "gamma", Delta = "delta")

ui <- fluidPage(
  useGlassTabs(),
  glassMultiSelect("category", choices),
  verbatimTextOutput("selected")
)
```

### Step 2 — read the selection in the server

```{r ms-server}
server <- function(input, output, session) {
  output$selected <- renderPrint(input$category)
}

shinyApp(ui, server)
```

`input$category` is always a plain character vector of the checked values —
use it like any other Shiny input to filter data, drive outputs, or trigger
reactives.

### Optional reactive helper

If you want a small convenience wrapper:


```{r ms-helper}
server <- function(input, output, session) {
  ms <- glassMultiSelectValue(input, "category")

  observe({
    message("Selected: ", paste(ms$selected(), collapse = ", "))
    message("Style: ", ms$style())
  })
}
```


### Updating from the server

`glassMultiSelect()` also supports server-side updates:

```{r ms-update}
server <- function(input, output, session) {
  observeEvent(input$reset, {
    updateGlassMultiSelect(
      session,
      "category",
      selected = character(0)
    )
  })
}
```

---


---

## Single-select dropdown

### Step 1: add a single-select input


```{r gs-basic}
choices <- c(
  North = "north",
  South = "south",
  East  = "east",
  West  = "west"
)

ui <- fluidPage(
  useGlassTabs(),
  glassSelect("region", choices, clearable = TRUE),
  verbatimTextOutput("selected")
)
```


### Step 2: read the value in the server

```{r gs-server}
server <- function(input, output, session) {
  output$selected <- renderPrint(input$region)
}

shinyApp(ui, server)
```

`input$region` is a single character value, or `NULL` when nothing is
selected.

### Updating from the server

```{r gs-update}
server <- function(input, output, session) {
  observeEvent(input$pick_south, {
    updateGlassSelect(
      session,
      "region",
      selected = "south"
    )
  })
}
```

---

## Using them together

A common pattern is using one or more filters to drive content inside
tab panes. Pass a widget to `extra_ui` and place `glassFilterTags()`
inside panes to show active multi-select filters as removable tag pills.

```{r together}
choices <- c(North = "north", South = "south", East = "east", West = "west")

ui <- fluidPage(
  useGlassTabs(),
  glassTabsUI("main",
    extra_ui = glassMultiSelect(
      inputId             = "region",
      choices             = choices,
      show_style_switcher = FALSE
    ),
    glassTabPanel("summary", "Summary", selected = TRUE,
      shiny::h3("Summary"),
      glassFilterTags("region"),        # tag pills appear here
      shiny::uiOutput("summary_text")
    ),
    glassTabPanel("detail", "Detail",
      shiny::h3("Detail"),
      glassFilterTags("region"),        # same filter, second pane
      shiny::tableOutput("detail_table")
    )
  )
)

server <- function(input, output, session) {

  selected_regions <- reactive({
    input$region %||% unique(unname(choices))
  })

  output$summary_text <- renderUI({
    shiny::p("Showing data for: ",
             shiny::strong(paste(selected_regions(), collapse = ", ")))
  })

  output$detail_table <- renderTable({
    data.frame(Region = selected_regions())
  })
}

shinyApp(ui, server)
```

---

## Choosing a theme

Both widgets default to `"dark"`. Switch to `"light"` or supply a custom
theme object — in each case you only override what you need:

```{r themes}
# Built-in light preset
glassTabsUI("nav",    theme = "light", ...)
glassMultiSelect("f", theme = "light", ...)

# Custom — one field each
glassTabsUI("nav",
  theme = glass_tab_theme(halo_bg = "rgba(251,191,36,0.15)"),
  ...
)

glassMultiSelect("f", choices,
  theme = glass_select_theme(accent_color = "#f59e0b")
)
```

---

## bs4Dash

Add `wrap = FALSE` so the glass halo positions itself relative to the card
body rather than a full-page container. Pair with `theme = "light"`:

```{r bs4dash}
library(bs4Dash)
library(glasstabs)

choices <- c(Alpha = "alpha", Beta = "beta", Gamma = "gamma")

ui <- bs4DashPage(
  header  = bs4DashNavbar(title = "My App"),
  sidebar = bs4DashSidebar(disable = TRUE),
  body    = bs4DashBody(
    useGlassTabs(),
    bs4Card(
      title = "Analysis", width = 12,
      glassTabsUI("dash",
        wrap = FALSE,
        theme = "light",
        extra_ui = glassMultiSelect(
          "f",
          choices,
          theme = "light",
          show_style_switcher = FALSE
        ),
        glassTabPanel("a", "Overview", selected = TRUE,
          shiny::p("Overview content.")
        ),
        glassTabPanel("b", "Detail",
          shiny::p("Detail content.")
        )
      )
    )
  )
)

server <- function(input, output, session) {}
shinyApp(ui, server)
```

---

## Next steps

- **[Animated Tabs](tabs.html)** — full reference for `glassTabsUI()`:
  theming, keyboard nav, multiple instances, server patterns
- **[Multi-Select Filter](multiselect.html)** — full reference for
  `glassMultiSelect()`: checkbox styles, custom hues, tag pills, theming
- **[Single-Select Dropdown](glassSelect.html)**: search, clearable
  inputs, explicit “All” choices, and server-side updates
- **Reference** — complete function documentation at `help(package = "glasstabs")`
