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

ux4g-components-angular

v1.4.1

Published

UX4G Design System — Angular wrapper components

Readme

ux4g-components-angular

Angular wrapper components for the UX4G Design System.

Thin, typed Angular components that map inputs to UX4G CSS classes. Each component is tree-shakeable via sub-path imports and NgModule.

Installation

npm install ux4g-components-angular ux4g-components-web

Note: ux4g-components-web is required — it provides the CSS bundle that styles all components.

Setup

Add the CSS bundle to your angular.json styles array:

{
  "projects": {
    "your-app": {
      "architect": {
        "build": {
          "options": {
            "styles": [
              "node_modules/ux4g-components-web/styles/ux4g.css",
              "src/styles.css"
            ]
          }
        }
      }
    }
  }
}

That's it. Runtime behaviors (dropdowns, modals, tooltips, etc.) are auto-initialized when you import any component module — no manual setup needed.

Peer Dependencies

  • @angular/core >= 15.0.0
  • @angular/common >= 15.0.0

Components

Button

// app.module.ts
import { UX4GButtonModule } from 'ux4g-components-angular/button';

@NgModule({
  imports: [UX4GButtonModule],
})
export class AppModule {}
<!-- app.component.html -->
<ux4g-button variant="primary" size="md" (clicked)="onSave()">
  Save
</ux4g-button>

<ux4g-button variant="outline-danger" size="lg">
  Delete
</ux4g-button>

<ux4g-button variant="tonal-primary" size="sm" shape="pill">
  Tag
</ux4g-button>

<ux4g-button variant="primary" size="md" [loading]="true">
  Saving...
</ux4g-button>

<ux4g-button variant="primary" size="md" [disabled]="true">
  Disabled
</ux4g-button>

| Input | Type | Default | Description | |---|---|---|---| | variant | 'primary' \| 'outline-primary' \| 'text-primary' \| 'tonal-primary' \| 'danger' \| 'outline-danger' \| 'text-danger' \| 'tonal-danger' | 'primary' | Visual style | | size | 'xl' \| 'lg' \| 'md' \| 'sm' \| 'xs' | 'md' | Button size | | shape | 'rectangle' \| 'pill' | 'rectangle' | Border shape | | disabled | boolean | false | Disabled state | | loading | boolean | false | Loading state (shows spinner) |

| Output | Type | Description | |---|---|---| | clicked | EventEmitter<MouseEvent> | Emitted on click (suppressed when disabled) |

Spinner

import { UX4GSpinnerModule } from 'ux4g-components-angular/spinner';

@NgModule({ imports: [UX4GSpinnerModule] })
export class AppModule {}
<ux4g-spinner variant="primary" size="md" type="full"></ux4g-spinner>
<ux4g-spinner variant="danger" size="lg" type="split"></ux4g-spinner>
<ux4g-spinner variant="inverse" size="xs" type="partial" label="Processing"></ux4g-spinner>

| Input | Type | Default | Description | |---|---|---|---| | variant | 'primary' \| 'inverse' \| 'danger' | 'primary' | Color variant | | size | 'xl' \| 'lg' \| 'md' \| 'sm' \| 'xs' | 'md' | Spinner size | | type | 'full' \| 'split' \| 'partial' | 'full' | Spinner style | | label | string | 'Loading' | Accessible label |

Link

import { UX4GLinkModule } from 'ux4g-components-angular/link';

@NgModule({ imports: [UX4GLinkModule] })
export class AppModule {}
<ux4g-link href="/docs" variant="default" size="md">Documentation</ux4g-link>
<ux4g-link href="/terms" variant="neutral" size="sm">Terms of Service</ux4g-link>

| Input | Type | Default | Description | |---|---|---|---| | variant | 'default' \| 'neutral' | 'default' | Link color style | | size | 'sm' \| 'md' | 'md' | Link size | | href | string | — | Link URL |

Badge

import { UX4GBadgeModule } from 'ux4g-components-angular/badge';

@NgModule({ imports: [UX4GBadgeModule] })
export class AppModule {}
<ux4g-badge type="dot" color="primary"></ux4g-badge>
<ux4g-badge type="digit" color="danger" size="m">5</ux4g-badge>
<ux4g-badge type="icon" color="success" size="l">✓</ux4g-badge>

| Input | Type | Default | Description | |---|---|---|---| | type | 'dot' \| 'icon' \| 'digit' | 'dot' | Badge type | | color | 'primary' \| 'success' \| 'warning' \| 'danger' \| 'info' \| 'secondary' \| 'tertiary' \| 'neutral' | 'primary' | Badge color | | size | 's' \| 'm' \| 'l' \| 'profile-l' \| 'profile-xl' \| 'profile-2xl' \| 'profile-3xl' | — | Badge size |

Avatar

import { UX4GAvatarModule } from 'ux4g-components-angular/avatar';

@NgModule({ imports: [UX4GAvatarModule] })
export class AppModule {}
<ux4g-avatar avatarType="status" size="m">
  <img src="user.jpg" alt="User" />
</ux4g-avatar>

<ux4g-avatar avatarType="profile" size="xl">
  <img src="profile.jpg" alt="Profile" />
</ux4g-avatar>

<ux4g-avatar avatarType="group">
  <img src="u1.jpg" alt="" />
  <img src="u2.jpg" alt="" />
</ux4g-avatar>

| Input | Type | Default | Description | |---|---|---|---| | avatarType | 'status' \| 'profile' \| 'group' | 'status' | Avatar type | | size | 'xs' \| 's' \| 'm' \| 'l' \| 'xl' \| '2xl' \| '3xl' | — | Avatar size |

Image

import { UX4GImageModule } from 'ux4g-components-angular/image';

@NgModule({ imports: [UX4GImageModule] })
export class AppModule {}
<ux4g-image src="photo.jpg" alt="Photo" ratio="16-9"></ux4g-image>
<ux4g-image src="photo.jpg" alt="Photo" ratio="4-3" [rounded]="true"></ux4g-image>
<ux4g-image src="photo.jpg" alt="Photo" ratio="16-9" [overlay]="true" overlayPosition="bottom">
  <ng-template #overlayContent>
    <p class="ux4g-body-m-default">Caption text</p>
  </ng-template>
</ux4g-image>

| Input | Type | Default | Description | |---|---|---|---| | ratio | '1-1' \| '4-3' \| '3-2' \| '16-10' \| '16-9' \| '2-1' \| '5-2' \| '3-1' \| '1-16' \| '2-3' \| '3-4' | — | Aspect ratio | | rounded | boolean | false | Rounded corners | | overlay | boolean | false | Enable overlay container | | overlayPosition | 'top' \| 'bottom' \| 'center' \| 'full' | 'bottom' | Overlay position |

Chip

import { UX4GChipModule } from 'ux4g-components-angular/chip';

@NgModule({ imports: [UX4GChipModule] })
export class AppModule {}
<ux4g-chip chipType="filter" size="md">Category</ux4g-chip>
<ux4g-chip chipType="choice" size="sm" [active]="true">Selected</ux4g-chip>
<ux4g-chip chipType="input" size="xs">Tag</ux4g-chip>

| Input | Type | Default | Description | |---|---|---|---| | chipType | 'filter' \| 'choice' \| 'input' | 'filter' | Chip type | | size | 'md' \| 'sm' \| 'xs' | 'md' | Chip size (xs only for input) | | active | boolean | false | Active/selected state |

Tag

import { UX4GTagModule } from 'ux4g-components-angular/tag';

@NgModule({ imports: [UX4GTagModule] })
export class AppModule {}
<ux4g-tag variant="tonal" color="neutral">Default</ux4g-tag>
<ux4g-tag variant="filled" color="success" [small]="true">Active</ux4g-tag>
<ux4g-tag variant="outline" color="error">Error</ux4g-tag>

| Input | Type | Default | Description | |---|---|---|---| | variant | 'tonal' \| 'filled' \| 'outline' \| 'text' | 'tonal' | Tag style | | color | 'neutral' \| 'brand' \| 'success' \| 'warning' \| 'error' \| 'info' | 'neutral' | Tag color | | small | boolean | false | Small size |

Divider

import { UX4GDividerModule } from 'ux4g-components-angular/divider';

@NgModule({ imports: [UX4GDividerModule] })
export class AppModule {}
<ux4g-divider orientation="horizontal"></ux4g-divider>
<ux4g-divider orientation="vertical"></ux4g-divider>

| Input | Type | Default | Description | |---|---|---|---| | orientation | 'horizontal' \| 'vertical' | 'horizontal' | Divider direction |

Breadcrumb

import { UX4GBreadcrumbModule } from 'ux4g-components-angular/breadcrumb';

@NgModule({ imports: [UX4GBreadcrumbModule] })
export class AppModule {}
<ux4g-breadcrumb separator="divider">
  <a href="#">Home</a>
  <a href="#">Products</a>
  <span>Current</span>
</ux4g-breadcrumb>

| Input | Type | Default | Description | |---|---|---|---| | separator | 'divider' \| 'icon' | 'divider' | Separator style |

Checkbox

import { UX4GCheckboxModule } from 'ux4g-components-angular/checkbox';

@NgModule({ imports: [UX4GCheckboxModule] })
export class AppModule {}
<label>
  <ux4g-checkbox size="md" [checked]="isChecked" (changed)="onCheck($event)"></ux4g-checkbox>
  Accept terms
</label>

<label>
  <ux4g-checkbox size="sm" [error]="true"></ux4g-checkbox>
  Required field
</label>

<label>
  <ux4g-checkbox size="md" [indeterminate]="true"></ux4g-checkbox>
  Select all
</label>

| Input | Type | Default | Description | |---|---|---|---| | size | 'sm' \| 'md' \| 'lg' | 'md' | Checkbox size | | checked | boolean | false | Checked state | | indeterminate | boolean | false | Indeterminate state | | disabled | boolean | false | Disabled state | | error | boolean | false | Error state |

| Output | Type | Description | |---|---|---| | changed | EventEmitter<Event> | Emitted on change |

Note: This is a control-only wrapper. Wrap with <label> to associate visible text.

Radio

import { UX4GRadioModule } from 'ux4g-components-angular/radio';

@NgModule({ imports: [UX4GRadioModule] })
export class AppModule {}
<label>
  <ux4g-radio size="md" name="option" value="a" [checked]="selected === 'a'" (changed)="onSelect($event)"></ux4g-radio>
  Option A
</label>
<label>
  <ux4g-radio size="lg" name="option" value="b" [error]="true"></ux4g-radio>
  Option B
</label>

| Input | Type | Default | Description | |---|---|---|---| | size | 'sm' \| 'md' \| 'lg' | 'md' | Radio size | | checked | boolean | false | Checked state | | disabled | boolean | false | Disabled state | | error | boolean | false | Error state | | name | string | '' | Radio group name | | value | string | '' | Radio value |

| Output | Type | Description | |---|---|---| | changed | EventEmitter<Event> | Emitted on change |

Note: This is a control-only wrapper. Wrap with <label> to associate visible text.

Switch

import { UX4GSwitchModule } from 'ux4g-components-angular/switch';

@NgModule({ imports: [UX4GSwitchModule] })
export class AppModule {}
<label>
  <ux4g-switch size="md" [checked]="isOn" (changed)="onToggle($event)"></ux4g-switch>
  Enable notifications
</label>

| Input | Type | Default | Description | |---|---|---|---| | size | 'sm' \| 'md' \| 'lg' | 'md' | Switch size | | checked | boolean | false | Checked state | | disabled | boolean | false | Disabled state |

| Output | Type | Description | |---|---|---| | changed | EventEmitter<Event> | Emitted on change |

Note: This is a control-only wrapper. Wrap with <label> to associate visible text.

Card

import { UX4GCardModule } from 'ux4g-components-angular/card';

@NgModule({ imports: [UX4GCardModule] })
export class AppModule {}
<ux4g-card variant="solid" layout="vertical">
  <h3>Card Title</h3>
  <p>Card content goes here.</p>
</ux4g-card>

<ux4g-card variant="outline" layout="horizontal">
  <img src="thumb.jpg" alt="" />
  <p>Horizontal card</p>
</ux4g-card>

| Input | Type | Default | Description | |---|---|---|---| | variant | 'solid' \| 'outline' \| 'no-fill' | 'solid' | Card style | | layout | 'vertical' \| 'horizontal' | 'vertical' | Card layout |

Input

import { UX4GInputModule } from 'ux4g-components-angular/input';

@NgModule({ imports: [UX4GInputModule] })
export class AppModule {}
<ux4g-input size="md" state="default">
  <label class="ux4g-input-label">Email</label>
  <input class="ux4g-input" type="email" placeholder="Enter email" />
</ux4g-input>

<ux4g-input size="lg" state="error">
  <label class="ux4g-input-label">Password</label>
  <input class="ux4g-input" type="password" />
  <span class="ux4g-input-helper">Password is required</span>
</ux4g-input>

<ux4g-input size="md" state="default" [disabled]="true">
  <label class="ux4g-input-label">Disabled</label>
  <input class="ux4g-input" type="text" disabled />
</ux4g-input>

| Input | Type | Default | Description | |---|---|---|---| | size | 'sm' \| 'md' \| 'lg' \| 'xl' | 'md' | Input container size | | state | 'default' \| 'error' \| 'success' \| 'warning' | 'default' | Validation state | | disabled | boolean | false | Disabled state |

Note: This is a container shell. Label, input element, and helper text are projected as children using UX4G CSS classes.

List

import { UX4GListModule } from 'ux4g-components-angular/list';

@NgModule({ imports: [UX4GListModule] })
export class AppModule {}
<ux4g-list variant="default" size="m">
  <li>Item one</li>
  <li>Item two</li>
</ux4g-list>

| Input | Type | Default | Description | |---|---|---|---| | variant | 'default' \| 'error' \| 'success' \| 'warning' | 'default' | List style | | size | 's' \| 'm' \| 'l' \| 'xl' | 'm' | List size |

Dropdown

import { UX4GDropdownModule } from 'ux4g-components-angular/dropdown';

@NgModule({ imports: [UX4GDropdownModule] })
export class AppModule {}
<ux4g-dropdown type="selection" mode="single" size="md" state="default">
  <ux4g-dropdown-item value="1">Option 1</ux4g-dropdown-item>
  <ux4g-dropdown-item value="2">Option 2</ux4g-dropdown-item>
</ux4g-dropdown>

| Input | Type | Default | Description | |---|---|---|---| | type | 'selection' \| 'button' \| 'overflow' | 'selection' | Dropdown type | | mode | 'single' \| 'multi' | 'single' | Selection mode | | size | 'sm' \| 'md' \| 'lg' | 'md' | Dropdown size | | state | 'default' \| 'error' \| 'success' \| 'warning' | 'default' | Validation state | | open | boolean | false | Open state |

Combobox

import { UX4GComboboxModule } from 'ux4g-components-angular/combobox';

@NgModule({ imports: [UX4GComboboxModule] })
export class AppModule {}
<ux4g-combobox type="single" size="md" state="default" placeholder="Search..."></ux4g-combobox>

| Input | Type | Default | Description | |---|---|---|---| | type | 'single' \| 'multi' | 'single' | Combobox type | | size | 'sm' \| 'md' \| 'lg' | 'md' | Combobox size | | state | 'default' \| 'error' \| 'success' \| 'warning' | 'default' | Validation state | | open | boolean | false | Open state |

Modal

import { UX4GModalModule } from 'ux4g-components-angular/modal';

@NgModule({ imports: [UX4GModalModule] })
export class AppModule {}
<ux4g-modal size="m" opacity="50" [open]="isOpen">
  <h2>Modal Title</h2>
  <p>Modal content here.</p>
  <button (click)="isOpen = false">Close</button>
</ux4g-modal>

| Input | Type | Default | Description | |---|---|---|---| | size | 's' \| 'm' \| 'l' | 'm' | Modal size | | opacity | '25' \| '50' \| '75' | '50' | Backdrop opacity | | blur | boolean | false | Backdrop blur | | open | boolean | false | Open state | | centerContent | boolean | false | Center modal content |

Note: Close handling is external — toggle the open input from your component state.

Alert / Toast

import { UX4GAlertModule } from 'ux4g-components-angular/alert';

@NgModule({ imports: [UX4GAlertModule] })
export class AppModule {}
<ux4g-alert variant="info">This is an informational message.</ux4g-alert>
<ux4g-alert variant="success" layout="wide">Saved successfully!</ux4g-alert>

<!-- Toast variant -->
<ux4g-alert variant="success" [toast]="true">Toast notification</ux4g-alert>

<!-- Toast container for positioning -->
<ux4g-alert-container position="top-right">
  <ux4g-alert variant="success" [toast]="true">Toast notification</ux4g-alert>
</ux4g-alert-container>

| Input | Type | Default | Description | |---|---|---|---| | variant | 'info' \| 'success' \| 'warning' \| 'error' | 'info' | Alert type | | toast | boolean | false | Use contextual toast styling instead of inline alert | | layout | 'fluid' \| 'center' \| 'wide' | 'fluid' | Alert layout (when toast=false) |

AlertContainer Inputs:

| Input | Type | Default | Description | |---|---|---|---| | position | 'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right' | 'top-right' | Container position |

Search

import { UX4GSearchModule } from 'ux4g-components-angular/search';

@NgModule({ imports: [UX4GSearchModule] })
export class AppModule {}
<ux4g-search-container size="m">
  <input class="ux4g-search-input" type="search" placeholder="Search..." />
  <button class="ux4g-search-btn">
    <span class="ux4g-icon-outlined">search</span>
  </button>
</ux4g-search-container>

| Input | Type | Default | Description | |---|---|---|---| | size | 's' \| 'm' \| 'lg' | 'm' | Search container size |

Note: This is a container shell — the search input, button, and event handling are projected as children. The selector is ux4g-search-container.

Pagination

import { UX4GPaginationModule } from 'ux4g-components-angular/pagination';

@NgModule({ imports: [UX4GPaginationModule] })
export class AppModule {}
<ux4g-pagination variant="default">
  <button class="ux4g-pagination-prev" aria-label="Previous">‹</button>
  <button class="ux4g-pagination-item ux4g-pagination-active">1</button>
  <button class="ux4g-pagination-item">2</button>
  <button class="ux4g-pagination-item">3</button>
  <button class="ux4g-pagination-next" aria-label="Next">›</button>
</ux4g-pagination>

<ux4g-pagination variant="dotted" paginationStyle="solid">
  <span class="ux4g-pagination-dot ux4g-pagination-active"></span>
  <span class="ux4g-pagination-dot"></span>
  <span class="ux4g-pagination-dot"></span>
</ux4g-pagination>

| Input | Type | Default | Description | |---|---|---|---| | variant | 'default' \| 'dotted' | 'default' | Pagination style | | paginationStyle | 'default' \| 'solid' \| 'translucent' | 'default' | Dotted variant style |

Note: This is a container shell — page items, navigation buttons, and active state management are handled externally via content projection.

Table

import { UX4GTableModule } from 'ux4g-components-angular/table';

@NgModule({ imports: [UX4GTableModule] })
export class AppModule {}
<ux4g-table size="m" divider="row" [interactive]="true">
  <thead>
    <tr><th>Name</th><th>Email</th></tr>
  </thead>
  <tbody>
    <tr><td>Alice</td><td>[email protected]</td></tr>
  </tbody>
</ux4g-table>

| Input | Type | Default | Description | |---|---|---|---| | size | 's' \| 'm' \| 'lg' | 'm' | Table size | | divider | 'row' \| 'column' \| 'none' | 'row' | Divider style | | zebra | 'none' \| 'rows' \| 'cols' | 'none' | Zebra striping | | interactive | boolean | false | Hover highlight | | sortable | boolean | false | Sortable columns | | resizable | boolean | false | Resizable columns | | headerBrand | boolean | false | Brand-colored header |

Popover

import { UX4GPopoverModule } from 'ux4g-components-angular/popover';

@NgModule({ imports: [UX4GPopoverModule] })
export class AppModule {}
<ux4g-popover placement="right" [show]="showPopover">
  <div class="ux4g-popover-header">Popover Title</div>
  <div class="ux4g-popover-body">Body text goes here</div>
</ux4g-popover>

| Input | Type | Default | Description | |---|---|---|---| | placement | 'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end' \| 'left' \| 'left-start' \| 'left-end' \| 'right' \| 'right-start' \| 'right-end' | 'bottom' | Popover position | | show | boolean | false | Visibility |

Note: Content (title, body) is projected as children using UX4G popover CSS classes. There are no title or content inputs.

Tooltip

import { UX4GTooltipModule } from 'ux4g-components-angular/tooltip';

@NgModule({ imports: [UX4GTooltipModule] })
export class AppModule {}
<ux4g-tooltip placement="top-center" size="s">
  Tooltip text content goes here
</ux4g-tooltip>

| Input | Type | Default | Description | |---|---|---|---| | placement | 'top-left' \| 'top-center' \| 'top-right' \| 'bottom-left' \| 'bottom-center' \| 'bottom-right' \| 'left-center' \| 'right-center' | 'top-center' | Tooltip position | | size | 's' \| 'xs' | 's' | Tooltip size |

Note: Tooltip text is projected as content. There is no content input. Visibility is controlled by the UX4G runtime.

Tab

import { UX4GTabModule } from 'ux4g-components-angular/tab';

@NgModule({ imports: [UX4GTabModule] })
export class AppModule {}
<ux4g-tab variant="underline" size="md">
  <ux4g-tab-item label="Tab 1" [active]="true">Content 1</ux4g-tab-item>
  <ux4g-tab-item label="Tab 2">Content 2</ux4g-tab-item>
</ux4g-tab>

| Input | Type | Default | Description | |---|---|---|---| | variant | 'underline' \| 'pill' | 'underline' | Tab style | | size | 'sm' \| 'md' \| 'lg' | 'md' | Tab size | | vertical | boolean | false | Vertical layout |

Icon Button

import { UX4GIconButtonModule } from 'ux4g-components-angular/icon-button';

@NgModule({ imports: [UX4GIconButtonModule] })
export class AppModule {}
<ux4g-icon-button variant="primary" size="md" aria-label="Edit">
  <i class="ux4g-icon-edit"></i>
</ux4g-icon-button>

<ux4g-icon-button variant="tonal-primary" size="lg" [pill]="true" aria-label="Add">
  <i class="ux4g-icon-plus"></i>
</ux4g-icon-button>

| Input | Type | Default | Description | |---|---|---|---| | variant | 'primary' \| 'outline-primary' \| 'tonal-primary' \| 'text-primary' | 'text-primary' | Button style | | size | 'xl' \| 'lg' \| 'md' \| 'sm' \| 'xs' | 'md' | Button size | | pill | boolean | false | Pill shape |

Accessibility Bar

import { UX4GAccessibilityBarModule } from 'ux4g-components-angular/accessibility-bar';

@NgModule({ imports: [UX4GAccessibilityBarModule] })
export class AppModule {}
<ux4g-accessibility-bar>
  <a href="#main-content">Skip to main content</a>
</ux4g-accessibility-bar>

Accordion

import { UX4GAccordionModule } from 'ux4g-components-angular/accordion';

@NgModule({ imports: [UX4GAccordionModule] })
export class AppModule {}
<ux4g-accordion arrowPosition="right" variant="default">
  <ux4g-accordion-item title="Section 1">Content 1</ux4g-accordion-item>
  <ux4g-accordion-item title="Section 2">Content 2</ux4g-accordion-item>
</ux4g-accordion>

| Input | Type | Default | Description | |---|---|---|---| | arrowPosition | 'right' \| 'left' | 'right' | Arrow icon position | | variant | 'default' \| 'bordered' | 'default' | Accordion style |

Stepper

import { UX4GStepperModule } from 'ux4g-components-angular/stepper';

@NgModule({ imports: [UX4GStepperModule] })
export class AppModule {}
<ux4g-stepper orientation="horizontal" alignment="center">
  <ux4g-stepper-step status="completed">Step 1</ux4g-stepper-step>
  <ux4g-stepper-step status="active">Step 2</ux4g-stepper-step>
  <ux4g-stepper-step>Step 3</ux4g-stepper-step>
</ux4g-stepper>

| Input | Type | Default | Description | |---|---|---|---| | orientation | 'horizontal' \| 'vertical' | 'horizontal' | Layout direction | | alignment | 'default' \| 'center' \| 'left' | 'default' | Horizontal alignment | | variant | 'default' \| 'bottom-line' \| 'bottom-line-fill' \| 'mobile' \| 'progress' | 'default' | Stepper style | | size | 'default' \| 's' | 'default' | Stepper size |

Slider

import { UX4GSliderFieldModule } from 'ux4g-components-angular/slider';

@NgModule({ imports: [UX4GSliderFieldModule] })
export class AppModule {}
<ux4g-slider-field size="sm">
  <label class="ux4g-slider-label">Volume</label>
  <input class="ux4g-slider-input" type="range" min="0" max="100" value="50" />
</ux4g-slider-field>

<ux4g-slider-field size="md">
  <input class="ux4g-slider-input" type="range" min="0" max="100" value="75" />
</ux4g-slider-field>

| Input | Type | Default | Description | |---|---|---|---| | size | 'sm' \| 'md' | 'sm' | Slider size |

Note: The module is UX4GSliderFieldModule and the selector is ux4g-slider-field. The range input and label are projected as children.

Drawer

import { UX4GDrawerModule } from 'ux4g-components-angular/drawer';

@NgModule({ imports: [UX4GDrawerModule] })
export class AppModule {}
<ux4g-drawer placement="right" [open]="isOpen">
  <h3>Drawer Title</h3>
  <p>Drawer content</p>
  <button (click)="isOpen = false">Close</button>
</ux4g-drawer>

| Input | Type | Default | Description | |---|---|---|---| | placement | 'right' \| 'left' \| 'top' \| 'bottom' | 'right' | Slide-in direction | | open | boolean | false | Open state |

Note: Close handling is external — toggle the open input from your component state.

Date-Time Picker

import { UX4GDateTimePickerModule } from 'ux4g-components-angular/date-time-picker';

@NgModule({ imports: [UX4GDateTimePickerModule] })
export class AppModule {}
<ux4g-date-time-picker mode="date"></ux4g-date-time-picker>
<ux4g-date-time-picker mode="time"></ux4g-date-time-picker>

| Input | Type | Default | Description | |---|---|---|---| | mode | 'date' \| 'time' | 'date' | Picker mode |

Status Pipeline

import { UX4GStatusPipelineModule } from 'ux4g-components-angular/status-pipeline';

@NgModule({ imports: [UX4GStatusPipelineModule] })
export class AppModule {}
<ux4g-status-pipeline orientation="horizontal" alignment="center">
  <ux4g-status-pipeline-step status="completed">Submitted</ux4g-status-pipeline-step>
  <ux4g-status-pipeline-step status="active">In Review</ux4g-status-pipeline-step>
  <ux4g-status-pipeline-step>Approved</ux4g-status-pipeline-step>
</ux4g-status-pipeline>

| Input | Type | Default | Description | |---|---|---|---| | orientation | 'horizontal' \| 'vertical' | 'horizontal' | Layout direction | | alignment | 'default' \| 'center' \| 'left' | 'default' | Horizontal alignment | | variant | 'default' \| 'bottom-line' \| 'bottom-line-fill' \| 'mobile' \| 'progress' | 'default' | Pipeline style | | size | 'default' \| 's' | 'default' | Pipeline size |

Journey Timeline

import { UX4GJourneyTimelineModule } from 'ux4g-components-angular/journey-timeline';

@NgModule({ imports: [UX4GJourneyTimelineModule] })
export class AppModule {}
<ux4g-journey-timeline orientation="vertical">
  <ux4g-journey-timeline-item>Event 1</ux4g-journey-timeline-item>
  <ux4g-journey-timeline-item>Event 2</ux4g-journey-timeline-item>
</ux4g-journey-timeline>

| Input | Type | Default | Description | |---|---|---|---| | orientation | 'vertical' \| 'horizontal' | 'vertical' | Timeline direction |

Form Field Group

import { UX4GFormFieldGroupModule } from 'ux4g-components-angular/form-field-group';

@NgModule({ imports: [UX4GFormFieldGroupModule] })
export class AppModule {}
<ux4g-form-field-group>
  <label>Full Name</label>
  <input type="text" />
  <span>Enter your full legal name</span>
</ux4g-form-field-group>

OTP Input

import { UX4GOtpInputModule } from 'ux4g-components-angular/otp-input';

@NgModule({ imports: [UX4GOtpInputModule] })
export class AppModule {}
<ux4g-otp-input state="default">
  <div class="ux4g-otp-label ux4g-label-l-default">Enter OTP</div>
  <div class="ux4g-otp-group">
    <input class="ux4g-otp-source" type="hidden" value="" data-ux-count="4" placeholder="—" />
  </div>
  <div class="ux4g-otp-meta ux4g-body-s-default">
    <span class="ux4g-otp-helper">Didn't receive OTP?</span>
    <span class="ux4g-otp-resend">Resend</span>
  </div>
</ux4g-otp-input>

<ux4g-otp-input state="error">
  <div class="ux4g-otp-label ux4g-label-l-default">Enter OTP</div>
  <div class="ux4g-otp-group">
    <input class="ux4g-otp-source" type="hidden" value="" data-ux-count="6" placeholder="—" />
  </div>
</ux4g-otp-input>

| Input | Type | Default | Description | |---|---|---|---| | state | 'default' \| 'success' \| 'error' \| 'locked' | 'default' | Input state |

Note: The OTP digit inputs are constructed by the runtime JS. The data-ux-count attribute on the hidden input controls how many digit boxes render. There is no length input — content is projected as children.

File Upload

import { UX4GFileUploadModule } from 'ux4g-components-angular/file-upload';

@NgModule({ imports: [UX4GFileUploadModule] })
export class AppModule {}
<ux4g-file-upload state="default"></ux4g-file-upload>
<ux4g-file-upload state="uploaded" fileName="document.pdf"></ux4g-file-upload>

| Input | Type | Default | Description | |---|---|---|---| | state | 'default' \| 'default-vle' \| 'selecting' \| 'scanning' \| 'uploaded' \| 'uploaded-vle' \| 'error' | 'default' | Upload state |

Progress Indicator

import { UX4GProgressIndicatorModule } from 'ux4g-components-angular/progress-indicator';

@NgModule({ imports: [UX4GProgressIndicatorModule] })
export class AppModule {}
<!-- Bar variant -->
<ux4g-progress-indicator type="bar">
  <div class="ux4g-progress-bar-track">
    <div class="ux4g-progress-bar-fill" style="width: 60%"></div>
  </div>
  <span class="ux4g-progress-label">60%</span>
</ux4g-progress-indicator>

<!-- Circle variant -->
<ux4g-progress-indicator type="circle" size="l" labelPlacement="inside">
  <span class="ux4g-progress-value">75%</span>
</ux4g-progress-indicator>

<!-- Rounded shape -->
<ux4g-progress-indicator type="bar" shape="rounded">
  <div class="ux4g-progress-bar-track">
    <div class="ux4g-progress-bar-fill" style="width: 45%"></div>
  </div>
</ux4g-progress-indicator>

| Input | Type | Default | Description | |---|---|---|---| | type | 'bar' \| 'circle' | — (required) | Indicator type | | labelPlacement | 'outside' \| 'inside' | — | Label position | | shape | 'default' \| 'rounded' | — | Bar shape | | size | 'xs' \| 's' \| 'm' \| 'l' \| 'xl' \| '2xl' \| '3xl' | — | Circle size (ignored for bar) |

Note: This is a container shell. Progress track, fill, and value label are projected as children. There is no value input.

Feedback

import { UX4GFeedbackModule } from 'ux4g-components-angular/feedback';

@NgModule({ imports: [UX4GFeedbackModule] })
export class AppModule {}
<ux4g-feedback>
  <p>Was this helpful?</p>
  <button>Yes</button>
  <button>No</button>
</ux4g-feedback>

Draft Status Banner

import { UX4GDraftStatusBannerModule } from 'ux4g-components-angular/draft-status-banner';

@NgModule({ imports: [UX4GDraftStatusBannerModule] })
export class AppModule {}
<ux4g-draft-status-banner variant="default">Draft saved</ux4g-draft-status-banner>
<ux4g-draft-status-banner variant="auto">Auto-saving...</ux4g-draft-status-banner>
<ux4g-draft-status-banner variant="success">Published</ux4g-draft-status-banner>

| Input | Type | Default | Description | |---|---|---|---| | variant | 'default' \| 'auto' \| 'success' | 'default' | Banner style |

SLA Progress Indicator

import { UX4GSlaProgressIndicatorModule } from 'ux4g-components-angular/sla-progress-indicator';

@NgModule({ imports: [UX4GSlaProgressIndicatorModule] })
export class AppModule {}
<ux4g-sla-progress-indicator type="circle">
  <div class="ux4g-sla-circle-track">
    <span class="ux4g-sla-value">75%</span>
  </div>
</ux4g-sla-progress-indicator>

<ux4g-sla-progress-indicator type="linear">
  <div class="ux4g-sla-linear-track">
    <div class="ux4g-sla-linear-fill" style="width: 50%"></div>
  </div>
</ux4g-sla-progress-indicator>

<ux4g-sla-progress-indicator type="badge">On Track</ux4g-sla-progress-indicator>

| Input | Type | Default | Description | |---|---|---|---| | type | 'circle' \| 'linear' \| 'badge' | — (required) | Indicator type |

Note: This is a container shell. Progress value and track are projected as children. There is no value input.

Carousel

import { UX4GCarouselModule } from 'ux4g-components-angular/carousel';

@NgModule({ imports: [UX4GCarouselModule] })
export class AppModule {}
<ux4g-carousel>
  <ux4g-carousel-item>Slide 1</ux4g-carousel-item>
  <ux4g-carousel-item>Slide 2</ux4g-carousel-item>
  <ux4g-carousel-item>Slide 3</ux4g-carousel-item>
</ux4g-carousel>

Empty State

import { UX4GEmptyStateModule } from 'ux4g-components-angular/empty-state';

@NgModule({ imports: [UX4GEmptyStateModule] })
export class AppModule {}
<ux4g-empty-state>
  <img src="empty.svg" alt="" />
  <h3>No results found</h3>
  <p>Try adjusting your search.</p>
</ux4g-empty-state>

Chip Group

import { UX4GChipGroupModule } from 'ux4g-components-angular/chip-group';

@NgModule({ imports: [UX4GChipGroupModule] })
export class AppModule {}
<ux4g-chip-group variant="filter">
  <ux4g-chip chipType="filter" size="md" [active]="true">All</ux4g-chip>
  <ux4g-chip chipType="filter" size="md">Category A</ux4g-chip>
</ux4g-chip-group>

| Input | Type | Default | Description | |---|---|---|---| | variant | 'filter' \| 'choice' | 'filter' | Group type |

Navbar

import { UX4GNavbarModule } from 'ux4g-components-angular/navbar';

@NgModule({ imports: [UX4GNavbarModule] })
export class AppModule {}
<ux4g-navbar>
  <a href="/">Logo</a>
  <nav>
    <a href="#">Home</a>
    <a href="#">About</a>
  </nav>
</ux4g-navbar>

Social Links

import { UX4GSocialLinksModule } from 'ux4g-components-angular/social-links';

@NgModule({ imports: [UX4GSocialLinksModule] })
export class AppModule {}
<ux4g-social-links size="md">
  <a href="#" aria-label="Twitter"><i class="ux4g-icon-twitter"></i></a>
  <a href="#" aria-label="LinkedIn"><i class="ux4g-icon-linkedin"></i></a>
</ux4g-social-links>

| Input | Type | Default | Description | |---|---|---|---| | size | 'sm' \| 'md' \| 'lg' | 'md' | Icon spacing size |

Slot Grid

import { UX4GSlotGridModule } from 'ux4g-components-angular/slot-grid';

@NgModule({ imports: [UX4GSlotGridModule] })
export class AppModule {}
<ux4g-slot-grid variant="weekly">
  <div>9:00 AM</div>
  <div>10:00 AM</div>
</ux4g-slot-grid>

<ux4g-slot-grid variant="compact">
  <div>9:00</div>
  <div>9:30</div>
</ux4g-slot-grid>

| Input | Type | Default | Description | |---|---|---|---| | variant | 'weekly' \| 'compact' | 'weekly' | Grid layout |

Footer

import { UX4GFooterModule } from 'ux4g-components-angular/footer';

@NgModule({ imports: [UX4GFooterModule] })
export class AppModule {}
<ux4g-footer theme="primary">
  <p>&copy; 2024 Company Name</p>
</ux4g-footer>

| Input | Type | Default | Description | |---|---|---|---| | theme | 'default' \| 'primary' \| 'dark' | 'default' | Footer theme |

Mega Menu

import { UX4GMegaMenuModule } from 'ux4g-components-angular/mega-menu';

@NgModule({ imports: [UX4GMegaMenuModule] })
export class AppModule {}
<ux4g-mega-menu>
  <ux4g-mega-menu-sidebar>
    <ux4g-mega-menu-category-item [active]="true">Category 1</ux4g-mega-menu-category-item>
    <ux4g-mega-menu-category-item>Category 2</ux4g-mega-menu-category-item>
  </ux4g-mega-menu-sidebar>
  <ux4g-mega-menu-content [active]="true">
    <ux4g-mega-menu-column>
      <a href="#">Link 1</a>
      <a href="#">Link 2</a>
    </ux4g-mega-menu-column>
  </ux4g-mega-menu-content>
</ux4g-mega-menu>

<!-- Dropdown variant -->
<ux4g-mega-menu [dropdown]="true">
  <ux4g-mega-menu-sidebar>
    <ux4g-mega-menu-category-item [active]="true">Services</ux4g-mega-menu-category-item>
  </ux4g-mega-menu-sidebar>
  <ux4g-mega-menu-content [active]="true">
    <ux4g-mega-menu-column>
      <a href="#">Service A</a>
    </ux4g-mega-menu-column>
  </ux4g-mega-menu-content>
</ux4g-mega-menu>

UX4GMegaMenu Inputs:

| Input | Type | Default | Description | |---|---|---|---| | dropdown | boolean | false | Render as dropdown (wraps in positioning container) | | dropdownRight | boolean | false | Align dropdown to the right |

UX4GMegaMenuCategoryItem Inputs:

| Input | Type | Default | Description | |---|---|---|---| | active | boolean | false | Active/selected state |

UX4GMegaMenuContent Inputs:

| Input | Type | Default | Description | |---|---|---|---| | active | boolean | false | Active/visible state |

Result List Row

import { UX4GResultListRowModule } from 'ux4g-components-angular/result-list-row';

@NgModule({ imports: [UX4GResultListRowModule] })
export class AppModule {}
<ux4g-result-list-row variation="v1">
  <!-- Header -->
  <div class="ux4g-result-list-header">
    <div class="ux4g-result-list-info">
      <div class="ux4g-result-list-icon"></div>
      <div class="ux4g-result-list-title-group">
        <h2 class="ux4g-title-s-default ux4g-result-list-title">Certificate Name</h2>
      </div>
    </div>
    <div class="ux4g-result-list-actions-container">
      <div class="ux4g-result-list-actions">
        <button class="ux4g-btn-outline-neutral ux4g-btn-sm ux4g-btn">Track</button>
      </div>
    </div>
  </div>
  <!-- Expanded Content -->
  <div class="ux4g-result-list-content">
    <div class="ux4g-result-list-details">
      <div class="ux4g-result-list-detail-item">
        <span class="ux4g-label-m-default ux4g-text-neutral-tertiary">Submitted Date</span>
        <span class="ux4g-body-s-default ux4g-text-neutral-secondary">1 Apr 2026</span>
      </div>
    </div>
  </div>
</ux4g-result-list-row>

| Input | Type | Default | Description | |---|---|---|---| | variation | 'default' \| 'v1' \| 'v2' \| 'v3' \| 'v4' \| 'v5' | 'default' | Row layout variation |


Dark Theme

Apply the dark theme by adding data-theme="dark" to any container or the <html> element:

<!-- In index.html -->
<html data-theme="dark">

<!-- Or scoped to a section in a template -->
<div data-theme="dark">
  <ux4g-button variant="primary" size="md">Dark themed</ux4g-button>
</div>

Design tokens automatically switch values — no additional imports needed.


Architecture

This package follows a CSS-first architecture:

  • CSS is the source of truth — all visual decisions live in CSS from ux4g-components-web
  • Wrappers are thin — they map typed inputs to CSS class strings via buildXxxClasses() functions
  • No inline styles, no CSS-in-JS — only [class] bindings
  • Class_Builder functions are imported from ux4g-components-web/types
  • Runtime auto-bootstrap — interactive behaviors initialize automatically

Compatibility

  • Angular >= 15.0.0
  • Built with Ivy partial compilation (compatible with Angular 15–19+)
  • typesVersions included for moduleResolution: node compatibility

Available Components (51)

All components are available as sub-path imports:

import { UX4GButtonModule } from 'ux4g-components-angular/button';
import { UX4GSpinnerModule } from 'ux4g-components-angular/spinner';
import { UX4GBadgeModule } from 'ux4g-components-angular/badge';
// ... etc.

Full list: accessibility-bar, accordion, alert, avatar, badge, breadcrumb, button, card, carousel, checkbox, chip, chip-group, combobox, date-time-picker, divider, draft-status-banner, drawer, dropdown, empty-state, feedback, file-upload, footer, form-field-group, icon-button, image, input, journey-timeline, link, list, mega-menu, modal, navbar, otp-input, pagination, popover, progress-indicator, radio, result-list-row, search, sla-progress-indicator, slider, slot-grid, social-links, spinner, status-pipeline, stepper, switch, tab, table, tag, tooltip


Related Packages

License

MIT