跳至正文
uiify

Candle chart

以纯CSS渲染的静态OHLC蜡烛图。

浏览器
Chrome 123+Firefox 121+Safari 17.5+
层级
0
强制布局预算
0 ms
axe 预算
0
支持 SSR
是
公开契约
测试环境

交互示例

Candle chart

100 daily OHLC items with CSS geometry, automatic axes, and an optional interactive client entry.

CSS-only chart

BTC / USD daily candles
TimeOpenHighLowClose
2025-08-2024000242002387524060
2025-08-2124166245672402324405
2025-08-2224324245082410224263
2025-08-2324470246762423624415
2025-08-2424598250522447324824
2025-08-2524703248612456024721
2025-08-2624782249442446824629
2025-08-2724834251552465524971
2025-08-2824859251562473424950
2025-08-2924859250872451524658
2025-08-3024836249802467524840
2025-08-3124797250922461824930
2025-09-0124746249302443924564
2025-09-0224689248952441524558
2025-09-0324633249932447224765
2025-09-0424584247242430324482
2025-09-0524548247102420224327
2025-09-0624530248032438724619
2025-09-0724533247522437224546
2025-09-0824559247872414324322
2025-09-0924609247662448424626
2025-09-1024683249692454024807
2025-09-1124776249602444124602
2025-09-1224886250922464724826
2025-09-1325008254312488325203
2025-09-1425135252752493925082
2025-09-1525261254232498325144
2025-09-1625380257652520125581
2025-09-1725486257782536125572
2025-09-1825574258022529625439
2025-09-1925639259192547825779
2025-09-2025678260352549925873
2025-09-2125691258752545525580
2025-09-2225678259162553525710
2025-09-2325641261072548025879
2025-09-2425582257222535325532
2025-09-2525507256692529425419
2025-09-2625422258082527925624
2025-09-2725332255642517125358
2025-09-2825246254742488725066
2025-09-2925168254072504325267
2025-09-3025106253612496325199
2025-10-0125064252482469124852
2025-10-0225046252522483025009
2025-10-0325055254132493025185
2025-10-0425092252322477524918
2025-10-0525156253182483524996
2025-10-0625245255542506625370
2025-10-0725354255602515225277
2025-10-0825480257082510825251
2025-10-0925616258352545525695
2025-10-1025755259632557625801
2025-10-1125892260762554625671
2025-10-1226021262362587826030
2025-10-1326135265182597426290
2025-10-1426230263702591126090
2025-10-1526302264642611326238
2025-10-1626351267482620826564
2025-10-1726376265822620326364
2025-10-1826379266072608426263
2025-10-1926361267012623626561
2025-10-2026329266102618626448
2025-10-2126286264702599426155
2025-10-2226239265652606026359
2025-10-2326194266322606926404
2025-10-2426158262982591226055
2025-10-2526136262982597426135
2025-10-2626134265482595526364
2025-10-2726154263602598726112
2025-10-2826199264272593326076
2025-10-2926271265842611026444
2025-10-3026368265622618926400
2025-10-3126488266722615926284
2025-11-0126627268922648426686
2025-11-0226780271042661926876
2025-11-0326941270812654526724
2025-11-0427103272652690427029
2025-11-0527261275732711827389
2025-11-0627406276122708727248
2025-11-0727535277632717427353
2025-11-0827641279012751627761
2025-11-0927721278832753227675
2025-11-1027774279582738527546
2025-11-1127799280782762027872
2025-11-1227797281082767227880
2025-11-1327771279112743027573
2025-11-1427726278902756527728
2025-11-1527666280352748727851
2025-11-1627598278042737027495
2025-11-1727527277552731527458
2025-11-1827462278272730127687
2025-11-1927407275952722827433
2025-11-2027368275522712527250
2025-11-2127349277462720627540
2025-11-2227353277272719227499
2025-11-2327382275222707427253
2025-11-2427435276892731027527
2025-11-2527510279102736727726
2025-11-2627604278102734527506
2025-11-2727712279402749527674

Interactive chart

Interactive BTC / USD daily candles
2025-11-27O 27712H 27940L 27495C 27674
  1. Aug 25
  2. Sep 25
  3. Oct 25
  4. Nov 25
  1. 28,108
  2. 27,261.4
  3. 26,414.8
  4. 25,568.2
  5. 24,721.6
  6. 23,875
TimeOpenHighLowClose
2025-08-2024000242002387524060
2025-08-2124166245672402324405
2025-08-2224324245082410224263
2025-08-2324470246762423624415
2025-08-2424598250522447324824
2025-08-2524703248612456024721
2025-08-2624782249442446824629
2025-08-2724834251552465524971
2025-08-2824859251562473424950
2025-08-2924859250872451524658
2025-08-3024836249802467524840
2025-08-3124797250922461824930
2025-09-0124746249302443924564
2025-09-0224689248952441524558
2025-09-0324633249932447224765
2025-09-0424584247242430324482
2025-09-0524548247102420224327
2025-09-0624530248032438724619
2025-09-0724533247522437224546
2025-09-0824559247872414324322
2025-09-0924609247662448424626
2025-09-1024683249692454024807
2025-09-1124776249602444124602
2025-09-1224886250922464724826
2025-09-1325008254312488325203
2025-09-1425135252752493925082
2025-09-1525261254232498325144
2025-09-1625380257652520125581
2025-09-1725486257782536125572
2025-09-1825574258022529625439
2025-09-1925639259192547825779
2025-09-2025678260352549925873
2025-09-2125691258752545525580
2025-09-2225678259162553525710
2025-09-2325641261072548025879
2025-09-2425582257222535325532
2025-09-2525507256692529425419
2025-09-2625422258082527925624
2025-09-2725332255642517125358
2025-09-2825246254742488725066
2025-09-2925168254072504325267
2025-09-3025106253612496325199
2025-10-0125064252482469124852
2025-10-0225046252522483025009
2025-10-0325055254132493025185
2025-10-0425092252322477524918
2025-10-0525156253182483524996
2025-10-0625245255542506625370
2025-10-0725354255602515225277
2025-10-0825480257082510825251
2025-10-0925616258352545525695
2025-10-1025755259632557625801
2025-10-1125892260762554625671
2025-10-1226021262362587826030
2025-10-1326135265182597426290
2025-10-1426230263702591126090
2025-10-1526302264642611326238
2025-10-1626351267482620826564
2025-10-1726376265822620326364
2025-10-1826379266072608426263
2025-10-1926361267012623626561
2025-10-2026329266102618626448
2025-10-2126286264702599426155
2025-10-2226239265652606026359
2025-10-2326194266322606926404
2025-10-2426158262982591226055
2025-10-2526136262982597426135
2025-10-2626134265482595526364
2025-10-2726154263602598726112
2025-10-2826199264272593326076
2025-10-2926271265842611026444
2025-10-3026368265622618926400
2025-10-3126488266722615926284
2025-11-0126627268922648426686
2025-11-0226780271042661926876
2025-11-0326941270812654526724
2025-11-0427103272652690427029
2025-11-0527261275732711827389
2025-11-0627406276122708727248
2025-11-0727535277632717427353
2025-11-0827641279012751627761
2025-11-0927721278832753227675
2025-11-1027774279582738527546
2025-11-1127799280782762027872
2025-11-1227797281082767227880
2025-11-1327771279112743027573
2025-11-1427726278902756527728
2025-11-1527666280352748727851
2025-11-1627598278042737027495
2025-11-1727527277552731527458
2025-11-1827462278272730127687
2025-11-1927407275952722827433
2025-11-2027368275522712527250
2025-11-2127349277462720627540
2025-11-2227353277272719227499
2025-11-2327382275222707427253
2025-11-2427435276892731027527
2025-11-2527510279102736727726
2025-11-2627604278102734527506
2025-11-2727712279402749527674

Live stream

A simulated trade feed with volatility clustering and drifting trends. Every candle lives in a horizontal VirtualScroll sized to show 20 at a time: scroll back through the history, and the chart follows new candles again once you return to the newest one.

Live BTC / USD one-minute candles
10:29O 63973.85H 63993.3L 63888.51C 63888.51
  1. 10:05
  2. 10:10
  3. 10:15
  4. 10:20
  5. 10:25
  1. 64,365.59
  2. 64,251.48
  3. 64,137.38
  4. 64,023.27
  5. 63,909.17
  6. 63,795.06
TimeOpenHighLowClose
10:1064342.7464343.9664284.564343.96
10:1164343.9664365.5964281.2964365.59
10:1264365.5964365.5964268.4564323.33
10:1364323.3364354.5464279.5964316.85
10:1464316.8564316.8564192.764226.09
10:1564226.0964226.0964147.2264162.9
10:1664162.964211.2764118.7664118.76
10:1764118.7664150.4664028.6764061.06
10:1864061.0664061.0663901.4263901.42
10:1963901.4263901.4263811.1663867.61
10:2063867.6163899.4163795.0663795.06
10:2163795.0663864.0763795.0663859.14
10:2263859.1463895.1863832.4963895.18
10:2363895.1863895.1863820.0263833.26
10:2463833.2663910.9563827.5463910.95
10:2563910.9563980.3763896.7463975.28
10:2663975.2864031.1463961.3564017.19
10:2764017.1964106.4764017.1964102.34
10:2864102.3464118.4863973.1863973.85
10:2963973.8563993.363888.5163888.51
import { useEffect, useState } from "react";
import { CandleChart } from "@gunkin/uiify";
import { CandleChartClient } from "@gunkin/uiify/components/candle-chart/client";

const data = Array.from({ length: 100 }, (_, index) => {
  const open = Math.round(24000 + index * 38 + Math.sin(index / 4) * 420);
  const close = open + Math.round(Math.sin(index * 1.9) * 190);

  return {
    time: new Date(Date.UTC(2025, 7, 20 + index)).toISOString().slice(0, 10),
    open,
    high: Math.max(open, close) + 180,
    low: Math.min(open, close) - 160,
    close,
  };
});

export default function Example() {
  return (
    <>
      <CandleChart className="" data={data} aria-label="BTC / USD daily candles" />
      <CandleChartClient className="" data={data} aria-label="Interactive BTC / USD daily candles" />
      <LiveChart />
    </>
  );
}

function LiveChart() {
  const [candles, setCandles] = useState(data);
  const [running, setRunning] = useState(false);

  useEffect(() => {
    if (!running) return;
    const timer = setInterval(() => {
      setCandles((current) => {
        const last = current.at(-1);
        if (!last) return current;
        const close = Math.round(last.close * (1 + (Math.random() - 0.5) * 0.004));
        const next = {
          time: String(current.length),
          open: last.close,
          high: Math.max(last.close, close),
          low: Math.min(last.close, close),
          close,
        };
        return [...current, next];
      });
    }, 1000);
    return () => clearInterval(timer);
  }, [running]);

  return (
    <>
      <button type="button" onClick={() => setRunning((value) => !value)}>
        {running ? "Stop" : "Start"}
      </button>
      {/* All candles, virtualized; 20 fit the viewport and new ones stay in view at the end. */}
      <CandleChartClient className="" data={candles} visibleCount={20} aria-label="Live BTC / USD candles" />
    </>
  );
}
@property --candle-body-height {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}

@property --candle-body-top {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --candle-slot {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 100%;
}

@property --candle-wick-height {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}

@property --candle-wick-top {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --candle-x {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}

@property --candle-scale {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}

@layer components {
  [data-uiify-candle-chart] {
    --candle-grid: color-mix(in srgb, currentcolor 10%, transparent);
    --candle-down: oklch(64% 0.21 24deg);
    --candle-flat: color-mix(in srgb, currentcolor 60%, transparent);
    --candle-up: oklch(67% 0.14 166deg);
    --candle-axis: var(--muted-foreground);

    position: relative;
    display: block;
    inline-size: 100%;
    min-block-size: 21rem;
    padding: 1rem 0.75rem 0.5rem;
    overflow: clip;
    overscroll-behavior: none;
    isolation: isolate;
    color-scheme: light dark;
    background: transparent;
    color: light-dark(oklch(28% 0.04 165deg), oklch(82% 0.04 165deg));
  }

  /* Interactive charts own touch and horizontal wheel gestures (crosshair,
     zoom, native scroll); a static chart leaves page scrolling alone. */
  [data-uiify-candle-chart][data-interactive] {
    touch-action: none;
  }

  [data-uiify-candle-chart][data-interactive] [data-part="scroll-viewport"] {
    overscroll-behavior-inline: none;
  }

  /* The time-axis row also reserves the horizontal scrollbar, measured by the
     client entry (0 for overlay scrollbars and static charts), so the flexible
     candle row does not absorb it and stays aligned with the value axis. */
  [data-uiify-candle-chart] > [data-part="plot"] {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 4.5rem;
    grid-template-rows: minmax(18rem, 1fr) calc(1.5rem + var(--candle-scrollbar-size, 0px));
    gap: 0 0.75rem;
    min-inline-size: 0;
    min-block-size: 18rem;
    overscroll-behavior: none;
  }

  [data-uiify-candle-chart] [data-part="scroll-viewport"] {
    grid-column: 1;
    grid-row: 1 / span 2;
    min-inline-size: 0;
    min-block-size: 18rem;
    overflow: auto hidden;
    container-type: inline-size;
    direction: rtl;
  }

  [data-uiify-candle-chart] [data-part="canvas"] {
    display: grid;
    grid-template-rows: minmax(18rem, 1fr) 1.5rem;
    inline-size: calc(100% * var(--candle-scale));
    min-inline-size: 100%;
    min-block-size: 100%;
    direction: ltr;
  }

  [data-uiify-candle-chart] [data-part="candles"] {
    position: absolute;
    inset-block: 0;
    inset-inline: auto 0;
    inline-size: 100%;
    margin: 0;
    padding: 1rem 0.5rem;
    list-style: none;
  }

  /* Live mode: a horizontal VirtualScroll replaces the static list. The grid sits
     on the viewport, so it holds still while candles scroll past and a classic
     scrollbar cannot squeeze it. */
  [data-uiify-candle-chart] [data-part="viewport"] > [data-uiify-virtual-scroll] {
    position: absolute;
    inset: 0;
  }

  /* A classic scrollbar shortens the virtual rows; size candles from the plot
     height so they stay aligned with the price axis. */
  [data-uiify-candle-chart] [data-uiify-virtual-scroll] [data-part="candle"] {
    inset-block: 1rem auto;
    block-size: calc(var(--candle-plot-height, 18rem) - 2rem);
  }

  [data-uiify-candle-chart] [data-part="candles"],
  [data-uiify-candle-chart] [data-part="viewport"]:has(> [data-uiify-virtual-scroll]) {
    background-image:
      linear-gradient(to right, var(--candle-grid) 1px, transparent 1px),
      linear-gradient(to bottom, var(--candle-grid) 1px, transparent 1px);
    background-size:
      10% 100%,
      100% 25%;
  }

  [data-uiify-candle-chart] [data-part="viewport"] {
    position: relative;
    grid-column: 1;
    grid-row: 1;
    min-inline-size: 0;
    min-block-size: 18rem;
    overflow: clip;
    overscroll-behavior: none;
  }

  [data-uiify-candle-chart] [data-part="time-viewport"] {
    position: relative;
    grid-column: 1;
    grid-row: 2;
    min-inline-size: 0;
    overflow: clip;
    overscroll-behavior: none;
  }

  [data-uiify-candle-chart] > figcaption {
    position: absolute;
    z-index: 1;
    inset-block-start: 0.75rem;
    inset-inline-start: 1rem;
    color: var(--muted-foreground);
    font-size: 0.75rem;
    font-weight: 650;
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }

  [data-uiify-candle-chart] [data-part="readout"] {
    position: absolute;
    z-index: 1;
    inset-block-start: 0.75rem;
    inset-inline-end: 1rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem 0.625rem;
    align-items: baseline;
    color: var(--candle-axis);
    font-size: 0.7rem;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    white-space: nowrap;
  }

  [data-uiify-candle-chart] [data-part="readout-time"] {
    font-weight: 650;
  }

  [data-uiify-candle-chart] [data-part="candle"] {
    position: absolute;
    inset: 1rem 0.5rem;
    pointer-events: none;
    inset-inline-start: var(--candle-x);
    inline-size: var(--candle-slot);
    display: block;
    color: var(--candle-flat);
    list-style: none;
  }

  [data-uiify-candle-chart][data-interactive] [data-part="candle"] {
    pointer-events: auto;
  }

  [data-uiify-candle-chart] [data-part="candle-hit"] {
    position: absolute;
    z-index: 1;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    appearance: none;
    background: transparent;
    color: transparent;
    cursor: crosshair;
    font: inherit;
  }

  [data-uiify-candle-chart] [data-part="candle"]::before,
  [data-uiify-candle-chart] [data-part="candle"]::after {
    content: "";
    position: absolute;
    display: block;
    background: currentcolor;
  }

  [data-uiify-candle-chart] [data-part="candle"]::before {
    inset-block-start: var(--candle-wick-top);
    inset-inline-start: 50%;
    inline-size: max(1px, 0.08em);
    block-size: var(--candle-wick-height);
    transform: translateX(-50%);
  }

  [data-uiify-candle-chart] [data-part="candle"]::after {
    inset-block-start: var(--candle-body-top);
    inset-inline: 17%;
    block-size: var(--candle-body-height);
    min-block-size: 1px;
  }

  [data-uiify-candle-chart] [data-part="candle"][data-direction="up"] {
    color: var(--candle-up);
  }

  [data-uiify-candle-chart] [data-part="candle"][data-direction="down"] {
    color: var(--candle-down);
  }

  /* The crosshair and time axis span the scrolled content in live mode:
     `--candle-content-size` is its width, `--candle-scroll-x` its scroll offset. */
  [data-uiify-candle-chart] [data-part="crosshair"] {
    position: absolute;
    z-index: 3;
    inset: 0;
    inline-size: var(--candle-content-size, 100%);
    translate: calc(-1 * var(--candle-scroll-x, 0px)) 0;
    block-size: 100%;
    color: light-dark(oklch(52% 0.01 0deg), oklch(72% 0.01 0deg));
    pointer-events: none;
  }

  [data-uiify-candle-chart] [data-part="crosshair"]::before,
  [data-uiify-candle-chart] [data-part="crosshair"]::after {
    content: "";
    position: absolute;
    display: block;
    background: currentcolor;
  }

  [data-uiify-candle-chart] [data-part="crosshair"]::before {
    inset-block: 0;
    inset-inline-start: var(--candle-crosshair-x);
    inline-size: 1px;
    background-image: repeating-linear-gradient(
      to bottom,
      currentcolor 0 0.4rem,
      transparent 0.4rem 0.8rem
    );
    background-color: transparent;
  }

  [data-uiify-candle-chart] [data-part="crosshair"]::after {
    inset-block-start: calc(var(--candle-cursor-y, 50%) + 1rem);
    inset-inline: 0;
    block-size: 1px;
    background-image: repeating-linear-gradient(
      to right,
      currentcolor 0 0.4rem,
      transparent 0.4rem 0.8rem
    );
    background-color: transparent;
  }

  [data-uiify-candle-chart] [data-part="crosshair-marker"] {
    position: absolute;
    inset-block-start: calc(var(--candle-cursor-y, 50%) + 1rem);
    inset-inline-start: var(--candle-crosshair-x);
    font-size: 1rem;
    line-height: 1;
    transform: translate(-50%, -50%);
  }

  [data-uiify-candle-chart] [data-part="time-axis"] > [data-part="crosshair-time"] {
    inset-block-start: 0;
    inset-inline-start: var(--candle-crosshair-x);
    padding: 0.25rem 0.5rem;
    background: var(--candle-axis);
    color: Canvas;
    font-weight: 650;
    transform: translateX(-50%);
  }

  [data-uiify-candle-chart] [data-part="price-axis"] > [data-part="crosshair-price"] {
    inset-block-start: calc(var(--candle-cursor-y, 50%) + 1rem);
    inset-inline-end: 0;
    padding: 0.25rem 0.5rem;
    background: var(--candle-axis);
    color: Canvas;
    font-weight: 650;
    transform: translateY(-50%);
  }

  [data-uiify-candle-chart][data-interactive] [data-part="candle-hit"]:focus-visible {
    outline: 2px solid currentcolor;
    outline-offset: -2px;
  }

  [data-uiify-candle-chart] [data-part="price-axis"],
  [data-uiify-candle-chart] [data-part="time-axis"] {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  [data-uiify-candle-chart] [data-part="price-axis"] {
    position: relative;
    grid-column: 2;
    grid-row: 1;
    min-inline-size: 0;
  }

  [data-uiify-candle-chart] [data-part="price-axis"] > li {
    position: absolute;
    inset-inline: 0;
    inset-block-start: var(--candle-axis-y);
    overflow: hidden;
    color: var(--candle-axis);
    font-size: 0.65rem;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    text-align: end;
    text-overflow: ellipsis;
    white-space: nowrap;
    transform: translateY(-50%);
  }

  [data-uiify-candle-chart] [data-part="price-axis"] > li:first-child {
    transform: none;
  }

  [data-uiify-candle-chart] [data-part="price-axis"] > li:last-child {
    transform: translateY(-100%);
  }

  [data-uiify-candle-chart] [data-part="time-axis"] {
    position: relative;
    inset-block: 0;
    inline-size: var(--candle-content-size, 100%);
    translate: calc(-1 * var(--candle-scroll-x, 0px)) 0;
    min-inline-size: 0;
  }

  [data-uiify-candle-chart] [data-part="time-axis"] > li {
    position: absolute;
    inset-block-start: 0.375rem;
    inset-inline-start: var(--candle-axis-x);
    color: var(--candle-axis);
    font-size: 0.7rem;
    white-space: nowrap;
    transform: translateX(-50%);
  }

  [data-uiify-candle-chart] [data-part="time-axis"] > li:first-child {
    transform: none;
  }

  [data-uiify-candle-chart] [data-part="time-axis"] > li:last-child {
    transform: translateX(-100%);
  }

  [data-uiify-candle-chart] [data-part="time-axis"] > li:only-child {
    transform: translateX(-50%);
  }

  [data-uiify-candle-chart] [data-part="time-axis"] > li[data-part="crosshair-time"] {
    transform: translateX(-50%);
  }

  [data-uiify-candle-chart] [data-part="price-axis"] > li[data-part="crosshair-price"] {
    transform: translateY(-50%);
  }

  [data-uiify-candle-chart] > table {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}
import { useEffect, useState } from "react";
import { CandleChart } from "@gunkin/uiify";
import { CandleChartClient } from "@gunkin/uiify/components/candle-chart/client";

const data = Array.from({ length: 100 }, (_, index) => {
  const open = Math.round(24000 + index * 38 + Math.sin(index / 4) * 420);
  const close = open + Math.round(Math.sin(index * 1.9) * 190);

  return {
    time: new Date(Date.UTC(2025, 7, 20 + index)).toISOString().slice(0, 10),
    open,
    high: Math.max(open, close) + 180,
    low: Math.min(open, close) - 160,
    close,
  };
});

export default function Example() {
  return (
    <>
      <CandleChart
        className={
          "[--candle-grid:color-mix(in_srgb,_currentcolor_10%,_transparent)] [--candle-down:oklch(64%_0.21_24deg)] [" +
          "--candle-flat:color-mix(in_srgb,_currentcolor_60%,_transparent)] [--candle-up:oklch(67%_0.14_166deg)] [--" +
          "candle-axis:var(--muted-foreground)] relative block [inline-size:100%] [min-block-size:21rem] [padding:1r" +
          "em_0.75rem_0.5rem] overflow-clip [overscroll-behavior:none] isolate [color-scheme:light_dark] bg-transpar" +
          "ent [color:light-dark(oklch(28%_0.04_165deg),_oklch(82%_0.04_165deg))] data-[interactive]:[touch-action:n" +
          "one] [&[data-interactive]_[data-part=scroll-viewport]]:[overscroll-behavior-inline:none] [&>[data-part=pl" +
          "ot]]:relative [&>[data-part=plot]]:grid [&>[data-part=plot]]:[grid-template-columns:minmax(0,_1fr)_4.5rem" +
          "] [&>[data-part=plot]]:[grid-template-rows:minmax(18rem,_1fr)_calc(1.5rem_+_var(--candle-scrollbar-size,_" +
          "0px))] [&>[data-part=plot]]:[gap:0_0.75rem] [&>[data-part=plot]]:[min-inline-size:0] [&>[data-part=plot]]" +
          ":[min-block-size:18rem] [&>[data-part=plot]]:[overscroll-behavior:none] [&_[data-part=scroll-viewport]]:[" +
          "grid-column:1] [&_[data-part=scroll-viewport]]:[grid-row:1_/_span_2] [&_[data-part=scroll-viewport]]:[min" +
          "-inline-size:0] [&_[data-part=scroll-viewport]]:[min-block-size:18rem] [&_[data-part=scroll-viewport]]:[o" +
          "verflow:auto_hidden] [&_[data-part=scroll-viewport]]:[container-type:inline-size] [&_[data-part=scroll-vi" +
          "ewport]]:[direction:rtl] [&_[data-part=canvas]]:grid [&_[data-part=canvas]]:[grid-template-rows:minmax(18" +
          "rem,_1fr)_1.5rem] [&_[data-part=canvas]]:[inline-size:calc(100%_*_var(--candle-scale))] [&_[data-part=can" +
          "vas]]:[min-inline-size:100%] [&_[data-part=canvas]]:[min-block-size:100%] [&_[data-part=canvas]]:[directi" +
          "on:ltr] [&_[data-part=candles]]:absolute [&_[data-part=candles]]:[inset-block:0] [&_[data-part=candles]]:" +
          "[inset-inline:auto_0] [&_[data-part=candles]]:[inline-size:100%] [&_[data-part=candles]]:m-0 [&_[data-par" +
          "t=candles]]:[padding:1rem_0.5rem] [&_[data-part=candles]]:list-none [&_[data-part=viewport]>[data-uiify-v" +
          "irtual-scroll]]:absolute [&_[data-part=viewport]>[data-uiify-virtual-scroll]]:inset-0 [&_[data-uiify-virt" +
          "ual-scroll]_[data-part=candle]]:[inset-block:1rem_auto] [&_[data-uiify-virtual-scroll]_[data-part=candle]" +
          "]:[block-size:calc(var(--candle-plot-height,_18rem)_-_2rem)] [&_[data-part=candles]]:[background-image:li" +
          "near-gradient(to_right,_var(--candle-grid)_1px,_transparent_1px),_linear-gradient(to_bottom,_var(--candle" +
          "-grid)_1px,_transparent_1px)] [&_[data-part=candles]]:[background-size:10%_100%,_100%_25%] [&_[data-part=" +
          "viewport]:has(>[data-uiify-virtual-scroll])]:[background-image:linear-gradient(to_right,_var(--candle-gri" +
          "d)_1px,_transparent_1px),_linear-gradient(to_bottom,_var(--candle-grid)_1px,_transparent_1px)] [&_[data-p" +
          "art=viewport]:has(>[data-uiify-virtual-scroll])]:[background-size:10%_100%,_100%_25%] [&_[data-part=viewp" +
          "ort]]:relative [&_[data-part=viewport]]:[grid-column:1] [&_[data-part=viewport]]:[grid-row:1] [&_[data-pa" +
          "rt=viewport]]:[min-inline-size:0] [&_[data-part=viewport]]:[min-block-size:18rem] [&_[data-part=viewport]" +
          "]:overflow-clip [&_[data-part=viewport]]:[overscroll-behavior:none] [&_[data-part=time-viewport]]:relativ" +
          "e [&_[data-part=time-viewport]]:[grid-column:1] [&_[data-part=time-viewport]]:[grid-row:2] [&_[data-part=" +
          "time-viewport]]:[min-inline-size:0] [&_[data-part=time-viewport]]:overflow-clip [&_[data-part=time-viewpo" +
          "rt]]:[overscroll-behavior:none] [&>figcaption]:absolute [&>figcaption]:z-[1] [&>figcaption]:[inset-block-" +
          "start:0.75rem] [&>figcaption]:[inset-inline-start:1rem] [&>figcaption]:text-muted-foreground [&>figcaptio" +
          "n]:[font-size:0.75rem] [&>figcaption]:[font-weight:650] [&>figcaption]:[letter-spacing:0.04em] [&>figcapt" +
          "ion]:[text-transform:uppercase] [&_[data-part=readout]]:absolute [&_[data-part=readout]]:z-[1] [&_[data-p" +
          "art=readout]]:[inset-block-start:0.75rem] [&_[data-part=readout]]:[inset-inline-end:1rem] [&_[data-part=r" +
          "eadout]]:flex [&_[data-part=readout]]:flex-wrap [&_[data-part=readout]]:[gap:0.375rem_0.625rem] [&_[data-" +
          "part=readout]]:items-baseline [&_[data-part=readout]]:[color:var(--candle-axis)] [&_[data-part=readout]]:" +
          "[font-size:0.7rem] [&_[data-part=readout]]:[font-variant-numeric:tabular-nums] [&_[data-part=readout]]:le" +
          "ading-none [&_[data-part=readout]]:whitespace-nowrap [&_[data-part=readout-time]]:[font-weight:650] [&_[d" +
          "ata-part=candle]]:absolute [&_[data-part=candle]]:[inset:1rem_0.5rem] [&_[data-part=candle]]:pointer-even" +
          "ts-none [&_[data-part=candle]]:[inset-inline-start:var(--candle-x)] [&_[data-part=candle]]:[inline-size:v" +
          "ar(--candle-slot)] [&_[data-part=candle]]:block [&_[data-part=candle]]:[color:var(--candle-flat)] [&_[dat" +
          "a-part=candle]]:list-none [&[data-interactive]_[data-part=candle]]:[pointer-events:auto] [&_[data-part=ca" +
          "ndle-hit]]:absolute [&_[data-part=candle-hit]]:z-[1] [&_[data-part=candle-hit]]:inset-0 [&_[data-part=can" +
          "dle-hit]]:[inline-size:100%] [&_[data-part=candle-hit]]:[block-size:100%] [&_[data-part=candle-hit]]:m-0 " +
          "[&_[data-part=candle-hit]]:p-0 [&_[data-part=candle-hit]]:border-0 [&_[data-part=candle-hit]]:border-curr" +
          "ent [&_[data-part=candle-hit]]:border-none [&_[data-part=candle-hit]]:appearance-none [&_[data-part=candl" +
          "e-hit]]:bg-transparent [&_[data-part=candle-hit]]:text-transparent [&_[data-part=candle-hit]]:[cursor:cro" +
          "sshair] [&_[data-part=candle-hit]]:[font-style:inherit] [&_[data-part=candle-hit]]:[font-variant:inherit]" +
          " [&_[data-part=candle-hit]]:[font-weight:inherit] [&_[data-part=candle-hit]]:[font-stretch:inherit] [&_[d" +
          "ata-part=candle-hit]]:text-[length:inherit] [&_[data-part=candle-hit]]:leading-[inherit] [&_[data-part=ca" +
          "ndle-hit]]:font-[family-name:inherit] [&_[data-part=candle]::before]:content-[''] [&_[data-part=candle]::" +
          "before]:absolute [&_[data-part=candle]::before]:block [&_[data-part=candle]::before]:[background:currentc" +
          "olor] [&_[data-part=candle]::after]:content-[''] [&_[data-part=candle]::after]:absolute [&_[data-part=can" +
          "dle]::after]:block [&_[data-part=candle]::after]:[background:currentcolor] [&_[data-part=candle]::before]" +
          ":[inset-block-start:var(--candle-wick-top)] [&_[data-part=candle]::before]:[inset-inline-start:50%] [&_[d" +
          "ata-part=candle]::before]:[inline-size:max(1px,_0.08em)] [&_[data-part=candle]::before]:[block-size:var(-" +
          "-candle-wick-height)] [&_[data-part=candle]::before]:[transform:translateX(-50%)] [&_[data-part=candle]::" +
          "after]:[inset-block-start:var(--candle-body-top)] [&_[data-part=candle]::after]:[inset-inline:17%] [&_[da" +
          "ta-part=candle]::after]:[block-size:var(--candle-body-height)] [&_[data-part=candle]::after]:[min-block-s" +
          "ize:1px] [&_[data-part=candle][data-direction=up]]:[color:var(--candle-up)] [&_[data-part=candle][data-di" +
          "rection=down]]:[color:var(--candle-down)] [&_[data-part=crosshair]]:absolute [&_[data-part=crosshair]]:z-" +
          "[3] [&_[data-part=crosshair]]:inset-0 [&_[data-part=crosshair]]:[inline-size:var(--candle-content-size,_1" +
          "00%)] [&_[data-part=crosshair]]:[translate:calc(-1_*_var(--candle-scroll-x,_0px))_0] [&_[data-part=crossh" +
          "air]]:[block-size:100%] [&_[data-part=crosshair]]:[color:light-dark(oklch(52%_0.01_0deg),_oklch(72%_0.01_" +
          "0deg))] [&_[data-part=crosshair]]:pointer-events-none [&_[data-part=crosshair]::before]:content-[''] [&_[" +
          "data-part=crosshair]::before]:absolute [&_[data-part=crosshair]::before]:block [&_[data-part=crosshair]::" +
          "before]:[background:currentcolor] [&_[data-part=crosshair]::after]:content-[''] [&_[data-part=crosshair]:" +
          ":after]:absolute [&_[data-part=crosshair]::after]:block [&_[data-part=crosshair]::after]:[background:curr" +
          "entcolor] [&_[data-part=crosshair]::before]:[inset-block:0] [&_[data-part=crosshair]::before]:[inset-inli" +
          "ne-start:var(--candle-crosshair-x)] [&_[data-part=crosshair]::before]:[inline-size:1px] [&_[data-part=cro" +
          "sshair]::before]:[background-image:repeating-linear-gradient(_to_bottom,_currentcolor_0_0.4rem,_transpare" +
          "nt_0.4rem_0.8rem_)] [&_[data-part=crosshair]::before]:bg-transparent [&_[data-part=crosshair]::after]:[in" +
          "set-block-start:calc(var(--candle-cursor-y,_50%)_+_1rem)] [&_[data-part=crosshair]::after]:[inset-inline:" +
          "0] [&_[data-part=crosshair]::after]:[block-size:1px] [&_[data-part=crosshair]::after]:[background-image:r" +
          "epeating-linear-gradient(_to_right,_currentcolor_0_0.4rem,_transparent_0.4rem_0.8rem_)] [&_[data-part=cro" +
          "sshair]::after]:bg-transparent [&_[data-part=crosshair-marker]]:absolute [&_[data-part=crosshair-marker]]" +
          ":[inset-block-start:calc(var(--candle-cursor-y,_50%)_+_1rem)] [&_[data-part=crosshair-marker]]:[inset-inl" +
          "ine-start:var(--candle-crosshair-x)] [&_[data-part=crosshair-marker]]:[font-size:1rem] [&_[data-part=cros" +
          "shair-marker]]:leading-none [&_[data-part=crosshair-marker]]:[transform:translate(-50%,_-50%)] [&_[data-p" +
          "art=time-axis]>[data-part=crosshair-time]]:[inset-block-start:0] [&_[data-part=time-axis]>[data-part=cros" +
          "shair-time]]:[inset-inline-start:var(--candle-crosshair-x)] [&_[data-part=time-axis]>[data-part=crosshair" +
          "-time]]:[padding:0.25rem_0.5rem] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[background:var(--c" +
          "andle-axis)] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[color:Canvas] [&_[data-part=time-axis]" +
          ">[data-part=crosshair-time]]:[font-weight:650] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[tran" +
          "sform:translateX(-50%)] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[inset-block-start:calc(va" +
          "r(--candle-cursor-y,_50%)_+_1rem)] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[inset-inline-e" +
          "nd:0] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[padding:0.25rem_0.5rem] [&_[data-part=price" +
          "-axis]>[data-part=crosshair-price]]:[background:var(--candle-axis)] [&_[data-part=price-axis]>[data-part=" +
          "crosshair-price]]:[color:Canvas] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[font-weight:650]" +
          " [&_[data-part=price-axis]>[data-part=crosshair-price]]:[transform:translateY(-50%)] [&[data-interactive]" +
          "_[data-part=candle-hit]:focus-visible]:[outline:2px_solid_currentcolor] [&[data-interactive]_[data-part=c" +
          "andle-hit]:focus-visible]:[outline-offset:-2px] [&_[data-part=price-axis]]:m-0 [&_[data-part=price-axis]]" +
          ":p-0 [&_[data-part=price-axis]]:list-none [&_[data-part=time-axis]]:m-0 [&_[data-part=time-axis]]:p-0 [&_" +
          "[data-part=time-axis]]:list-none [&_[data-part=price-axis]]:relative [&_[data-part=price-axis]]:[grid-col" +
          "umn:2] [&_[data-part=price-axis]]:[grid-row:1] [&_[data-part=price-axis]]:[min-inline-size:0] [&_[data-pa" +
          "rt=price-axis]>li]:absolute [&_[data-part=price-axis]>li]:[inset-inline:0] [&_[data-part=price-axis]>li]:" +
          "[inset-block-start:var(--candle-axis-y)] [&_[data-part=price-axis]>li]:overflow-hidden [&_[data-part=pric" +
          "e-axis]>li]:[color:var(--candle-axis)] [&_[data-part=price-axis]>li]:[font-size:0.65rem] [&_[data-part=pr" +
          "ice-axis]>li]:[font-variant-numeric:tabular-nums] [&_[data-part=price-axis]>li]:leading-none [&_[data-par" +
          "t=price-axis]>li]:text-end [&_[data-part=price-axis]>li]:[text-overflow:ellipsis] [&_[data-part=price-axi" +
          "s]>li]:whitespace-nowrap [&_[data-part=price-axis]>li]:[transform:translateY(-50%)] [&_[data-part=price-a" +
          "xis]>li:first-child]:[transform:none] [&_[data-part=price-axis]>li:last-child]:[transform:translateY(-100" +
          "%)] [&_[data-part=time-axis]]:relative [&_[data-part=time-axis]]:[inset-block:0] [&_[data-part=time-axis]" +
          "]:[inline-size:var(--candle-content-size,_100%)] [&_[data-part=time-axis]]:[translate:calc(-1_*_var(--can" +
          "dle-scroll-x,_0px))_0] [&_[data-part=time-axis]]:[min-inline-size:0] [&_[data-part=time-axis]>li]:absolut" +
          "e [&_[data-part=time-axis]>li]:[inset-block-start:0.375rem] [&_[data-part=time-axis]>li]:[inset-inline-st" +
          "art:var(--candle-axis-x)] [&_[data-part=time-axis]>li]:[color:var(--candle-axis)] [&_[data-part=time-axis" +
          "]>li]:[font-size:0.7rem] [&_[data-part=time-axis]>li]:whitespace-nowrap [&_[data-part=time-axis]>li]:[tra" +
          "nsform:translateX(-50%)] [&_[data-part=time-axis]>li:first-child]:[transform:none] [&_[data-part=time-axi" +
          "s]>li:last-child]:[transform:translateX(-100%)] [&_[data-part=time-axis]>li:only-child]:[transform:transl" +
          "ateX(-50%)] [&_[data-part=time-axis]>li[data-part=crosshair-time]]:[transform:translateX(-50%)] [&_[data-" +
          "part=price-axis]>li[data-part=crosshair-price]]:[transform:translateY(-50%)] [&>table]:absolute [&>table]" +
          ":[inline-size:1px] [&>table]:[block-size:1px] [&>table]:overflow-hidden [&>table]:[clip-path:inset(50%)] " +
          "[&>table]:whitespace-nowrap"
        }
        data={data}
        aria-label="BTC / USD daily candles"
      />
      <CandleChartClient
        className={
          "[--candle-grid:color-mix(in_srgb,_currentcolor_10%,_transparent)] [--candle-down:oklch(64%_0.21_24deg)] [" +
          "--candle-flat:color-mix(in_srgb,_currentcolor_60%,_transparent)] [--candle-up:oklch(67%_0.14_166deg)] [--" +
          "candle-axis:var(--muted-foreground)] relative block [inline-size:100%] [min-block-size:21rem] [padding:1r" +
          "em_0.75rem_0.5rem] overflow-clip [overscroll-behavior:none] isolate [color-scheme:light_dark] bg-transpar" +
          "ent [color:light-dark(oklch(28%_0.04_165deg),_oklch(82%_0.04_165deg))] data-[interactive]:[touch-action:n" +
          "one] [&[data-interactive]_[data-part=scroll-viewport]]:[overscroll-behavior-inline:none] [&>[data-part=pl" +
          "ot]]:relative [&>[data-part=plot]]:grid [&>[data-part=plot]]:[grid-template-columns:minmax(0,_1fr)_4.5rem" +
          "] [&>[data-part=plot]]:[grid-template-rows:minmax(18rem,_1fr)_calc(1.5rem_+_var(--candle-scrollbar-size,_" +
          "0px))] [&>[data-part=plot]]:[gap:0_0.75rem] [&>[data-part=plot]]:[min-inline-size:0] [&>[data-part=plot]]" +
          ":[min-block-size:18rem] [&>[data-part=plot]]:[overscroll-behavior:none] [&_[data-part=scroll-viewport]]:[" +
          "grid-column:1] [&_[data-part=scroll-viewport]]:[grid-row:1_/_span_2] [&_[data-part=scroll-viewport]]:[min" +
          "-inline-size:0] [&_[data-part=scroll-viewport]]:[min-block-size:18rem] [&_[data-part=scroll-viewport]]:[o" +
          "verflow:auto_hidden] [&_[data-part=scroll-viewport]]:[container-type:inline-size] [&_[data-part=scroll-vi" +
          "ewport]]:[direction:rtl] [&_[data-part=canvas]]:grid [&_[data-part=canvas]]:[grid-template-rows:minmax(18" +
          "rem,_1fr)_1.5rem] [&_[data-part=canvas]]:[inline-size:calc(100%_*_var(--candle-scale))] [&_[data-part=can" +
          "vas]]:[min-inline-size:100%] [&_[data-part=canvas]]:[min-block-size:100%] [&_[data-part=canvas]]:[directi" +
          "on:ltr] [&_[data-part=candles]]:absolute [&_[data-part=candles]]:[inset-block:0] [&_[data-part=candles]]:" +
          "[inset-inline:auto_0] [&_[data-part=candles]]:[inline-size:100%] [&_[data-part=candles]]:m-0 [&_[data-par" +
          "t=candles]]:[padding:1rem_0.5rem] [&_[data-part=candles]]:list-none [&_[data-part=viewport]>[data-uiify-v" +
          "irtual-scroll]]:absolute [&_[data-part=viewport]>[data-uiify-virtual-scroll]]:inset-0 [&_[data-uiify-virt" +
          "ual-scroll]_[data-part=candle]]:[inset-block:1rem_auto] [&_[data-uiify-virtual-scroll]_[data-part=candle]" +
          "]:[block-size:calc(var(--candle-plot-height,_18rem)_-_2rem)] [&_[data-part=candles]]:[background-image:li" +
          "near-gradient(to_right,_var(--candle-grid)_1px,_transparent_1px),_linear-gradient(to_bottom,_var(--candle" +
          "-grid)_1px,_transparent_1px)] [&_[data-part=candles]]:[background-size:10%_100%,_100%_25%] [&_[data-part=" +
          "viewport]:has(>[data-uiify-virtual-scroll])]:[background-image:linear-gradient(to_right,_var(--candle-gri" +
          "d)_1px,_transparent_1px),_linear-gradient(to_bottom,_var(--candle-grid)_1px,_transparent_1px)] [&_[data-p" +
          "art=viewport]:has(>[data-uiify-virtual-scroll])]:[background-size:10%_100%,_100%_25%] [&_[data-part=viewp" +
          "ort]]:relative [&_[data-part=viewport]]:[grid-column:1] [&_[data-part=viewport]]:[grid-row:1] [&_[data-pa" +
          "rt=viewport]]:[min-inline-size:0] [&_[data-part=viewport]]:[min-block-size:18rem] [&_[data-part=viewport]" +
          "]:overflow-clip [&_[data-part=viewport]]:[overscroll-behavior:none] [&_[data-part=time-viewport]]:relativ" +
          "e [&_[data-part=time-viewport]]:[grid-column:1] [&_[data-part=time-viewport]]:[grid-row:2] [&_[data-part=" +
          "time-viewport]]:[min-inline-size:0] [&_[data-part=time-viewport]]:overflow-clip [&_[data-part=time-viewpo" +
          "rt]]:[overscroll-behavior:none] [&>figcaption]:absolute [&>figcaption]:z-[1] [&>figcaption]:[inset-block-" +
          "start:0.75rem] [&>figcaption]:[inset-inline-start:1rem] [&>figcaption]:text-muted-foreground [&>figcaptio" +
          "n]:[font-size:0.75rem] [&>figcaption]:[font-weight:650] [&>figcaption]:[letter-spacing:0.04em] [&>figcapt" +
          "ion]:[text-transform:uppercase] [&_[data-part=readout]]:absolute [&_[data-part=readout]]:z-[1] [&_[data-p" +
          "art=readout]]:[inset-block-start:0.75rem] [&_[data-part=readout]]:[inset-inline-end:1rem] [&_[data-part=r" +
          "eadout]]:flex [&_[data-part=readout]]:flex-wrap [&_[data-part=readout]]:[gap:0.375rem_0.625rem] [&_[data-" +
          "part=readout]]:items-baseline [&_[data-part=readout]]:[color:var(--candle-axis)] [&_[data-part=readout]]:" +
          "[font-size:0.7rem] [&_[data-part=readout]]:[font-variant-numeric:tabular-nums] [&_[data-part=readout]]:le" +
          "ading-none [&_[data-part=readout]]:whitespace-nowrap [&_[data-part=readout-time]]:[font-weight:650] [&_[d" +
          "ata-part=candle]]:absolute [&_[data-part=candle]]:[inset:1rem_0.5rem] [&_[data-part=candle]]:pointer-even" +
          "ts-none [&_[data-part=candle]]:[inset-inline-start:var(--candle-x)] [&_[data-part=candle]]:[inline-size:v" +
          "ar(--candle-slot)] [&_[data-part=candle]]:block [&_[data-part=candle]]:[color:var(--candle-flat)] [&_[dat" +
          "a-part=candle]]:list-none [&[data-interactive]_[data-part=candle]]:[pointer-events:auto] [&_[data-part=ca" +
          "ndle-hit]]:absolute [&_[data-part=candle-hit]]:z-[1] [&_[data-part=candle-hit]]:inset-0 [&_[data-part=can" +
          "dle-hit]]:[inline-size:100%] [&_[data-part=candle-hit]]:[block-size:100%] [&_[data-part=candle-hit]]:m-0 " +
          "[&_[data-part=candle-hit]]:p-0 [&_[data-part=candle-hit]]:border-0 [&_[data-part=candle-hit]]:border-curr" +
          "ent [&_[data-part=candle-hit]]:border-none [&_[data-part=candle-hit]]:appearance-none [&_[data-part=candl" +
          "e-hit]]:bg-transparent [&_[data-part=candle-hit]]:text-transparent [&_[data-part=candle-hit]]:[cursor:cro" +
          "sshair] [&_[data-part=candle-hit]]:[font-style:inherit] [&_[data-part=candle-hit]]:[font-variant:inherit]" +
          " [&_[data-part=candle-hit]]:[font-weight:inherit] [&_[data-part=candle-hit]]:[font-stretch:inherit] [&_[d" +
          "ata-part=candle-hit]]:text-[length:inherit] [&_[data-part=candle-hit]]:leading-[inherit] [&_[data-part=ca" +
          "ndle-hit]]:font-[family-name:inherit] [&_[data-part=candle]::before]:content-[''] [&_[data-part=candle]::" +
          "before]:absolute [&_[data-part=candle]::before]:block [&_[data-part=candle]::before]:[background:currentc" +
          "olor] [&_[data-part=candle]::after]:content-[''] [&_[data-part=candle]::after]:absolute [&_[data-part=can" +
          "dle]::after]:block [&_[data-part=candle]::after]:[background:currentcolor] [&_[data-part=candle]::before]" +
          ":[inset-block-start:var(--candle-wick-top)] [&_[data-part=candle]::before]:[inset-inline-start:50%] [&_[d" +
          "ata-part=candle]::before]:[inline-size:max(1px,_0.08em)] [&_[data-part=candle]::before]:[block-size:var(-" +
          "-candle-wick-height)] [&_[data-part=candle]::before]:[transform:translateX(-50%)] [&_[data-part=candle]::" +
          "after]:[inset-block-start:var(--candle-body-top)] [&_[data-part=candle]::after]:[inset-inline:17%] [&_[da" +
          "ta-part=candle]::after]:[block-size:var(--candle-body-height)] [&_[data-part=candle]::after]:[min-block-s" +
          "ize:1px] [&_[data-part=candle][data-direction=up]]:[color:var(--candle-up)] [&_[data-part=candle][data-di" +
          "rection=down]]:[color:var(--candle-down)] [&_[data-part=crosshair]]:absolute [&_[data-part=crosshair]]:z-" +
          "[3] [&_[data-part=crosshair]]:inset-0 [&_[data-part=crosshair]]:[inline-size:var(--candle-content-size,_1" +
          "00%)] [&_[data-part=crosshair]]:[translate:calc(-1_*_var(--candle-scroll-x,_0px))_0] [&_[data-part=crossh" +
          "air]]:[block-size:100%] [&_[data-part=crosshair]]:[color:light-dark(oklch(52%_0.01_0deg),_oklch(72%_0.01_" +
          "0deg))] [&_[data-part=crosshair]]:pointer-events-none [&_[data-part=crosshair]::before]:content-[''] [&_[" +
          "data-part=crosshair]::before]:absolute [&_[data-part=crosshair]::before]:block [&_[data-part=crosshair]::" +
          "before]:[background:currentcolor] [&_[data-part=crosshair]::after]:content-[''] [&_[data-part=crosshair]:" +
          ":after]:absolute [&_[data-part=crosshair]::after]:block [&_[data-part=crosshair]::after]:[background:curr" +
          "entcolor] [&_[data-part=crosshair]::before]:[inset-block:0] [&_[data-part=crosshair]::before]:[inset-inli" +
          "ne-start:var(--candle-crosshair-x)] [&_[data-part=crosshair]::before]:[inline-size:1px] [&_[data-part=cro" +
          "sshair]::before]:[background-image:repeating-linear-gradient(_to_bottom,_currentcolor_0_0.4rem,_transpare" +
          "nt_0.4rem_0.8rem_)] [&_[data-part=crosshair]::before]:bg-transparent [&_[data-part=crosshair]::after]:[in" +
          "set-block-start:calc(var(--candle-cursor-y,_50%)_+_1rem)] [&_[data-part=crosshair]::after]:[inset-inline:" +
          "0] [&_[data-part=crosshair]::after]:[block-size:1px] [&_[data-part=crosshair]::after]:[background-image:r" +
          "epeating-linear-gradient(_to_right,_currentcolor_0_0.4rem,_transparent_0.4rem_0.8rem_)] [&_[data-part=cro" +
          "sshair]::after]:bg-transparent [&_[data-part=crosshair-marker]]:absolute [&_[data-part=crosshair-marker]]" +
          ":[inset-block-start:calc(var(--candle-cursor-y,_50%)_+_1rem)] [&_[data-part=crosshair-marker]]:[inset-inl" +
          "ine-start:var(--candle-crosshair-x)] [&_[data-part=crosshair-marker]]:[font-size:1rem] [&_[data-part=cros" +
          "shair-marker]]:leading-none [&_[data-part=crosshair-marker]]:[transform:translate(-50%,_-50%)] [&_[data-p" +
          "art=time-axis]>[data-part=crosshair-time]]:[inset-block-start:0] [&_[data-part=time-axis]>[data-part=cros" +
          "shair-time]]:[inset-inline-start:var(--candle-crosshair-x)] [&_[data-part=time-axis]>[data-part=crosshair" +
          "-time]]:[padding:0.25rem_0.5rem] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[background:var(--c" +
          "andle-axis)] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[color:Canvas] [&_[data-part=time-axis]" +
          ">[data-part=crosshair-time]]:[font-weight:650] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[tran" +
          "sform:translateX(-50%)] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[inset-block-start:calc(va" +
          "r(--candle-cursor-y,_50%)_+_1rem)] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[inset-inline-e" +
          "nd:0] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[padding:0.25rem_0.5rem] [&_[data-part=price" +
          "-axis]>[data-part=crosshair-price]]:[background:var(--candle-axis)] [&_[data-part=price-axis]>[data-part=" +
          "crosshair-price]]:[color:Canvas] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[font-weight:650]" +
          " [&_[data-part=price-axis]>[data-part=crosshair-price]]:[transform:translateY(-50%)] [&[data-interactive]" +
          "_[data-part=candle-hit]:focus-visible]:[outline:2px_solid_currentcolor] [&[data-interactive]_[data-part=c" +
          "andle-hit]:focus-visible]:[outline-offset:-2px] [&_[data-part=price-axis]]:m-0 [&_[data-part=price-axis]]" +
          ":p-0 [&_[data-part=price-axis]]:list-none [&_[data-part=time-axis]]:m-0 [&_[data-part=time-axis]]:p-0 [&_" +
          "[data-part=time-axis]]:list-none [&_[data-part=price-axis]]:relative [&_[data-part=price-axis]]:[grid-col" +
          "umn:2] [&_[data-part=price-axis]]:[grid-row:1] [&_[data-part=price-axis]]:[min-inline-size:0] [&_[data-pa" +
          "rt=price-axis]>li]:absolute [&_[data-part=price-axis]>li]:[inset-inline:0] [&_[data-part=price-axis]>li]:" +
          "[inset-block-start:var(--candle-axis-y)] [&_[data-part=price-axis]>li]:overflow-hidden [&_[data-part=pric" +
          "e-axis]>li]:[color:var(--candle-axis)] [&_[data-part=price-axis]>li]:[font-size:0.65rem] [&_[data-part=pr" +
          "ice-axis]>li]:[font-variant-numeric:tabular-nums] [&_[data-part=price-axis]>li]:leading-none [&_[data-par" +
          "t=price-axis]>li]:text-end [&_[data-part=price-axis]>li]:[text-overflow:ellipsis] [&_[data-part=price-axi" +
          "s]>li]:whitespace-nowrap [&_[data-part=price-axis]>li]:[transform:translateY(-50%)] [&_[data-part=price-a" +
          "xis]>li:first-child]:[transform:none] [&_[data-part=price-axis]>li:last-child]:[transform:translateY(-100" +
          "%)] [&_[data-part=time-axis]]:relative [&_[data-part=time-axis]]:[inset-block:0] [&_[data-part=time-axis]" +
          "]:[inline-size:var(--candle-content-size,_100%)] [&_[data-part=time-axis]]:[translate:calc(-1_*_var(--can" +
          "dle-scroll-x,_0px))_0] [&_[data-part=time-axis]]:[min-inline-size:0] [&_[data-part=time-axis]>li]:absolut" +
          "e [&_[data-part=time-axis]>li]:[inset-block-start:0.375rem] [&_[data-part=time-axis]>li]:[inset-inline-st" +
          "art:var(--candle-axis-x)] [&_[data-part=time-axis]>li]:[color:var(--candle-axis)] [&_[data-part=time-axis" +
          "]>li]:[font-size:0.7rem] [&_[data-part=time-axis]>li]:whitespace-nowrap [&_[data-part=time-axis]>li]:[tra" +
          "nsform:translateX(-50%)] [&_[data-part=time-axis]>li:first-child]:[transform:none] [&_[data-part=time-axi" +
          "s]>li:last-child]:[transform:translateX(-100%)] [&_[data-part=time-axis]>li:only-child]:[transform:transl" +
          "ateX(-50%)] [&_[data-part=time-axis]>li[data-part=crosshair-time]]:[transform:translateX(-50%)] [&_[data-" +
          "part=price-axis]>li[data-part=crosshair-price]]:[transform:translateY(-50%)] [&>table]:absolute [&>table]" +
          ":[inline-size:1px] [&>table]:[block-size:1px] [&>table]:overflow-hidden [&>table]:[clip-path:inset(50%)] " +
          "[&>table]:whitespace-nowrap"
        }
        data={data}
        aria-label="Interactive BTC / USD daily candles"
      />
      <LiveChart />
    </>
  );
}

function LiveChart() {
  const [candles, setCandles] = useState(data);
  const [running, setRunning] = useState(false);

  useEffect(() => {
    if (!running) return;
    const timer = setInterval(() => {
      setCandles((current) => {
        const last = current.at(-1);
        if (!last) return current;
        const close = Math.round(last.close * (1 + (Math.random() - 0.5) * 0.004));
        const next = {
          time: String(current.length),
          open: last.close,
          high: Math.max(last.close, close),
          low: Math.min(last.close, close),
          close,
        };
        return [...current, next];
      });
    }, 1000);
    return () => clearInterval(timer);
  }, [running]);

  return (
    <>
      <button type="button" onClick={() => setRunning((value) => !value)}>
        {running ? "Stop" : "Start"}
      </button>
      {/* All candles, virtualized; 20 fit the viewport and new ones stay in view at the end. */}
      <CandleChartClient
        className={
          "[--candle-grid:color-mix(in_srgb,_currentcolor_10%,_transparent)] [--candle-down:oklch(64%_0.21_24deg)] [" +
          "--candle-flat:color-mix(in_srgb,_currentcolor_60%,_transparent)] [--candle-up:oklch(67%_0.14_166deg)] [--" +
          "candle-axis:var(--muted-foreground)] relative block [inline-size:100%] [min-block-size:21rem] [padding:1r" +
          "em_0.75rem_0.5rem] overflow-clip [overscroll-behavior:none] isolate [color-scheme:light_dark] bg-transpar" +
          "ent [color:light-dark(oklch(28%_0.04_165deg),_oklch(82%_0.04_165deg))] data-[interactive]:[touch-action:n" +
          "one] [&[data-interactive]_[data-part=scroll-viewport]]:[overscroll-behavior-inline:none] [&>[data-part=pl" +
          "ot]]:relative [&>[data-part=plot]]:grid [&>[data-part=plot]]:[grid-template-columns:minmax(0,_1fr)_4.5rem" +
          "] [&>[data-part=plot]]:[grid-template-rows:minmax(18rem,_1fr)_calc(1.5rem_+_var(--candle-scrollbar-size,_" +
          "0px))] [&>[data-part=plot]]:[gap:0_0.75rem] [&>[data-part=plot]]:[min-inline-size:0] [&>[data-part=plot]]" +
          ":[min-block-size:18rem] [&>[data-part=plot]]:[overscroll-behavior:none] [&_[data-part=scroll-viewport]]:[" +
          "grid-column:1] [&_[data-part=scroll-viewport]]:[grid-row:1_/_span_2] [&_[data-part=scroll-viewport]]:[min" +
          "-inline-size:0] [&_[data-part=scroll-viewport]]:[min-block-size:18rem] [&_[data-part=scroll-viewport]]:[o" +
          "verflow:auto_hidden] [&_[data-part=scroll-viewport]]:[container-type:inline-size] [&_[data-part=scroll-vi" +
          "ewport]]:[direction:rtl] [&_[data-part=canvas]]:grid [&_[data-part=canvas]]:[grid-template-rows:minmax(18" +
          "rem,_1fr)_1.5rem] [&_[data-part=canvas]]:[inline-size:calc(100%_*_var(--candle-scale))] [&_[data-part=can" +
          "vas]]:[min-inline-size:100%] [&_[data-part=canvas]]:[min-block-size:100%] [&_[data-part=canvas]]:[directi" +
          "on:ltr] [&_[data-part=candles]]:absolute [&_[data-part=candles]]:[inset-block:0] [&_[data-part=candles]]:" +
          "[inset-inline:auto_0] [&_[data-part=candles]]:[inline-size:100%] [&_[data-part=candles]]:m-0 [&_[data-par" +
          "t=candles]]:[padding:1rem_0.5rem] [&_[data-part=candles]]:list-none [&_[data-part=viewport]>[data-uiify-v" +
          "irtual-scroll]]:absolute [&_[data-part=viewport]>[data-uiify-virtual-scroll]]:inset-0 [&_[data-uiify-virt" +
          "ual-scroll]_[data-part=candle]]:[inset-block:1rem_auto] [&_[data-uiify-virtual-scroll]_[data-part=candle]" +
          "]:[block-size:calc(var(--candle-plot-height,_18rem)_-_2rem)] [&_[data-part=candles]]:[background-image:li" +
          "near-gradient(to_right,_var(--candle-grid)_1px,_transparent_1px),_linear-gradient(to_bottom,_var(--candle" +
          "-grid)_1px,_transparent_1px)] [&_[data-part=candles]]:[background-size:10%_100%,_100%_25%] [&_[data-part=" +
          "viewport]:has(>[data-uiify-virtual-scroll])]:[background-image:linear-gradient(to_right,_var(--candle-gri" +
          "d)_1px,_transparent_1px),_linear-gradient(to_bottom,_var(--candle-grid)_1px,_transparent_1px)] [&_[data-p" +
          "art=viewport]:has(>[data-uiify-virtual-scroll])]:[background-size:10%_100%,_100%_25%] [&_[data-part=viewp" +
          "ort]]:relative [&_[data-part=viewport]]:[grid-column:1] [&_[data-part=viewport]]:[grid-row:1] [&_[data-pa" +
          "rt=viewport]]:[min-inline-size:0] [&_[data-part=viewport]]:[min-block-size:18rem] [&_[data-part=viewport]" +
          "]:overflow-clip [&_[data-part=viewport]]:[overscroll-behavior:none] [&_[data-part=time-viewport]]:relativ" +
          "e [&_[data-part=time-viewport]]:[grid-column:1] [&_[data-part=time-viewport]]:[grid-row:2] [&_[data-part=" +
          "time-viewport]]:[min-inline-size:0] [&_[data-part=time-viewport]]:overflow-clip [&_[data-part=time-viewpo" +
          "rt]]:[overscroll-behavior:none] [&>figcaption]:absolute [&>figcaption]:z-[1] [&>figcaption]:[inset-block-" +
          "start:0.75rem] [&>figcaption]:[inset-inline-start:1rem] [&>figcaption]:text-muted-foreground [&>figcaptio" +
          "n]:[font-size:0.75rem] [&>figcaption]:[font-weight:650] [&>figcaption]:[letter-spacing:0.04em] [&>figcapt" +
          "ion]:[text-transform:uppercase] [&_[data-part=readout]]:absolute [&_[data-part=readout]]:z-[1] [&_[data-p" +
          "art=readout]]:[inset-block-start:0.75rem] [&_[data-part=readout]]:[inset-inline-end:1rem] [&_[data-part=r" +
          "eadout]]:flex [&_[data-part=readout]]:flex-wrap [&_[data-part=readout]]:[gap:0.375rem_0.625rem] [&_[data-" +
          "part=readout]]:items-baseline [&_[data-part=readout]]:[color:var(--candle-axis)] [&_[data-part=readout]]:" +
          "[font-size:0.7rem] [&_[data-part=readout]]:[font-variant-numeric:tabular-nums] [&_[data-part=readout]]:le" +
          "ading-none [&_[data-part=readout]]:whitespace-nowrap [&_[data-part=readout-time]]:[font-weight:650] [&_[d" +
          "ata-part=candle]]:absolute [&_[data-part=candle]]:[inset:1rem_0.5rem] [&_[data-part=candle]]:pointer-even" +
          "ts-none [&_[data-part=candle]]:[inset-inline-start:var(--candle-x)] [&_[data-part=candle]]:[inline-size:v" +
          "ar(--candle-slot)] [&_[data-part=candle]]:block [&_[data-part=candle]]:[color:var(--candle-flat)] [&_[dat" +
          "a-part=candle]]:list-none [&[data-interactive]_[data-part=candle]]:[pointer-events:auto] [&_[data-part=ca" +
          "ndle-hit]]:absolute [&_[data-part=candle-hit]]:z-[1] [&_[data-part=candle-hit]]:inset-0 [&_[data-part=can" +
          "dle-hit]]:[inline-size:100%] [&_[data-part=candle-hit]]:[block-size:100%] [&_[data-part=candle-hit]]:m-0 " +
          "[&_[data-part=candle-hit]]:p-0 [&_[data-part=candle-hit]]:border-0 [&_[data-part=candle-hit]]:border-curr" +
          "ent [&_[data-part=candle-hit]]:border-none [&_[data-part=candle-hit]]:appearance-none [&_[data-part=candl" +
          "e-hit]]:bg-transparent [&_[data-part=candle-hit]]:text-transparent [&_[data-part=candle-hit]]:[cursor:cro" +
          "sshair] [&_[data-part=candle-hit]]:[font-style:inherit] [&_[data-part=candle-hit]]:[font-variant:inherit]" +
          " [&_[data-part=candle-hit]]:[font-weight:inherit] [&_[data-part=candle-hit]]:[font-stretch:inherit] [&_[d" +
          "ata-part=candle-hit]]:text-[length:inherit] [&_[data-part=candle-hit]]:leading-[inherit] [&_[data-part=ca" +
          "ndle-hit]]:font-[family-name:inherit] [&_[data-part=candle]::before]:content-[''] [&_[data-part=candle]::" +
          "before]:absolute [&_[data-part=candle]::before]:block [&_[data-part=candle]::before]:[background:currentc" +
          "olor] [&_[data-part=candle]::after]:content-[''] [&_[data-part=candle]::after]:absolute [&_[data-part=can" +
          "dle]::after]:block [&_[data-part=candle]::after]:[background:currentcolor] [&_[data-part=candle]::before]" +
          ":[inset-block-start:var(--candle-wick-top)] [&_[data-part=candle]::before]:[inset-inline-start:50%] [&_[d" +
          "ata-part=candle]::before]:[inline-size:max(1px,_0.08em)] [&_[data-part=candle]::before]:[block-size:var(-" +
          "-candle-wick-height)] [&_[data-part=candle]::before]:[transform:translateX(-50%)] [&_[data-part=candle]::" +
          "after]:[inset-block-start:var(--candle-body-top)] [&_[data-part=candle]::after]:[inset-inline:17%] [&_[da" +
          "ta-part=candle]::after]:[block-size:var(--candle-body-height)] [&_[data-part=candle]::after]:[min-block-s" +
          "ize:1px] [&_[data-part=candle][data-direction=up]]:[color:var(--candle-up)] [&_[data-part=candle][data-di" +
          "rection=down]]:[color:var(--candle-down)] [&_[data-part=crosshair]]:absolute [&_[data-part=crosshair]]:z-" +
          "[3] [&_[data-part=crosshair]]:inset-0 [&_[data-part=crosshair]]:[inline-size:var(--candle-content-size,_1" +
          "00%)] [&_[data-part=crosshair]]:[translate:calc(-1_*_var(--candle-scroll-x,_0px))_0] [&_[data-part=crossh" +
          "air]]:[block-size:100%] [&_[data-part=crosshair]]:[color:light-dark(oklch(52%_0.01_0deg),_oklch(72%_0.01_" +
          "0deg))] [&_[data-part=crosshair]]:pointer-events-none [&_[data-part=crosshair]::before]:content-[''] [&_[" +
          "data-part=crosshair]::before]:absolute [&_[data-part=crosshair]::before]:block [&_[data-part=crosshair]::" +
          "before]:[background:currentcolor] [&_[data-part=crosshair]::after]:content-[''] [&_[data-part=crosshair]:" +
          ":after]:absolute [&_[data-part=crosshair]::after]:block [&_[data-part=crosshair]::after]:[background:curr" +
          "entcolor] [&_[data-part=crosshair]::before]:[inset-block:0] [&_[data-part=crosshair]::before]:[inset-inli" +
          "ne-start:var(--candle-crosshair-x)] [&_[data-part=crosshair]::before]:[inline-size:1px] [&_[data-part=cro" +
          "sshair]::before]:[background-image:repeating-linear-gradient(_to_bottom,_currentcolor_0_0.4rem,_transpare" +
          "nt_0.4rem_0.8rem_)] [&_[data-part=crosshair]::before]:bg-transparent [&_[data-part=crosshair]::after]:[in" +
          "set-block-start:calc(var(--candle-cursor-y,_50%)_+_1rem)] [&_[data-part=crosshair]::after]:[inset-inline:" +
          "0] [&_[data-part=crosshair]::after]:[block-size:1px] [&_[data-part=crosshair]::after]:[background-image:r" +
          "epeating-linear-gradient(_to_right,_currentcolor_0_0.4rem,_transparent_0.4rem_0.8rem_)] [&_[data-part=cro" +
          "sshair]::after]:bg-transparent [&_[data-part=crosshair-marker]]:absolute [&_[data-part=crosshair-marker]]" +
          ":[inset-block-start:calc(var(--candle-cursor-y,_50%)_+_1rem)] [&_[data-part=crosshair-marker]]:[inset-inl" +
          "ine-start:var(--candle-crosshair-x)] [&_[data-part=crosshair-marker]]:[font-size:1rem] [&_[data-part=cros" +
          "shair-marker]]:leading-none [&_[data-part=crosshair-marker]]:[transform:translate(-50%,_-50%)] [&_[data-p" +
          "art=time-axis]>[data-part=crosshair-time]]:[inset-block-start:0] [&_[data-part=time-axis]>[data-part=cros" +
          "shair-time]]:[inset-inline-start:var(--candle-crosshair-x)] [&_[data-part=time-axis]>[data-part=crosshair" +
          "-time]]:[padding:0.25rem_0.5rem] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[background:var(--c" +
          "andle-axis)] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[color:Canvas] [&_[data-part=time-axis]" +
          ">[data-part=crosshair-time]]:[font-weight:650] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[tran" +
          "sform:translateX(-50%)] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[inset-block-start:calc(va" +
          "r(--candle-cursor-y,_50%)_+_1rem)] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[inset-inline-e" +
          "nd:0] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[padding:0.25rem_0.5rem] [&_[data-part=price" +
          "-axis]>[data-part=crosshair-price]]:[background:var(--candle-axis)] [&_[data-part=price-axis]>[data-part=" +
          "crosshair-price]]:[color:Canvas] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[font-weight:650]" +
          " [&_[data-part=price-axis]>[data-part=crosshair-price]]:[transform:translateY(-50%)] [&[data-interactive]" +
          "_[data-part=candle-hit]:focus-visible]:[outline:2px_solid_currentcolor] [&[data-interactive]_[data-part=c" +
          "andle-hit]:focus-visible]:[outline-offset:-2px] [&_[data-part=price-axis]]:m-0 [&_[data-part=price-axis]]" +
          ":p-0 [&_[data-part=price-axis]]:list-none [&_[data-part=time-axis]]:m-0 [&_[data-part=time-axis]]:p-0 [&_" +
          "[data-part=time-axis]]:list-none [&_[data-part=price-axis]]:relative [&_[data-part=price-axis]]:[grid-col" +
          "umn:2] [&_[data-part=price-axis]]:[grid-row:1] [&_[data-part=price-axis]]:[min-inline-size:0] [&_[data-pa" +
          "rt=price-axis]>li]:absolute [&_[data-part=price-axis]>li]:[inset-inline:0] [&_[data-part=price-axis]>li]:" +
          "[inset-block-start:var(--candle-axis-y)] [&_[data-part=price-axis]>li]:overflow-hidden [&_[data-part=pric" +
          "e-axis]>li]:[color:var(--candle-axis)] [&_[data-part=price-axis]>li]:[font-size:0.65rem] [&_[data-part=pr" +
          "ice-axis]>li]:[font-variant-numeric:tabular-nums] [&_[data-part=price-axis]>li]:leading-none [&_[data-par" +
          "t=price-axis]>li]:text-end [&_[data-part=price-axis]>li]:[text-overflow:ellipsis] [&_[data-part=price-axi" +
          "s]>li]:whitespace-nowrap [&_[data-part=price-axis]>li]:[transform:translateY(-50%)] [&_[data-part=price-a" +
          "xis]>li:first-child]:[transform:none] [&_[data-part=price-axis]>li:last-child]:[transform:translateY(-100" +
          "%)] [&_[data-part=time-axis]]:relative [&_[data-part=time-axis]]:[inset-block:0] [&_[data-part=time-axis]" +
          "]:[inline-size:var(--candle-content-size,_100%)] [&_[data-part=time-axis]]:[translate:calc(-1_*_var(--can" +
          "dle-scroll-x,_0px))_0] [&_[data-part=time-axis]]:[min-inline-size:0] [&_[data-part=time-axis]>li]:absolut" +
          "e [&_[data-part=time-axis]>li]:[inset-block-start:0.375rem] [&_[data-part=time-axis]>li]:[inset-inline-st" +
          "art:var(--candle-axis-x)] [&_[data-part=time-axis]>li]:[color:var(--candle-axis)] [&_[data-part=time-axis" +
          "]>li]:[font-size:0.7rem] [&_[data-part=time-axis]>li]:whitespace-nowrap [&_[data-part=time-axis]>li]:[tra" +
          "nsform:translateX(-50%)] [&_[data-part=time-axis]>li:first-child]:[transform:none] [&_[data-part=time-axi" +
          "s]>li:last-child]:[transform:translateX(-100%)] [&_[data-part=time-axis]>li:only-child]:[transform:transl" +
          "ateX(-50%)] [&_[data-part=time-axis]>li[data-part=crosshair-time]]:[transform:translateX(-50%)] [&_[data-" +
          "part=price-axis]>li[data-part=crosshair-price]]:[transform:translateY(-50%)] [&>table]:absolute [&>table]" +
          ":[inline-size:1px] [&>table]:[block-size:1px] [&>table]:overflow-hidden [&>table]:[clip-path:inset(50%)] " +
          "[&>table]:whitespace-nowrap"
        }
        data={candles}
        visibleCount={20}
        aria-label="Live BTC / USD candles"
      />
    </>
  );
}
/* app.css */

@layer reset, ui, app, tokens, base, demo, components, utilities, theme;

@import "@gunkin/uiify/styles/reset";

@import "@gunkin/uiify/components/behavior.css";

@import "@gunkin/uiify/styles/tokens";

@import "@gunkin/uiify/styles/tailwind";

@import "tailwindcss/utilities.css";

@theme { --spacing: 0.25rem; --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; }

@source inline('[--candle-grid:color-mix(in_srgb,_currentcolor_10%,_transparent)] [--candle-down:oklch(64%_0.21_24deg)] [--candle-flat:color-mix(in_srgb,_currentcolor_60%,_transparent)] [--candle-up:oklch(67%_0.14_166deg)] [--candle-axis:var(--muted-foreground)] relative block [inline-size:100%] [min-block-size:21rem] [padding:1rem_0.75rem_0.5rem] overflow-clip [overscroll-behavior:none] isolate [color-scheme:light_dark] bg-transparent [color:light-dark(oklch(28%_0.04_165deg),_oklch(82%_0.04_165deg))] data-[interactive]:[touch-action:none] [&[data-interactive]_[data-part=scroll-viewport]]:[overscroll-behavior-inline:none] [&>[data-part=plot]]:relative [&>[data-part=plot]]:grid [&>[data-part=plot]]:[grid-template-columns:minmax(0,_1fr)_4.5rem] [&>[data-part=plot]]:[grid-template-rows:minmax(18rem,_1fr)_calc(1.5rem_+_var(--candle-scrollbar-size,_0px))] [&>[data-part=plot]]:[gap:0_0.75rem] [&>[data-part=plot]]:[min-inline-size:0] [&>[data-part=plot]]:[min-block-size:18rem] [&>[data-part=plot]]:[overscroll-behavior:none] [&_[data-part=scroll-viewport]]:[grid-column:1] [&_[data-part=scroll-viewport]]:[grid-row:1_/_span_2] [&_[data-part=scroll-viewport]]:[min-inline-size:0] [&_[data-part=scroll-viewport]]:[min-block-size:18rem] [&_[data-part=scroll-viewport]]:[overflow:auto_hidden] [&_[data-part=scroll-viewport]]:[container-type:inline-size] [&_[data-part=scroll-viewport]]:[direction:rtl] [&_[data-part=canvas]]:grid [&_[data-part=canvas]]:[grid-template-rows:minmax(18rem,_1fr)_1.5rem] [&_[data-part=canvas]]:[inline-size:calc(100%_*_var(--candle-scale))] [&_[data-part=canvas]]:[min-inline-size:100%] [&_[data-part=canvas]]:[min-block-size:100%] [&_[data-part=canvas]]:[direction:ltr] [&_[data-part=candles]]:absolute [&_[data-part=candles]]:[inset-block:0] [&_[data-part=candles]]:[inset-inline:auto_0] [&_[data-part=candles]]:[inline-size:100%] [&_[data-part=candles]]:m-0 [&_[data-part=candles]]:[padding:1rem_0.5rem] [&_[data-part=candles]]:list-none [&_[data-part=viewport]>[data-uiify-virtual-scroll]]:absolute [&_[data-part=viewport]>[data-uiify-virtual-scroll]]:inset-0 [&_[data-uiify-virtual-scroll]_[data-part=candle]]:[inset-block:1rem_auto] [&_[data-uiify-virtual-scroll]_[data-part=candle]]:[block-size:calc(var(--candle-plot-height,_18rem)_-_2rem)] [&_[data-part=candles]]:[background-image:linear-gradient(to_right,_var(--candle-grid)_1px,_transparent_1px),_linear-gradient(to_bottom,_var(--candle-grid)_1px,_transparent_1px)] [&_[data-part=candles]]:[background-size:10%_100%,_100%_25%] [&_[data-part=viewport]:has(>[data-uiify-virtual-scroll])]:[background-image:linear-gradient(to_right,_var(--candle-grid)_1px,_transparent_1px),_linear-gradient(to_bottom,_var(--candle-grid)_1px,_transparent_1px)] [&_[data-part=viewport]:has(>[data-uiify-virtual-scroll])]:[background-size:10%_100%,_100%_25%] [&_[data-part=viewport]]:relative [&_[data-part=viewport]]:[grid-column:1] [&_[data-part=viewport]]:[grid-row:1] [&_[data-part=viewport]]:[min-inline-size:0] [&_[data-part=viewport]]:[min-block-size:18rem] [&_[data-part=viewport]]:overflow-clip [&_[data-part=viewport]]:[overscroll-behavior:none] [&_[data-part=time-viewport]]:relative [&_[data-part=time-viewport]]:[grid-column:1] [&_[data-part=time-viewport]]:[grid-row:2] [&_[data-part=time-viewport]]:[min-inline-size:0] [&_[data-part=time-viewport]]:overflow-clip [&_[data-part=time-viewport]]:[overscroll-behavior:none] [&>figcaption]:absolute [&>figcaption]:z-[1] [&>figcaption]:[inset-block-start:0.75rem] [&>figcaption]:[inset-inline-start:1rem] [&>figcaption]:text-muted-foreground [&>figcaption]:[font-size:0.75rem] [&>figcaption]:[font-weight:650] [&>figcaption]:[letter-spacing:0.04em] [&>figcaption]:[text-transform:uppercase] [&_[data-part=readout]]:absolute [&_[data-part=readout]]:z-[1] [&_[data-part=readout]]:[inset-block-start:0.75rem] [&_[data-part=readout]]:[inset-inline-end:1rem] [&_[data-part=readout]]:flex [&_[data-part=readout]]:flex-wrap [&_[data-part=readout]]:[gap:0.375rem_0.625rem] [&_[data-part=readout]]:items-baseline [&_[data-part=readout]]:[color:var(--candle-axis)] [&_[data-part=readout]]:[font-size:0.7rem] [&_[data-part=readout]]:[font-variant-numeric:tabular-nums] [&_[data-part=readout]]:leading-none [&_[data-part=readout]]:whitespace-nowrap [&_[data-part=readout-time]]:[font-weight:650] [&_[data-part=candle]]:absolute [&_[data-part=candle]]:[inset:1rem_0.5rem] [&_[data-part=candle]]:pointer-events-none [&_[data-part=candle]]:[inset-inline-start:var(--candle-x)] [&_[data-part=candle]]:[inline-size:var(--candle-slot)] [&_[data-part=candle]]:block [&_[data-part=candle]]:[color:var(--candle-flat)] [&_[data-part=candle]]:list-none [&[data-interactive]_[data-part=candle]]:[pointer-events:auto] [&_[data-part=candle-hit]]:absolute [&_[data-part=candle-hit]]:z-[1] [&_[data-part=candle-hit]]:inset-0 [&_[data-part=candle-hit]]:[inline-size:100%] [&_[data-part=candle-hit]]:[block-size:100%] [&_[data-part=candle-hit]]:m-0 [&_[data-part=candle-hit]]:p-0 [&_[data-part=candle-hit]]:border-0 [&_[data-part=candle-hit]]:border-current [&_[data-part=candle-hit]]:border-none [&_[data-part=candle-hit]]:appearance-none [&_[data-part=candle-hit]]:bg-transparent [&_[data-part=candle-hit]]:text-transparent [&_[data-part=candle-hit]]:[cursor:crosshair] [&_[data-part=candle-hit]]:[font-style:inherit] [&_[data-part=candle-hit]]:[font-variant:inherit] [&_[data-part=candle-hit]]:[font-weight:inherit] [&_[data-part=candle-hit]]:[font-stretch:inherit] [&_[data-part=candle-hit]]:text-[length:inherit] [&_[data-part=candle-hit]]:leading-[inherit] [&_[data-part=candle-hit]]:font-[family-name:inherit] [&_[data-part=candle]::before]:absolute [&_[data-part=candle]::before]:block [&_[data-part=candle]::before]:[background:currentcolor] [&_[data-part=candle]::after]:absolute [&_[data-part=candle]::after]:block [&_[data-part=candle]::after]:[background:currentcolor] [&_[data-part=candle]::before]:[inset-block-start:var(--candle-wick-top)] [&_[data-part=candle]::before]:[inset-inline-start:50%] [&_[data-part=candle]::before]:[inline-size:max(1px,_0.08em)] [&_[data-part=candle]::before]:[block-size:var(--candle-wick-height)] [&_[data-part=candle]::before]:[transform:translateX(-50%)] [&_[data-part=candle]::after]:[inset-block-start:var(--candle-body-top)] [&_[data-part=candle]::after]:[inset-inline:17%] [&_[data-part=candle]::after]:[block-size:var(--candle-body-height)] [&_[data-part=candle]::after]:[min-block-size:1px] [&_[data-part=candle][data-direction=up]]:[color:var(--candle-up)] [&_[data-part=candle][data-direction=down]]:[color:var(--candle-down)] [&_[data-part=crosshair]]:absolute [&_[data-part=crosshair]]:z-[3] [&_[data-part=crosshair]]:inset-0 [&_[data-part=crosshair]]:[inline-size:var(--candle-content-size,_100%)] [&_[data-part=crosshair]]:[translate:calc(-1_*_var(--candle-scroll-x,_0px))_0] [&_[data-part=crosshair]]:[block-size:100%] [&_[data-part=crosshair]]:[color:light-dark(oklch(52%_0.01_0deg),_oklch(72%_0.01_0deg))] [&_[data-part=crosshair]]:pointer-events-none [&_[data-part=crosshair]::before]:absolute [&_[data-part=crosshair]::before]:block [&_[data-part=crosshair]::before]:[background:currentcolor] [&_[data-part=crosshair]::after]:absolute [&_[data-part=crosshair]::after]:block [&_[data-part=crosshair]::after]:[background:currentcolor] [&_[data-part=crosshair]::before]:[inset-block:0] [&_[data-part=crosshair]::before]:[inset-inline-start:var(--candle-crosshair-x)] [&_[data-part=crosshair]::before]:[inline-size:1px] [&_[data-part=crosshair]::before]:[background-image:repeating-linear-gradient(_to_bottom,_currentcolor_0_0.4rem,_transparent_0.4rem_0.8rem_)] [&_[data-part=crosshair]::before]:bg-transparent [&_[data-part=crosshair]::after]:[inset-block-start:calc(var(--candle-cursor-y,_50%)_+_1rem)] [&_[data-part=crosshair]::after]:[inset-inline:0] [&_[data-part=crosshair]::after]:[block-size:1px] [&_[data-part=crosshair]::after]:[background-image:repeating-linear-gradient(_to_right,_currentcolor_0_0.4rem,_transparent_0.4rem_0.8rem_)] [&_[data-part=crosshair]::after]:bg-transparent [&_[data-part=crosshair-marker]]:absolute [&_[data-part=crosshair-marker]]:[inset-block-start:calc(var(--candle-cursor-y,_50%)_+_1rem)] [&_[data-part=crosshair-marker]]:[inset-inline-start:var(--candle-crosshair-x)] [&_[data-part=crosshair-marker]]:[font-size:1rem] [&_[data-part=crosshair-marker]]:leading-none [&_[data-part=crosshair-marker]]:[transform:translate(-50%,_-50%)] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[inset-block-start:0] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[inset-inline-start:var(--candle-crosshair-x)] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[padding:0.25rem_0.5rem] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[background:var(--candle-axis)] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[color:Canvas] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[font-weight:650] [&_[data-part=time-axis]>[data-part=crosshair-time]]:[transform:translateX(-50%)] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[inset-block-start:calc(var(--candle-cursor-y,_50%)_+_1rem)] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[inset-inline-end:0] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[padding:0.25rem_0.5rem] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[background:var(--candle-axis)] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[color:Canvas] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[font-weight:650] [&_[data-part=price-axis]>[data-part=crosshair-price]]:[transform:translateY(-50%)] [&[data-interactive]_[data-part=candle-hit]:focus-visible]:[outline:2px_solid_currentcolor] [&[data-interactive]_[data-part=candle-hit]:focus-visible]:[outline-offset:-2px] [&_[data-part=price-axis]]:m-0 [&_[data-part=price-axis]]:p-0 [&_[data-part=price-axis]]:list-none [&_[data-part=time-axis]]:m-0 [&_[data-part=time-axis]]:p-0 [&_[data-part=time-axis]]:list-none [&_[data-part=price-axis]]:relative [&_[data-part=price-axis]]:[grid-column:2] [&_[data-part=price-axis]]:[grid-row:1] [&_[data-part=price-axis]]:[min-inline-size:0] [&_[data-part=price-axis]>li]:absolute [&_[data-part=price-axis]>li]:[inset-inline:0] [&_[data-part=price-axis]>li]:[inset-block-start:var(--candle-axis-y)] [&_[data-part=price-axis]>li]:overflow-hidden [&_[data-part=price-axis]>li]:[color:var(--candle-axis)] [&_[data-part=price-axis]>li]:[font-size:0.65rem] [&_[data-part=price-axis]>li]:[font-variant-numeric:tabular-nums] [&_[data-part=price-axis]>li]:leading-none [&_[data-part=price-axis]>li]:text-end [&_[data-part=price-axis]>li]:[text-overflow:ellipsis] [&_[data-part=price-axis]>li]:whitespace-nowrap [&_[data-part=price-axis]>li]:[transform:translateY(-50%)] [&_[data-part=price-axis]>li:first-child]:[transform:none] [&_[data-part=price-axis]>li:last-child]:[transform:translateY(-100%)] [&_[data-part=time-axis]]:relative [&_[data-part=time-axis]]:[inset-block:0] [&_[data-part=time-axis]]:[inline-size:var(--candle-content-size,_100%)] [&_[data-part=time-axis]]:[translate:calc(-1_*_var(--candle-scroll-x,_0px))_0] [&_[data-part=time-axis]]:[min-inline-size:0] [&_[data-part=time-axis]>li]:absolute [&_[data-part=time-axis]>li]:[inset-block-start:0.375rem] [&_[data-part=time-axis]>li]:[inset-inline-start:var(--candle-axis-x)] [&_[data-part=time-axis]>li]:[color:var(--candle-axis)] [&_[data-part=time-axis]>li]:[font-size:0.7rem] [&_[data-part=time-axis]>li]:whitespace-nowrap [&_[data-part=time-axis]>li]:[transform:translateX(-50%)] [&_[data-part=time-axis]>li:first-child]:[transform:none] [&_[data-part=time-axis]>li:last-child]:[transform:translateX(-100%)] [&_[data-part=time-axis]>li:only-child]:[transform:translateX(-50%)] [&_[data-part=time-axis]>li[data-part=crosshair-time]]:[transform:translateX(-50%)] [&_[data-part=price-axis]>li[data-part=crosshair-price]]:[transform:translateY(-50%)] [&>table]:absolute [&>table]:[inline-size:1px] [&>table]:[block-size:1px] [&>table]:overflow-hidden [&>table]:[clip-path:inset(50%)] [&>table]:whitespace-nowrap');

@source inline("[&_[data-part=candle]::before]:content-[''] [&_[data-part=candle]::after]:content-[''] [&_[data-part=crosshair]::before]:content-[''] [&_[data-part=crosshair]::after]:content-['']");

@layer base { :root { --uiify-control-text: var(--text-sm); } @media (pointer: coarse) { :root { --uiify-control-text: var(--text-base); } } }

/* Authored animation and registered properties used by the Tailwind skin.
 * Visual rules belong in utility recipes; only at-rule definitions live here. */
@layer components {
  @keyframes uiify-presence-in {
    from {
      opacity: 0;
      scale: var(--presence-scale);
    }
  }
}

@layer components {
  @keyframes uiify-presence-out {
    to {
      opacity: 0;
      scale: var(--presence-scale);
    }
  }
}

@property --uiify-spinner-tail {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

@property --uiify-spinner-length {
  syntax: "<angle>";
  inherits: false;
  initial-value: 36deg;
}

@layer components {
  @keyframes uiify-spinner-rotate {
    to {
      transform: rotate(360deg);
    }
  }
}

@layer components {
  @keyframes uiify-spinner-orbit {
    0% {
      --uiify-spinner-tail: 0deg;
      --uiify-spinner-length: 36deg;
    }

    50% {
      --uiify-spinner-tail: 90deg;
      --uiify-spinner-length: 324deg;
    }

    100% {
      --uiify-spinner-tail: 360deg;
      --uiify-spinner-length: 36deg;
    }
  }
}

@layer components {
  @keyframes uiify-skeleton-pulse {
    50% {
      opacity: 0.45;
    }
  }
}

@layer components {
  @keyframes uiify-skeleton-shimmer {
    to {
      background-position: -200% 0;
    }
  }
}

@layer components {
  @keyframes uiify-skeleton-reveal {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }
}

@property --candle-body-height {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}

@property --candle-body-top {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --candle-slot {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 100%;
}

@property --candle-wick-height {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}

@property --candle-wick-top {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --candle-x {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}

@property --candle-scale {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}

@property --line-y {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --line-prev-y {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --line-count {
  syntax: "<integer>";
  inherits: false;
  initial-value: 1;
}

@property --line-scale {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}

@layer components {
  @keyframes uiify-otp-input-caret-blink {
    50% {
      opacity: 0;
    }
  }
}

API

CandleChart

属性类型默认值说明
data*readonly CandleChartData[]—OHLC记录;每项包含time、open、high、low和close值。
aria-labelstring"Candlestick chart"用于图表及其数据表格的无障碍名称。
xAxisreadonly CandleChartAxisLabel[]—可选的自定义底部轴标签。每项提供任意React内容和0到100%的位置。
yAxisreadonly CandleChartAxisLabel[]—可选的自定义右侧轴标签。每项提供任意React内容和0到100%的位置。
interactiveboolean—启用蜡烛命中区域、十字线状态、键盘激活和React渲染的OHLC读数;CandleChartClient会自动设置。
renderReactElement | ((props, state) => ReactElement)—替换渲染元素,同时保留行为和无障碍连接关系。

CandleChartClient (@gunkin/uiify/components/candle-chart/client)

属性类型默认值说明
data*readonly CandleChartData[]—与CandleChart相同的OHLC数据;客户端添加滚轮缩放、水平滚动、吸附蜡烛的十字线、键盘蜡烛选择、固定轴值和OHLC读数。
visibleCountnumber—实时模式:N根蜡烛填满视口;历史数据使用虚拟化。轴、读数和表格跟随可见蜡烛;未向回滚动时,图表跟随新增蜡烛,并关闭缩放和播报。

useChartViewport (@gunkin/uiify/hooks)

属性类型默认值说明
itemCount*number—视口模型中的蜡烛数量。
initialScalenumber3.2初始CSS缩放比例;视口初始固定在右边缘。
minScale / maxScalenumber—可选的缩放边界。缩放不会使图表小于容器;默认最大值为项数的一半,因此100项时,每个蜡烛槽位最多占50%。

键盘

按键操作
Tab聚焦可交互的蜡烛
Enter / Space选择已聚焦的蜡烛并更新读数

无障碍

静态蜡烛图形用于装饰,图中包含视觉隐藏的表格,列出原始时间、开盘、最高、最低和收盘值。可选客户端入口保留该表格,同时使蜡烛可通过键盘聚焦,并添加滚轮缩放、原生水平滚动、吸附十字线和React渲染的OHLC读数。

样式钩子

data-uiify-candle-chartdata-interactivedata-directiondata-timedata-crosshair-activedata-axis--candle-x--candle-slot--candle-wick-top--candle-wick-height--candle-body-top--candle-body-height--candle-axis-x--candle-axis-y--candle-scale--candle-crosshair-x--candle-cursor-y
本页由机器翻译,尚未经人工审核。