npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fr0st/ui

v3.0.3

Published

Customizable JavaScript UI library with responsive, Bootstrap-compatible components, utilities, and opinionated Sass styling.

Readme

Frost UI

CI codecov npm version npm downloads CSS gzip size JS gzip size license

Customizable JavaScript UI framework with responsive components, utilities, and opinionated Sass styling.

Highlights

  • Responsive containers, grid layout, gutters, and utility classes
  • Styled content, forms, navigation, feedback, and overlay components
  • Declarative data-ui-* APIs alongside programmatic component classes
  • Modals, offcanvas panels, dropdowns, carousels, tabs, toasts, tooltips, popovers, and more
  • Keyboard navigation, focus trapping, scroll handling, and dynamic popper positioning
  • System-aware light and dark themes with nested scopes and runtime CSS custom properties
  • Frosted overlays, ambient gradients, glass surfaces, and theme-aware elevation
  • Configurable Sass variables with public functions and mixins
  • Prebuilt ESM and UMD bundles, with external or bundled fQuery
  • JSDoc-powered IntelliSense

Installation

Browser projects / bundlers

npm i @fr0st/ui

Frost UI's package entry point is ESM-only. Import the compiled CSS and use the named component exports from the JavaScript entry point:

import '@fr0st/ui/dist/frost-ui.min.css';
import { Modal, Toast } from '@fr0st/ui';

const modal = Modal.init(document.querySelector('#settings-modal'));
modal.show();

The package entry point registers the complete component suite, its data APIs, and its fQuery plugins. A component can instead be imported directly when a project only needs part of the JavaScript:

import Modal from '@fr0st/ui/src/js/modal/index.js';

@fr0st/query is installed as a dependency.

Browser (ESM)

The ESM bundle imports @fr0st/query, which in turn imports @fr0st/core. Map both dependencies when loading the bundle directly in a browser:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fr0st/ui@latest/dist/frost-ui.min.css">

<script type="importmap">
{
    "imports": {
        "@fr0st/core": "https://cdn.jsdelivr.net/npm/@fr0st/core@latest/dist/frost-core.esm.min.js",
        "@fr0st/query": "https://cdn.jsdelivr.net/npm/@fr0st/query@latest/dist/fquery.esm.min.js"
    }
}
</script>
<script type="module">
    import { Modal } from 'https://cdn.jsdelivr.net/npm/@fr0st/ui@latest/dist/frost-ui.esm.min.js';

    const modal = Modal.init(document.querySelector('#settings-modal'));
    modal.show();
</script>

Browser (UMD)

Load the CSS, fQuery, and Frost UI scripts from your own copy or a CDN:

<link rel="stylesheet" href="/path/to/dist/frost-ui.min.css">

<script src="/path/to/dist/fquery.min.js"></script>
<script src="/path/to/dist/frost-ui.min.js"></script>
<!-- or -->
<script src="https://cdn.jsdelivr.net/npm/@fr0st/query@latest/dist/fquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@fr0st/ui@latest/dist/frost-ui.min.js"></script>

The JavaScript bundle exposes the component exports as globalThis.UI and expects fQuery to be available as globalThis.fQuery.

An all-in-one build containing fQuery is also available:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fr0st/ui@latest/dist/frost-ui.min.css">
<script src="https://cdn.jsdelivr.net/npm/@fr0st/ui@latest/dist/frost-ui-bundle.min.js"></script>

<script>
    const modal = UI.Modal.init(document.querySelector('#settings-modal'));
    modal.show();
</script>

Do not load the separate fQuery script when using frost-ui-bundle.js or frost-ui-bundle.min.js.

The package root resolves to the prebuilt ESM bundle. Published files under dist/ and src/ are also available through matching package subpaths.

Custom Sass builds

Install Sass and create an application stylesheet when the default Frost UI build needs different colors, typography, sizing, or layout settings:

npm i -D sass

src/styles.scss

@use "@fr0st/ui/src/scss/ui" as ui with (
    $primary: #6750a4,
    $accent: #db2777,
    $secondary: #546e7a,
    $body-bg: #f8fafc,
    $body-color: #172033,
    $body-bg-dark: #111318,
    $body-color-dark: #e4e7ee,
    $font-sans-serif: ("Inter", system-ui, sans-serif),
    $border-radius: .75rem,
    $grid-size: 16
);

.app-shell {
    @include ui.media-breakpoint-up(lg) {
        max-width: 90rem;
    }
}

Compile the entry point with npm package resolution enabled:

npx sass --load-path=node_modules src/styles.scss dist/styles.css

The ui module applies the configured values before emitting the complete framework. It also forwards Frost UI's public variables, functions, and mixins for use by application styles. Build tools that already resolve Sass modules from npm packages do not need the explicit load path.

Quick Start

Frost UI's data API handles common interactions without application JavaScript. This control toggles the targeted collapse element:

<button
    class="btn btn-primary collapsed"
    type="button"
    data-ui-toggle="collapse"
    data-ui-target="#details"
    aria-controls="details"
    aria-expanded="false">
    Show details
</button>

<div class="collapse" id="details">
    <div class="card card-body mt-3">
        Content can be toggled declaratively or through the Collapse class.
    </div>
</div>

Components can also be created and controlled directly:

<div
    class="toast fade"
    id="status-toast"
    role="status"
    aria-live="polite"
    aria-atomic="true"
    style="display: none !important;">
    <div class="toast-body">Your changes were saved.</div>
</div>
import { Toast } from '@fr0st/ui';

const toast = Toast.init(document.querySelector('#status-toast'), {
    autohide: true,
    delay: 3000,
});

toast.show();

See the demo/ folder for theme-aware examples with a System, Light, and Dark switcher covering components, forms, layout, helpers, and utilities.

What's Included

| Area | Included features | | --- | --- | | Content | Base styles, typography, images, figures, and tables | | Layout | Responsive containers, a configurable grid, columns, offsets, and gutters | | Forms | Filled and outline inputs, floating labels, checks, ranges, input groups, and validation states | | Components | Accordions, alerts, badges, breadcrumbs, buttons, cards, carousels, dropdowns, list groups, modals, navigation, navbars, offcanvas panels, pagination, placeholders, popovers, progress bars, spinners, tabs, toasts, and tooltips | | Helpers | Clearfix, color backgrounds and links, focus rings, aspect ratios, stacks, stretched links, ambient and glass surfaces, gradient text, glow shadows, text truncation, vertical rules, and visually hidden content | | Utilities | Colors, borders, display, flexbox, grid, spacing, sizing, positioning, overflow, shadows, text, visibility, and responsive variants | | Enhancements | Clipboard controls, click ripples, and expanding text areas |

JavaScript components

| Export | Purpose | | --- | --- | | Alert | Closes dismissible alerts with cancellable lifecycle events | | Button | Toggles active and pressed button state | | Carousel | Cycles slides with controls, indicators, keyboard input, and swipe gestures | | Collapse | Shows and hides one or more vertical or horizontal regions | | Dropdown | Positions menus and manages click, focus, and keyboard behavior | | Modal | Manages dialogs, backdrops, focus trapping, keyboard dismissal, and document scrolling | | Offcanvas | Manages edge panels, backdrops, keyboard dismissal, and document scrolling | | Popover | Displays positioned, optionally sanitized rich content | | Tab | Coordinates tab controls, panels, accessibility state, and keyboard navigation | | Toast | Shows transient notifications with optional autohide timers | | Tooltip | Displays positioned, optionally sanitized contextual labels | | FocusTrap | Keeps keyboard focus inside an active region | | Popper | Positions floating content relative to a reference element | | BaseComponent | Provides shared initialization, options, element data, and disposal |

The package also exports helpers for component registration, target resolution, pointer positions, scroll containers, scrollbar compensation, CSS transition waiting, and generated IDs.

Component Model

Instances and options

Every component derives from BaseComponent and is associated with one element. Call the class's static init() method to retrieve the existing instance or create it:

import { Modal } from '@fr0st/ui';

const node = document.querySelector('#settings-modal');
const modal = Modal.init(node, {
    backdrop: 'static',
    focus: true,
    keyboard: true,
});

Options are combined in this order:

  1. Component defaults
  2. The element's data-ui-* attributes
  3. Options passed to init()

For example, this element overrides the default backdrop and keyboard behavior:

<div
    class="modal"
    id="settings-modal"
    data-ui-backdrop="static"
    data-ui-keyboard="false"
    tabindex="-1"
    aria-hidden="true">
    <!-- modal markup -->
</div>

Defaults can be adjusted before instances are initialized:

import { Toast } from '@fr0st/ui';

Toast.defaults.delay = 4000;
Toast.defaults.autohide = true;

Each instance exposes:

  • component.node: the associated element, or null after disposal
  • component.options: the frozen resolved options, or null after disposal
  • component.dispose(): remove registered state and release resources owned by the instance

Calling init() again for the same element returns its current instance. Dispose it before initializing that element with a new set of options.

Data API

Frost UI registers delegated document handlers for controls such as:

  • data-ui-toggle="button"
  • data-ui-toggle="collapse"
  • data-ui-toggle="dropdown"
  • data-ui-toggle="modal"
  • data-ui-toggle="offcanvas"
  • data-ui-toggle="tab"
  • data-ui-dismiss="alert"
  • data-ui-dismiss="modal"
  • data-ui-dismiss="offcanvas"
  • data-ui-dismiss="toast"
  • data-ui-slide and data-ui-slide-to

Targets are normally resolved from data-ui-target or href. Because the handlers are delegated, matching controls added after Frost UI loads work without being registered individually.

Tooltip and popover triggers are initialized explicitly so their listeners and options can be configured:

import { Tooltip } from '@fr0st/ui';

for (const node of document.querySelectorAll('[data-ui-toggle="tooltip"]')) {
    Tooltip.init(node);
}

Ride-enabled carousels marked with data-ui-ride="carousel" initialize when the document is ready.

fQuery plugins

Importing a component registers a method on fQuery.QuerySet using the component's lowercase name:

import $ from '@fr0st/query';
import '@fr0st/ui';

$('.toast').toast({
    autohide: false,
});

$('.toast').toast('show');

Pass an options object to initialize every matched element, or pass a public method name followed by its arguments. The first component or method result is returned.

Plugins are registered for alerts, buttons, carousels, collapses, dropdowns, focus traps, modals, offcanvas panels, popovers, poppers, tabs, toasts, and tooltips.

Events and lifecycle

Interactive components emit namespaced fQuery events around state changes. Before-events can be cancelled with preventDefault(); completion events run after the transition finishes.

import $ from '@fr0st/query';

$.addEvent('#settings-modal', 'show.ui.modal', (event) => {
    if (!userCanOpenSettings()) {
        event.preventDefault();
    }
});

$.addEvent('#settings-modal', 'shown.ui.modal', (_) => {
    console.log('Settings are visible');
});

| Components | Before event | Completion event | | --- | --- | --- | | Collapse, Dropdown, Modal, Offcanvas, Popover, Tab, Toast, Tooltip | show.ui.* | shown.ui.* | | Collapse, Dropdown, Modal, Offcanvas, Popover, Tab, Toast, Tooltip | hide.ui.* | hidden.ui.* | | Alert | close.ui.alert | closed.ui.alert | | Carousel | slide.ui.carousel | slid.ui.carousel |

Clipboard controls emit copied.ui.clipboard with the completed action and copied text.

Styling and Layout

Frost UI layouts use containers, rows, a configurable twelve-column grid, breakpoint prefixes, and spacing utilities:

<main class="container py-5">
    <div class="row g-3">
        <section class="col-12 col-md-8">
            <div class="card shadow-sm">
                <div class="card-body">Main content</div>
            </div>
        </section>
        <aside class="col-12 col-md-4">
            <div class="p-3 rounded bg-body-tertiary">Sidebar</div>
        </aside>
    </div>
</main>

Breakpoint-prefixed classes apply from that breakpoint upwards. The default breakpoint map contains xs, sm, md, lg, xl, and xxl, and can be replaced through Sass configuration.

CSS-only components and utilities do not require Frost UI's JavaScript. Load the JavaScript when the page needs interactive behavior, event lifecycles, positioning, or accessibility state management.

Themes and Customization

Frost UI follows the user's preferred color scheme by default. Set data-ui-theme="light" or data-ui-theme="dark" on the document or any container to select an explicit theme for that subtree:

<html lang="en" data-ui-theme="dark">
<nav class="navbar" data-ui-theme="dark">
    <!-- a dark themed region inside a light page -->
</nav>

Theme attributes can be nested. Each boundary recalculates the theme colors and overrides the inherited color scheme for its subtree.

Generated styles expose colors, typography, borders, shadows, focus rings, and component values through --ui-* custom properties. Override them after Frost UI for runtime theming:

:root,
[data-ui-theme] {
    --ui-primary: #6750a4;
    --ui-body-bg: light-dark(#f8fafc, #111318);
    --ui-body-color: light-dark(#172033, #e4e7ee);
}

:root {
    --ui-border-radius: .5rem;
}

Use Sass configuration when derived colors, utility maps, breakpoints, component defaults, or generated class sets also need to change. Frost UI variables use !default, allowing them to be configured through the ui module shown in the installation section.

Behavior Notes

  • Frost UI's JavaScript requires a browser DOM or a compatible DOM environment configured through fQuery.
  • The package entry point registers all component data handlers, QuerySet plugins, and the clipboard, ripple, and expanding-textarea enhancements.
  • frost-ui.js expects a separate fQuery global; frost-ui-bundle.js includes it.
  • Component options are resolved once, frozen, and retained until the instance is disposed.
  • Tooltip and popover HTML is sanitized by default when HTML content is enabled.
  • Event namespaces are managed by fQuery; the underlying native event types are show, shown, hide, hidden, and so on.
  • Motion styles are enabled under prefers-reduced-motion: no-preference, with component transition timing controlled through CSS custom properties.
  • Compiled CSS targets browsers in the Baseline Widely Available Browserslist range.
  • Component markup and accessibility attributes remain the application's responsibility; interactive components update the state they own.

Development

npm test
npm run lint
npm run lint:sass:unused
npm run build

npm test runs the Playwright suite in Chromium, Firefox, and WebKit.

License

Frost UI is released under the MIT License.