argentui 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +160 -0
- package/dist/index.cjs +838 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +306 -0
- package/dist/index.d.ts +306 -0
- package/dist/index.js +794 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +289 -0
- package/package.json +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/surfaces.tsx","../src/metal.tsx","../src/engine.ts","../src/haptics.ts","../src/controls.tsx","../src/text.tsx","../src/logo.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport { MetalFill, type MetalEffect, type MetalFinish, type MetalTone } from \"./metal\";\nimport type { MetalEngine } from \"./engine\";\nimport { PRESS_PATTERN, vibrate } from \"./haptics\";\n\nfunction cx(...parts: (string | false | undefined | null)[]): string {\n return parts.filter(Boolean).join(\" \");\n}\n\nfunction assignRef<T>(ref: React.ForwardedRef<T>, node: T | null) {\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n}\n\n/** Where the liquid metal shows: just the edge, or the whole surface. */\nexport type MetalVariant = \"border\" | \"fill\";\n\n/** Border framing: a single rim, or a rim plus an inner hairline frame. */\nexport type MetalFrame = \"single\" | \"double\";\n\ntype StyleVars = React.CSSProperties & Record<`--${string}`, string>;\n\nexport interface MetalProps extends React.HTMLAttributes<HTMLElement> {\n /** Element/component to render. Defaults to `div`. */\n as?: React.ElementType;\n /** Metal finish. */\n tone?: MetalTone;\n /** `\"border\"` (metal edge only, default) or `\"fill\"` (metal fills the surface). */\n variant?: MetalVariant;\n /** `\"single\"` rim (default) or `\"double\"` — rim plus an inner hairline frame. */\n frame?: MetalFrame;\n /** Let the metal show faintly through the interior panel (border variant). */\n tint?: boolean;\n /** Border thickness in px (border variant). */\n borderWidth?: number;\n /** Fill the whole surface with metal on hover (border variant). */\n revealOnHover?: boolean;\n /** Corner radius in px. */\n radius?: number;\n /** Shader animation speed (0 pauses the metal). */\n speed?: number;\n /** Pattern scale — higher spreads the reflection bands out. */\n metalScale?: number;\n /** Shader engine: Paper's LiquidMetal (default) or Argent's own. */\n engine?: MetalEngine;\n /** Shape-tuned shader preset. Defaults to `\"surface\"`. */\n finish?: MetalFinish;\n /** Motion character: flow, molten, ripple, chrome, or wave. */\n effect?: MetalEffect;\n /** Band direction in degrees — overrides the tone/finish default. */\n angle?: number;\n /** A specular streak that sweeps across on hover. */\n sheen?: boolean;\n /**\n * A frosted standoff ring outside the metal — a few px of backdrop blur\n * finished with a ~5% hairline. `true` for 8px, or a number for the ring\n * width. Theme the line with `--argent-halo-line`.\n */\n halo?: boolean | number;\n}\n\nfunction buildVars(radius: number, borderWidth: number, halo: boolean | number, style?: React.CSSProperties): StyleVars {\n const vars: StyleVars = {\n borderRadius: radius,\n \"--argent-bw\": `${borderWidth}px`,\n \"--argent-radius\": `${radius}px`,\n ...style,\n } as StyleVars;\n if (halo) vars[\"--argent-halo\"] = `${halo === true ? 8 : halo}px`;\n return vars;\n}\n\n/**\n * A liquid-metal surface powered by Paper's `LiquidMetal` shader. By default the\n * metal is just the edge; pass `variant=\"fill\"` for a full metal surface, or\n * `revealOnHover` to fill in on interaction. The base for every Argent component.\n */\nexport const Metal = forwardRef<HTMLElement, MetalProps>(function Metal(\n {\n as,\n tone = \"silver\",\n variant = \"border\",\n frame = \"single\",\n tint = false,\n borderWidth = 1.5,\n revealOnHover = false,\n radius = 14,\n speed,\n metalScale,\n engine,\n finish,\n effect,\n angle,\n sheen = false,\n halo = false,\n className,\n style,\n children,\n ...rest\n },\n ref,\n) {\n const Tag = (as ?? \"div\") as React.ElementType;\n const border = variant === \"border\";\n return (\n <Tag\n ref={(node: HTMLElement | null) => assignRef(ref, node)}\n className={cx(\n \"argent\",\n border ? \"argent--border\" : \"argent--fill\",\n border && frame === \"double\" && \"argent--double\",\n border && tint && \"argent--tint\",\n revealOnHover && \"argent--reveal\",\n sheen && \"argent--sheen\",\n !!halo && \"argent--halo\",\n className,\n )}\n data-tone={tone}\n style={buildVars(radius, borderWidth, halo, style)}\n {...rest}\n >\n <span className=\"argent-fill\" aria-hidden=\"true\">\n <MetalFill tone={tone} speed={speed} scale={metalScale} engine={engine} finish={finish} effect={effect} angle={angle} />\n </span>\n {border && <span className=\"argent-core\" aria-hidden=\"true\" />}\n {sheen && <span className=\"argent-sheen\" aria-hidden=\"true\" />}\n <span className=\"argent-content\">{children}</span>\n </Tag>\n );\n});\n\nexport interface MetalCardProps extends MetalProps {}\n\n/** A padded liquid-metal container. Metal edge by default. */\nexport const MetalCard = forwardRef<HTMLElement, MetalCardProps>(function MetalCard(\n { className, radius = 18, ...rest },\n ref,\n) {\n return <Metal ref={ref} radius={radius} className={cx(\"argent-card\", className)} {...rest} />;\n});\n\nexport interface MetalButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n tone?: MetalTone;\n size?: \"sm\" | \"md\" | \"lg\";\n /** `\"border\"` (default — readable, fills on hover) or `\"fill\"` (full chrome). */\n variant?: MetalVariant;\n /** Corner radius in px. */\n radius?: number;\n borderWidth?: number;\n /** Fill with metal on hover (border variant). Defaults to `true`. */\n revealOnHover?: boolean;\n /** Vibrate on press where supported. Defaults to `true`. */\n haptics?: boolean;\n speed?: number;\n engine?: MetalEngine;\n finish?: MetalFinish;\n effect?: MetalEffect;\n angle?: number;\n halo?: boolean | number;\n}\n\nconst SIZE_RADIUS = { sm: 11, md: 13, lg: 15 } as const;\n\n/** A liquid-metal button — readable at rest, molten on hover, with a stamped press. */\nexport const MetalButton = forwardRef<HTMLButtonElement, MetalButtonProps>(function MetalButton(\n { tone = \"silver\", size = \"md\", variant = \"border\", radius, borderWidth = 1.5, revealOnHover = true, haptics = true, speed, engine, finish = \"button\", effect, angle, halo = false, type = \"button\", className, children, style, onPointerDown, ...rest },\n ref,\n) {\n const border = variant === \"border\";\n return (\n <button\n ref={ref}\n type={type}\n onPointerDown={(e) => {\n if (haptics) vibrate(PRESS_PATTERN);\n onPointerDown?.(e);\n }}\n className={cx(\"argent\", border ? \"argent--border\" : \"argent--fill\", border && revealOnHover && \"argent--reveal\", \"argent--sheen\", !!halo && \"argent--halo\", \"argent-btn\", `argent-btn--${size}`, className)}\n data-tone={tone}\n style={buildVars(radius ?? SIZE_RADIUS[size], borderWidth, halo, style)}\n {...rest}\n >\n <span className=\"argent-fill\" aria-hidden=\"true\">\n <MetalFill tone={tone} speed={speed} engine={engine} finish={finish} effect={effect} angle={angle} />\n </span>\n {border && <span className=\"argent-core\" aria-hidden=\"true\" />}\n <span className=\"argent-sheen\" aria-hidden=\"true\" />\n <span className=\"argent-content argent-btn-label\">{children}</span>\n </button>\n );\n});\n","import { useEffect, useRef, useState } from \"react\";\nimport { LiquidMetal, type LiquidMetalParams } from \"@paper-design/shaders-react\";\nimport { mountMetal, NATIVE_TONES, type MetalEngine, type MetalMount, type NativeMetalParams } from \"./engine\";\n\n/**\n * The liquid-metal surface is Paper's `LiquidMetal` WebGL shader\n * (@paper-design/shaders) run with `shape=\"none\"` so it fills the whole element\n * instead of painting a blob. Each tone is a tuned set of shader params; the\n * canvas sits behind the content and is clipped to the surface's radius.\n *\n * `@paper-design/shaders-react` is a peer dependency — install it alongside\n * `argentui`. It is licensed under PolyForm Shield by Paper.\n */\n\nexport type MetalTone = \"silver\" | \"gold\" | \"gunmetal\" | \"obsidian\";\n\ntype Tuned = Pick<\n LiquidMetalParams,\n \"colorBack\" | \"colorTint\" | \"repetition\" | \"softness\" | \"shiftRed\" | \"shiftBlue\" | \"distortion\" | \"contour\" | \"angle\"\n>;\n\nexport const TONE_PARAMS: Record<MetalTone, Tuned> = {\n silver: {\n colorBack: \"#a7abb1\", colorTint: \"#ffffff\",\n repetition: 3, softness: 0.18, shiftRed: 0.32, shiftBlue: 0.32, distortion: 0.14, contour: 0.55, angle: 68,\n },\n gold: {\n colorBack: \"#94700e\", colorTint: \"#ffedb0\",\n repetition: 3, softness: 0.2, shiftRed: 0.3, shiftBlue: 0.12, distortion: 0.13, contour: 0.5, angle: 68,\n },\n gunmetal: {\n colorBack: \"#33373d\", colorTint: \"#b2bac4\",\n repetition: 2.6, softness: 0.26, shiftRed: 0.22, shiftBlue: 0.32, distortion: 0.1, contour: 0.45, angle: 80,\n },\n obsidian: {\n colorBack: \"#000000\", colorTint: \"#9498a6\",\n repetition: 2, softness: 0.4, shiftRed: 0.14, shiftBlue: 0.24, distortion: 0.07, contour: 0.32, angle: 92,\n },\n};\n\n// Paper's image pre-processing misbehaves when several image-mask shaders\n// initialise at once (only one survives) — serialise mounts a beat apart.\nlet imageMountQueue: Promise<void> = Promise.resolve();\nexport function useStaggeredMount(): boolean {\n const [go, setGo] = useState(false);\n useEffect(() => {\n let alive = true;\n imageMountQueue = imageMountQueue.then(async () => {\n if (!alive) return; // unmounted while queued — release the queue instantly\n setGo(true);\n await new Promise((r) => setTimeout(r, 300));\n });\n return () => {\n alive = false;\n };\n }, []);\n return go;\n}\n\n/** True once mounted on the client — the WebGL canvas can't render during SSR. */\nexport function useMounted(): boolean {\n const [m, setM] = useState(false);\n useEffect(() => setM(true), []);\n return m;\n}\n\n/** True when the user prefers reduced motion — the metal freezes (speed 0). */\nexport function useReducedMotion(): boolean {\n const [reduced, setReduced] = useState(false);\n useEffect(() => {\n const mq = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n setReduced(mq.matches);\n const onChange = (e: MediaQueryListEvent) => setReduced(e.matches);\n mq.addEventListener(\"change\", onChange);\n return () => mq.removeEventListener(\"change\", onChange);\n }, []);\n return reduced;\n}\n\n/**\n * Reports whether `ref` is on/near screen. Each metal surface is a WebGL\n * canvas, and browsers cap concurrent contexts (~16) — so we only mount the\n * shader while it's visible and release the context when it scrolls away.\n */\nexport function useInView(ref: React.RefObject<Element | null>, margin = \"250px\"): boolean {\n const [inView, setInView] = useState(false);\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const io = new IntersectionObserver(([entry]) => setInView(entry.isIntersecting), { rootMargin: margin });\n io.observe(el);\n return () => io.disconnect();\n }, [ref, margin]);\n return inView;\n}\n\n/**\n * Finishes — shader presets tuned to the shape and size of the element. One\n * pattern does not fit all: a card wants broad flowing bands, a thin progress\n * bar wants many stripes crossing it, a 22px toggle thumb wants one soft\n * highlight like a ball bearing, and a hairline badge rim wants dense bands so\n * a tiny visible slice always catches some light.\n */\nexport type MetalFinish = \"surface\" | \"button\" | \"bar\" | \"orb\" | \"rim\";\n\ninterface FinishTuning {\n /** Band direction override (deg). */\n angle?: number;\n /** Random per-mount angle variation (±deg) so identical elements don't look cloned. */\n angleJitter?: number;\n repetition?: number;\n softness?: number;\n distortion?: number;\n /** Multiplier on the tone's chromatic shift. */\n shift?: number;\n /** Default pattern scale. */\n scale?: number;\n /** Multiplier on the animation speed. */\n speed?: number;\n}\n\nexport const FINISHES: Record<MetalFinish, FinishTuning> = {\n /** Cards, nav, panels — broad flowing reflection bands (the tone defaults). */\n surface: { scale: 1.1 },\n /** Buttons — slightly spread, calmer warp so labels stay readable. */\n button: { scale: 1.4, distortion: 0.1 },\n /** Thin horizontal strips (progress) — near-vertical stripes crossing the bar. */\n bar: { angle: 14, repetition: 5, softness: 0.3, distortion: 0.06, shift: 0.5, scale: 0.8, speed: 0.75 },\n /** Small round things (toggle thumbs) — one soft highlight, like a polished sphere. */\n orb: { angle: 112, angleJitter: 20, repetition: 1.7, softness: 0.5, distortion: 0.05, shift: 0.4, scale: 1.5 },\n /** Hairline edges (badges, thin borders) — dense bands so any slice sparkles. */\n rim: { angle: 40, repetition: 4.5, softness: 0.3, distortion: 0.08, shift: 0.5, scale: 0.85, speed: 0.85 },\n};\n\n/**\n * Effects — the character of the liquid's motion, independent of tone and\n * finish: how soft the bands are, how hard the noise churns them, how fast\n * everything moves.\n */\nexport type MetalEffect = \"flow\" | \"molten\" | \"ripple\" | \"chrome\" | \"wave\";\n\ninterface EffectTuning {\n angle?: number;\n repetition?: number;\n softness?: number;\n distortion?: number;\n /** Multiplier on chromatic shift. */\n shift?: number;\n /** Multiplier on animation speed. */\n speed?: number;\n}\n\nexport const EFFECTS: Record<MetalEffect, EffectTuning> = {\n /** The default — steady flowing reflection bands. */\n flow: {},\n /** Slow, heavy, half-melted — soft wide bands churning lazily. */\n molten: { softness: 0.5, distortion: 0.3, speed: 0.45, shift: 0.6 },\n /** Agitated surface — tighter bands, hard noise, quick motion. */\n ripple: { repetition: 4, softness: 0.24, distortion: 0.5, speed: 1.4 },\n /** Mirror-polished — crisp hard bands, strong chromatic fringe, calm. */\n chrome: { softness: 0.05, distortion: 0.05, shift: 1.6, speed: 0.8 },\n /** Horizontal swells rolling through the surface. */\n wave: { angle: 0, repetition: 5, softness: 0.36, distortion: 0.18, speed: 0.7 },\n};\n\nexport interface MetalFillProps {\n tone: MetalTone;\n /** Shader animation speed (0 pauses). */\n speed?: number;\n /** Pattern scale — higher spreads the bands out. Defaults per finish. */\n scale?: number;\n /** `\"paper\"` (Paper's LiquidMetal, default) or `\"native\"` (Argent's own shader). */\n engine?: MetalEngine;\n /** Shape-tuned shader preset. Defaults to `\"surface\"`. */\n finish?: MetalFinish;\n /** Motion character preset. Defaults to `\"flow\"`. */\n effect?: MetalEffect;\n /** Band direction in degrees — overrides the tone/finish default. */\n angle?: number;\n}\n\nconst FILL_STYLE: React.CSSProperties = { position: \"absolute\", inset: 0, width: \"100%\", height: \"100%\" };\n\n/** Argent's own clean-room shader on a plain canvas. */\nfunction NativeCanvas({ params }: { params: NativeMetalParams }) {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const mountRef = useRef<MetalMount | null>(null);\n const initial = useRef(params);\n initial.current = params;\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n mountRef.current = mountMetal(canvas, initial.current);\n return () => {\n mountRef.current?.destroy();\n mountRef.current = null;\n };\n }, []);\n useEffect(() => {\n mountRef.current?.update(params);\n }, [params]);\n return <canvas ref={canvasRef} style={{ ...FILL_STYLE, display: \"block\" }} />;\n}\n\n/** The shader canvas, absolutely filling its positioned parent (when in view). */\nexport function MetalFill({ tone, speed = 1, scale, engine = \"paper\", finish = \"surface\", effect = \"flow\", angle }: MetalFillProps) {\n const ref = useRef<HTMLSpanElement>(null);\n const mounted = useMounted();\n const inView = useInView(ref);\n const reduced = useReducedMotion();\n const f = FINISHES[finish];\n const e = EFFECTS[effect];\n const [jitter] = useState(() => (f.angleJitter ? (Math.random() * 2 - 1) * f.angleJitter : 0));\n\n const base = TONE_PARAMS[tone];\n // precedence: explicit prop > effect > finish > tone\n const effAngle = (angle ?? e.angle ?? f.angle ?? base.angle ?? 70) + jitter;\n const effScale = scale ?? f.scale ?? 1.1;\n const effSpeed = (reduced ? 0 : speed) * (f.speed ?? 1) * (e.speed ?? 1);\n const shift = (f.shift ?? 1) * (e.shift ?? 1);\n const repetition = e.repetition ?? f.repetition ?? base.repetition;\n const softness = e.softness ?? f.softness ?? base.softness;\n const distortion = e.distortion ?? f.distortion ?? base.distortion;\n\n const native = NATIVE_TONES[tone];\n const nativeParams: NativeMetalParams = {\n ...native,\n angle: effAngle,\n repetition: repetition ?? native.repetition,\n softness: softness ?? native.softness,\n // the native warp amount runs ~3× paper's distortion scale\n distortion: distortion !== undefined ? distortion * 3 : native.distortion,\n dispersion: native.dispersion * shift,\n speed: effSpeed,\n scale: effScale,\n };\n\n return (\n <span ref={ref} aria-hidden=\"true\" style={{ position: \"absolute\", inset: 0 }}>\n {mounted && inView && (\n engine === \"native\" ? (\n <NativeCanvas params={nativeParams} />\n ) : (\n <LiquidMetal\n shape=\"none\"\n fit=\"cover\"\n scale={effScale}\n speed={effSpeed}\n {...base}\n angle={effAngle}\n repetition={repetition}\n softness={softness}\n distortion={distortion}\n shiftRed={(base.shiftRed ?? 0.3) * shift}\n shiftBlue={(base.shiftBlue ?? 0.3) * shift}\n style={FILL_STYLE}\n />\n )\n )}\n </span>\n );\n}\n","/**\n * Argent's own liquid-metal shader — a clean-room WebGL2 implementation of the\n * classic recipe: hard light→dark reflection banding, curvature-warped UVs,\n * time-driven simplex-noise flow, per-channel chromatic dispersion, and a rim\n * lift. No third-party shader code beyond the public-domain-style simplex\n * noise (Ashima Arts / Stefan Gustavson, MIT).\n *\n * Used when a surface sets `engine=\"native\"`; removes the need for\n * @paper-design/shaders-react entirely.\n */\n\nexport interface NativeMetalParams {\n /** Highlight band colour (hex). */\n light: string;\n /** Shadow band colour (hex). */\n dark: string;\n /** Stripe density. */\n repetition: number;\n /** Band direction in degrees. */\n angle: number;\n /** Band edge softness 0–1. */\n softness: number;\n /** Per-channel band offset (chromatic dispersion). */\n dispersion: number;\n /** Noise warp amount. */\n distortion: number;\n /** Animation speed (0 = still). */\n speed: number;\n /** Pattern scale — higher spreads the bands out. */\n scale: number;\n}\n\nexport type MetalEngine = \"paper\" | \"native\";\n\nconst VERT = `#version 300 es\nvoid main() {\n vec2 pos = vec2(float((gl_VertexID << 1) & 2), float(gl_VertexID & 2));\n gl_Position = vec4(pos * 2.0 - 1.0, 0.0, 1.0);\n}`;\n\nconst FRAG = `#version 300 es\nprecision highp float;\nuniform vec2 u_res;\nuniform float u_time;\nuniform vec3 u_light;\nuniform vec3 u_dark;\nuniform float u_rep;\nuniform float u_angle;\nuniform float u_soft;\nuniform float u_disp;\nuniform float u_dist;\nuniform float u_scale;\nout vec4 outColor;\n\n// 2D simplex noise — Ashima Arts / Stefan Gustavson (webgl-noise, MIT).\nvec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }\nvec2 mod289(vec2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }\nvec3 permute(vec3 x) { return mod289(((x * 34.0) + 1.0) * x); }\nfloat snoise(vec2 v) {\n const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439);\n vec2 i = floor(v + dot(v, C.yy));\n vec2 x0 = v - i + dot(i, C.xx);\n vec2 i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);\n vec4 x12 = x0.xyxy + C.xxzz;\n x12.xy -= i1;\n i = mod289(i);\n vec3 p = permute(permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0, i1.x, 1.0));\n vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0);\n m = m * m;\n m = m * m;\n vec3 x = 2.0 * fract(p * C.www) - 1.0;\n vec3 h = abs(x) - 0.5;\n vec3 ox = floor(x + 0.5);\n vec3 a0 = x - ox;\n m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);\n vec3 g;\n g.x = a0.x * x0.x + h.x * x0.y;\n g.yz = a0.yz * x12.xz + h.yz * x12.yw;\n return 130.0 * dot(m, g);\n}\n\n// One reflection band: a soft triangle wave over the warped coordinate.\nfloat stripe(float coord) {\n float f = fract(coord);\n float tri = abs(f * 2.0 - 1.0);\n return smoothstep(0.5 - u_soft, 0.5 + u_soft, tri);\n}\n\nvoid main() {\n vec2 uv = (gl_FragCoord.xy / u_res - 0.5);\n uv.x *= u_res.x / u_res.y;\n uv /= max(u_scale, 0.001);\n\n float t = u_time;\n\n // curvature: bands bend as if wrapping a bulged surface\n float d = length(uv);\n float bulge = 1.0 - 0.45 * d * d;\n\n // flowing warp — two noise octaves drifting at different rates\n float n = snoise(uv * 0.9 + vec2(0.0, -t * 0.28));\n n += 0.35 * snoise(uv * 1.8 + vec2(t * 0.1, -t * 0.45));\n\n // rotate so bands run along u_angle\n float c = cos(u_angle), s = sin(u_angle);\n vec2 ruv = mat2(c, -s, s, c) * uv;\n\n float coord = ruv.y * bulge * u_rep + n * u_dist * 2.2 - t * 0.22;\n\n // per-channel dispersion — the chrome fringing\n float r = stripe(coord + u_disp);\n float g = stripe(coord);\n float b = stripe(coord - u_disp);\n\n vec3 col = vec3(\n mix(u_dark.r, u_light.r, r),\n mix(u_dark.g, u_light.g, g),\n mix(u_dark.b, u_light.b, b)\n );\n\n // rim lift toward the edges\n col *= 0.94 + 0.14 * smoothstep(0.25, 0.85, d);\n\n outColor = vec4(col, 1.0);\n}`;\n\nfunction hexToRgb(hex: string): [number, number, number] {\n const h = hex.replace(\"#\", \"\");\n const v = h.length === 3 ? h.split(\"\").map((ch) => ch + ch).join(\"\") : h;\n const n = parseInt(v, 16);\n return [((n >> 16) & 255) / 255, ((n >> 8) & 255) / 255, (n & 255) / 255];\n}\n\nexport const NATIVE_TONES: Record<string, Omit<NativeMetalParams, \"speed\" | \"scale\">> = {\n silver: { light: \"#f8fafc\", dark: \"#23262b\", repetition: 1.8, angle: 68, softness: 0.34, dispersion: 0.03, distortion: 0.38 },\n gold: { light: \"#ffe9a8\", dark: \"#6e5408\", repetition: 1.8, angle: 68, softness: 0.34, dispersion: 0.028, distortion: 0.36 },\n gunmetal: { light: \"#b6bec9\", dark: \"#14161a\", repetition: 1.6, angle: 80, softness: 0.36, dispersion: 0.025, distortion: 0.34 },\n obsidian: { light: \"#787c88\", dark: \"#000000\", repetition: 1.4, angle: 92, softness: 0.42, dispersion: 0.02, distortion: 0.28 },\n};\n\nexport interface MetalMount {\n update(params: Partial<NativeMetalParams>): void;\n destroy(): void;\n}\n\nfunction compile(gl: WebGL2RenderingContext, type: number, src: string): WebGLShader | null {\n const sh = gl.createShader(type);\n if (!sh) return null;\n gl.shaderSource(sh, src);\n gl.compileShader(sh);\n if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {\n console.error(\"argent shader:\", gl.getShaderInfoLog(sh));\n gl.deleteShader(sh);\n return null;\n }\n return sh;\n}\n\n/** Mount the native liquid-metal shader on a canvas. Returns null without WebGL2. */\nexport function mountMetal(canvas: HTMLCanvasElement, params: NativeMetalParams): MetalMount | null {\n const gl = canvas.getContext(\"webgl2\", { antialias: true });\n if (!gl) return null;\n\n const vs = compile(gl, gl.VERTEX_SHADER, VERT);\n const fs = compile(gl, gl.FRAGMENT_SHADER, FRAG);\n if (!vs || !fs) return null;\n const prog = gl.createProgram()!;\n gl.attachShader(prog, vs);\n gl.attachShader(prog, fs);\n gl.linkProgram(prog);\n if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) {\n console.error(\"argent shader link:\", gl.getProgramInfoLog(prog));\n return null;\n }\n gl.useProgram(prog);\n\n const U = (name: string) => gl.getUniformLocation(prog, name);\n const uRes = U(\"u_res\"), uTime = U(\"u_time\"), uLight = U(\"u_light\"), uDark = U(\"u_dark\");\n const uRep = U(\"u_rep\"), uAngle = U(\"u_angle\"), uSoft = U(\"u_soft\");\n const uDisp = U(\"u_disp\"), uDist = U(\"u_dist\"), uScale = U(\"u_scale\");\n\n let p = { ...params };\n let raf = 0;\n let tAcc = Math.random() * 40; // desync multiple surfaces\n let last = performance.now();\n let dead = false;\n\n function draw() {\n raf = 0;\n if (dead) return;\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n const w = Math.max(1, Math.round(canvas.clientWidth * dpr));\n const h = Math.max(1, Math.round(canvas.clientHeight * dpr));\n if (canvas.width !== w || canvas.height !== h) {\n canvas.width = w;\n canvas.height = h;\n gl!.viewport(0, 0, w, h);\n }\n const now = performance.now();\n tAcc += ((now - last) / 1000) * p.speed;\n last = now;\n\n gl!.uniform2f(uRes, w, h);\n gl!.uniform1f(uTime, tAcc);\n gl!.uniform3fv(uLight, hexToRgb(p.light));\n gl!.uniform3fv(uDark, hexToRgb(p.dark));\n gl!.uniform1f(uRep, p.repetition);\n gl!.uniform1f(uAngle, (p.angle * Math.PI) / 180);\n gl!.uniform1f(uSoft, Math.max(0.02, p.softness));\n gl!.uniform1f(uDisp, p.dispersion);\n gl!.uniform1f(uDist, p.distortion);\n gl!.uniform1f(uScale, p.scale);\n gl!.drawArrays(gl!.TRIANGLES, 0, 3);\n\n if (p.speed > 0) raf = requestAnimationFrame(draw);\n }\n draw();\n\n return {\n update(np) {\n p = { ...p, ...np };\n last = performance.now();\n if (!raf) raf = requestAnimationFrame(draw);\n },\n destroy() {\n dead = true;\n if (raf) cancelAnimationFrame(raf);\n gl.getExtension(\"WEBGL_lose_context\")?.loseContext();\n },\n };\n}\n","/**\n * Tiny haptics for metal presses — `navigator.vibrate` where available\n * (Android Chrome; iOS Safari ignores it). On by default, like Glacé.\n */\n\nlet enabled = true;\n\n/** Globally enable/disable Argent haptics. */\nexport function setHaptics(on: boolean) {\n enabled = on;\n}\n\nexport function vibrate(pattern: number | number[]) {\n if (!enabled || typeof navigator === \"undefined\" || !(\"vibrate\" in navigator)) return;\n try {\n navigator.vibrate(pattern);\n } catch {\n // some browsers throw on vibrate without user activation — fine to ignore\n }\n}\n\n/** The stamped-press click. */\nexport const PRESS_PATTERN = 8;\n","import { forwardRef, useState } from \"react\";\nimport { MetalFill, type MetalTone } from \"./metal\";\nimport { Metal, type MetalProps } from \"./surfaces\";\nimport { PRESS_PATTERN, vibrate } from \"./haptics\";\n\nexport interface MetalToggleProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onChange\"> {\n tone?: MetalTone;\n checked?: boolean;\n defaultChecked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n /** Vibrate on toggle where supported. Defaults to `true`. */\n haptics?: boolean;\n}\n\n/**\n * A mercury switch — the thumb is a drop of liquid metal that slides (and\n * squishes) across a dark channel.\n */\nexport const MetalToggle = forwardRef<HTMLButtonElement, MetalToggleProps>(function MetalToggle(\n { tone = \"silver\", checked, defaultChecked = false, onCheckedChange, haptics = true, className, onClick, ...rest },\n ref,\n) {\n const [internal, setInternal] = useState(defaultChecked);\n const isOn = checked ?? internal;\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"switch\"\n aria-checked={isOn}\n data-tone={tone}\n data-checked={isOn || undefined}\n className={[\"argent-toggle\", className].filter(Boolean).join(\" \")}\n onClick={(e) => {\n if (haptics) vibrate(PRESS_PATTERN);\n if (checked === undefined) setInternal(!isOn);\n onCheckedChange?.(!isOn);\n onClick?.(e);\n }}\n {...rest}\n >\n <span className=\"argent-toggle-thumb\" aria-hidden=\"true\">\n <MetalFill tone={tone} finish=\"orb\" />\n </span>\n </button>\n );\n});\n\nexport interface MetalProgressProps extends React.HTMLAttributes<HTMLDivElement> {\n tone?: MetalTone;\n /** 0–100. Omit for an indeterminate molten sweep. */\n value?: number;\n /** Track height in px. */\n height?: number;\n}\n\n/** A molten progress bar — liquid metal rising in a dark channel. */\nexport const MetalProgress = forwardRef<HTMLDivElement, MetalProgressProps>(function MetalProgress(\n { tone = \"silver\", value, height = 10, className, style, ...rest },\n ref,\n) {\n const indeterminate = value === undefined;\n const clamped = indeterminate ? 0 : Math.max(0, Math.min(100, value));\n return (\n <div\n ref={ref}\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={indeterminate ? undefined : clamped}\n data-tone={tone}\n className={[\"argent-progress\", indeterminate && \"argent-progress--indeterminate\", className].filter(Boolean).join(\" \")}\n style={{ height, ...style }}\n {...rest}\n >\n <span\n className=\"argent-progress-fill\"\n style={indeterminate ? undefined : { width: `${clamped}%` }}\n aria-hidden=\"true\"\n >\n <MetalFill tone={tone} finish=\"bar\" />\n </span>\n </div>\n );\n});\n\nexport interface MetalBadgeProps extends Omit<MetalProps, \"as\" | \"variant\"> {}\n\n/** A small liquid-metal pill — a metal rim around a quiet label. */\nexport const MetalBadge = forwardRef<HTMLElement, MetalBadgeProps>(function MetalBadge(\n { className, radius = 999, borderWidth = 1, finish = \"rim\", ...rest },\n ref,\n) {\n return (\n <Metal\n ref={ref}\n as=\"span\"\n variant=\"border\"\n radius={radius}\n borderWidth={borderWidth}\n finish={finish}\n className={[\"argent-badge\", className].filter(Boolean).join(\" \")}\n {...rest}\n />\n );\n});\n","import { forwardRef, useEffect, useRef, useState } from \"react\";\nimport { LiquidMetal } from \"@paper-design/shaders-react\";\nimport { TONE_PARAMS, useInView, useMounted, useReducedMotion, useStaggeredMount, type MetalTone } from \"./metal\";\n\n/** Where the metal lives in shader text: the whole glyph, or just its edge. */\nexport type MetalTextVariant = \"fill\" | \"outline\";\n\nexport interface MetalTextProps extends React.HTMLAttributes<HTMLElement> {\n /** Element to render. Defaults to `span`. */\n as?: React.ElementType;\n tone?: MetalTone;\n /** Animate the highlight band across the glyphs (CSS mode). Defaults to `true`. */\n shimmer?: boolean;\n /**\n * Pour the real liquid-metal shader into the glyphs — flowing bands, liquid\n * edges, chromatic fringe. Costs a WebGL canvas; the CSS gradient renders as\n * a placeholder until the shader is ready, and stands in wherever WebGL\n * isn't. Children must be a plain string in this mode.\n */\n shader?: boolean;\n /**\n * Shader mode: `\"fill\"` (metal fills the glyphs, default) or `\"outline\"` —\n * the metal runs around the edge of each letterform and the interior takes\n * `fill` / `fillGradient`.\n */\n variant?: MetalTextVariant;\n /** Interior colour for `variant=\"outline\"`. */\n fill?: string;\n /** Interior vertical gradient `[top, bottom]` for `variant=\"outline\"` — wins over `fill`. */\n fillGradient?: [string, string];\n /** Metal edge thickness in px for `variant=\"outline\"`. Defaults to ~5% of the font size. */\n outlineWidth?: number;\n /** Type size in px (shader mode). Defaults to `64`. */\n fontSize?: number;\n /** Weight for the glyph silhouette (shader mode). Defaults to `800`. */\n fontWeight?: number;\n /**\n * Font for the silhouette (shader mode). Rendered inside an SVG image, which\n * sees system fonts only — to use a webfont, pass `fontCss` with a\n * data-URI @font-face for the same family.\n */\n fontFamily?: string;\n /**\n * Raw CSS embedded in the glyph SVG (shader mode) — typically a @font-face\n * whose `src` is a data: URI, which lets webfonts (e.g. Google Fonts) render\n * inside the silhouette. Load the same face into `document.fonts` so the\n * width measurement matches.\n */\n fontCss?: string;\n /** Shader animation speed (0 pauses). */\n speed?: number;\n}\n\nconst DEFAULT_STACK = \"-apple-system, 'Helvetica Neue', Helvetica, Arial, sans-serif\";\n\ninterface GlyphGeom {\n text: string;\n w: number;\n h: number;\n fontSize: number;\n fontWeight: number;\n fontFamily: string;\n fontCss?: string;\n}\n\nfunction svgOpen(g: GlyphGeom): string {\n const style = g.fontCss ? `<style>${g.fontCss}</style>` : \"\";\n return `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 ${g.w} ${g.h}' width='${g.w}' height='${g.h}'>${style}`;\n}\n\nfunction svgText(g: GlyphGeom, attrs: string): string {\n const safe = g.text.replace(/&/g, \"&\").replace(/</g, \"<\");\n return `<text x='50%' y='${Math.round(g.fontSize * 1.0)}' font-size='${g.fontSize}' font-family=\"${g.fontFamily.replace(/\"/g, \"'\")}\" font-weight='${g.fontWeight}' text-anchor='middle' ${attrs}>${safe}</text>`;\n}\n\nfunction encode(svg: string): string {\n return `data:image/svg+xml,${encodeURIComponent(svg)}`;\n}\n\n/** Solid glyphs — the shader fills the whole letterform. */\nfunction fillSilhouette(g: GlyphGeom): string {\n return encode(`${svgOpen(g)}${svgText(g, \"fill='#000'\")}</svg>`);\n}\n\n/** Stroke-only glyphs — the shader flows in a ring around each letterform. */\nfunction outlineSilhouette(g: GlyphGeom, ow: number): string {\n return encode(`${svgOpen(g)}${svgText(g, `fill='none' stroke='#000' stroke-width='${ow}' stroke-linejoin='round'`)}</svg>`);\n}\n\n/** The interior of outline text — flat or gradient fill, geometry-identical to the silhouette. */\nfunction interior(g: GlyphGeom, fill: string, gradient?: [string, string]): string {\n if (!gradient) return encode(`${svgOpen(g)}${svgText(g, `fill='${fill}'`)}</svg>`);\n const defs = `<defs><linearGradient id='g' x1='0' y1='0' x2='0' y2='1'><stop offset='0' stop-color='${gradient[0]}'/><stop offset='1' stop-color='${gradient[1]}'/></linearGradient></defs>`;\n return encode(`${svgOpen(g)}${defs}${svgText(g, \"fill='url(#g)'\")}</svg>`);\n}\n\nconst LAYER: React.CSSProperties = { position: \"absolute\", inset: 0, width: \"100%\", height: \"100%\" };\n\nfunction ShaderText({\n text,\n tone,\n variant,\n fill,\n fillGradient,\n outlineWidth,\n fontSize,\n fontWeight,\n fontFamily,\n fontCss,\n speed,\n shimmer,\n className,\n style,\n ...rest\n}: {\n text: string;\n tone: MetalTone;\n variant: MetalTextVariant;\n fill: string;\n fillGradient?: [string, string];\n outlineWidth?: number;\n fontSize: number;\n fontWeight: number;\n fontFamily: string;\n fontCss?: string;\n speed: number;\n shimmer: boolean;\n} & React.HTMLAttributes<HTMLElement>) {\n const ref = useRef<HTMLSpanElement>(null);\n const mounted = useMounted();\n const inView = useInView(ref);\n const reduced = useReducedMotion();\n const turn = useStaggeredMount();\n const [geom, setGeom] = useState<GlyphGeom | null>(null);\n\n const outlined = variant === \"outline\";\n const ow = outlineWidth ?? Math.max(2, Math.round(fontSize * 0.05));\n\n useEffect(() => {\n let alive = true;\n const fontSpec = `${fontWeight} ${fontSize}px ${fontFamily}`;\n const measure = () => {\n if (!alive) return;\n const ctx = document.createElement(\"canvas\").getContext(\"2d\");\n if (!ctx) return;\n ctx.font = fontSpec;\n const m = ctx.measureText(text);\n setGeom({\n text,\n w: Math.ceil(m.width + fontSize * 0.24 + ow * 2),\n h: Math.ceil(fontSize * 1.3 + ow),\n fontSize,\n fontWeight,\n fontFamily,\n fontCss,\n });\n };\n // wait for webfonts so the measured width matches the silhouette\n if (document.fonts?.load) document.fonts.load(fontSpec, text).then(measure, measure);\n else measure();\n return () => {\n alive = false;\n };\n }, [text, fontSize, fontWeight, fontFamily, fontCss, ow]);\n\n const ready = mounted && inView && turn && geom;\n const { colorBack: _drop, ...params } = TONE_PARAMS[tone];\n // a thin ring can't survive heavy edge distortion — calm it down for outlines\n const shaderParams = outlined ? { ...params, contour: 0.2, distortion: Math.min(params.distortion ?? 0.1, 0.08) } : params;\n\n return (\n <span\n ref={ref}\n role=\"img\"\n aria-label={text}\n className={className}\n style={{\n position: \"relative\",\n display: \"inline-block\",\n verticalAlign: \"middle\",\n width: geom?.w,\n height: geom?.h,\n ...style,\n }}\n {...rest}\n >\n {ready ? (\n <>\n {outlined && <img src={interior(geom, fill, fillGradient)} alt=\"\" aria-hidden=\"true\" style={LAYER} />}\n <LiquidMetal\n // keyed by silhouette: rapid prop changes can finish processing\n // out of order and leave stale glyphs — a clean re-init can't\n key={`${geom.text}|${geom.fontFamily}|${geom.w}|${outlined ? \"o\" : \"f\"}`}\n image={outlined ? outlineSilhouette(geom, ow) : fillSilhouette(geom)}\n suspendWhenProcessingImage={false}\n colorBack=\"#00000000\"\n fit=\"contain\"\n scale={0.97}\n speed={reduced ? 0 : speed}\n {...shaderParams}\n style={LAYER}\n />\n </>\n ) : (\n // CSS chrome stands in until the shader is ready (and during SSR)\n <span\n aria-hidden=\"true\"\n className={[\"argent-text\", shimmer && !outlined && \"argent-text--shimmer\"].filter(Boolean).join(\" \")}\n data-tone={tone}\n style={{\n fontSize,\n fontWeight,\n fontFamily,\n lineHeight: 1.3,\n whiteSpace: \"nowrap\",\n ...(outlined && {\n background: \"none\",\n WebkitTextFillColor: fillGradient?.[0] ?? fill,\n color: fillGradient?.[0] ?? fill,\n WebkitTextStroke: \"1px rgba(220, 224, 230, 0.55)\",\n }),\n }}\n >\n {text}\n </span>\n )}\n </span>\n );\n}\n\n/**\n * Metal type. By default a chrome gradient clipped to the glyphs with a flowing\n * shimmer — pure CSS, use it freely at any scale. Pass `shader` to pour the\n * real liquid-metal shader into the letterforms — `variant=\"fill\"` floods the\n * glyphs; `variant=\"outline\"` runs the metal around their edges over a dark or\n * gradient interior.\n */\nexport const MetalText = forwardRef<HTMLElement, MetalTextProps>(function MetalText(\n {\n as,\n tone = \"silver\",\n shimmer = true,\n shader = false,\n variant = \"fill\",\n fill = \"#101114\",\n fillGradient,\n outlineWidth,\n fontSize = 64,\n fontWeight = 800,\n fontFamily = DEFAULT_STACK,\n fontCss,\n speed = 1,\n className,\n children,\n ...rest\n },\n ref,\n) {\n if (shader) {\n return (\n <ShaderText\n text={String(children)}\n tone={tone}\n variant={variant}\n fill={fill}\n fillGradient={fillGradient}\n outlineWidth={outlineWidth}\n fontSize={fontSize}\n fontWeight={fontWeight}\n fontFamily={fontFamily}\n fontCss={fontCss}\n speed={speed}\n shimmer={shimmer}\n className={className}\n {...rest}\n />\n );\n }\n const Tag = (as ?? \"span\") as React.ElementType;\n return (\n <Tag\n ref={ref}\n className={[\"argent-text\", shimmer && \"argent-text--shimmer\", className].filter(Boolean).join(\" \")}\n data-tone={tone}\n {...rest}\n >\n {children}\n </Tag>\n );\n});\n","import { useRef } from \"react\";\nimport { LiquidMetal } from \"@paper-design/shaders-react\";\nimport { TONE_PARAMS, useInView, useMounted, useReducedMotion, useStaggeredMount, type MetalTone } from \"./metal\";\n\nexport interface MetalLogoProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Image URL (or data URI) with a transparent background — the metal flows inside its silhouette. */\n src: string;\n tone?: MetalTone;\n /** Rendered size in px (square by default). */\n size?: number;\n width?: number;\n height?: number;\n /** Shader animation speed (0 pauses). */\n speed?: number;\n}\n\n/**\n * Liquid metal poured into a logo — pass any image with a transparent\n * background and the metal flows inside its silhouette. The classic\n * liquid-metal treatment for marks, monograms, and icons.\n */\nexport function MetalLogo({ src, tone = \"silver\", size = 160, width, height, speed = 1, style, ...rest }: MetalLogoProps) {\n const ref = useRef<HTMLDivElement>(null);\n const mounted = useMounted();\n const inView = useInView(ref);\n const reduced = useReducedMotion();\n const turn = useStaggeredMount();\n const w = width ?? size;\n const h = height ?? size;\n const { colorBack: _drop, ...params } = TONE_PARAMS[tone];\n return (\n <div ref={ref} style={{ position: \"relative\", width: w, height: h, ...style }} {...rest}>\n {mounted && inView && turn && (\n <LiquidMetal\n key={src}\n image={src}\n suspendWhenProcessingImage={false}\n colorBack=\"#00000000\"\n fit=\"contain\"\n scale={0.92}\n speed={reduced ? 0 : speed}\n {...params}\n style={{ position: \"absolute\", inset: 0, width: \"100%\", height: \"100%\" }}\n />\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["jsx","Metal","MetalCard","MetalButton","forwardRef","useState","jsx","forwardRef","MetalToggle","useState","MetalProgress","MetalBadge","forwardRef","useEffect","useRef","useState","LiquidMetal","jsx","jsxs","useRef","useState","useEffect","LiquidMetal","forwardRef","MetalText","useRef","LiquidMetal","jsx","useRef","LiquidMetal"]}
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/* Argent — liquid-metal UI. One stylesheet, themeable via CSS variables. */
|
|
2
|
+
|
|
3
|
+
.argent {
|
|
4
|
+
position: relative;
|
|
5
|
+
isolation: isolate;
|
|
6
|
+
display: inline-block;
|
|
7
|
+
color: var(--argent-text);
|
|
8
|
+
border: 1px solid var(--argent-edge);
|
|
9
|
+
box-shadow: var(--argent-shadow);
|
|
10
|
+
font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* ── Finishes ─────────────────────────────────────────────────────────── */
|
|
14
|
+
.argent[data-tone="silver"], [data-tone="silver"] {
|
|
15
|
+
--argent-grad: linear-gradient(135deg, #ffffff 0%, #dfe3e8 15%, #a6acb5 35%, #34383e 50%, #b4bac2 64%, #eef1f4 82%, #ffffff 100%);
|
|
16
|
+
--argent-text: #1a1c20;
|
|
17
|
+
--argent-edge: rgba(255, 255, 255, 0.7);
|
|
18
|
+
--argent-shadow: 0 10px 30px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.9), inset 0 -2px 3px rgba(0, 0, 0, 0.22);
|
|
19
|
+
--argent-sheen: rgba(255, 255, 255, 0.85);
|
|
20
|
+
--argent-label-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
|
|
21
|
+
}
|
|
22
|
+
.argent[data-tone="gold"], [data-tone="gold"] {
|
|
23
|
+
--argent-grad: linear-gradient(135deg, #fff7d6 0%, #ffe08a 20%, #e3a812 44%, #7c5f12 52%, #e6c24e 68%, #ffe08a 86%, #fff7d6 100%);
|
|
24
|
+
--argent-text: #3a2c05;
|
|
25
|
+
--argent-edge: rgba(255, 240, 200, 0.7);
|
|
26
|
+
--argent-shadow: 0 10px 30px rgba(60, 40, 0, 0.4), inset 0 1px 0 rgba(255, 248, 220, 0.9), inset 0 -2px 3px rgba(70, 50, 0, 0.3);
|
|
27
|
+
--argent-sheen: rgba(255, 250, 220, 0.85);
|
|
28
|
+
--argent-label-shadow: 0 1px 0 rgba(255, 245, 200, 0.5);
|
|
29
|
+
}
|
|
30
|
+
.argent[data-tone="gunmetal"], [data-tone="gunmetal"] {
|
|
31
|
+
--argent-grad: linear-gradient(135deg, #9aa0aa 0%, #6b7079 18%, #2c2f36 46%, #16181c 54%, #3a3e46 70%, #7a808a 90%, #aab0ba 100%);
|
|
32
|
+
--argent-text: #f0f2f5;
|
|
33
|
+
--argent-edge: rgba(255, 255, 255, 0.16);
|
|
34
|
+
--argent-shadow: 0 12px 34px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.18), inset 0 -2px 3px rgba(0, 0, 0, 0.5);
|
|
35
|
+
--argent-sheen: rgba(255, 255, 255, 0.55);
|
|
36
|
+
--argent-label-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
|
|
37
|
+
}
|
|
38
|
+
.argent[data-tone="obsidian"], [data-tone="obsidian"] {
|
|
39
|
+
--argent-grad: linear-gradient(135deg, #4a4e56 0%, #2a2d33 20%, #0b0c0f 48%, #000000 56%, #23262c 72%, #44484f 92%, #5a5f68 100%);
|
|
40
|
+
--argent-text: #eef0f3;
|
|
41
|
+
--argent-edge: rgba(255, 255, 255, 0.12);
|
|
42
|
+
--argent-shadow: 0 14px 36px rgba(0, 0, 0, 0.65), inset 0 1px 0 rgba(255, 255, 255, 0.12), inset 0 -2px 4px rgba(0, 0, 0, 0.6);
|
|
43
|
+
--argent-sheen: rgba(200, 210, 255, 0.5);
|
|
44
|
+
--argent-label-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* ── The flowing metal fill (Paper LiquidMetal shader canvas) ─────────── */
|
|
48
|
+
.argent-fill {
|
|
49
|
+
position: absolute;
|
|
50
|
+
inset: 0;
|
|
51
|
+
z-index: 0;
|
|
52
|
+
border-radius: inherit;
|
|
53
|
+
overflow: hidden;
|
|
54
|
+
background: var(--argent-grad); /* shown until the shader canvas mounts */
|
|
55
|
+
}
|
|
56
|
+
.argent-fill canvas { display: block; width: 100% !important; height: 100% !important; }
|
|
57
|
+
|
|
58
|
+
/* Border variant: a panel covers the centre, leaving the metal as an edge.
|
|
59
|
+
--argent-panel is the interior colour; theme it to your surface. */
|
|
60
|
+
.argent-core {
|
|
61
|
+
position: absolute;
|
|
62
|
+
inset: var(--argent-bw, 1.5px);
|
|
63
|
+
z-index: 1;
|
|
64
|
+
border-radius: inherit;
|
|
65
|
+
background: var(--argent-panel, #0d0e11);
|
|
66
|
+
transition: opacity 0.4s ease;
|
|
67
|
+
}
|
|
68
|
+
.argent--reveal:hover .argent-core { opacity: 0; }
|
|
69
|
+
|
|
70
|
+
/* In border mode the metal ring is the border, and content sits on the panel. */
|
|
71
|
+
.argent--border { border-color: transparent; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.32); }
|
|
72
|
+
.argent--border > .argent-content { color: var(--argent-panel-text, #f1f2f4); }
|
|
73
|
+
|
|
74
|
+
/* Tint: let the metal show faintly through the interior panel. */
|
|
75
|
+
.argent--tint .argent-core {
|
|
76
|
+
background: color-mix(in srgb, var(--argent-panel, #0d0e11) 70%, transparent);
|
|
77
|
+
backdrop-filter: saturate(120%) brightness(0.7);
|
|
78
|
+
-webkit-backdrop-filter: saturate(120%) brightness(0.7);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* Double frame: an inner hairline frame inset from the metal rim, with a gap. */
|
|
82
|
+
.argent--double .argent-core::after {
|
|
83
|
+
content: "";
|
|
84
|
+
position: absolute;
|
|
85
|
+
inset: var(--argent-gap, 5px);
|
|
86
|
+
z-index: 2;
|
|
87
|
+
border-radius: inherit;
|
|
88
|
+
border: 1px solid var(--argent-edge, rgba(255, 255, 255, 0.5));
|
|
89
|
+
opacity: 0.7;
|
|
90
|
+
pointer-events: none;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* ── Halo: frosted standoff ring outside the metal ───────────────────── */
|
|
94
|
+
.argent--halo::before {
|
|
95
|
+
content: "";
|
|
96
|
+
position: absolute;
|
|
97
|
+
inset: calc(-1 * var(--argent-halo, 8px));
|
|
98
|
+
z-index: -1;
|
|
99
|
+
border-radius: calc(var(--argent-radius, 14px) + var(--argent-halo, 8px));
|
|
100
|
+
background: rgba(255, 255, 255, 0.02);
|
|
101
|
+
-webkit-backdrop-filter: blur(10px) saturate(120%);
|
|
102
|
+
backdrop-filter: blur(10px) saturate(120%);
|
|
103
|
+
border: 1px solid var(--argent-halo-line, rgba(255, 255, 255, 0.05));
|
|
104
|
+
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
|
|
105
|
+
pointer-events: none;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* ── Specular sheen sweep ─────────────────────────────────────────────── */
|
|
109
|
+
.argent-sheen {
|
|
110
|
+
position: absolute;
|
|
111
|
+
inset: 0;
|
|
112
|
+
z-index: 1;
|
|
113
|
+
border-radius: inherit;
|
|
114
|
+
pointer-events: none;
|
|
115
|
+
background: linear-gradient(110deg, transparent 36%, var(--argent-sheen) 50%, transparent 64%);
|
|
116
|
+
background-size: 260% 100%;
|
|
117
|
+
background-position: -60% 0;
|
|
118
|
+
background-repeat: no-repeat;
|
|
119
|
+
opacity: 0;
|
|
120
|
+
mix-blend-mode: screen;
|
|
121
|
+
transition: background-position 0.6s ease, opacity 0.3s ease;
|
|
122
|
+
}
|
|
123
|
+
.argent--sheen:hover .argent-sheen { background-position: 160% 0; opacity: 0.95; }
|
|
124
|
+
|
|
125
|
+
/* ── Content sits above the metal ─────────────────────────────────────── */
|
|
126
|
+
.argent-content { position: relative; z-index: 2; display: block; }
|
|
127
|
+
|
|
128
|
+
@media (prefers-reduced-motion: reduce) {
|
|
129
|
+
.argent-fill { animation: none; }
|
|
130
|
+
.argent-sheen { transition: opacity 0.2s ease; }
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* ── Card ─────────────────────────────────────────────────────────────── */
|
|
134
|
+
.argent-card { display: block; }
|
|
135
|
+
.argent-card > .argent-content { padding: 20px; }
|
|
136
|
+
|
|
137
|
+
/* ── Button ───────────────────────────────────────────────────────────── */
|
|
138
|
+
.argent-btn {
|
|
139
|
+
display: inline-flex;
|
|
140
|
+
cursor: pointer;
|
|
141
|
+
-webkit-user-select: none;
|
|
142
|
+
user-select: none;
|
|
143
|
+
transition: transform 0.14s cubic-bezier(0.34, 1.5, 0.5, 1), box-shadow 0.2s ease, filter 0.15s ease;
|
|
144
|
+
}
|
|
145
|
+
.argent-btn > .argent-content {
|
|
146
|
+
display: inline-flex;
|
|
147
|
+
align-items: center;
|
|
148
|
+
justify-content: center;
|
|
149
|
+
gap: 8px;
|
|
150
|
+
font-weight: 650;
|
|
151
|
+
letter-spacing: -0.01em;
|
|
152
|
+
}
|
|
153
|
+
/* Border button: light label on the dark pill. */
|
|
154
|
+
.argent-btn.argent--border > .argent-content {
|
|
155
|
+
color: var(--argent-panel-text, #f1f2f4);
|
|
156
|
+
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
|
|
157
|
+
}
|
|
158
|
+
/* Fill button: white label with a layered dark halo so it reads over any band. */
|
|
159
|
+
.argent-btn.argent--fill > .argent-content {
|
|
160
|
+
color: #ffffff;
|
|
161
|
+
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9), 0 0 10px rgba(0, 0, 0, 0.65);
|
|
162
|
+
}
|
|
163
|
+
.argent-btn--sm > .argent-content { padding: 8px 16px; font-size: 13px; }
|
|
164
|
+
.argent-btn--md > .argent-content { padding: 11px 22px; font-size: 14px; }
|
|
165
|
+
.argent-btn--lg > .argent-content { padding: 14px 28px; font-size: 16px; }
|
|
166
|
+
.argent-btn:hover { transform: translateY(-1px); filter: brightness(1.04); }
|
|
167
|
+
.argent-btn:active {
|
|
168
|
+
transform: translateY(1px) scale(0.99);
|
|
169
|
+
box-shadow: var(--argent-shadow), inset 0 3px 7px rgba(0, 0, 0, 0.42);
|
|
170
|
+
}
|
|
171
|
+
.argent-btn:focus-visible { outline: 2px solid var(--argent-edge); outline-offset: 2px; }
|
|
172
|
+
|
|
173
|
+
/* ── Chrome text ──────────────────────────────────────────────────────── */
|
|
174
|
+
.argent-text {
|
|
175
|
+
--argent-text-grad: linear-gradient(135deg, #ffffff 0%, #cdd2da 22%, #7e858f 42%, #3a3e44 50%, #aab0b9 60%, #f0f2f5 80%, #ffffff 100%);
|
|
176
|
+
background: var(--argent-text-grad);
|
|
177
|
+
background-size: 220% 220%;
|
|
178
|
+
background-position: 0% 50%;
|
|
179
|
+
-webkit-background-clip: text;
|
|
180
|
+
background-clip: text;
|
|
181
|
+
-webkit-text-fill-color: transparent;
|
|
182
|
+
color: transparent;
|
|
183
|
+
}
|
|
184
|
+
.argent-text[data-tone="gold"] {
|
|
185
|
+
--argent-text-grad: linear-gradient(135deg, #fff7d6 0%, #ffdf85 20%, #e0a912 42%, #8a6a10 50%, #e8c54e 62%, #ffe9a4 82%, #fff7d6 100%);
|
|
186
|
+
}
|
|
187
|
+
.argent-text[data-tone="gunmetal"] {
|
|
188
|
+
--argent-text-grad: linear-gradient(135deg, #c6ccd6 0%, #8a9098 22%, #3a3e46 46%, #21242a 54%, #585d66 68%, #a8aeb8 86%, #ccd2dc 100%);
|
|
189
|
+
}
|
|
190
|
+
.argent-text[data-tone="obsidian"] {
|
|
191
|
+
--argent-text-grad: linear-gradient(135deg, #9a9ca8 0%, #54565e 25%, #17181c 48%, #060608 56%, #3c3e46 72%, #84868f 92%, #a8aab4 100%);
|
|
192
|
+
}
|
|
193
|
+
.argent-text--shimmer { animation: argent-shimmer 7s linear infinite; }
|
|
194
|
+
@keyframes argent-shimmer {
|
|
195
|
+
to { background-position: 200% 50%; }
|
|
196
|
+
}
|
|
197
|
+
@media (prefers-reduced-motion: reduce) {
|
|
198
|
+
.argent-text--shimmer { animation: none; }
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/* ── Toggle (mercury switch) ──────────────────────────────────────────── */
|
|
202
|
+
.argent-toggle {
|
|
203
|
+
position: relative;
|
|
204
|
+
width: 50px;
|
|
205
|
+
height: 28px;
|
|
206
|
+
border-radius: 999px;
|
|
207
|
+
border: 1px solid rgba(255, 255, 255, 0.14);
|
|
208
|
+
background: var(--argent-panel, #0d0e11);
|
|
209
|
+
box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.55);
|
|
210
|
+
cursor: pointer;
|
|
211
|
+
padding: 0;
|
|
212
|
+
transition: border-color 0.25s ease, box-shadow 0.25s ease;
|
|
213
|
+
}
|
|
214
|
+
/* the channel floods with the tone's metal when on — unmistakable state */
|
|
215
|
+
.argent-toggle::before {
|
|
216
|
+
content: "";
|
|
217
|
+
position: absolute;
|
|
218
|
+
inset: 0;
|
|
219
|
+
border-radius: inherit;
|
|
220
|
+
background: var(--argent-grad);
|
|
221
|
+
opacity: 0;
|
|
222
|
+
transition: opacity 0.25s ease;
|
|
223
|
+
}
|
|
224
|
+
.argent-toggle[data-checked]::before { opacity: 0.45; }
|
|
225
|
+
.argent-toggle:hover { border-color: rgba(255, 255, 255, 0.28); }
|
|
226
|
+
.argent-toggle[data-checked] {
|
|
227
|
+
border-color: var(--argent-edge, rgba(255, 255, 255, 0.5));
|
|
228
|
+
box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.55), 0 0 14px -4px var(--argent-sheen, rgba(255, 255, 255, 0.5));
|
|
229
|
+
}
|
|
230
|
+
.argent-toggle-thumb {
|
|
231
|
+
z-index: 1;
|
|
232
|
+
position: absolute;
|
|
233
|
+
top: 2px;
|
|
234
|
+
left: 2px;
|
|
235
|
+
width: 22px;
|
|
236
|
+
height: 22px;
|
|
237
|
+
border-radius: 50%;
|
|
238
|
+
overflow: hidden;
|
|
239
|
+
transform: translateX(0);
|
|
240
|
+
transition: transform 0.26s cubic-bezier(0.34, 1.45, 0.55, 1);
|
|
241
|
+
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
|
|
242
|
+
background: var(--argent-grad);
|
|
243
|
+
}
|
|
244
|
+
.argent-toggle[data-checked] .argent-toggle-thumb { transform: translateX(22px); }
|
|
245
|
+
/* mercury squish while pressed */
|
|
246
|
+
.argent-toggle:active .argent-toggle-thumb { transform: translateX(0) scale(1.12, 0.9); }
|
|
247
|
+
.argent-toggle[data-checked]:active .argent-toggle-thumb { transform: translateX(22px) scale(1.12, 0.9); }
|
|
248
|
+
.argent-toggle:focus-visible { outline: 2px solid var(--argent-edge, rgba(255, 255, 255, 0.5)); outline-offset: 2px; }
|
|
249
|
+
.argent-toggle:disabled { opacity: 0.45; cursor: not-allowed; }
|
|
250
|
+
|
|
251
|
+
/* ── Progress (molten bar) ────────────────────────────────────────────── */
|
|
252
|
+
.argent-progress {
|
|
253
|
+
position: relative;
|
|
254
|
+
border-radius: 999px;
|
|
255
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
256
|
+
background: var(--argent-panel, #0d0e11);
|
|
257
|
+
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.5);
|
|
258
|
+
overflow: hidden;
|
|
259
|
+
}
|
|
260
|
+
.argent-progress-fill {
|
|
261
|
+
position: absolute;
|
|
262
|
+
top: 0;
|
|
263
|
+
bottom: 0;
|
|
264
|
+
left: 0;
|
|
265
|
+
border-radius: inherit;
|
|
266
|
+
overflow: hidden;
|
|
267
|
+
background: var(--argent-grad);
|
|
268
|
+
transition: width 0.45s cubic-bezier(0.33, 1, 0.68, 1);
|
|
269
|
+
}
|
|
270
|
+
.argent-progress--indeterminate .argent-progress-fill {
|
|
271
|
+
width: 36%;
|
|
272
|
+
animation: argent-sweep 1.5s ease-in-out infinite;
|
|
273
|
+
}
|
|
274
|
+
@keyframes argent-sweep {
|
|
275
|
+
from { left: -36%; }
|
|
276
|
+
to { left: 100%; }
|
|
277
|
+
}
|
|
278
|
+
@media (prefers-reduced-motion: reduce) {
|
|
279
|
+
.argent-progress--indeterminate .argent-progress-fill { animation-duration: 3s; }
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/* ── Badge ────────────────────────────────────────────────────────────── */
|
|
283
|
+
.argent-badge > .argent-content {
|
|
284
|
+
padding: 4px 12px;
|
|
285
|
+
font-size: 12px;
|
|
286
|
+
font-weight: 620;
|
|
287
|
+
letter-spacing: 0.01em;
|
|
288
|
+
white-space: nowrap;
|
|
289
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "argentui",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Argent — liquid-metal UI for React. Chrome, gold, and gunmetal surfaces that ripple like mercury, powered by Paper's LiquidMetal WebGL shader. A metal sibling to Glacé.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Sean Geng (https://seangeng.com)",
|
|
8
|
+
"homepage": "https://github.com/seangeng/argent#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/seangeng/argent.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": "https://github.com/seangeng/argent/issues",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"react",
|
|
16
|
+
"liquid-metal",
|
|
17
|
+
"metal",
|
|
18
|
+
"chrome",
|
|
19
|
+
"metallic",
|
|
20
|
+
"button",
|
|
21
|
+
"ui",
|
|
22
|
+
"webgl",
|
|
23
|
+
"shader",
|
|
24
|
+
"paper-shaders"
|
|
25
|
+
],
|
|
26
|
+
"sideEffects": [
|
|
27
|
+
"**/*.css"
|
|
28
|
+
],
|
|
29
|
+
"main": "./dist/index.cjs",
|
|
30
|
+
"module": "./dist/index.js",
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"import": "./dist/index.js",
|
|
36
|
+
"require": "./dist/index.cjs"
|
|
37
|
+
},
|
|
38
|
+
"./styles.css": "./dist/styles.css"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist"
|
|
42
|
+
],
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsup",
|
|
45
|
+
"dev": "tsup --watch",
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"prepublishOnly": "npm run build"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"react": ">=18",
|
|
51
|
+
"react-dom": ">=18",
|
|
52
|
+
"@paper-design/shaders-react": ">=0.0.40"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@paper-design/shaders-react": "^0.0.76",
|
|
56
|
+
"@types/react": "^18.3.12",
|
|
57
|
+
"@types/react-dom": "^18.3.1",
|
|
58
|
+
"react": "^18.3.1",
|
|
59
|
+
"react-dom": "^18.3.1",
|
|
60
|
+
"tsup": "^8.3.5",
|
|
61
|
+
"typescript": "^5.7.2"
|
|
62
|
+
}
|
|
63
|
+
}
|