DEV Community

Cover image for Building a trading dashboard UI with zero JavaScript — just st-core.fscss
FSCSS tutorial for FSCSS tutorial

Posted on • Originally published at fscss-ttr.github.io

Building a trading dashboard UI with zero JavaScript — just st-core.fscss

No JS. No SVG. No canvas. Just CSS — and one import.

Here's what that actually looks like in practice.


The problem with dashboard UIs

Every time I need a stats dashboard — chart, bars, stat cards, the whole thing — I end up writing the same boilerplate. CSS variables, clip-path polygons, card layouts. It's not hard, but it's repetitive. And when you're working across multiple projects, copy-pasting that foundation every time gets old fast.

So packaged it.

st-core.fscss is an open source plugin for FSCSS that gives you a complete trading/stats dashboard design system in a single import. MIT licensed, no dependencies besides the FSCSS runtime or cli.


What you get

A full set of @st-* mixins that each generate a production-ready component:

Mixin Output
@st-root() Design tokens (colors, radius, spacing) on :root
@st-stat-card Stat card — label, value, up/down delta
@st-chart-fill Gradient area fill under a chart line
@st-chart-line Glowing line stroke
@st-chart-dot Positioned data point with tooltip support
@st-chart-grid Background grid lines
@st-chart-axis-x/y Axis label rows
@st-chart-points Inject 8 data values into a chart
@st-cat-bar-fill Gradient progress bar fill
@st-phone Mock phone/device frame

How the chart works — pure CSS, no JS

This is the interesting part. The chart is a clip-path: polygon() shape.

You pass 8 Y values to @st-chart-points, which writes them as CSS custom properties — --st-p1 through --st-p8 — on your chart container. The fill and line elements inside read those values and clip themselves accordingly.

.chart {
  position: relative;
  height: 200px;
  overflow: hidden;
  background: var(--st-surface);

  /* your 8 data points */
  @st-chart-points(20, 35, 33, 30, 48, 35, 66, 37)
}
Enter fullscreen mode Exit fullscreen mode

That's it. No JS. No SVG path calculations. The "line" is a thin filled polygon with two rows of points — the front edge and the back edge — separated by --st-chart-line-width. Change the width, the line redraws.

.chart-line {
  @st-chart-line-width(2px)
}
Enter fullscreen mode Exit fullscreen mode

A minimal full example

demo using runtime

<script src="https://cdn.jsdelivr.net/npm/fscss@1.1.24/exec.min.js" async></script>

<style>
@import((*) from st-core)

/* ================= INIT ================= */

@st-root()
@st-container(body)

/* ================= COMPONENTS ================= */

@st-chart-fill(.chart-fill)
@st-chart-line(.chart-line)
@st-chart-dot(.chart-dot, 70, 60)

/* ================= CHART ================= */

.chart{
  width: 100%;
  height: 200px;
  border-radius: 25px;
  position: relative;
  overflow: hidden;

  background: var(--st-surface);

  /*  DATA (main power) */
  @st-chart-points(20,25,21,37,30,60,27,50)
}
@st-phone(.wrapper)
/* ================= LINE ================= */

.chart-line{
  /* controlled via helper */
  @st-chart-line-width(2px);

  /* optional override */
  filter: drop-shadow(0 0 8px var(--st-accent));
}

/* ================= FILL ================= */

.chart-fill{
  /* enhance fill visibility */
  opacity: .85;
}

/* ================= DOT ================= */

.chart-dot{
  position: relative;
  overflow: visible;

  /*  local customization */
  --st-accent: #c4a8ff; /* overrides root accent just for dot */
}

/* tooltip */
.chart-dot:after{
  content: attr(data-point);
  background: var(--st-accent);
  padding: 6px 8px;
  font-size: 12px;
  font-weight: 700;
  color: #fff;
  border-radius: var(--st-radius-sm);
  position: absolute;
  top: -40px;
  left: -22px;
  white-space: nowrap;
}

/* arrow */
.chart-dot:before{
  content: '';
  width: 10px;
  height: 10px;
  background: var(--st-accent);
  transform: rotate(45deg);
  position: absolute;
  top: -18px;
  left: 2px;
}

/* ================= EXTRA (USING st-core IDEA) ================= */


@st-stat-card(.stat-card)
@st-chart-axis-x(.x-axis)
@st-chart-axis-y(.y-axis)



@st-chart-grid(.chart-grid, 10, 7)
</style>
<div class="wrapper">
    <div class="stat-card">
    <div class="st-stat-label">TOTAL EXPENSES</div>
    <div class="st-stat-value">$1,326.03</div>
    <div class="st-stat-delta up">+5.1% vs last week</div>
  </div>
<div class="chart">
  <div class="chart-fill"></div>
  <div class="chart-line"></div>
  <div class="chart-dot" data-point="$405.67"></div>
  <div class="chart-grid"></div>
   <div class="y-axis">
   <span>0</span>
   <span>10</span>
   <span>20</span>
   <span>30</span>
   <span>40</span>
   <span>50</span>
   <span>60</span>
   <span>70</span>
   <span>80</span>
   <span>90</span>
   <span>100</span>
 </div>
  </div>
        <div class="x-axis days">
      <span>Sun</span>
      <span>Mon</span>
      <span>Tue</span>
      <span>Wed</span>
      <span>Thu</span>
      <span>Fri</span>
      <span>Sat</span>
      <span>Sun</span>
    </div>

  </div>

Enter fullscreen mode Exit fullscreen mode

A full chart with a stat card and axis labels. That's the entire CSS. No custom polygon math, no JavaScript data binding.


Token overrides — it's just CSS variables

All the colors, spacing, and radii are CSS custom properties. Override any of them locally — they cascade normally.

/* global theme tweak */
:root {
  --st-accent: #00d4ff;
  --st-bg: #0a0f1e;
}

/* local override — just for the dot */
.chart-dot {
  --st-accent: var(--st-accent-2);
}
Enter fullscreen mode Exit fullscreen mode

Multiple charts on the same page? Each container has its own --st-p1--st-p8, so they're fully independent.


Category bars

The @st-cat-bar-fill mixin builds a gradient progress bar. You set the fill per element using a CSS variable — no extra params needed once the mixin is declared.

@st-cat-bar-fill(.bar-fill, 0)

/* per-bar widths */
.equities { --st-cat-bar-fill-range: 82%; }
.crypto   { --st-cat-bar-fill-range: 61%; }
.forex    { --st-cat-bar-fill-range: 45%; }
Enter fullscreen mode Exit fullscreen mode
<div class="bar-track">
  <div class="bar-fill equities"></div>
</div>
Enter fullscreen mode Exit fullscreen mode

See it live

Live demo

GitHub — fscss-ttr/st-core.fscss (MIT)

FSCSS NPM (MIT)

The full demo includes stat cards, a chart with fill + line + dot + grid + axes, category bars, and a phone frame — all driven by @st-* mixins with no custom CSS beyond the mixin calls themselves.


Why FSCSS?

FSCSS is a lightweight modern CSS preprocessor.

If you're unfamiliar with FSCSS, the docs are a good starting point.


Drop a ⭐ on the repo if it's useful, and feel free to open issues or PRs — it's MIT, go wild.


Top comments (0)