use crate::{Depth, Emit, class, depth_rule, gated, hover_condition};
use makeover_layout::{Intent as _, Tone};
use std::fmt::Write as _;
pub const CHART_CLASSES: &[&str] = &[
"chart",
"chart-bars",
"chart-bar-col",
"chart-bar",
"chart-bar-label",
];
fn chart_rules(opts: &Emit) -> String {
let chart = class("chart", opts);
let bars = class("chart-bars", opts);
let col = class("chart-bar-col", opts);
let bar = class("chart-bar", opts);
let label = class("chart-bar-label", opts);
let mut css = depth_rule(&chart, Depth::Well);
let _ = writeln!(
css,
".{bars} {{\n display: flex;\n align-items: flex-end;\n \
gap: var(--chart-gap, 2px);\n height: var(--chart-height, 200px);\n}}"
);
let _ = writeln!(
css,
".{col} {{\n flex: 1;\n display: flex;\n flex-direction: column;\n \
justify-content: flex-end;\n align-self: stretch;\n \
align-items: center;\n min-width: 0;\n position: relative;\n}}"
);
let _ = writeln!(
css,
".{bar} {{\n width: 100%;\n background: var(--action);\n \
min-height: var(--chart-bar-least, 2px);\n \
height: min(calc(var(--value, 0) * 100% / max(var(--most, 1), 1)), 100%);\n \
height: min(calc(var(--value, 0) * (100% - 1lh) / max(var(--most, 1), 1)), 100% - 1lh);\n}}"
);
for tone in [Tone::Info, Tone::Success, Tone::Warning, Tone::Danger] {
let _ = writeln!(
css,
".{chart}[data-tone=\"{0}\"] .{bar} {{\n background: var(--{0});\n}}",
tone.token()
);
}
let _ = writeln!(
css,
".{label} {{\n color: var(--content-muted);\n max-width: 100%;\n \
white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}}"
);
let _ = writeln!(css, ".{bars} {{\n overflow-x: clip;\n}}");
for (from, every) in [(13, 7), (121, 30)] {
let many = format!(".{bars}:has(> .{col}:nth-child({from}))");
let _ = writeln!(
css,
"{many} > .{col} > .{label} {{\n visibility: hidden;\n}}\n\
{many} > .{col}:nth-child({every}n + 1) > .{label} {{\n visibility: visible;\n \
max-width: none;\n overflow: visible;\n align-self: flex-start;\n}}"
);
}
css.push_str(&gated(
hover_condition(),
&format!(
".{col}[data-tooltip]:hover::before {{\n content: attr(data-tooltip);\n \
position: absolute;\n bottom: 100%;\n inset-inline: 0;\n \
margin-inline: auto;\n width: max-content;\n \
background: var(--surface-raised);\n color: var(--content);\n \
border: var(--border);\n box-shadow: var(--elevation-overlay);\n \
padding: var(--chart-readout-padding, 0.25em 0.5em);\n \
white-space: nowrap;\n pointer-events: none;\n}}\n"
),
));
css
}
#[must_use]
pub fn rules(opts: &Emit) -> String {
chart_rules(opts)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn every_class_this_module_names_has_a_rule() {
let css = chart_rules(&Emit::default());
for name in CHART_CLASSES {
assert!(css.contains(&format!(".{name}")), "{name} has no rule");
}
}
}