/ component

Calc Editor

Edit a CSS math expression โ€” calc(), clamp(), min(), max(), nested โ€” with compile-time DIMENSIONAL ANALYSIS. length ยฑ length โœ“, length ยฑ angle โœ—, length ร— length โœ—, รท by non-number โœ—. The strict tier resolves invalid math to never.

/ basic-usage

Edit a calc value

Controlled value + onChange. The popover editor parses, dimension-checks, and only emits a valid CSS math string.

clamp(1rem, 0.5rem + 2vw, 3rem)
/ fluid-type playground

clamp() across the viewport

Drag the viewport slider and watch the computed font-size resolve live. This is fluid typography โ€” a single clamp() that scales between a min and max as the screen grows.

length
resolves to lengthโ‰ˆ 37.6px @ 1280px
Fluid-type playground34.4px
Fluid-type playground34.4px
computed font-size
320px
18.4px
768px
27.36px
1440px
40px

The quick brown fox

/ types

Three usage tiers

From useState-and-go to literal-validated dimensional algebra.

01 casual
string

Pass any string

useState<string>. No compile-time validation; the runtime parser handles whatever you type.

calc(100% - 2rem)
const [value, setValue] = useState<string>("calc(100% - 2rem)")
02 intellisense
CalcString

Literal-shaped hints

State typed as CalcString โ€” the calc() / clamp() / min() / max() union. Also the onChange return.

min(50%, 30rem)
const [value, setValue] = useState<CalcString>("min(50%, 30rem)")
03 strict
CalcLiteral<S>

Dimensional algebra at compile time

cssCalc() resolves invalid math to never. Mismatched units type- error before you ever run the code.

calc(10px + 2rem)
cssCalc("calc(10px + 2rem)") // โœ“ length
// @ts-expect-error length + angle
cssCalc("calc(10px + 45deg)")
// @ts-expect-error length ร— length
cssCalc("calc(10px * 2px)")

Note: var() is undecidable at compile time โ€” use the casual or IntelliSense tier for expressions containing it.

/ api

API

Public surface โ€” component props, runtime helpers, and the type exports.

ยง CalcEditor / CalcEditorPanel

<CalcEditor
  value: CalcString | (string & {})
  onChange: (next: CalcString) => void
  fn?: 'calc' | 'clamp' | 'min' | 'max'
  referenceViewport?: number
  className?: string
  aria-label?: string
/>

CalcEditor is popover-wrapped; CalcEditorPanel renders the same editor inline. Both are controlled.

PropTypeDescription
valueCalcString | (string & {})Current CSS math expression. Required.
onChange(next) => voidFires only when the edited expression is dimensionally valid. Return type narrows by `fn`.
fnCalcFn?Lock the outer function to calc/clamp/min/max. Narrows onChange to that flavor.
referenceViewportnumberViewport width (px) for the computed-value readout. Default 1280.

ยง Sub-components

<ExpressionField value onChange dimension? error? />

The text field + live validity/dimension badge.

<TokenPalette onInsert />

Click-to-insert operators, units, functions, and var().

<FluidTypePlayground expression minViewport? maxViewport? />

Viewport-width slider with a live computeCalc readout โ€” the clamp() showcase.

ยง Runtime helpers

cssCalc<S extends string>(value: S & CalcLiteral<S>): S

Call-site validator. Mirrors color() and easing().

parseCalc(src: string): CalcNode | null

String โ†’ AST, or null on any syntax error.

evaluateCalc(src: string): { node, dimension, error }

Parse + dimension-check facade the editor calls each keystroke.

calcDimension(node: CalcNode): Dimension | null

Resolve an AST to its dimension, or null on a unit conflict. var()-tolerant.

computeCalc(node, ctx): number | null

Numeric evaluation resolving px/rem/vw/% against a ComputeContext. Null when var() blocks it.

formatCalc(node: CalcNode): CalcString

Canonical re-serialization (normalized spacing).

tokenizeCalc(src: string): Token[]

Lexer โ€” numbers (with units), idents, operators, parens, commas.

ยง Types

CalcLiteral<S>
Strict validator โ€” S if dimensionally valid, else never.
CalcString
Suggestion union: calc()/clamp()/min()/max().
CalcStringMap / CalcFn
Function โ†’ output-string map for `fn` narrowing.
FunctionOf<S>
Outer function family of a literal.
DimensionOfCalc<S>
Resolved dimension of a literal at the type level.
ArgCountOf<S>
Top-level comma-argument count of the outer function.
CalcNode
Parse-tree discriminated union (exported for advanced use).

ยง Strict-tier scope

  • Full dimensional algebra: + - require equal dimensions; * needs a number operand; / needs a number divisor. % is its own dimension.
  • Evaluation is right-associative at the type level โ€” dimensionally lossless. The runtime parser applies real * / precedence for the computed value.
  • Nesting is depth-capped at 8 levels (weak-accept beyond); the runtime parser is uncapped.
  • var() is undecidable at compile time, so the strict tier rejects it. The runtime treats it as dimension-agnostic โ€” use the casual / IntelliSense tier for var() expressions.
/ install

Drop it in

One command via the shadcn CLI.

$ pnpm dlx shadcn@latest add https://turtiesocks.github.io/ridiculous/r/calc-editor.json