ModsCodeMERGEBLE LLC Search Claude Code Mods

ModsCode / Gallery / Designs / Bar chart around zero

Bar chart around zero

Twenty-four hourly bars around a zero line, up and down on one scale, with the largest bar labelled at its tip.

Bar chart around zeroBar chart around zero
Over time · 380×260 · sample data
hooks/designs/bars.mjs
// bars: 24 hourly bars around a zero line in candle's look. Bars take candle's 62% slot and 65%
// fill, so the two designs read as one system. Up and down share one scale; the scale end is rounded
// up to a whole hundred so the three ticks are plain numbers. The largest bar carries its value.
// Sample data only.
const W = 380
const H = 260
const STAGE = '#FAF9F5'
const UP = '#2C7A39'
const DOWN = '#AB2B3F'
const INK = '#141413'
const MUTED = '#73726C'
const FONT = "'Inter Tight','Segoe UI',system-ui,sans-serif"
const PLOT = { left: 44, right: 372, top: 16, bottom: 232 }
const N = 24

// A seeded walk of hourly values, biased a little to the plus side: the same picture every time
function sample(n) {
  let seed = 20261010
  const rnd = () => (seed = (Math.imul(seed, 1103515245) + 12345) & 0x7fffffff) / 0x7fffffff
  const out = []
  for (let i = 0; i < n; i++) out.push(Math.round((rnd() - 0.45) * 520))
  return out
}

function barsSource(vals) {
  const maxAbs = Math.max(...vals.map(v => Math.abs(v)))
  const T = Math.ceil((maxAbs * 1.12) / 100) * 100 // the scale end; the ticks sit at +T, 0 and -T
  const zeroY = (PLOT.top + PLOT.bottom) / 2
  const half = (PLOT.bottom - PLOT.top) / 2
  const slot = (PLOT.right - PLOT.left) / N
  const bw = slot * 0.62
  const y = v => zeroY - (v / T) * half
  const cx = i => PLOT.left + slot * (i + 0.5)
  const parts = [`<rect width="${W}" height="${H}" rx="4" fill="${STAGE}"/>`]

  for (const [v, label] of [[T, `+${T}`], [0, '0'], [-T, `-${T}`]]) {
    parts.push(`<line x1="40" x2="${PLOT.left}" y1="${y(v)}" y2="${y(v)}" stroke="${MUTED}" stroke-width="1"/>`)
    parts.push(`<text x="36" y="${y(v) + 3}" text-anchor="end" font-size="9" font-family="${FONT}" fill="${MUTED}">${label}</text>`)
  }
  parts.push(`<line x1="${PLOT.left}" x2="${PLOT.right}" y1="${zeroY}" y2="${zeroY}" stroke="${INK}" stroke-opacity="0.35" stroke-width="1"/>`)

  let big = 0
  vals.forEach((v, i) => {
    if (Math.abs(v) > Math.abs(vals[big])) big = i
    const top = Math.min(y(v), zeroY)
    const h = Math.max(1, Math.abs(y(v) - zeroY))
    parts.push(`<rect x="${(cx(i) - bw / 2).toFixed(1)}" y="${top.toFixed(1)}" width="${bw.toFixed(1)}" height="${h.toFixed(1)}" fill="${v >= 0 ? UP : DOWN}" fill-opacity="0.65"/>`)
  })

  // The largest bar is labelled outside its tip: above a plus bar, below a minus bar
  const bv = vals[big]
  const ly = bv >= 0 ? y(bv) - 4 : y(bv) + 11
  parts.push(`<text x="${cx(big).toFixed(1)}" y="${ly.toFixed(1)}" text-anchor="middle" font-size="9" font-family="${FONT}" fill="${INK}">${bv > 0 ? '+' : ''}${bv}</text>`)

  for (const h of [0, 6, 12, 18]) {
    parts.push(`<text x="${cx(h).toFixed(1)}" y="${H - 8}" text-anchor="middle" font-size="9" font-family="${FONT}" fill="${MUTED}">${String(h).padStart(2, '0')}</text>`)
  }
  parts.push(`<text x="${W - 12}" y="${H - 8}" text-anchor="end" font-size="9" font-family="${FONT}" fill="${MUTED}">SAMPLE 1h</text>`)
  return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${W} ${H}" width="${W}" height="${H}">${parts.join('')}</svg>`
}

const SOURCE = barsSource(sample(N))

export default {
  id: 'bars',
  title: 'Bar chart around zero',
  category: 'time',
  description: 'Twenty-four hourly bars around a zero line, up and down on one scale, with the largest bar labelled at its tip.',
  element: ui => ui.Svg({ source: SOURCE, alt: '24 hourly bars around a zero line, up and down, sample data', width: W, height: H }),
}

To use it in a mod: copy the file to your mod's hooks/designs/ and return its element(ui) from a pane's ui.render. How a pane is built.

Code: PolyForm Noncommercial License 1.0.0: noncommercial use only. Required Notice: Copyright 2026 Haruki Nakada (https://modscode.com).