Changelog Azalea Kit UI 101 Usage Customizing Utilities Form controls Laravel Vue FHIR Types Accessibility Icons Actions Button Button group Layout and structure Card Card section Care summary Care timeline Divider Empty state Footer Header Layout Stack Table Selection and input Calendar Checkbox Checkbox group Color picker Combobox Combobox option Input Input mask Memorable date Number input Option Phone input Radio Radio button Radio group Range Select SSN input Tag Textarea Toggle ZIP code input Images and icons Avatar Icon Icon button Logo Feedback indicators Badge Banner Progress bar Skeleton Skeleton body text Skeleton display text Skeleton thumbnail Spinner Typography Text Navigation Breadcrumb Breadcrumb item Dropdown Menu Menu item Menu label Navigation Nav group Nav item Nav toggle Pagination Tab Tab group Tab panel Top bar Tree Tree item User menu Overlays Dialog Popover Tooltip Utilities Collapsible FHIR address FHIR human name FHIR quantity FHIR questionnaire Format bytes Format date Format number Relative time Resize observer Split panel Tooltip Border Color Shadow Spacing Transition Typography Z-index Contributing Visual Tests Light Dark System

Azalea Kit UI 101

Azalea Kit UI is Azalea Health’s design system for our products. It is a collection of reusable web components and utilities that enable our engineers to:

  • Improve UI consistency and quality
  • Build things faster
  • Build multiple applications that all share the same UI components
  • Incrementally adopt components as needed
  • Share guidelines and standards through documentation
  • Improve communication between teams and people

Installation

Azalea Kit UI is distributed as a collection of standard ES modules that all modern browsers can understand. You can install Azalea Kit UI via npm.

To install the latest version:

npm install git@bitbucket.org:azaleahealth/azalea-kit-ui.git

To pin to a specific version range, add the dependency directly to your package.json using npm’s Bitbucket shorthand with a semver selector:

{
  "dependencies": {
    "@azaleahealth/azalea-kit-ui": "bitbucket:azaleahealth/azalea-kit-ui#semver:^1.9.0"
  }
}

Then run npm install. The ^1.9.0 range follows standard semver rules — it will resolve to the latest 1.x.x release that is >= 1.9.0. Replace the version constraint with any valid semver range (e.g. ~1.11.0 for patch-only updates, or 1.11.1 to pin exactly).

For projects not using npm, a stand-alone build is available for download here.

Now it’s time to configure your framework or bundler. Configurations vary for each tool, but here are some examples to help you get started.

Once your framework or bundler is configured, you’ll be able to import Azalea Kit UI components and utilities.

import '@azaleahealth/azalea-kit-ui/themes/light.css';
import '@azaleahealth/azalea-kit-ui/themes/dark.tokens.css';
import '@azaleahealth/azalea-kit-ui/components/button/button.js';
import '@azaleahealth/azalea-kit-ui/components/icon/icon.js';
import '@azaleahealth/azalea-kit-ui/components/input/input.js';
import { setBasePath } from '@azaleahealth/azalea-kit-ui/utilities/base-path.js';

// Set the base path to the folder you copied Azalea Kit UI's assets to
setBasePath('/path/to/azalea-kit-ui/dist');

// <ahi-button>, <ahi-icon>, and <ahi-input> are ready to use!

Component modules include side effects for registration purposes. Because of this, importing directly from @azaleahealth/azalea-kit-ui may result in a larger bundle size than necessary. For optimal tree shaking, always cherry pick, i.e. import components and utilities from their respective files, as shown above.

Shipping both themes

Every theme is published twice:

File Contents Use it when
themes/light.css, themes/dark.css The theme’s tokens plus the shared utility tail You load exactly one theme
themes/light.tokens.css, themes/dark.tokens.css The theme’s tokens only You load a second theme alongside the first

The tail — .ahi-toast-stack, the density modifiers, .ahi-visually-hidden, and @layer ahi-utilities — is theme-independent and identical in every theme, so loading two complete theme files ships it twice. Load one complete theme and the other’s tokens instead:

import '@azaleahealth/azalea-kit-ui/themes/light.css'; // complete
import '@azaleahealth/azalea-kit-ui/themes/dark.tokens.css'; // tokens only

This is not only about the ~10KB. Those tail rules are unscoped, so with two complete files whichever one loads last wins them outright — invisible while the two copies are identical, a load-order bug the day they are not. Order the tokens files however you like: light.css declares its tokens at :where(:root) (specificity zero) and dark.css at .ahi-theme-dark, so specificity decides, not order.

Both themes must be present for .ahi-invert to work — it flips an element to the opposite theme, and with only one theme loaded there is nothing to flip to.

Import paths

Cherry-picked imports can omit the dist/ prefix — @azaleahealth/azalea-kit-ui/components/button/button.js and @azaleahealth/azalea-kit-ui/dist/components/button/button.js resolve to the same module. Prefer the shorter form in new code: it doesn’t tie your imports to the package’s internal build layout. The dist/-prefixed paths continue to work and are not deprecated, so there is no need to rewrite existing imports.

Both spellings are available for every subpath — components/, utilities/, themes/, translations/, and fhir/.

Avoiding auto-registering imports

By default, imports to components will auto-register themselves. This may not be ideal in all cases. To import just the component’s class without auto-registering it’s tag we can do the following:

- import AhiButton from '@azaleahealth/azalea-kit-ui/components/button/button.js';
+ import AhiButton from '@azaleahealth/azalea-kit-ui/components/button/button.component.js';

Notice how the import ends with .component.js. This is the current convention to convey the import does not register itself.

Load only one copy of Azalea Kit UI per page

Custom element names are global to the page. Azalea Kit UI registers each component under its ahi- tag in the browser’s one shared registry, so only one version of Azalea Kit UI can be active on a page at a time. The first copy to register a tag owns it; any later copy that tries to register the same tag is ignored.

This matters because the losing version doesn’t fail loudly — it simply doesn’t take effect. Every <ahi-button> on the page is upgraded by whichever copy loaded first, even markup written against a newer version. You’ll see a console warning for each affected tag:

Attempted to register <ahi-button> v2.0.0, but <ahi-button> v1.19.0 has already been registered.

If components behave like a different version than the one you installed — a missing property, an event that never fires, an attribute that seems to do nothing — check the console for this warning first.

Two copies usually get onto a page one of these ways:

  • Mixing distributions. Loading the CDN bundle (azalea-kit-ui.js) on a page that also imports components from the npm package. Pick one per page.
  • An embedded widget or SDK that bundles its own copy. If you ship a library that depends on Azalea Kit UI and is embedded in an Azalea application, import the host page’s copy rather than bundling your own, so the host controls the version.

When you do vendor a copy of the built bundle, treat it and anything built against it as a matched set: upgrade them together, since a partial upgrade leaves two versions racing to register and load order decides which one wins.

Browser Support

We aim to support the latest versions of the following browsers. We do not support IE11 or pre-Chromium Edge.

Chrome Edge Safari Firefox

Attribution

Special thanks to the following projects that help make Azalea Kit UI possible: