r/angular • u/Old-Parsley-5826 • 23h ago
ng-prism 22.6: hover and focus aren't variants anymore, every variant in every state in one grid
I just released ng-prism 22.6. Short recap if you haven't seen it before: ng-prism is a component lab for Angular libraries, a Storybook alternative without story files. You put a u/Showcase decorator on a component, inputs and types are read at build time, and the components render in the same document as the styleguide, no iframe.
The main change this time is that hover, pressed and focus are no longer variants. In 22.5 I added a way to force :hover or :focus-visible on a variant, and pretty quickly the demo button had variants called "Hovered", "Pressed" and "Focus visible". They showed up in the Playground's variant list, kept the button hovered while you changed the controls, and only existed for the one variant somebody had written them for.
Now a component declares its states once and they get combined with every variant:
@Showcase<ButtonComponent>({
title: 'Button',
states: [
{ name: 'Hover', pseudo: { hover: '.btn' } },
{ name: 'Pressed', pseudo: { hover: '.btn', active: '.btn' } },
{ name: 'Focus visible', pseudo: { 'focus-visible': '.btn' } },
],
variants: [ /* Filled, Outlined, Elevated, Disabled, … */ ],
})
The Overview then shows every variant in every state as a grid, and clicking a cell opens that combination in the Playground. The styling comes from your own CSS, ng-prism rewrites :hover so it also matches a helper class. A state only gets applied where the browser could actually produce it, so there's no focus ring on a disabled button and no hover on something with pointer-events: none. The cell tells you why it's empty instead.
In the Playground the states are buttons in the tools menu. They stay on when you switch variants and they're part of the URL. For visual regression there's a state= URL parameter, the render marker gets the state index, and a data-prism-excluded attribute tells the runner when a state doesn't fit. Without states nothing changes for existing runners.
Other things in 22.6: a Claude Code plugin (/plugin marketplace add ng-prism/ng-prism) that teaches agents how to write showcases and check them in the running styleguide, watch rebuilds down from about 450 ms to 60 ms, and fixes for aliased inputs and outputs, named content slots and libraries with only a primary entry point.
- Demo with the Button grid: https://ng-prism.github.io/ng-prism/demo/?component=ButtonComponent&view=overview
- Repo: https://github.com/ng-prism/ng-prism
Question for anyone with their own component library: which states do your components need that a pseudo-class can't express? Drag-over, open, loading? I'd like to base the next step on real components rather than on my own guesses.