@axiapps/axi-design 1.44.0 → 1.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/axi.css +229 -0
- package/docs/RULES.md +22 -0
- package/package.json +1 -1
- package/src/base.css +40 -0
- package/src/data.css +129 -0
- package/src/primitives.css +46 -0
- package/src/tokens.css +14 -0
package/README.md
CHANGED
|
@@ -147,6 +147,7 @@ not "what does the system look like". Everything else is
|
|
|
147
147
|
| `--axi-action-hit` | the hit target of an `.axi-action--glyph`, whose label is one character and gives the pointer nothing to land on | `24px` | `<button class="axi-action axi-action--glyph" style="--axi-action-hit: 32px">` |
|
|
148
148
|
| `--axi-well-pad` | the padding inside an `.axi-well` | `10px` | `<div class="axi-well" style="--axi-well-pad: 18px">` |
|
|
149
149
|
| `--axi-well-radius` | an `.axi-well`'s corner radius, for a well used at reading scale rather than page scale | `var(--axi-radius)` | `<div class="axi-well" style="--axi-well-radius: var(--axi-radius-sm)">` |
|
|
150
|
+
| `--axi-empty-pad` | the padding inside an `.axi-empty`, for an empty state standing in a tighter space than a table would | `24px 16px` | `<div class="axi-empty" style="--axi-empty-pad: 12px">` |
|
|
150
151
|
| `--axi-rail-w` | an `.axi-rail`'s width, for labels longer than the default holds | `208px` | `<aside class="axi-rail" style="--axi-rail-w: 260px">` |
|
|
151
152
|
| `--axi-rail-pad` | the padding inside an `.axi-rail` | `10px` | `<aside class="axi-rail" style="--axi-rail-pad: 6px">` |
|
|
152
153
|
| `--axi-toolbar-pad` | the padding inside an `.axi-toolbar` | `14px` | `<div class="axi-toolbar" style="--axi-toolbar-pad: 4px 7px">` |
|
package/dist/axi.css
CHANGED
|
@@ -122,6 +122,20 @@
|
|
|
122
122
|
--axi-ink-on-fill below, on the other side of the same token. */
|
|
123
123
|
--axi-ground-deep: var(--axi-ink-line);
|
|
124
124
|
--axi-rule: #3a4250; /* internal rules, inside an outlined panel */
|
|
125
|
+
/* A gridline is quieter than a rule. A rule divides two things; a grid is
|
|
126
|
+
scaffolding a value is read against, and it has to sit barely above the
|
|
127
|
+
ground it is drawn on or the chart becomes a grid of boxes with numbers
|
|
128
|
+
in them - the failure rule 3 names for tables, arriving in a plot.
|
|
129
|
+
|
|
130
|
+
Derived, not picked, and that is the point of its being a token. The one
|
|
131
|
+
consumer that had drawn a chart grid wrote #262c36 for it: the default
|
|
132
|
+
rule laid over the default ground at 47%, to within one step per channel,
|
|
133
|
+
and a fixed slate that stayed slate under glass and under flat while both
|
|
134
|
+
themes relit their rules. Mixing toward transparent rather than toward
|
|
135
|
+
the ground keeps it right on a panel fill too, and keeps it following
|
|
136
|
+
--axi-rule when a theme restates that - so a theme has nothing to say
|
|
137
|
+
here, and says nothing. */
|
|
138
|
+
--axi-grid: color-mix(in srgb, var(--axi-rule) 47%, transparent);
|
|
125
139
|
/* --- the well --- */
|
|
126
140
|
/* A field sunk INTO a surface rather than raised off one: a table picker's
|
|
127
141
|
list, a bar's trough, a column of cards standing on the page. The language
|
|
@@ -347,6 +361,46 @@ a { color: inherit; }
|
|
|
347
361
|
}
|
|
348
362
|
}
|
|
349
363
|
|
|
364
|
+
/* The scrollbar is chrome, and chrome is drawn in the language's own ink. A
|
|
365
|
+
browser's default bar is a light capsule on a light channel, which is two
|
|
366
|
+
things this language does not have: a colour at partial opacity over the
|
|
367
|
+
ground (rule 2) and the one radius the system refuses (see --axi-radius).
|
|
368
|
+
The consumer that first themed it had written both anyway - a 999px thumb
|
|
369
|
+
in white at 35% - in its own stylesheet, because the language said nothing
|
|
370
|
+
here, and a decision the language leaves unsaid is one every consumer makes
|
|
371
|
+
differently.
|
|
372
|
+
|
|
373
|
+
So: the thumb is the rule ink, a rectangle, in a transparent channel. The
|
|
374
|
+
channel is transparent rather than the ground for the reason the well's fill
|
|
375
|
+
gives: an opaque page colour inside a translucent pane is a black patch, and
|
|
376
|
+
a bar runs down the inside of panes and wells as often as down the page.
|
|
377
|
+
|
|
378
|
+
Two spellings, one per engine, and neither is a fallback for the other.
|
|
379
|
+
`::-webkit-scrollbar` is the only spelling that controls the SHAPE - the
|
|
380
|
+
standard `scrollbar-color` pair recolours whatever the engine draws, and
|
|
381
|
+
what Chromium draws is a capsule with arrow buttons, the shape this language
|
|
382
|
+
refuses. Worse, Chromium (121+) switches the pseudo-elements off entirely the
|
|
383
|
+
moment either standard property is set, so writing both does not combine
|
|
384
|
+
them: it hands Chromium the capsule and throws the rectangle away. (The
|
|
385
|
+
consumer this replaces had written both, and had been tuning a webkit block
|
|
386
|
+
Chromium stopped reading, for years.) So the standard pair is scoped to the
|
|
387
|
+
engines that have no pseudo-element to disable, which today is Firefox, and
|
|
388
|
+
the pseudo-elements carry the design everywhere else. scrollbar-color
|
|
389
|
+
inherits, so the root says it once; scrollbar-width does not, so it is set
|
|
390
|
+
on everything.
|
|
391
|
+
|
|
392
|
+
The quiet-scroll rule in utilities.css still wins where it applies: those
|
|
393
|
+
selectors carry a class and these carry none, so a strip that has asked for
|
|
394
|
+
no bar gets none, and everything else gets this one. */
|
|
395
|
+
@supports not selector(::-webkit-scrollbar) {
|
|
396
|
+
html { scrollbar-color: var(--axi-rule) transparent; }
|
|
397
|
+
* { scrollbar-width: thin; }
|
|
398
|
+
}
|
|
399
|
+
::-webkit-scrollbar { width: 10px; height: 10px; }
|
|
400
|
+
::-webkit-scrollbar-track,
|
|
401
|
+
::-webkit-scrollbar-corner { background: transparent; }
|
|
402
|
+
::-webkit-scrollbar-thumb { background: var(--axi-rule); border-radius: 0; }
|
|
403
|
+
|
|
350
404
|
/* --- primitives.css --- */
|
|
351
405
|
/* axi design language - primitives.
|
|
352
406
|
The pieces that recur in every property. Two rules govern the whole file:
|
|
@@ -425,6 +479,28 @@ a.axi-panel--tile:hover,
|
|
|
425
479
|
button.axi-panel--tile:hover,
|
|
426
480
|
.axi-panel--tile[role='button']:hover { box-shadow: var(--axi-shadow-control-hover); }
|
|
427
481
|
|
|
482
|
+
/* The status cap rule 5 describes, as a thing you can write. A verdict about
|
|
483
|
+
the reading inside a panel, a tile or a stat is said once, across its head,
|
|
484
|
+
in the status ink - directly over the value it judges - and the rest of the
|
|
485
|
+
outline stays the ink line every other edge in the language is drawn in. Not
|
|
486
|
+
down the left: a full-height stripe is the box's frame, and five tiles in a
|
|
487
|
+
row become five coloured frames saying nothing about any one number.
|
|
488
|
+
|
|
489
|
+
It recolours the top edge the element already has rather than adding a bar,
|
|
490
|
+
so it is drawn at the element's own weight by construction - the panel step
|
|
491
|
+
on a panel, the control step on a tile or a stat - which is rule 5's own
|
|
492
|
+
argument against a heavy cap on a light frame. The state is an attribute the
|
|
493
|
+
consumer declares about its data (rule 13), read by the three objects a
|
|
494
|
+
reading lives in; a card's strip is a different claim (which category) and
|
|
495
|
+
keeps its own word.
|
|
496
|
+
|
|
497
|
+
Four values and no fifth: the accent is not a verdict, and a cap in it would
|
|
498
|
+
say "picked" about a thing nobody picked. */
|
|
499
|
+
.axi-panel[data-status="ok"], .axi-stat[data-status="ok"] { border-top-color: var(--axi-ok); }
|
|
500
|
+
.axi-panel[data-status="warn"], .axi-stat[data-status="warn"] { border-top-color: var(--axi-warn); }
|
|
501
|
+
.axi-panel[data-status="danger"], .axi-stat[data-status="danger"] { border-top-color: var(--axi-danger); }
|
|
502
|
+
.axi-panel[data-status="meta"], .axi-stat[data-status="meta"] { border-top-color: var(--axi-meta); }
|
|
503
|
+
|
|
428
504
|
/* The one of these you picked. A grid of panels, tiles or cards where one is
|
|
429
505
|
chosen - a theme picker, a fight picker, a leader you have opened - and the
|
|
430
506
|
surface has to say which.
|
|
@@ -514,6 +590,30 @@ button.axi-panel--tile:hover,
|
|
|
514
590
|
the pad knob is still the right way to say anything else. */
|
|
515
591
|
.axi-well--sm { --axi-well-radius: var(--axi-radius-sm); }
|
|
516
592
|
|
|
593
|
+
/* ---------- the empty state ---------- */
|
|
594
|
+
/* A well with nothing in it but the sentence saying so.
|
|
595
|
+
|
|
596
|
+
Every view that can have no data has to say so somewhere, and the first
|
|
597
|
+
consumer counted said it eighty times - a dashed-border box, centred, small,
|
|
598
|
+
dim - in eighty copies of the same eleven utilities, none of them a word the
|
|
599
|
+
language had. Dashed, because the box was "provisional"; the language says
|
|
600
|
+
provisional with the outlined/filled distinction (rule 5), so the edge is
|
|
601
|
+
the well's own rule. It is a well because an absence is a recess: the place
|
|
602
|
+
a table would stand, sunk into the surface, with nothing standing in it.
|
|
603
|
+
|
|
604
|
+
Only the sentence's type and placement are added to the well, and the
|
|
605
|
+
generous pad is the point - an empty state that is as tall as a single row
|
|
606
|
+
reads as a row that failed to render. */
|
|
607
|
+
.axi-empty {
|
|
608
|
+
background: var(--axi-well-fill);
|
|
609
|
+
border: var(--axi-border-control) solid var(--axi-well-line);
|
|
610
|
+
border-radius: var(--axi-radius-sm);
|
|
611
|
+
padding: var(--axi-empty-pad, 24px 16px);
|
|
612
|
+
text-align: center;
|
|
613
|
+
font: var(--axi-t-small);
|
|
614
|
+
color: var(--axi-text-dim);
|
|
615
|
+
}
|
|
616
|
+
|
|
517
617
|
/* ---------- button ---------- */
|
|
518
618
|
.axi-btn {
|
|
519
619
|
display: inline-flex; align-items: center; gap: 8px;
|
|
@@ -3380,6 +3480,135 @@ textarea.axi-input {
|
|
|
3380
3480
|
color: var(--axi-text-faint);
|
|
3381
3481
|
}
|
|
3382
3482
|
|
|
3483
|
+
/* ---------- library charts ---------- */
|
|
3484
|
+
/* The language draws its own bars, plot and ticks above. An app that needs a
|
|
3485
|
+
stacked area, a brush or a pie reaches for a charting library instead, and
|
|
3486
|
+
the library arrives with its own furniture: a dashed grey grid, a #666 axis,
|
|
3487
|
+
a slate tooltip with a half-rem corner. Every series it draws is the
|
|
3488
|
+
consumer's data and keeps its own colour (rule 10). Everything drawn AROUND
|
|
3489
|
+
the series is furniture, and furniture is the language's.
|
|
3490
|
+
|
|
3491
|
+
This is the binding for recharts, which is the library the suite uses. It
|
|
3492
|
+
is scoped to `.axi-chart` so a chart opts in by wrapping, and it reaches the
|
|
3493
|
+
library's elements by the class names recharts puts on them. recharts spreads
|
|
3494
|
+
stroke and fill onto its SVG as presentation attributes, which a stylesheet
|
|
3495
|
+
outranks, so nothing here needs to be passed into the library - and nothing
|
|
3496
|
+
here is written with !important. A consumer that hands the library an inline
|
|
3497
|
+
`contentStyle` has written a second design for the tooltip, and the answer
|
|
3498
|
+
is to stop writing it, not for the language to shout over it: the tooltip is
|
|
3499
|
+
`.axi-tooltip--flow` as custom content, drawn once, like every other tooltip.
|
|
3500
|
+
|
|
3501
|
+
The grammar is the one every component here already follows. Furniture is
|
|
3502
|
+
drawn in the neutral ramp and recedes: the grid at --axi-grid, a step below
|
|
3503
|
+
the rule (see tokens.css); the axis as a rule at the hairline weight, the
|
|
3504
|
+
same line the table draws between rows; tick labels in the faint ink with
|
|
3505
|
+
tabular figures, so a y-axis whose digits change width holds still. Every
|
|
3506
|
+
small object standing on a series - a point, a bar, a slice - takes the ink
|
|
3507
|
+
edge rule 3 gives every other small object, at the hairline because it is a
|
|
3508
|
+
mark and not a raised surface, and keeps its fill, because the fill is which
|
|
3509
|
+
series it belongs to. The hover band is the raised step's -paint companion
|
|
3510
|
+
(a `fill` cannot be a gradient) rather than a white wash, which is rule 2.
|
|
3511
|
+
|
|
3512
|
+
The brush is the one place an accent is spent. Its two travellers are the
|
|
3513
|
+
only thing in any chart you can grab, and they are small: a target you have
|
|
3514
|
+
to find before you can use it is what the accent is for, unlike the hover
|
|
3515
|
+
band, which is already under the pointer. The slide between them is the
|
|
3516
|
+
surface as one paint, the trough behind them a well. One accent in the plot,
|
|
3517
|
+
on the one control.
|
|
3518
|
+
|
|
3519
|
+
Solid, never dashed. A dash is decoration, and fifteen charts of dashes is a
|
|
3520
|
+
texture rather than a scale; the reference line - a threshold, a claim - is
|
|
3521
|
+
solid too, because it is one of the few lines in a chart meant to be read. */
|
|
3522
|
+
.axi-chart {
|
|
3523
|
+
/* Every figure in a chart is a label of a number, so the whole scope reads
|
|
3524
|
+
tabular. Nothing else is declared on the scope: a chart's size belongs to
|
|
3525
|
+
the library's container and the consumer's layout. */
|
|
3526
|
+
font-variant-numeric: tabular-nums;
|
|
3527
|
+
}
|
|
3528
|
+
.axi-chart .recharts-cartesian-grid line {
|
|
3529
|
+
stroke: var(--axi-grid);
|
|
3530
|
+
stroke-dasharray: none;
|
|
3531
|
+
stroke-width: 1;
|
|
3532
|
+
}
|
|
3533
|
+
/* Stripes are a second background inside a chart that already has one. */
|
|
3534
|
+
.axi-chart .recharts-cartesian-grid-bg,
|
|
3535
|
+
.axi-chart .recharts-cartesian-gridstripes-horizontal,
|
|
3536
|
+
.axi-chart .recharts-cartesian-gridstripes-vertical { display: none; }
|
|
3537
|
+
|
|
3538
|
+
.axi-chart .recharts-cartesian-axis-line {
|
|
3539
|
+
stroke: var(--axi-rule);
|
|
3540
|
+
stroke-width: var(--axi-border-hairline);
|
|
3541
|
+
}
|
|
3542
|
+
.axi-chart .recharts-cartesian-axis-tick-line { stroke: var(--axi-rule); }
|
|
3543
|
+
.axi-chart .recharts-cartesian-axis-tick-value { fill: var(--axi-text-faint); }
|
|
3544
|
+
.axi-chart .recharts-label,
|
|
3545
|
+
.axi-chart .recharts-legend-item-text { fill: var(--axi-text-dim); color: var(--axi-text-dim); }
|
|
3546
|
+
/* The legend is a key, so it reads as labels rather than as chips - the same
|
|
3547
|
+
type .axi-legend__key sets. */
|
|
3548
|
+
.axi-chart .recharts-legend-wrapper {
|
|
3549
|
+
font: var(--axi-t-micro);
|
|
3550
|
+
letter-spacing: var(--axi-ls-micro);
|
|
3551
|
+
text-transform: uppercase;
|
|
3552
|
+
}
|
|
3553
|
+
|
|
3554
|
+
/* The hover band. A fill change rather than a wash: the next surface up, as
|
|
3555
|
+
one paint, edged with the rule at the hairline like every line here. */
|
|
3556
|
+
.axi-chart .recharts-tooltip-cursor {
|
|
3557
|
+
fill: var(--axi-surface-raised-paint);
|
|
3558
|
+
fill-opacity: 1;
|
|
3559
|
+
stroke: var(--axi-rule);
|
|
3560
|
+
stroke-width: var(--axi-border-hairline);
|
|
3561
|
+
}
|
|
3562
|
+
/* A line chart's cursor is a crosshair, not a band, so it stays a line. */
|
|
3563
|
+
.axi-chart .recharts-curve.recharts-tooltip-cursor {
|
|
3564
|
+
fill: none;
|
|
3565
|
+
stroke: var(--axi-rule);
|
|
3566
|
+
stroke-dasharray: none;
|
|
3567
|
+
}
|
|
3568
|
+
|
|
3569
|
+
/* Small objects standing on a series keep their fill and take the ink edge. */
|
|
3570
|
+
.axi-chart .recharts-line-dot,
|
|
3571
|
+
.axi-chart .recharts-scatter-symbol > path,
|
|
3572
|
+
.axi-chart .recharts-pie-sector > path,
|
|
3573
|
+
.axi-chart .recharts-bar-rectangle > path {
|
|
3574
|
+
stroke: var(--axi-ink-line);
|
|
3575
|
+
stroke-width: var(--axi-border-hairline);
|
|
3576
|
+
}
|
|
3577
|
+
.axi-chart .recharts-active-dot > * {
|
|
3578
|
+
stroke: var(--axi-ink-line);
|
|
3579
|
+
stroke-width: var(--axi-border-control);
|
|
3580
|
+
}
|
|
3581
|
+
.axi-chart .recharts-bar-background-rectangle { fill: var(--axi-well-fill); }
|
|
3582
|
+
|
|
3583
|
+
.axi-chart .recharts-reference-line-line {
|
|
3584
|
+
stroke: var(--axi-text-faint);
|
|
3585
|
+
stroke-width: var(--axi-border-hairline);
|
|
3586
|
+
stroke-dasharray: none;
|
|
3587
|
+
}
|
|
3588
|
+
|
|
3589
|
+
/* The brush: a well, a slide, two travellers, and the preview curve dropped to
|
|
3590
|
+
furniture weight because it is context rather than data you read off. */
|
|
3591
|
+
.axi-chart .recharts-brush > rect:first-of-type {
|
|
3592
|
+
fill: var(--axi-well-fill);
|
|
3593
|
+
stroke: var(--axi-well-line);
|
|
3594
|
+
stroke-width: var(--axi-border-control);
|
|
3595
|
+
}
|
|
3596
|
+
.axi-chart .recharts-brush-slide {
|
|
3597
|
+
fill: var(--axi-surface-paint);
|
|
3598
|
+
fill-opacity: 1;
|
|
3599
|
+
}
|
|
3600
|
+
.axi-chart .recharts-brush-traveller > rect {
|
|
3601
|
+
fill: var(--axi-accent);
|
|
3602
|
+
stroke: var(--axi-ink-line);
|
|
3603
|
+
stroke-width: var(--axi-border-hairline);
|
|
3604
|
+
}
|
|
3605
|
+
.axi-chart .recharts-brush-traveller > line { stroke: var(--axi-accent-ink); }
|
|
3606
|
+
.axi-chart .recharts-brush-texts { fill: var(--axi-text-faint); }
|
|
3607
|
+
.axi-chart .recharts-brush .recharts-curve {
|
|
3608
|
+
stroke: var(--axi-text-faint);
|
|
3609
|
+
fill: none;
|
|
3610
|
+
}
|
|
3611
|
+
|
|
3383
3612
|
/* --- feedback.css --- */
|
|
3384
3613
|
/* axi design language - feedback.
|
|
3385
3614
|
Things that report on work, and things that report on how work went. Rule
|
package/docs/RULES.md
CHANGED
|
@@ -506,6 +506,28 @@ their meanings inside a chart, so nothing else may borrow them for a category.
|
|
|
506
506
|
The status inks still mean status inside a plot: a line drawn in `--axi-danger`
|
|
507
507
|
is asserting that the quantity is bad, not that it is the third series.
|
|
508
508
|
|
|
509
|
+
### A chart's furniture recedes
|
|
510
|
+
|
|
511
|
+
Rule 10 is about the series. Everything drawn *around* a series - gridlines,
|
|
512
|
+
the axis, tick labels, the hover band, a brush - is furniture, and furniture is
|
|
513
|
+
drawn in the neutral ramp so the series are the only colour in the plot. The
|
|
514
|
+
grid sits a step below the rule, at `--axi-grid`, because a rule divides two
|
|
515
|
+
things and a grid is only what a value is read against; the axis is a rule at
|
|
516
|
+
the hairline; tick labels are the faint ink with tabular figures. A point, a
|
|
517
|
+
bar or a slice keeps its own fill and takes the hairline ink edge every small
|
|
518
|
+
object takes under rule 3. Nothing in a chart is dashed: a dash is decoration,
|
|
519
|
+
and a threshold is one of the few lines in a chart meant to be read.
|
|
520
|
+
|
|
521
|
+
One accent is spent inside a plot, and only on the one thing in it you can
|
|
522
|
+
grab - a brush's travellers. The hover band is already under the pointer and
|
|
523
|
+
needs no colour to be found.
|
|
524
|
+
|
|
525
|
+
An app that draws its charts with a library gets the same furniture by
|
|
526
|
+
wrapping the chart in `.axi-chart`, which binds these decisions to the
|
|
527
|
+
library's own element classes. The binding is written without `!important`:
|
|
528
|
+
a consumer that hands the library an inline style has drawn a second design,
|
|
529
|
+
and the remedy is to stop handing it, not for the language to shout over it.
|
|
530
|
+
|
|
509
531
|
## 11. An indicator of work animates a composited property
|
|
510
532
|
|
|
511
533
|
Spinners, progress strips and pulses almost always report on something
|
package/package.json
CHANGED
package/src/base.css
CHANGED
|
@@ -72,3 +72,43 @@ a { color: inherit; }
|
|
|
72
72
|
transform: none !important;
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
+
|
|
76
|
+
/* The scrollbar is chrome, and chrome is drawn in the language's own ink. A
|
|
77
|
+
browser's default bar is a light capsule on a light channel, which is two
|
|
78
|
+
things this language does not have: a colour at partial opacity over the
|
|
79
|
+
ground (rule 2) and the one radius the system refuses (see --axi-radius).
|
|
80
|
+
The consumer that first themed it had written both anyway - a 999px thumb
|
|
81
|
+
in white at 35% - in its own stylesheet, because the language said nothing
|
|
82
|
+
here, and a decision the language leaves unsaid is one every consumer makes
|
|
83
|
+
differently.
|
|
84
|
+
|
|
85
|
+
So: the thumb is the rule ink, a rectangle, in a transparent channel. The
|
|
86
|
+
channel is transparent rather than the ground for the reason the well's fill
|
|
87
|
+
gives: an opaque page colour inside a translucent pane is a black patch, and
|
|
88
|
+
a bar runs down the inside of panes and wells as often as down the page.
|
|
89
|
+
|
|
90
|
+
Two spellings, one per engine, and neither is a fallback for the other.
|
|
91
|
+
`::-webkit-scrollbar` is the only spelling that controls the SHAPE - the
|
|
92
|
+
standard `scrollbar-color` pair recolours whatever the engine draws, and
|
|
93
|
+
what Chromium draws is a capsule with arrow buttons, the shape this language
|
|
94
|
+
refuses. Worse, Chromium (121+) switches the pseudo-elements off entirely the
|
|
95
|
+
moment either standard property is set, so writing both does not combine
|
|
96
|
+
them: it hands Chromium the capsule and throws the rectangle away. (The
|
|
97
|
+
consumer this replaces had written both, and had been tuning a webkit block
|
|
98
|
+
Chromium stopped reading, for years.) So the standard pair is scoped to the
|
|
99
|
+
engines that have no pseudo-element to disable, which today is Firefox, and
|
|
100
|
+
the pseudo-elements carry the design everywhere else. scrollbar-color
|
|
101
|
+
inherits, so the root says it once; scrollbar-width does not, so it is set
|
|
102
|
+
on everything.
|
|
103
|
+
|
|
104
|
+
The quiet-scroll rule in utilities.css still wins where it applies: those
|
|
105
|
+
selectors carry a class and these carry none, so a strip that has asked for
|
|
106
|
+
no bar gets none, and everything else gets this one. */
|
|
107
|
+
@supports not selector(::-webkit-scrollbar) {
|
|
108
|
+
html { scrollbar-color: var(--axi-rule) transparent; }
|
|
109
|
+
* { scrollbar-width: thin; }
|
|
110
|
+
}
|
|
111
|
+
::-webkit-scrollbar { width: 10px; height: 10px; }
|
|
112
|
+
::-webkit-scrollbar-track,
|
|
113
|
+
::-webkit-scrollbar-corner { background: transparent; }
|
|
114
|
+
::-webkit-scrollbar-thumb { background: var(--axi-rule); border-radius: 0; }
|
package/src/data.css
CHANGED
|
@@ -715,3 +715,132 @@
|
|
|
715
715
|
.axi-legend:has([aria-pressed="true"]) .axi-legend__key:where(:not([aria-pressed="true"], :hover)) {
|
|
716
716
|
color: var(--axi-text-faint);
|
|
717
717
|
}
|
|
718
|
+
|
|
719
|
+
/* ---------- library charts ---------- */
|
|
720
|
+
/* The language draws its own bars, plot and ticks above. An app that needs a
|
|
721
|
+
stacked area, a brush or a pie reaches for a charting library instead, and
|
|
722
|
+
the library arrives with its own furniture: a dashed grey grid, a #666 axis,
|
|
723
|
+
a slate tooltip with a half-rem corner. Every series it draws is the
|
|
724
|
+
consumer's data and keeps its own colour (rule 10). Everything drawn AROUND
|
|
725
|
+
the series is furniture, and furniture is the language's.
|
|
726
|
+
|
|
727
|
+
This is the binding for recharts, which is the library the suite uses. It
|
|
728
|
+
is scoped to `.axi-chart` so a chart opts in by wrapping, and it reaches the
|
|
729
|
+
library's elements by the class names recharts puts on them. recharts spreads
|
|
730
|
+
stroke and fill onto its SVG as presentation attributes, which a stylesheet
|
|
731
|
+
outranks, so nothing here needs to be passed into the library - and nothing
|
|
732
|
+
here is written with !important. A consumer that hands the library an inline
|
|
733
|
+
`contentStyle` has written a second design for the tooltip, and the answer
|
|
734
|
+
is to stop writing it, not for the language to shout over it: the tooltip is
|
|
735
|
+
`.axi-tooltip--flow` as custom content, drawn once, like every other tooltip.
|
|
736
|
+
|
|
737
|
+
The grammar is the one every component here already follows. Furniture is
|
|
738
|
+
drawn in the neutral ramp and recedes: the grid at --axi-grid, a step below
|
|
739
|
+
the rule (see tokens.css); the axis as a rule at the hairline weight, the
|
|
740
|
+
same line the table draws between rows; tick labels in the faint ink with
|
|
741
|
+
tabular figures, so a y-axis whose digits change width holds still. Every
|
|
742
|
+
small object standing on a series - a point, a bar, a slice - takes the ink
|
|
743
|
+
edge rule 3 gives every other small object, at the hairline because it is a
|
|
744
|
+
mark and not a raised surface, and keeps its fill, because the fill is which
|
|
745
|
+
series it belongs to. The hover band is the raised step's -paint companion
|
|
746
|
+
(a `fill` cannot be a gradient) rather than a white wash, which is rule 2.
|
|
747
|
+
|
|
748
|
+
The brush is the one place an accent is spent. Its two travellers are the
|
|
749
|
+
only thing in any chart you can grab, and they are small: a target you have
|
|
750
|
+
to find before you can use it is what the accent is for, unlike the hover
|
|
751
|
+
band, which is already under the pointer. The slide between them is the
|
|
752
|
+
surface as one paint, the trough behind them a well. One accent in the plot,
|
|
753
|
+
on the one control.
|
|
754
|
+
|
|
755
|
+
Solid, never dashed. A dash is decoration, and fifteen charts of dashes is a
|
|
756
|
+
texture rather than a scale; the reference line - a threshold, a claim - is
|
|
757
|
+
solid too, because it is one of the few lines in a chart meant to be read. */
|
|
758
|
+
.axi-chart {
|
|
759
|
+
/* Every figure in a chart is a label of a number, so the whole scope reads
|
|
760
|
+
tabular. Nothing else is declared on the scope: a chart's size belongs to
|
|
761
|
+
the library's container and the consumer's layout. */
|
|
762
|
+
font-variant-numeric: tabular-nums;
|
|
763
|
+
}
|
|
764
|
+
.axi-chart .recharts-cartesian-grid line {
|
|
765
|
+
stroke: var(--axi-grid);
|
|
766
|
+
stroke-dasharray: none;
|
|
767
|
+
stroke-width: 1;
|
|
768
|
+
}
|
|
769
|
+
/* Stripes are a second background inside a chart that already has one. */
|
|
770
|
+
.axi-chart .recharts-cartesian-grid-bg,
|
|
771
|
+
.axi-chart .recharts-cartesian-gridstripes-horizontal,
|
|
772
|
+
.axi-chart .recharts-cartesian-gridstripes-vertical { display: none; }
|
|
773
|
+
|
|
774
|
+
.axi-chart .recharts-cartesian-axis-line {
|
|
775
|
+
stroke: var(--axi-rule);
|
|
776
|
+
stroke-width: var(--axi-border-hairline);
|
|
777
|
+
}
|
|
778
|
+
.axi-chart .recharts-cartesian-axis-tick-line { stroke: var(--axi-rule); }
|
|
779
|
+
.axi-chart .recharts-cartesian-axis-tick-value { fill: var(--axi-text-faint); }
|
|
780
|
+
.axi-chart .recharts-label,
|
|
781
|
+
.axi-chart .recharts-legend-item-text { fill: var(--axi-text-dim); color: var(--axi-text-dim); }
|
|
782
|
+
/* The legend is a key, so it reads as labels rather than as chips - the same
|
|
783
|
+
type .axi-legend__key sets. */
|
|
784
|
+
.axi-chart .recharts-legend-wrapper {
|
|
785
|
+
font: var(--axi-t-micro);
|
|
786
|
+
letter-spacing: var(--axi-ls-micro);
|
|
787
|
+
text-transform: uppercase;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
/* The hover band. A fill change rather than a wash: the next surface up, as
|
|
791
|
+
one paint, edged with the rule at the hairline like every line here. */
|
|
792
|
+
.axi-chart .recharts-tooltip-cursor {
|
|
793
|
+
fill: var(--axi-surface-raised-paint);
|
|
794
|
+
fill-opacity: 1;
|
|
795
|
+
stroke: var(--axi-rule);
|
|
796
|
+
stroke-width: var(--axi-border-hairline);
|
|
797
|
+
}
|
|
798
|
+
/* A line chart's cursor is a crosshair, not a band, so it stays a line. */
|
|
799
|
+
.axi-chart .recharts-curve.recharts-tooltip-cursor {
|
|
800
|
+
fill: none;
|
|
801
|
+
stroke: var(--axi-rule);
|
|
802
|
+
stroke-dasharray: none;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
/* Small objects standing on a series keep their fill and take the ink edge. */
|
|
806
|
+
.axi-chart .recharts-line-dot,
|
|
807
|
+
.axi-chart .recharts-scatter-symbol > path,
|
|
808
|
+
.axi-chart .recharts-pie-sector > path,
|
|
809
|
+
.axi-chart .recharts-bar-rectangle > path {
|
|
810
|
+
stroke: var(--axi-ink-line);
|
|
811
|
+
stroke-width: var(--axi-border-hairline);
|
|
812
|
+
}
|
|
813
|
+
.axi-chart .recharts-active-dot > * {
|
|
814
|
+
stroke: var(--axi-ink-line);
|
|
815
|
+
stroke-width: var(--axi-border-control);
|
|
816
|
+
}
|
|
817
|
+
.axi-chart .recharts-bar-background-rectangle { fill: var(--axi-well-fill); }
|
|
818
|
+
|
|
819
|
+
.axi-chart .recharts-reference-line-line {
|
|
820
|
+
stroke: var(--axi-text-faint);
|
|
821
|
+
stroke-width: var(--axi-border-hairline);
|
|
822
|
+
stroke-dasharray: none;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
/* The brush: a well, a slide, two travellers, and the preview curve dropped to
|
|
826
|
+
furniture weight because it is context rather than data you read off. */
|
|
827
|
+
.axi-chart .recharts-brush > rect:first-of-type {
|
|
828
|
+
fill: var(--axi-well-fill);
|
|
829
|
+
stroke: var(--axi-well-line);
|
|
830
|
+
stroke-width: var(--axi-border-control);
|
|
831
|
+
}
|
|
832
|
+
.axi-chart .recharts-brush-slide {
|
|
833
|
+
fill: var(--axi-surface-paint);
|
|
834
|
+
fill-opacity: 1;
|
|
835
|
+
}
|
|
836
|
+
.axi-chart .recharts-brush-traveller > rect {
|
|
837
|
+
fill: var(--axi-accent);
|
|
838
|
+
stroke: var(--axi-ink-line);
|
|
839
|
+
stroke-width: var(--axi-border-hairline);
|
|
840
|
+
}
|
|
841
|
+
.axi-chart .recharts-brush-traveller > line { stroke: var(--axi-accent-ink); }
|
|
842
|
+
.axi-chart .recharts-brush-texts { fill: var(--axi-text-faint); }
|
|
843
|
+
.axi-chart .recharts-brush .recharts-curve {
|
|
844
|
+
stroke: var(--axi-text-faint);
|
|
845
|
+
fill: none;
|
|
846
|
+
}
|
package/src/primitives.css
CHANGED
|
@@ -75,6 +75,28 @@ a.axi-panel--tile:hover,
|
|
|
75
75
|
button.axi-panel--tile:hover,
|
|
76
76
|
.axi-panel--tile[role='button']:hover { box-shadow: var(--axi-shadow-control-hover); }
|
|
77
77
|
|
|
78
|
+
/* The status cap rule 5 describes, as a thing you can write. A verdict about
|
|
79
|
+
the reading inside a panel, a tile or a stat is said once, across its head,
|
|
80
|
+
in the status ink - directly over the value it judges - and the rest of the
|
|
81
|
+
outline stays the ink line every other edge in the language is drawn in. Not
|
|
82
|
+
down the left: a full-height stripe is the box's frame, and five tiles in a
|
|
83
|
+
row become five coloured frames saying nothing about any one number.
|
|
84
|
+
|
|
85
|
+
It recolours the top edge the element already has rather than adding a bar,
|
|
86
|
+
so it is drawn at the element's own weight by construction - the panel step
|
|
87
|
+
on a panel, the control step on a tile or a stat - which is rule 5's own
|
|
88
|
+
argument against a heavy cap on a light frame. The state is an attribute the
|
|
89
|
+
consumer declares about its data (rule 13), read by the three objects a
|
|
90
|
+
reading lives in; a card's strip is a different claim (which category) and
|
|
91
|
+
keeps its own word.
|
|
92
|
+
|
|
93
|
+
Four values and no fifth: the accent is not a verdict, and a cap in it would
|
|
94
|
+
say "picked" about a thing nobody picked. */
|
|
95
|
+
.axi-panel[data-status="ok"], .axi-stat[data-status="ok"] { border-top-color: var(--axi-ok); }
|
|
96
|
+
.axi-panel[data-status="warn"], .axi-stat[data-status="warn"] { border-top-color: var(--axi-warn); }
|
|
97
|
+
.axi-panel[data-status="danger"], .axi-stat[data-status="danger"] { border-top-color: var(--axi-danger); }
|
|
98
|
+
.axi-panel[data-status="meta"], .axi-stat[data-status="meta"] { border-top-color: var(--axi-meta); }
|
|
99
|
+
|
|
78
100
|
/* The one of these you picked. A grid of panels, tiles or cards where one is
|
|
79
101
|
chosen - a theme picker, a fight picker, a leader you have opened - and the
|
|
80
102
|
surface has to say which.
|
|
@@ -164,6 +186,30 @@ button.axi-panel--tile:hover,
|
|
|
164
186
|
the pad knob is still the right way to say anything else. */
|
|
165
187
|
.axi-well--sm { --axi-well-radius: var(--axi-radius-sm); }
|
|
166
188
|
|
|
189
|
+
/* ---------- the empty state ---------- */
|
|
190
|
+
/* A well with nothing in it but the sentence saying so.
|
|
191
|
+
|
|
192
|
+
Every view that can have no data has to say so somewhere, and the first
|
|
193
|
+
consumer counted said it eighty times - a dashed-border box, centred, small,
|
|
194
|
+
dim - in eighty copies of the same eleven utilities, none of them a word the
|
|
195
|
+
language had. Dashed, because the box was "provisional"; the language says
|
|
196
|
+
provisional with the outlined/filled distinction (rule 5), so the edge is
|
|
197
|
+
the well's own rule. It is a well because an absence is a recess: the place
|
|
198
|
+
a table would stand, sunk into the surface, with nothing standing in it.
|
|
199
|
+
|
|
200
|
+
Only the sentence's type and placement are added to the well, and the
|
|
201
|
+
generous pad is the point - an empty state that is as tall as a single row
|
|
202
|
+
reads as a row that failed to render. */
|
|
203
|
+
.axi-empty {
|
|
204
|
+
background: var(--axi-well-fill);
|
|
205
|
+
border: var(--axi-border-control) solid var(--axi-well-line);
|
|
206
|
+
border-radius: var(--axi-radius-sm);
|
|
207
|
+
padding: var(--axi-empty-pad, 24px 16px);
|
|
208
|
+
text-align: center;
|
|
209
|
+
font: var(--axi-t-small);
|
|
210
|
+
color: var(--axi-text-dim);
|
|
211
|
+
}
|
|
212
|
+
|
|
167
213
|
/* ---------- button ---------- */
|
|
168
214
|
.axi-btn {
|
|
169
215
|
display: inline-flex; align-items: center; gap: 8px;
|
package/src/tokens.css
CHANGED
|
@@ -118,6 +118,20 @@
|
|
|
118
118
|
--axi-ink-on-fill below, on the other side of the same token. */
|
|
119
119
|
--axi-ground-deep: var(--axi-ink-line);
|
|
120
120
|
--axi-rule: #3a4250; /* internal rules, inside an outlined panel */
|
|
121
|
+
/* A gridline is quieter than a rule. A rule divides two things; a grid is
|
|
122
|
+
scaffolding a value is read against, and it has to sit barely above the
|
|
123
|
+
ground it is drawn on or the chart becomes a grid of boxes with numbers
|
|
124
|
+
in them - the failure rule 3 names for tables, arriving in a plot.
|
|
125
|
+
|
|
126
|
+
Derived, not picked, and that is the point of its being a token. The one
|
|
127
|
+
consumer that had drawn a chart grid wrote #262c36 for it: the default
|
|
128
|
+
rule laid over the default ground at 47%, to within one step per channel,
|
|
129
|
+
and a fixed slate that stayed slate under glass and under flat while both
|
|
130
|
+
themes relit their rules. Mixing toward transparent rather than toward
|
|
131
|
+
the ground keeps it right on a panel fill too, and keeps it following
|
|
132
|
+
--axi-rule when a theme restates that - so a theme has nothing to say
|
|
133
|
+
here, and says nothing. */
|
|
134
|
+
--axi-grid: color-mix(in srgb, var(--axi-rule) 47%, transparent);
|
|
121
135
|
/* --- the well --- */
|
|
122
136
|
/* A field sunk INTO a surface rather than raised off one: a table picker's
|
|
123
137
|
list, a bar's trough, a column of cards standing on the page. The language
|