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

@fungalcode/ui

v0.1.0

Published

Shared Angular UI components and design tokens, themed entirely through CSS custom properties.

Downloads

164

Readme

@fungalcode/ui

Angular components and design tokens, shared across projects. Plain CSS, themed entirely through custom properties — no Tailwind, no theming API, no build step beyond the one Angular already runs.

Requires Angular 21. @angular/router is an optional peer, needed only by the components that generate their own links.

Install

npm install @fungalcode/ui

Then, at the top of your src/styles.css:

@import url('@fungalcode/ui/styles/tokens.css');

That is the only required step. Component styles ship inside the components.

Theme it

The shipped palette is a placeholder — a restrained slate, deliberately nobody's brand. Override any --ui-* token from your own :root. Your rules are unlayered and the library's live in @layer ui.tokens, so yours win whatever order the stylesheets load in.

:root {
  --ui-color-brand: #7a235a;
  --ui-font-family: 'Plus Jakarta Sans', sans-serif;
  --ui-radius-md: 15px;
  --ui-space-unit: 0.3125rem;  /* the whole spacing scale, from one knob */
}

Two rules worth knowing:

  • --ui-color-on-brand* means "ink that sits on the brand colour". If you set a light brand, these must go dark. Getting it backwards is the most common theming mistake and it fails contrast silently.
  • Component knobs (--ui-button-padding-inline, --ui-hero-scrim, …) are never declared, only read with a fallback. So you can set one on :root, on a section, or on a single instance's style attribute.

Optional stylesheets

@import url('@fungalcode/ui/styles/base.css');       /* reset + base typography */
@import url('@fungalcode/ui/styles/utilities.css');  /* .ui-container, .ui-visually-hidden */

Components never need either. base.css gives a page the same baseline — skip it if your project already has a reset it likes.

Components

| | | |---|---| | UiButton | a[uiButton], button[uiButton] — attaches to a native element | | UiHero | h1, lead, actions, three media placements | | UiQuote | pull quote, projected body | | UiLinkCards | grid of cards that link somewhere | | UiStepCards | numbered sequence | | UiInfoCards | cards that explain something | | UiTestimonials | feedback, with optional ratings and portraits | | UiFaq + UiFaqItem | native <details> accordion | | UiContactForm | fields, validation and ARIA — you own the transport |

import { UiButton, UiFaq, UiFaqItem } from '@fungalcode/ui';

@Component({ imports: [UiButton, UiFaq, UiFaqItem] })

The button is an attribute

<a uiButton routerLink="/contact">Get in touch</a>
<button uiButton type="submit" [disabled]="sending()">Send</button>

It attaches to an element you write, so href, routerLink, type and disabled are the real attributes and behave as such. Content is projected, so an icon can sit inside the label.

The contact form does not send

It owns the fields, the validation, the error wiring and the honeypot. You own the transport, and report back through status:

<ui-contact-form
  [labels]="german"
  [status]="status()"
  privacyHref="/privacy"
  (submitted)="send($event)"
/>

The emitted message carries elapsedMs — how long the form took to fill in — for your server to weigh. A submission that tripped the honeypot is silently accepted and never emitted.

All copy comes from labels; the library ships English defaults and no translations.

Development

npm run storybook       # the showcase, and the development loop
npm test                # unit tests, jsdom
npm run test:stories    # every story in Chromium, with axe
npm run build:lib
npm run pack:local      # a tarball, exactly as the registry would ship it

Two rules that are easy to trip over:

  • ng test, never npx vitest for the unit tests — the Angular builder installs the Vitest globals, so a direct run fails with ReferenceError: describe is not defined.
  • Stories import from @storybook/angular-vite, not @storybook/angular, which is not installed. The error names your story file, not the package.

Every value a component reads must be a --ui-* token. The check is mechanical, and it is the difference between a library and one project's CSS:

grep -rn 'var(--' projects/ui/src/lib | grep -v 'var(--ui-'   # must be empty