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

dibk-design

v15.0.1

Published

Shared React component library for DIBK applications — 43 components, design tokens, and themes, published as the [`dibk-design`](https://www.npmjs.com/package/dibk-design) npm package.

Readme

DIBK design

Shared React component library for DIBK applications — 43 components, design tokens, and themes, published as the dibk-design npm package.

Component documentation (Storybook): https://arkitektum.github.io/dibk-design/

Using the package

  1. Install

    npm install dibk-design

    Peer dependencies (must be installed in your app):

    • react 18 or 19
    • react-dom 18 or 19
    • react-router 7 or 8

    react-router is needed because Button, Step and DropdownButton render a router link when given a to prop. Import it from react-router, not react-router-dom: that package was removed in react-router 8 and is frozen at 7.18.2. On react-router 7 the two are interchangeable for Link, so react-router is the specifier that spans both majors.

    react-router 6 is not supported from 13.0.0 onwards, because Link lives in react-router-dom there. Use 12.x if you are still on 6.

    All three peers are required rather than optional, react-router included. The router import is static and top-level, so your bundler has to resolve it even if you never render a component that links anywhere.

    Your app and this library must resolve to one react-router instance. Two instances break links in two different ways, and only one of them is loud:

    • Step and DropdownButton throw useHref() may be used only in the context of a <Router> component, because router context is per instance.
    • Button fails silently. It identifies a <Link> child by comparing module identity, so a Link from a second instance is not recognised and the button renders as a plain <button> with no navigation and no error.

    The usual cause is a stray react-router-dom left in your dependencies alongside react-router 8. Check with npm ls react-router (or pnpm why react-router) and expect a single version.

  2. Import the component styles

    All compiled component styles ship in a single CSS file that your app must import once (e.g. in your global CSS or app entry):

    @import "dibk-design/dibk-design.css";

    This pulls in dibk-design/fonts.css (the PP Mori @font-face rules) for you. Import it directly only if you load the component styles some other way, or omit it if your app supplies its own copy of the font.

  3. Use the components

    import { Button } from "dibk-design";
    
    const Example = () => (
      <Button onClick={() => {}} size="small" color="primary">
        I'm a button
      </Button>
    );

Styles & tokens

In addition to dibk-design/dibk-design.css (component styles), the package ships:

  • dibk-design/theme.css — Tailwind-friendly theme tokens (via @theme)
  • dibk-design/tokens.css — plain CSS variables for non-Tailwind apps
  • dibk-design/fonts.css — the PP Mori @font-face rules, referencing the font files in dibk-design/dist/fonts/. Already imported by dibk-design.css.

Use with Tailwind (recommended)

Import the theme tokens in your global CSS:

@import "tailwindcss";
@import "dibk-design/theme.css";
@import "dibk-design/dibk-design.css";

Use without Tailwind

Import the plain tokens instead:

@import "dibk-design/tokens.css";
@import "dibk-design/dibk-design.css";

Migrating

Two releases changed Select in ways that break working consumer code, and both shipped as minor releases without a release note. Items 1 to 5 below cover those and the props since restored. Item 6 is the one breaking change in 12.0.0, item 7 the one in 13.0.0, items 8 and 9 the two in 14.0.0, and items 10 to 12 what 15.0.0 changes. The greps are the fastest way to find what needs changing. Full details in CHANGELOG.md.

1. Select onChange receives a value, not an event (9.1.0)

Before 9.1.0 the handler got the raw DOM event. It now gets the selected value.

// Before (≤ 9.0.2)
<Select onChange={(event) => setValue(event.target.value)} />

// After (≥ 9.1.0)
<Select onChange={(value) => setValue(value)} />

Symptom: TypeError: Cannot read properties of undefined (reading 'value') as soon as a selection is made.

# Every Select usage, to review its onChange
grep -rn "<Select" src

# Handlers still reading the event off a change callback
grep -rn "target\.value" src

2. Select multiple onChange receives the whole selection (9.1.0)

This is the one to check most carefully — nothing crashes. Before 9.1.0, each click fired onChange(option.value) with the single value that had just been toggled, and the consumer merged it into their own state. It now computes the next selection itself and fires onChange(nextValues) with the full array.

Consumer toggle logic therefore runs a second time on top of an already-correct array, and quietly corrupts state — a re-selected value gets removed, a deselected one gets added back.

// Before (≤ 9.0.2) — the consumer did the toggling
<Select
  multiple
  value={selected}
  onChange={(toggled) =>
    setSelected(
      selected.includes(toggled)
        ? selected.filter((v) => v !== toggled)
        : [...selected, toggled]
    )
  }
/>

// After (≥ 9.1.0) — just store what you are given
<Select multiple value={selected} onChange={setSelected} />
# Every multiple Select, then read each onChange: if it inspects the argument
# with includes/filter/spread, it is still doing the toggling and is now wrong
grep -rn -A 8 "<Select" src | grep -B 8 "multiple"

3. contentOnly was removed, and is back (10.3.2, 11.5.0, 12.0.0)

10.3.2 rewrote Select on top of react-select and deleted contentOnly from eight components, so read-only views silently started rendering as editable controls.

All eight have it back, with the same behaviour as 10.1.1: the label, then a plain <span> holding the content, with no form control in the DOM. Prefer it over disabled for view modes — disabled greys the text out, implies "temporarily unavailable", and still renders a focusable widget.

Select and InputField were restored in 11.5.0. Textarea, CheckBoxInput, CheckBoxListItem, RadioButtonInput, RadioButtonListItem and DragAndDropFileInput followed in 12.0.0.

Two things worth knowing if you are putting contentOnly back into use:

  • Textarea keeps the line breaks in a multi-line value, where the pre-10.3.2 markup collapsed them.
  • CheckBoxInput shows a bare checkmark, while RadioButtonInput shows no indicator at all. That is deliberate rather than an oversight: a read-only checkbox list renders every option and has to mark which are ticked, whereas a radio group has one answer, so a read-only view renders only the selected option and a dot beside it would be noise.
grep -rn "contentOnly" src

4. keyAsContent and placeholderValue were silent no-ops (10.3.2–11.3.x)

Both stayed in SelectProps after the rewrite stopped reading them, so they type-checked and did nothing. Both work again as of 11.5.0:

  • keyAsContent — contentOnly only. Shows the matching option's key instead of the raw value. It has no meaning outside contentOnly.
  • placeholderValue — the sentinel meaning "nothing selected". A value equal to it shows the placeholder, and clearing the selection reports it through onChange. Clearing a single select requires the new isClearable.

If you were relying on either between 10.3.2 and 11.3.x, your read-only views were rendering as editable controls and your sentinel was rendering as visible option text.

5. Select value types no longer have to match exactly (11.5.0)

Matching was options.find(o => o.value === value), so a string "5" against a numeric option value 5 matched nothing and rendered the raw id as the visible option label. Matching now falls back to comparing string forms, and warns in development when a non-empty value matches no option at all. If you see that warning, the value and the option values have different types.

6. DropdownButton's menu is no longer a list (12.0.0)

The menu was a <ul role="menu"> whose items each sat in an <li role="none">. It is now a <div role="menu"> with the items as direct children. role="menu" replaces a list's semantics outright, which is exactly why every item needed role="none" to suppress them again, so the list was doing no work.

This only affects you if you style or query the dropdown's internals. Anything selecting by role is unchanged, since role="menu" and role="menuitem" are both still there.

# CSS or queries reaching into the dropdown's list markup
grep -rn "menu li\|menu ul" src

7. react-router replaces react-router-dom (13.0.0)

Link is now imported from react-router, and the peer dependency is react-router 7 or 8 instead of react-router-dom 6.4+ or 7.

On react-router 7 this is a one-line change to your package.json at most: react-router is what react-router-dom depends on, so it is already installed. On react-router 6 it is a blocker, because Link lives in react-router-dom there. Stay on 12.x until you can move to 7.

react-router-dom was removed in react-router 8 and is frozen at 7.18.2, so importing from it capped every consumer at react-router 7. It was also worse than a cap: an app that installed react-router 8 and kept react-router-dom around for this library ended up with two react-router instances, and since router context is per instance, the library's Link threw useHref() may be used only in the context of a <Router> component.

# Anywhere your app still imports from the removed package
grep -rn "react-router-dom" src

8. NavigationBar no longer takes color (14.0.0)

The prop took "secondary" or "neutral". secondary painted the bar's links in the bar's own background colour, which made the navigation unreadable, and no app used it. neutral was the default and only restated the values already on the container.

// Before (≤ 13.1.0)
<NavigationBar themeId="dibk" color="neutral" links={links} />

// After (≥ 14.0.0)
<NavigationBar themeId="dibk" links={links} />

Delete the prop. Nothing replaces it and nothing changes on screen — the default is what neutral produced. To recolour the bar, set the --navigation-overlay, --navigation-text and --navigation-surface custom properties in your own stylesheet.

Symptom: a TypeScript error on the prop. It is deliberate — the alternative was accepting it and ignoring it.

grep -rn "<NavigationBar" src

9. ErrorMessage emits different markup (14.0.0)

The icon is an inline <svg> instead of an <img>, so it can take its colour from CSS, and the message now sits inside an always-present aria-live region so screen readers actually announce it. Both are fixes; both change the DOM.

<!-- Before (≤ 13.1.0) -->
<span aria-live="polite" class="…errorMessage"><img class="…errorSign">Message</span>

<!-- After (≥ 14.0.0) -->
<span class="…errorMessageRegion" aria-live="polite">
  <span class="…errorMessage"><svg class="…errorSign"></svg>Message</span>
</span>

errorMessage and errorSign still name the same things, so most CSS keeps working. Check two shapes: selectors treating the icon as an image, and selectors assuming .errorMessage is a direct or last child of the field. The region is rendered even when there is no error, so :last-child on a field's children now matches it instead of the input.

This affects every component that shows a validation error — InputField, Textarea, Select and DragAndDropFileInput — not just direct uses of ErrorMessage.

InfoBox's variant icon (.iconImage) and Step's finished-step checkmark (.checkmarkSymbol) changed from <img> to inline <svg> for the same reason. Their class names and sizing rules are unchanged; only selectors that assume an image break.

grep -rn "errorSign\|errorMessage\|iconImage\|checkmarkSymbol" src

10. Button disabled now really disables the button (15.0.0)

This is the one to check most carefully — nothing crashes. disabled used to add a CSS class and nothing else, so the button looked disabled while staying focusable and clickable, and onClick still fired. It now sets the disabled attribute on the rendered element.

// Before (≤ 14.0.0): looked disabled, still ran the handler
<Button disabled onClick={submit} content="Send inn" />

// After (≥ 15.0.0): the handler does not run
<Button disabled onClick={submit} content="Send inn" />

Symptom: a click that used to do something now does nothing. That is the fix working, but if any of your code depended on it — a button disabled for appearance that still needed to be clickable — drive it with your own state instead of disabled.

The same applies to DropdownButton, which passes disabled through to Button.

grep -rn "disabled" src | grep -i button

11. inputValue is gone from the radio components (15.0.0)

Deprecated in 13.1.0 in favour of value, removed now. It only ever affected RadioButtonInput and RadioButtonListItem; the two checkbox components always took value.

// Before (≤ 14.0.0)
<RadioButtonInput id="x" inputValue="value 1" onChange={onChange}>Ja</RadioButtonInput>

// After (≥ 15.0.0)
<RadioButtonInput id="x" value="value 1" onChange={onChange}>Ja</RadioButtonInput>

Symptom: a TypeScript error on the prop. value is required on all four components now.

grep -rn "inputValue" src

12. Two colour tokens changed value (15.0.0)

Both failed WCAG AA contrast. Nothing about the API changes, so this only matters if you hardcoded the old values somewhere to match the library.

| Token | Was | Now | Why | | --- | --- | --- | --- | | --color-error | #db0000 | #ad0000 | 3.83:1 as text on a checked list item | | optional field marker | #828282 | #5c4d4a | 3.45:1 on the page background |

--color-error drives every error affordance, so error text, icons, the required asterisk, error borders and the InfoBox and Badge error variants all shift together. Read the token rather than the hex and this stays in step by itself.

grep -rni "db0000\|828282" src

Use with Next.js

  1. Import the CSS entrypoints in your globals.css
@import "tailwindcss";
@import "dibk-design/theme.css";
@import "dibk-design/dibk-design.css";
  1. Import components from the library
"use client";
import React from "react";
import { Button } from "dibk-design";

const Home = () => {
  return (
    <main>
      <Button onClick={() => {}} size="small" color="primary">
        I'm a button
      </Button>
    </main>
  );
};

export default Home;

Developing the library

This project uses pnpm as the package manager.

  1. Install dependencies

    pnpm install
  2. Run Storybook for development

    To view and work on components in isolation, run the Storybook development server:

    pnpm run storybook

    This will open Storybook in your browser, usually at http://localhost:6006.

Building for production

Build library

Type-checks, bundles the library (ES/CJS + a bundled index.d.ts), and copies the token files. The output is saved to the /dist folder.

pnpm run build:lib

Build Storybook

Builds the Storybook as a static web application. The output is saved to the /storybook-static folder.

pnpm run build:storybook

Build everything

Builds both the library and the Storybook site:

pnpm run build

Testing local changes in a consuming app

Use yalc to test the built package in another app without publishing:

# In dibk-design — after making changes:
pnpm run build:lib && npx yalc push

# In the consuming app — first time only:
npx yalc add dibk-design