Candle chart
Gráfico estático de candles OHLC renderizado apenas com CSS.
- Navegadores
- Chrome 123+, Firefox 121+, Safari 17.5+
- Nível
- 0
- Limite de layout forçado
- 0 ms
- Limite do axe
- 0
- Compatível com SSR
- Sim
- Contrato publicado
- Ambiente de teste
Experimentar
Candle chart
100 daily OHLC items with CSS geometry, automatic axes, and an optional interactive client entry.
CSS-only chart
- Aug 25
- Sep 25
- Oct 25
- Nov 25
- 28,108
- 27,261.4
- 26,414.8
- 25,568.2
- 24,721.6
- 23,875
| Time | Open | High | Low | Close |
|---|---|---|---|---|
| 2025-08-20 | 24000 | 24200 | 23875 | 24060 |
| 2025-08-21 | 24166 | 24567 | 24023 | 24405 |
| 2025-08-22 | 24324 | 24508 | 24102 | 24263 |
| 2025-08-23 | 24470 | 24676 | 24236 | 24415 |
| 2025-08-24 | 24598 | 25052 | 24473 | 24824 |
| 2025-08-25 | 24703 | 24861 | 24560 | 24721 |
| 2025-08-26 | 24782 | 24944 | 24468 | 24629 |
| 2025-08-27 | 24834 | 25155 | 24655 | 24971 |
| 2025-08-28 | 24859 | 25156 | 24734 | 24950 |
| 2025-08-29 | 24859 | 25087 | 24515 | 24658 |
| 2025-08-30 | 24836 | 24980 | 24675 | 24840 |
| 2025-08-31 | 24797 | 25092 | 24618 | 24930 |
| 2025-09-01 | 24746 | 24930 | 24439 | 24564 |
| 2025-09-02 | 24689 | 24895 | 24415 | 24558 |
| 2025-09-03 | 24633 | 24993 | 24472 | 24765 |
| 2025-09-04 | 24584 | 24724 | 24303 | 24482 |
| 2025-09-05 | 24548 | 24710 | 24202 | 24327 |
| 2025-09-06 | 24530 | 24803 | 24387 | 24619 |
| 2025-09-07 | 24533 | 24752 | 24372 | 24546 |
| 2025-09-08 | 24559 | 24787 | 24143 | 24322 |
| 2025-09-09 | 24609 | 24766 | 24484 | 24626 |
| 2025-09-10 | 24683 | 24969 | 24540 | 24807 |
| 2025-09-11 | 24776 | 24960 | 24441 | 24602 |
| 2025-09-12 | 24886 | 25092 | 24647 | 24826 |
| 2025-09-13 | 25008 | 25431 | 24883 | 25203 |
| 2025-09-14 | 25135 | 25275 | 24939 | 25082 |
| 2025-09-15 | 25261 | 25423 | 24983 | 25144 |
| 2025-09-16 | 25380 | 25765 | 25201 | 25581 |
| 2025-09-17 | 25486 | 25778 | 25361 | 25572 |
| 2025-09-18 | 25574 | 25802 | 25296 | 25439 |
| 2025-09-19 | 25639 | 25919 | 25478 | 25779 |
| 2025-09-20 | 25678 | 26035 | 25499 | 25873 |
| 2025-09-21 | 25691 | 25875 | 25455 | 25580 |
| 2025-09-22 | 25678 | 25916 | 25535 | 25710 |
| 2025-09-23 | 25641 | 26107 | 25480 | 25879 |
| 2025-09-24 | 25582 | 25722 | 25353 | 25532 |
| 2025-09-25 | 25507 | 25669 | 25294 | 25419 |
| 2025-09-26 | 25422 | 25808 | 25279 | 25624 |
| 2025-09-27 | 25332 | 25564 | 25171 | 25358 |
| 2025-09-28 | 25246 | 25474 | 24887 | 25066 |
| 2025-09-29 | 25168 | 25407 | 25043 | 25267 |
| 2025-09-30 | 25106 | 25361 | 24963 | 25199 |
| 2025-10-01 | 25064 | 25248 | 24691 | 24852 |
| 2025-10-02 | 25046 | 25252 | 24830 | 25009 |
| 2025-10-03 | 25055 | 25413 | 24930 | 25185 |
| 2025-10-04 | 25092 | 25232 | 24775 | 24918 |
| 2025-10-05 | 25156 | 25318 | 24835 | 24996 |
| 2025-10-06 | 25245 | 25554 | 25066 | 25370 |
| 2025-10-07 | 25354 | 25560 | 25152 | 25277 |
| 2025-10-08 | 25480 | 25708 | 25108 | 25251 |
| 2025-10-09 | 25616 | 25835 | 25455 | 25695 |
| 2025-10-10 | 25755 | 25963 | 25576 | 25801 |
| 2025-10-11 | 25892 | 26076 | 25546 | 25671 |
| 2025-10-12 | 26021 | 26236 | 25878 | 26030 |
| 2025-10-13 | 26135 | 26518 | 25974 | 26290 |
| 2025-10-14 | 26230 | 26370 | 25911 | 26090 |
| 2025-10-15 | 26302 | 26464 | 26113 | 26238 |
| 2025-10-16 | 26351 | 26748 | 26208 | 26564 |
| 2025-10-17 | 26376 | 26582 | 26203 | 26364 |
| 2025-10-18 | 26379 | 26607 | 26084 | 26263 |
| 2025-10-19 | 26361 | 26701 | 26236 | 26561 |
| 2025-10-20 | 26329 | 26610 | 26186 | 26448 |
| 2025-10-21 | 26286 | 26470 | 25994 | 26155 |
| 2025-10-22 | 26239 | 26565 | 26060 | 26359 |
| 2025-10-23 | 26194 | 26632 | 26069 | 26404 |
| 2025-10-24 | 26158 | 26298 | 25912 | 26055 |
| 2025-10-25 | 26136 | 26298 | 25974 | 26135 |
| 2025-10-26 | 26134 | 26548 | 25955 | 26364 |
| 2025-10-27 | 26154 | 26360 | 25987 | 26112 |
| 2025-10-28 | 26199 | 26427 | 25933 | 26076 |
| 2025-10-29 | 26271 | 26584 | 26110 | 26444 |
| 2025-10-30 | 26368 | 26562 | 26189 | 26400 |
| 2025-10-31 | 26488 | 26672 | 26159 | 26284 |
| 2025-11-01 | 26627 | 26892 | 26484 | 26686 |
| 2025-11-02 | 26780 | 27104 | 26619 | 26876 |
| 2025-11-03 | 26941 | 27081 | 26545 | 26724 |
| 2025-11-04 | 27103 | 27265 | 26904 | 27029 |
| 2025-11-05 | 27261 | 27573 | 27118 | 27389 |
| 2025-11-06 | 27406 | 27612 | 27087 | 27248 |
| 2025-11-07 | 27535 | 27763 | 27174 | 27353 |
| 2025-11-08 | 27641 | 27901 | 27516 | 27761 |
| 2025-11-09 | 27721 | 27883 | 27532 | 27675 |
| 2025-11-10 | 27774 | 27958 | 27385 | 27546 |
| 2025-11-11 | 27799 | 28078 | 27620 | 27872 |
| 2025-11-12 | 27797 | 28108 | 27672 | 27880 |
| 2025-11-13 | 27771 | 27911 | 27430 | 27573 |
| 2025-11-14 | 27726 | 27890 | 27565 | 27728 |
| 2025-11-15 | 27666 | 28035 | 27487 | 27851 |
| 2025-11-16 | 27598 | 27804 | 27370 | 27495 |
| 2025-11-17 | 27527 | 27755 | 27315 | 27458 |
| 2025-11-18 | 27462 | 27827 | 27301 | 27687 |
| 2025-11-19 | 27407 | 27595 | 27228 | 27433 |
| 2025-11-20 | 27368 | 27552 | 27125 | 27250 |
| 2025-11-21 | 27349 | 27746 | 27206 | 27540 |
| 2025-11-22 | 27353 | 27727 | 27192 | 27499 |
| 2025-11-23 | 27382 | 27522 | 27074 | 27253 |
| 2025-11-24 | 27435 | 27689 | 27310 | 27527 |
| 2025-11-25 | 27510 | 27910 | 27367 | 27726 |
| 2025-11-26 | 27604 | 27810 | 27345 | 27506 |
| 2025-11-27 | 27712 | 27940 | 27495 | 27674 |
Interactive chart
- Aug 25
- Sep 25
- Oct 25
- Nov 25
- 28,108
- 27,261.4
- 26,414.8
- 25,568.2
- 24,721.6
- 23,875
| Time | Open | High | Low | Close |
|---|---|---|---|---|
| 2025-08-20 | 24000 | 24200 | 23875 | 24060 |
| 2025-08-21 | 24166 | 24567 | 24023 | 24405 |
| 2025-08-22 | 24324 | 24508 | 24102 | 24263 |
| 2025-08-23 | 24470 | 24676 | 24236 | 24415 |
| 2025-08-24 | 24598 | 25052 | 24473 | 24824 |
| 2025-08-25 | 24703 | 24861 | 24560 | 24721 |
| 2025-08-26 | 24782 | 24944 | 24468 | 24629 |
| 2025-08-27 | 24834 | 25155 | 24655 | 24971 |
| 2025-08-28 | 24859 | 25156 | 24734 | 24950 |
| 2025-08-29 | 24859 | 25087 | 24515 | 24658 |
| 2025-08-30 | 24836 | 24980 | 24675 | 24840 |
| 2025-08-31 | 24797 | 25092 | 24618 | 24930 |
| 2025-09-01 | 24746 | 24930 | 24439 | 24564 |
| 2025-09-02 | 24689 | 24895 | 24415 | 24558 |
| 2025-09-03 | 24633 | 24993 | 24472 | 24765 |
| 2025-09-04 | 24584 | 24724 | 24303 | 24482 |
| 2025-09-05 | 24548 | 24710 | 24202 | 24327 |
| 2025-09-06 | 24530 | 24803 | 24387 | 24619 |
| 2025-09-07 | 24533 | 24752 | 24372 | 24546 |
| 2025-09-08 | 24559 | 24787 | 24143 | 24322 |
| 2025-09-09 | 24609 | 24766 | 24484 | 24626 |
| 2025-09-10 | 24683 | 24969 | 24540 | 24807 |
| 2025-09-11 | 24776 | 24960 | 24441 | 24602 |
| 2025-09-12 | 24886 | 25092 | 24647 | 24826 |
| 2025-09-13 | 25008 | 25431 | 24883 | 25203 |
| 2025-09-14 | 25135 | 25275 | 24939 | 25082 |
| 2025-09-15 | 25261 | 25423 | 24983 | 25144 |
| 2025-09-16 | 25380 | 25765 | 25201 | 25581 |
| 2025-09-17 | 25486 | 25778 | 25361 | 25572 |
| 2025-09-18 | 25574 | 25802 | 25296 | 25439 |
| 2025-09-19 | 25639 | 25919 | 25478 | 25779 |
| 2025-09-20 | 25678 | 26035 | 25499 | 25873 |
| 2025-09-21 | 25691 | 25875 | 25455 | 25580 |
| 2025-09-22 | 25678 | 25916 | 25535 | 25710 |
| 2025-09-23 | 25641 | 26107 | 25480 | 25879 |
| 2025-09-24 | 25582 | 25722 | 25353 | 25532 |
| 2025-09-25 | 25507 | 25669 | 25294 | 25419 |
| 2025-09-26 | 25422 | 25808 | 25279 | 25624 |
| 2025-09-27 | 25332 | 25564 | 25171 | 25358 |
| 2025-09-28 | 25246 | 25474 | 24887 | 25066 |
| 2025-09-29 | 25168 | 25407 | 25043 | 25267 |
| 2025-09-30 | 25106 | 25361 | 24963 | 25199 |
| 2025-10-01 | 25064 | 25248 | 24691 | 24852 |
| 2025-10-02 | 25046 | 25252 | 24830 | 25009 |
| 2025-10-03 | 25055 | 25413 | 24930 | 25185 |
| 2025-10-04 | 25092 | 25232 | 24775 | 24918 |
| 2025-10-05 | 25156 | 25318 | 24835 | 24996 |
| 2025-10-06 | 25245 | 25554 | 25066 | 25370 |
| 2025-10-07 | 25354 | 25560 | 25152 | 25277 |
| 2025-10-08 | 25480 | 25708 | 25108 | 25251 |
| 2025-10-09 | 25616 | 25835 | 25455 | 25695 |
| 2025-10-10 | 25755 | 25963 | 25576 | 25801 |
| 2025-10-11 | 25892 | 26076 | 25546 | 25671 |
| 2025-10-12 | 26021 | 26236 | 25878 | 26030 |
| 2025-10-13 | 26135 | 26518 | 25974 | 26290 |
| 2025-10-14 | 26230 | 26370 | 25911 | 26090 |
| 2025-10-15 | 26302 | 26464 | 26113 | 26238 |
| 2025-10-16 | 26351 | 26748 | 26208 | 26564 |
| 2025-10-17 | 26376 | 26582 | 26203 | 26364 |
| 2025-10-18 | 26379 | 26607 | 26084 | 26263 |
| 2025-10-19 | 26361 | 26701 | 26236 | 26561 |
| 2025-10-20 | 26329 | 26610 | 26186 | 26448 |
| 2025-10-21 | 26286 | 26470 | 25994 | 26155 |
| 2025-10-22 | 26239 | 26565 | 26060 | 26359 |
| 2025-10-23 | 26194 | 26632 | 26069 | 26404 |
| 2025-10-24 | 26158 | 26298 | 25912 | 26055 |
| 2025-10-25 | 26136 | 26298 | 25974 | 26135 |
| 2025-10-26 | 26134 | 26548 | 25955 | 26364 |
| 2025-10-27 | 26154 | 26360 | 25987 | 26112 |
| 2025-10-28 | 26199 | 26427 | 25933 | 26076 |
| 2025-10-29 | 26271 | 26584 | 26110 | 26444 |
| 2025-10-30 | 26368 | 26562 | 26189 | 26400 |
| 2025-10-31 | 26488 | 26672 | 26159 | 26284 |
| 2025-11-01 | 26627 | 26892 | 26484 | 26686 |
| 2025-11-02 | 26780 | 27104 | 26619 | 26876 |
| 2025-11-03 | 26941 | 27081 | 26545 | 26724 |
| 2025-11-04 | 27103 | 27265 | 26904 | 27029 |
| 2025-11-05 | 27261 | 27573 | 27118 | 27389 |
| 2025-11-06 | 27406 | 27612 | 27087 | 27248 |
| 2025-11-07 | 27535 | 27763 | 27174 | 27353 |
| 2025-11-08 | 27641 | 27901 | 27516 | 27761 |
| 2025-11-09 | 27721 | 27883 | 27532 | 27675 |
| 2025-11-10 | 27774 | 27958 | 27385 | 27546 |
| 2025-11-11 | 27799 | 28078 | 27620 | 27872 |
| 2025-11-12 | 27797 | 28108 | 27672 | 27880 |
| 2025-11-13 | 27771 | 27911 | 27430 | 27573 |
| 2025-11-14 | 27726 | 27890 | 27565 | 27728 |
| 2025-11-15 | 27666 | 28035 | 27487 | 27851 |
| 2025-11-16 | 27598 | 27804 | 27370 | 27495 |
| 2025-11-17 | 27527 | 27755 | 27315 | 27458 |
| 2025-11-18 | 27462 | 27827 | 27301 | 27687 |
| 2025-11-19 | 27407 | 27595 | 27228 | 27433 |
| 2025-11-20 | 27368 | 27552 | 27125 | 27250 |
| 2025-11-21 | 27349 | 27746 | 27206 | 27540 |
| 2025-11-22 | 27353 | 27727 | 27192 | 27499 |
| 2025-11-23 | 27382 | 27522 | 27074 | 27253 |
| 2025-11-24 | 27435 | 27689 | 27310 | 27527 |
| 2025-11-25 | 27510 | 27910 | 27367 | 27726 |
| 2025-11-26 | 27604 | 27810 | 27345 | 27506 |
| 2025-11-27 | 27712 | 27940 | 27495 | 27674 |
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.
- 10:05
- 10:10
- 10:15
- 10:20
- 10:25
- 64,365.59
- 64,251.48
- 64,137.38
- 64,023.27
- 63,909.17
- 63,795.06
| Time | Open | High | Low | Close |
|---|---|---|---|---|
| 10:10 | 64342.74 | 64343.96 | 64284.5 | 64343.96 |
| 10:11 | 64343.96 | 64365.59 | 64281.29 | 64365.59 |
| 10:12 | 64365.59 | 64365.59 | 64268.45 | 64323.33 |
| 10:13 | 64323.33 | 64354.54 | 64279.59 | 64316.85 |
| 10:14 | 64316.85 | 64316.85 | 64192.7 | 64226.09 |
| 10:15 | 64226.09 | 64226.09 | 64147.22 | 64162.9 |
| 10:16 | 64162.9 | 64211.27 | 64118.76 | 64118.76 |
| 10:17 | 64118.76 | 64150.46 | 64028.67 | 64061.06 |
| 10:18 | 64061.06 | 64061.06 | 63901.42 | 63901.42 |
| 10:19 | 63901.42 | 63901.42 | 63811.16 | 63867.61 |
| 10:20 | 63867.61 | 63899.41 | 63795.06 | 63795.06 |
| 10:21 | 63795.06 | 63864.07 | 63795.06 | 63859.14 |
| 10:22 | 63859.14 | 63895.18 | 63832.49 | 63895.18 |
| 10:23 | 63895.18 | 63895.18 | 63820.02 | 63833.26 |
| 10:24 | 63833.26 | 63910.95 | 63827.54 | 63910.95 |
| 10:25 | 63910.95 | 63980.37 | 63896.74 | 63975.28 |
| 10:26 | 63975.28 | 64031.14 | 63961.35 | 64017.19 |
| 10:27 | 64017.19 | 64106.47 | 64017.19 | 64102.34 |
| 10:28 | 64102.34 | 64118.48 | 63973.18 | 63973.85 |
| 10:29 | 63973.85 | 63993.3 | 63888.51 | 63888.51 |
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
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" />
</>
);
}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 380
- 381
- 382
- 383
- 384
- 385
- 386
- 387
- 388
- 389
- 390
- 391
- 392
- 393
- 394
- 395
- 396
- 397
- 398
- 399
- 400
- 401
- 402
- 403
- 404
- 405
- 406
- 407
- 408
- 409
- 410
- 411
- 412
- 413
- 414
- 415
- 416
- 417
@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;
}
}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 380
- 381
- 382
- 383
- 384
- 385
- 386
- 387
- 388
- 389
- 390
- 391
- 392
- 393
- 394
- 395
- 396
- 397
- 398
- 399
- 400
- 401
- 402
- 403
- 404
- 405
- 406
- 407
- 408
- 409
- 410
- 411
- 412
- 413
- 414
- 415
- 416
- 417
- 418
- 419
- 420
- 421
- 422
- 423
- 424
- 425
- 426
- 427
- 428
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"
/>
</>
);
}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
/* 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
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
data* | readonly CandleChartData[] | — | Registros OHLC; cada item contém valores de tempo, abertura, máxima, mínima e fechamento. |
aria-label | string | "Candlestick chart" | Nome acessível usado no gráfico e em sua tabela de dados. |
xAxis | readonly CandleChartAxisLabel[] | — | Rótulos personalizados opcionais do eixo inferior. Cada item fornece conteúdo React livre e uma posição de 0 a 100 por cento. |
yAxis | readonly CandleChartAxisLabel[] | — | Rótulos personalizados opcionais do eixo direito. Cada item fornece conteúdo React livre e uma posição de 0 a 100 por cento. |
interactive | boolean | — | Ativa áreas de interação dos candles, estado da mira, ativação por teclado e leitura OHLC renderizada pelo React; CandleChartClient define isso automaticamente. |
render | ReactElement | ((props, state) => ReactElement) | — | Substitua o elemento renderizado preservando comportamento e conexões de acessibilidade. |
CandleChartClient (@gunkin/uiify/components/candle-chart/client)
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
data* | readonly CandleChartData[] | — | Os mesmos dados OHLC de CandleChart; o cliente acrescenta zoom pela roda do mouse, rolagem horizontal, mira ajustada ao candle, seleção de candles por teclado, valores fixos dos eixos e leitura OHLC. |
visibleCount | number | — | Modo ao vivo: N candles preenchem a área visível; o histórico é virtualizado. Eixos, leitura e tabela acompanham os candles visíveis; o gráfico acompanha novos candles, salvo se você rolar para trás, com zoom e anúncios desativados. |
useChartViewport (@gunkin/uiify/hooks)
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
itemCount* | number | — | Número de candles no modelo da área visível. |
initialScale | number | 3.2 | Escala CSS inicial; a área visível começa fixada na borda direita. |
minScale / maxScale | number | — | Limites opcionais de zoom. O zoom nunca reduz o gráfico para menos que seu contêiner; o máximo padrão é metade da quantidade de itens, de modo que 100 itens limitam cada espaço de candle a 50%. |
Teclado
| Tecla | Ação |
|---|---|
| Tab | Foque um candle interativo |
| Enter / Space | Selecione o candle em foco e atualize a leitura |
Acessibilidade
Os símbolos estáticos dos candles são decorativos, e a figura inclui uma tabela visualmente oculta com os valores originais de tempo, abertura, máxima, mínima e fechamento. A entrada opcional de cliente permite focar candles pelo teclado e acrescenta zoom pela roda do mouse, rolagem horizontal nativa, uma mira que se ajusta aos candles e leitura OHLC renderizada pelo React, preservando essa tabela.
Pontos de integração de estilos
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