This component no longer exists. It was in ns-ui’s manifest when we first indexed it and is not there now — the registry served its inventory on 2026-08-07 and this item was not on it. The install command below will fail. It is kept here because a tutorial somewhere still tells people to run it.
Chart Bar Halftone
ns-ui/chart-bar-halftoneRemovedComponent
Bar chart whose fills are an ordered-dither halftone instead of a flat color — ink density tracks value as a second, redundant channel to height.
Live preview
live · rendered by the registry
Rendered by ns-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://design.helpmarq.com/r/chart-bar-halftone.jsonSource
1"use client";23import { useEffect, useId, useMemo, useState } from "react";4import type { CSSProperties } from "react";56// ---------------------------------------------------------------------------7// ChartBarHalftone — the dithered-chart family's bar chart. Bar fills are not8// flat color: each bar is a plate stamped with the SAME 4x4 Bayer matrix used9// by background-ascii-dither and ascii-engraving-contour elsewhere in this10// suite (the family's shared ordered-dither ramp — 17 discrete ink levels,11// 0 = empty, 16 = solid), so a bar's height is redundant with its own ink12// density: cover one channel and the other still carries the value. Density13// is the family's only value channel — pure var(--foreground) ink on14// var(--background) paper, no --accent in the data itself, exactly like15// heatmap-year-stipple's choice. --accent is reserved for keyboard focus,16// same convention as every other component in the suite.17//18// Bars are SVG paths filled with `url(#pattern)`, one pattern per ink level,19// so var(--foreground)/var(--background)/var(--border) resolve as ordinary20// CSS custom properties on presentation attributes — no canvas, no21// getComputedStyle, no theme MutationObserver: the browser's own cascade22// repaints both themes correctly on toggle for free.23// ---------------------------------------------------------------------------2425export interface ChartBarHalftoneDatum {26 label: string;27 value: number;28}2930export interface ChartBarHalftoneProps {31 data?: ChartBarHalftoneDatum[];32 /** chart title, used as the figure's accessible name and table caption */33 title?: string;34 className?: string;35}3637// 4x4 Bayer matrix — the family's shared dither constant, raw 0..15 ints38const BAYER = [0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5];39const LEVELS = 16; // 17 discrete steps, 0..1640const CELL = 4; // px per dither cell, shared pattern tile is 4x4 cells4142const BAR_W = 22; // <=24px per the mark spec43const SLOT_W = 58;44const PLOT_H = 220;45const TOP_PAD = 34; // room for the tip label above the tallest bar46const AXIS_H = 8;47const LABEL_H = 22;48const LEFT_PAD = 12;49const RIGHT_PAD = 12;5051function levelFor(norm: number): number {52 return Math.round(Math.min(1, Math.max(0, norm)) * LEVELS);53}5455function formatValue(v: number): string {56 const abs = Math.abs(v);57 if (abs >= 1_000_000) return `${(v / 1_000_000).toFixed(1).replace(/\.0$/, "")}M`;58 if (abs >= 1_000) return `${(v / 1_000).toFixed(1).replace(/\.0$/, "")}K`;59// … truncated
