                        Changes in version 0.4.1                        

Fixes

  - Select dropdowns now grow beyond narrow triggers when their controls
    or longer option labels need more room, up to a comfortable
    viewport-aware cap. The multi-select Check / Box / Fill switcher
    also falls back to compact text-only buttons on extremely narrow
    screens, so Fill is never clipped.

  - Added runGlassExample("light-mode"), a dedicated light-interface
    example covering tabs, single-select, multi-select, and
    intentionally long labels.

  - no_matches_text moved to the end of the glassSelect() and
    glassMultiSelect() signatures. It was added in the middle, so
    existing positional calls could silently bind the wrong arguments.

  - The full-screen overlay observer now watches the whole document
    subtree and scans descendants of inserted nodes, so overlays nested
    inside app wrappers and hidden overlays revealed by class/style
    toggles also dismiss open select dropdowns. Browser tests cover the
    nested and toggled cases.

  - glassTabsUI(content_min_height = NULL) (the new default) no longer
    writes an inline --gt-content-min-height, restoring the 60px compact
    minimum: compact widgets use 60px, regular widgets 120px, and an
    explicitly supplied value still wins.

  - Attached vertical tabs in RTL layouts now fully reset to the stacked
    top-bar layout below 760px (the base [dir="rtl"] rules previously
    outranked the narrow-screen reset, leaving side borders and corner
    radii active).

  - %||% is internal again instead of exported: its length-zero fallback
    semantics differ from rlang::%||%, and exporting it risked masking
    between the two. Vignettes and example apps now use a small local
    fallback() helper.

  - updateGlassTabBadge() caps huge counts at 100 instead of letting
    as.integer() coerce them to NA with a warning; the browser already
    renders anything above 99 as "99+".

  - glass_tab_theme() docs no longer claim unset fields always inherit
    dark defaults; they inherit from the mode base preset. The README
    function table now lists content_min_height, style, and transition
    in the glassTabsUI() signature.

  - The %||% operator is internal (@noRd) rather than a documented
    export, so R CMD check has no |-in-\name concern at all.

  - Browser-test and stylesheet tests updated to match intended
    behavior: open dropdowns reposition (not close) on window resize,
    and color-mix() in glass.css is used only where unsupported browsers
    degrade gracefully.

  - The spelling wordlist now covers package vocabulary (mojibake,
    rlang, shinytest, ungrouped), and browser tests clean up Chrome's
    temp directories so R CMD check reports no detritus.

  - Vignettes and example apps that used %||% now define a small local
    fallback() helper instead; the operator stays internal to the
    package.

  - updateGlassTabBadge() no longer crashes on count = NULL; NULL and
    empty vectors hide the badge like NA does. Non-numeric,
    multi-length, negative, or infinite counts now raise a clear
    glasstabs_error_bad_argument error instead of producing corrupt
    messages.

  - glassTabPanel() validates that value and label are single strings,
    replacing cryptic downstream errors (empty labels remain allowed for
    icon-only tabs).

  - glass_tab_theme() gains a mode argument ("dark"/"light"). Unset
    fields now inherit from the mode's base preset, and light-mode
    custom themes receive the structural theme-light class in
    glassTabsUI() (previously a dead branch).

  - Invalid tab theme presets no longer list "auto" as valid; "auto" is
    resolved by glassTabsUI() before theme resolution runs.

  - glassSelect() and glassMultiSelect() reject duplicate choice values
    with a clear error instead of rendering ambiguous duplicate options.

  - Out-of-range rgb()/rgba() components are clamped the way browsers
    do, and malformed components yield a clean fallback instead of
    invalid CSS.

  - Server-mode glassMultiSelect() now renders every explicitly selected
    value outside the initial server_limit slice as an extra checked
    row, so pre-selections stay visible (previously only a single
    out-of-slice value got an extra row). Default selections remain
    bounded to the slice.

  - Grouped-choices docs now note that a one-element named list is
    treated as a flat choice, mirroring shiny::selectInput().

  - Vignettes now document the input$<id>_ready signal emitted once a
    select widget finishes initializing.

  - Removed the dead glasstabs_close_select custom message handler and
    its orphaned closeDropdownById() helper from glass.js; single-widget
    closes travel through the widget controllers via input messages.

  - Corrected a stale CSS comment that claimed teleported dropdowns use
    position:fixed (they deliberately use position:absolute).

  - Open select dropdowns no longer slam shut when an unrelated Shiny
    output updates. Only dropdowns anchored inside the updated output
    are closed, so dropdowns stay usable next to live outputs like
    timers and previews.

  - Window resizes (mobile URL-bar show/hide, the on-screen keyboard)
    now keep open select dropdowns glued to their trigger via
    repositioning instead of closing them. Dropdowns still close when
    their trigger is detached or has no layout box.

  - Open select dropdowns are now dismissed when a full-screen overlay
    appears (loading screens, waiter veils, custom overlays), instead of
    floating above or lingering beneath it. Smaller floating panels do
    not trigger this.

  - glassSelect() and glassMultiSelect() gain a no_matches_text argument
    to customize the "No matches" empty-search message.

  - Tab content now sits in a subtle glass container by default
    (barely-there background and hairline border) instead of an
    invisible box, so the tab bar and content read as one component. The
    old invisible look is still available via glass_tab_theme(content_bg
    = "transparent", content_border = "transparent"). Double padding
    between the tab bar and content is gone (22px instead of 44px) and
    the tab bar sits slightly closer to the content.

  - glassTabsUI() gains content_min_height (default "120px", was a fixed
    200px) to control the content area's minimum height; use "0" for
    none.

  - Tabs feel connected to their content: the active tab now shows a
    subtle inner light on its content-facing edge (bottom for horizontal
    tabs, side for a vertical rail, RTL-aware) in the halo color, and
    the content box's top edge picks up the same halo color to bridge
    the gap. The underline indicator keeps its own connection cue.

  - glassTabsUI() gains style = "attached", which docks the tab bar
    directly onto the content box so they share one border and read as a
    single unified card ("floating" keeps the default two-piece look).

  - glassTabsUI() gains transition = "slide", sliding panes horizontally
    in the direction of travel following tab order ("fade" keeps the
    default fade-and-rise).

  - Server-side choice search now normalizes the choice set once per
    widget instead of on every keystroke, making search over large
    choice sets noticeably snappier.

Docs and examples

  - Fixed stale v0.4.0 references, a placeholder GitHub username in the
    getting-started vignette, mojibake em dashes in the
    dashboard/bs4dash examples, and a wrong input id in the basic
    example's narrative.
  - The pkgdown reference now indexes closeGlassMultiSelect,
    closeAllGlassSelects, and the newly exported %||%.
  - CI now installs stable Chrome so the shinytest2 browser suite
    actually runs instead of failing on a missing browser.

Select dropdown sizing

  - glassSelect() and glassMultiSelect() dropdown panels now follow
    their trigger width. Short option lists stay aligned with the field
    instead of opening a wider fixed panel, while the viewport cap still
    protects narrow screens.
  - Long option labels, group headings, and unbroken identifiers now
    wrap inside the panel instead of being clipped or creating
    horizontal overflow.
  - glassMultiSelect() gains configurable and automatic search
    visibility, compact count or label summaries, and a configurable
    option-list height.
  - updateGlassMultiSelect() now applies linked changes as one
    transaction, preserves or drops selections explicitly, and can
    notify Shiny only when the effective value changes, always, or
    never.
  - glassMultiSelectValue() now keeps the raw selection while offering a
    separate resolved value for apps where an empty filter means none,
    all, or NULL.

                 Changes in version 0.4.0 (2026-09-11)                  

Responsive and accessible navigation

  - This release makes tabs more dependable on small screens and for
    people who use a keyboard, screen reader, reduced-motion setting, or
    high-contrast mode.
  - glassTabsUI() gains overflow and opt-in swipe controls. The selected
    tab stays visible in a scrolling strip, multiline tabs remain
    available, and menu mode provides a compact native chooser.
  - Tabs now use roving keyboard focus, Home/End navigation, and
    explicit ARIA relationships between each tab and its panel.
  - Rapid tab changes now settle as one consistent state across the
    active link, content pane, halo, compact menu, and Shiny input.
    Interrupted destinations do not trigger transient server work.
  - glass_tab_theme() and glass_select_theme() gain a focus_ring color.
    Tabs, select triggers, and search fields share a deliberate focus
    treatment, including search fields inside teleported dropdowns.
  - glassPage() is an experimental, lightweight wrapper around
    bslib::page_fillable() that loads the glasstabs dependency
    automatically.
  - Missing optional packages now report the documented
    glasstabs_error_missing_package condition class.
  - Tab clicks and keyboard activation no longer pass through a second
    fallback initialization, so the glass halo keeps its full movement
    in vertical and horizontal layouts. The arrival pulse also preserves
    the halo's settled alignment with the active tab in both
    orientations.
  - Compact-menu options now use an explicit native dark or light colour
    scheme, keeping option text readable when the operating system opens
    the select menu.
  - tab_align now places the tab group in both orientations. The new
    text_align argument independently aligns labels and icons inside tab
    buttons, keeping layout and text choices separate. Non-centered
    horizontal labels use equal button widths so their alignment remains
    visible.
  - Compact menu overflow is now documented and validated as a
    horizontal-only layout. A vertical tab rail paired with overflow =
    "menu" gets a clear error instead of silently ignoring the setting.
  - glassSelect() and glassMultiSelect() dropdowns now close reliably on
    an immediate outside press, including when a loading veil or overlay
    stops bubbling events. Closing during the opening frame also cancels
    pending positioning and focus work, preventing a dropdown from
    reappearing after it has closed. Programmatically opened Bootstrap
    modals and offcanvas panels also close any open dropdown before the
    new layer appears.
  - Dynamically rendered tab widgets now release their timers, browser
    listeners, observers, and animations when Shiny removes them from
    the page.
  - glassPage() now declares and checks its minimum supported bslib
    version, so an older optional dependency produces a useful update
    message.

                 Changes in version 0.3.4 (2026-07-31)                  

Internal consistency and diagnostics

  - Refactored internal rendering, theme CSS, hue generation,
    serialization, and validation without changing exported signatures,
    rendered HTML contracts, or Shiny message formats.
  - Package-generated errors now inherit from glasstabs_error, with the
    leaf classes glasstabs_error_bad_argument,
    glasstabs_error_bad_choice, glasstabs_error_bad_theme, and
    glasstabs_error_no_session. This makes errors easier to catch
    programmatically while retaining instructive messages.
  - Side-effect update helpers now consistently return NULL invisibly,
    as documented.
  - glassTabCondition() now emits valid single-backslash JavaScript
    escapes for carriage returns, newlines, tabs, and Unicode line
    separators in tab values.
  - Added golden HTML and message-payload regression tests, lint
    configuration, and a coverage workflow.

Vertical orientation

  - New orientation argument for glassTabsUI(): "vertical" stacks the
    tab buttons in a left-hand rail beside the content pane.
    ArrowUp/ArrowDown navigate in vertical mode, aria-orientation is set
    on the tablist, and indicator = "underline" renders as a slim side
    bar adjacent to the content. Falls back to stacked layout
    under 760px.
  - New tab_align argument for glassTabsUI(): "center" (default),
    "left", or "right" aligns tab button text and icons.

bslib / Bootstrap 5 auto theming

  - New theme = "auto" preset bridges to Bootstrap 5 color modes: light
    variables apply by default and dark variables apply under
    data-bs-theme="dark", toggled live in the browser (works with
    bslib::input_dark_mode() / toggle_dark_mode() with no server code).
  - glassSelect() and glassMultiSelect() also support theme = "auto" so
    their triggers and dropdown panels keep the glass look in both light
    and dark Bootstrap 5 color modes.

New example and article

  - runGlassExample("indicators") demos the three indicator styles,
    vertical orientation, and auto theming side by side.
  - New "Indicator Styles, Vertical Tabs, and Auto Theming" article.
  - runGlassExample("connect-workflow") provides a Posit Connect-ready
    workflow review page showing filters, badges, server-driven tab
    changes, horizontal/vertical tabs, tab text alignment, and auto
    theming in one deployable Shiny app.
  - The Connect workflow example now has stronger dark-mode contrast,
    auto-themed glass select dropdowns, neutral quick-action buttons
    with selected state, indicator and tab shape controls, and a
    responsive controls grid for narrower browsers. Closed glassSelect()
    and glassMultiSelect() fields remain readable when the page is in
    dark mode.
  - New "Publishing a glasstabs Workflow to Posit Connect" article.

Select dropdown positioning

  - Teleported glassSelect() and glassMultiSelect() dropdowns now clamp
    to the viewport, so narrow browser widths no longer cut off the left
    or right edge of the dropdown panel.

Tab indicator

  - New indicator argument for glassTabsUI(): "glass" (default), "solid"
    (flat opaque sliding pill, no backdrop-filter or shimmer - lighter
    on the GPU and better suited to plain dashboards), and "underline"
    (slim sliding bar under the active tab).

Halo alignment fixes

  - The halo now fits the active tab exactly from its rendered edges,
    avoiding the right-side spill that could appear after initial load
    or tab changes.
  - Initial halo placement now starts at the full tab size instead of
    briefly rendering a smaller centered outline before the first tab
    change.
  - Default and compact tab buttons are larger and easier to hit.
  - Halo position now accounts for container borders
    (clientLeft/clientTop), fixing a horizontal shift inside bordered
    fallback containers such as bs4Dash .card-body.
  - A ResizeObserver re-aligns the halo whenever tab geometry changes
    without a window resize: badge count updates, label changes via
    renderUI, font swaps, or sidebar collapse.

Dropdown lifecycle

  - Added closeGlassSelect(), closeGlassMultiSelect(), and
    closeAllGlassSelects() so apps can explicitly close dropdowns before
    tab switches, modal changes, or dynamic UI replacement.
  - glassSelect() and glassMultiSelect() now expose open state as
    input$<inputId>_open.
  - Open dropdowns now close on additional lifecycle events, including
    outside pointer-down, window resize, Bootstrap tab/modal/collapse
    hiding, sidebar/offcanvas transitions, Shiny value replacement, and
    Shiny disconnect.

                 Changes in version 0.3.3 (2026-06-25)                  

Released to CRAN.

Native-layout parity

  - glassSelect() and glassMultiSelect() gained a width argument (passed
    to shiny::validateCssUnit()) so the widgets can fill a column or
    match a fixed layout, like native selectizeInput().
  - Both selects now accept grouped choices as a named list,
    selectInput()-style (e.g. list(Fruit = c(Apple = "apple"), Veg =
    c(...))), rendering non-interactive group headers. Search hides
    headers whose options are all filtered out.
  - Added disabled support: disabled = TRUE greys out and blocks the
    whole widget, and disabled_choices renders individual options as
    non-selectable. Both are also reachable at runtime via
    updateGlassSelect() / updateGlassMultiSelect() (disabled,
    disabled_choices). Disabled options are skipped by "Select all".
  - glassTabsUI() gained a shape argument ("rounded" default or
    "square") so the tab bar and content corners can match shape =
    "square" selects for a cohesive, selectize-style layout.

Square corners

  - Added a shape argument to glassSelect() and glassMultiSelect(). The
    default shape = "rounded" keeps the signature glass look, while
    shape = "square" applies crisp, selectize-style corners so the
    widgets sit flush next to native selectizeInput() controls without
    looking out of place.
  - updateGlassSelect() and updateGlassMultiSelect() gained a shape
    argument so the corner style can be switched at runtime from the
    server without re-rendering the widget (open dropdowns and selection
    state are preserved).
  - Added a runGlassExample("square-corners") example app that
    demonstrates the square shape live alongside native
    selectizeInput(), including a runtime rounded-vs-square toggle via
    update*() and a light-theme variant.
  - Added a runGlassExample("bslib") example app that shows square
    glassSelect() and glassMultiSelect() controls inside a Bootstrap 5
    bslib layout.

Large choice sets

  - Added opt-in server-side search support for large glassSelect() and
    glassMultiSelect() choice sets via server = TRUE,
    glassSelectServer(), and glassMultiSelectServer().
  - Added loading and no-results states for select search results,
    including server-backed search responses.
  - Added a runnable runGlassExample("server-select") example and
    vignette sections for server-backed single- and multi-select
    controls.

Bug fixes

  - Fixed updateGlassMultiSelect() updates being lost when a
    multi-select is created or replaced by renderUI() in the same
    reactive flush. Dynamic updates now target the replacement widget
    and retry briefly while it binds.
  - Fixed scalar selected values being interpreted as an empty selection
    by the multi-select JavaScript binding.

                 Changes in version 0.3.2 (2026-05-23)                  

Public dashboard readiness

  - Removed all color-mix() usage from the shipped stylesheet. Select
    widget alpha colors are now precomputed as CSS custom properties at
    render time for better compatibility with older embedded browsers.
  - Added ARIA combobox/listbox/option semantics to glassSelect() and
    glassMultiSelect(), with JavaScript keeping aria-expanded and
    aria-selected in sync during interaction.
  - Improved keyboard behavior for select widgets: Escape and Tab close
    open dropdowns and return focus to the trigger; single-select option
    clicks also return focus.
  - Added CSP nonce support for inline style tags via the
    glasstabs.csp_nonce option.
  - Added Windows High Contrast (forced-colors) CSS support and RTL
    layout support for tabs and select widgets.
  - Improved narrow-screen select trigger behavior so labels truncate
    cleanly inside dashboard cards instead of overflowing.

Bug fixes

  - Fixed tab initialization for glassTabsUI() inserted by renderUI() or
    dashboard layouts after the initial page boot.
  - Added a Shiny input binding and delegated activation fallback for
    tabs so click and keyboard activation remain reliable in public
    dashboards.
  - Bumped the html dependency version so browsers request fresh CSS/JS
    assets.

                        Changes in version 0.3.1                        

New features

  - Added glassTabCondition(id, value) — generates the correct
    JavaScript condition string for [shiny::conditionalPanel()] without
    needing to remember the input[["id-active_tab"]] key pattern.
  - Added glasstabs_news() — prints the package changelog to the R
    console.
  - Added ROADMAP.md tracking planned features and known limitations
    (not shipped in the package).

Improvements

  - Error messages across all functions are now actionable: they name
    the bad argument class, show what was received, and suggest the
    correct fix.
  - glass_tab_theme() and glass_select_theme() now have full @examples
    with interactive app snippets.
  - .gt-container no longer forces max-width:960px or margin:48px auto —
    the widget now behaves like a normal block element inside Shiny
    layouts.
  - Light-mode halo box-shadow replaced with a soft blue-tinted shadow
    via the --gt-halo-shadow CSS variable, replacing the harsh dark drop
    shadow.

                        Changes in version 0.3.0                        

New features

Tab widget

  - Added runGlassExample() to launch any of the built-in example apps
    directly from the R console (runGlassExample("smoke-test"), etc.).
  - Added icon argument to glassTabPanel() — accepts any
    htmltools-compatible tag (e.g. shiny::icon("table")). Renders with
    gt-tab-icon / gt-tab-label spans so icon and text can be styled
    independently.
  - Added disableGlassTab() and enableGlassTab() — gray out a tab
    without hiding it. Completes the visibility/disabled/removal trio
    alongside showGlassTab() / hideGlassTab().
  - Added updateGlassTabBadge() — set a numeric count badge on any tab
    button. Pass count = 0 or count = NA to hide the badge. Values
    above 99 display as "99+".
  - glassTabsServer() now integrates with Shiny's URL bookmarking: the
    active tab is automatically saved and restored when
    enableBookmarking = "url" is set on the app. Opt out per widget with
    bookmark = FALSE.
  - Added glassTabsOutput() / renderGlassTabs() for server-driven tab
    rendering. The JavaScript engine re-initialises automatically after
    each render via a scoped shiny:value listener, so no manual
    glasstabs_reinit calls are needed.

Improvements

  - glassTabsUI() now errors early on duplicate glassTabPanel() values,
    reporting the offending value(s) by name.
  - glassTabsUI() gains a compact = FALSE argument. Setting compact =
    TRUE applies the .gt-compact CSS modifier which reduces margins,
    tab-link padding, font size, and content area padding — ideal for
    embedding inside bs4Dash cards or any tight dashboard layout.
  - glassTabsServer() emits a warning() when the id argument contains
    "-", which is the most common sign that ns("tabs") was passed
    instead of the bare "tabs" id. The warning includes corrective
    guidance.
  - CSS: added .gt-tab-disabled, .gt-tab-icon, .gt-tab-label, and
    .gt-tab-badge rules. Badges adapt their background to the active
    halo colour via the existing CSS custom property.
  - CSS: all color values are now consumed via var(--gt-xxx, fallback)
    instead of being hardcoded — this was the root cause of light theme
    appearing invisible. Light theme defaults were also strengthened for
    better contrast.
  - CSS: dropdown active-state z-index raised to 9000/9001 so glasstabs
    dropdowns render above bs4Dash card stacking contexts.
  - shiny:value listener limits bootAll re-initialisation to outputs
    that actually contain glasstabs elements, so ordinary Shiny outputs
    are unaffected.
  - Added inst/cheatsheet/glasstabs-cheatsheet.tex — a printable
    four-column LaTeX reference card covering the full API, module
    pattern, bs4Dash integration, theming, and common gotchas.

Documentation

  - Cheatsheet vignette (vignettes/cheatsheet.Rmd) extended with new
    sections: "Tabs inside a Shiny module", "Dynamic tab values and
    selected", "Tabs inside bs4Dash", and updated common gotchas.
  - All new functions have full roxygen docs, @examples, and
    cross-links.

                 Changes in version 0.2.1 (2026-04-11)                  

New features

Tab widget

  - Added updateGlassTabsUI() for programmatic tab switching from the
    server.
  - Added showGlassTab() and hideGlassTab() for dynamically showing and
    hiding tabs at runtime.
  - Added appendGlassTab() and removeGlassTab() for adding and removing
    tabs at runtime.

Improvements

  - glassTabsUI() now validates selected against the available
    glassTabPanel() values and errors early on invalid tab ids.
  - The tab widget now reports its initial active tab to Shiny
    immediately after session startup, so glassTabsServer() is populated
    on first render.
  - Added ARIA roles and selected-state attributes to tab navigation
    markup.
  - Improved tab re-initialization and transition handling for dynamic
    tab changes, including show/hide, append/remove, and rapid
    successive updates.
  - Improved halo and transfer-trace positioning after runtime tab
    layout changes.

Bug fixes

  - Opening a dropdown now closes any other open glasstabs dropdown,
    fixing a visual stacking issue where multiple dropdowns appeared
    simultaneously.

  - Improved widget lifecycle in dynamic UI (renderUI(),
    conditionalPanel()). Widgets initialize more reliably and clean up
    properly when removed.

  - Widgets now emit their initial value to Shiny immediately after
    rendering, fixing timing issues with conditionalPanel() and dynamic
    UI.

Internal improvements

  - JavaScript engine refactored to use internal state instead of DOM
    scanning. No changes to the R API — all existing code works without
    modification.

  - Added scroll containers for long option lists, debounced search, and
    .gt-loading / .gt-disabled CSS utility classes.

Documentation

  - Added a dedicated cheatsheet vignette for common widget patterns and
    server-side helpers.
  - Added a smoke-test example app covering programmatic tab switching,
    dynamic tab visibility, runtime tab insertion/removal, and rapid
    interaction paths.
  - Expanded README and pkgdown navigation to surface the new
    server-side tab controls and cheatsheet more clearly.

                 Changes in version 0.1.1 (2026-03-13)                  

New features

Single-select widget

  - Added glassSelect(), an animated single-select dropdown for Shiny.
  - Added updateGlassSelect() for server-side updates to choices and
    selection.
  - Added glassSelectValue() as a convenience reactive helper for
    reading the selected value.

Multi-select widget

  - Added updateGlassMultiSelect() for server-side updates to choices,
    selection, and checkbox style.
  - Added glassMultiSelectValue() as a convenience reactive helper for
    reading selected values and active style.
  - Added optional label support to glassMultiSelect().
  - Added configurable all_label support to control the trigger text
    shown when all choices are selected.

Improvements

  - Aligned glassSelect() and glassMultiSelect() more closely with
    standard Shiny input behavior.
  - Added client-side input bindings so select widgets now support
    session$sendInputMessage() update patterns.
  - Preserved current glassMultiSelect() default behavior where selected
    = NULL initializes all choices as selected.
  - Improved choice normalization so named choices retain display labels
    correctly.
  - Improved hue normalization for the "filled" multi-select style.
  - Updated vignettes and examples to show direct Shiny input usage and
    server-side update patterns.

Documentation

  - Added a new vignette for glassSelect().
  - Updated the getting started vignette to include glassSelect().
  - Updated the multi-select vignette to document
    updateGlassMultiSelect() and glassMultiSelectValue().

Internal changes

  - Added tests for glassSelect(), updateGlassSelect(), and
    glassSelectValue().
  - Expanded tests for glassMultiSelect() server-side updates and helper
    utilities.

                 Changes in version 0.1.0 (2026-03-11)                  

Initial release.

New features

Tab widget

  - glassTabsUI() — animated glassmorphism-style tab navigation with a
    sliding glass halo and transfer trace between tabs.
  - glassTabPanel() — defines a single tab button and its content pane.
  - glassTabsServer() — reactive helper that tracks the active tab
    value.
  - glass_tab_theme() — custom color theme for glassTabsUI() with eight
    independent handles: tab_text, tab_active_text, halo_bg,
    halo_border, content_bg, content_border, card_bg, card_text.
  - Built-in "dark" (default) and "light" presets for glassTabsUI().
  - Keyboard navigation using the Left and Right arrow keys.
  - Full bs4Dash compatibility via wrap = FALSE.

Multi-select filter widget

  - glassMultiSelect() — dropdown filter with live search, select-all
    with indeterminate state, and three checkbox indicator styles:
    "checkbox", "check-only", and "filled".
  - glassFilterTags() — tag-pill display area that stays in sync with a
    glassMultiSelect() automatically via JavaScript; clicking × on a
    pill deselects that option.
  - glass_select_theme() — custom color theme with four handles:
    bg_color, border_color, text_color, accent_color.
  - Built-in "dark" and "light" presets for glassMultiSelect().
  - show_style_switcher, show_select_all, show_clear_all flags to hide
    UI chrome (all default TRUE).
  - Per-option HSL hue angles for the "filled" style via the hues
    argument (auto-assigned if omitted).

General

  - useGlassTabs() — injects CSS and JavaScript via
    htmltools::htmlDependency, which is deduplicated automatically by
    Shiny.
  - All theming uses pre-computed CSS variables (no color-mix()),
    ensuring compatibility with Shiny's embedded browser.
  - Multiple instances of either widget on the same page work
    independently; each instance is scoped to its own id.
