Skip to content

Commit 9483efd

Browse files
committed
fix legend option types; accept style and className on scale options
Generic legend options (`label`, `tickFormat`, `fontVariant`, `style`, `className`) were only declared on LegendOptions, which extends ColorLegendOptions. This meant passing `style` or `className` inside scale options was a type error. Instead we introduce `BaseLegendOptions` and have each specific legend type extend it. Fixes #2175
1 parent 1c6b239 commit 9483efd

3 files changed

Lines changed: 153 additions & 36 deletions

File tree

src/legends.d.ts

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,53 @@ export interface RampLegendOptions {
5757
round?: ScaleOptions["round"];
5858
}
5959

60-
export interface OpacityLegendOptions extends RampLegendOptions {
60+
/** Options common to all legend types. */
61+
export interface BaseLegendOptions {
62+
/** A textual label to place above the legend. */
63+
label?: string | null;
64+
65+
/**
66+
* How to format tick values sampled from the scale’s domain. This may be a
67+
* function, which will be passed the tick value *t* and zero-based index *i*
68+
* and must return the corresponding string. If the domain is numbers, the
69+
* tick format may also be expressed as a [d3-format string][1]; or if the
70+
* domain is dates, the tick format may also be expressed as a [d3-time-format
71+
* string][2].
72+
*
73+
* [1]: https://d3js.org/d3-format#locale_format
74+
* [2]: https://d3js.org/d3-time-format#locale_format
75+
*/
76+
tickFormat?: ScaleOptions["tickFormat"];
77+
78+
/**
79+
* The [CSS font-variant][1] for tick labels. For non-ordinal scales, or
80+
* ordinal scales without an interval, this defaults to *tabular-nums*.
81+
*
82+
* [1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant
83+
*/
84+
fontVariant?: ScaleOptions["fontVariant"];
85+
86+
/** Custom styles to override Plot’s defaults. */
87+
style?: string | Partial<CSSStyleDeclaration> | null;
88+
89+
/**
90+
* The generated element’s class name used for Plot’s default stylesheet; by
91+
* default, a random string prefixed with "plot-".
92+
*/
93+
className?: string | null;
94+
}
95+
96+
export interface OpacityLegendOptions extends BaseLegendOptions, RampLegendOptions {
6197
/** The constant color the ramp; defaults to black. */
6298
color?: string;
6399
}
64100

65-
export interface ColorLegendOptions extends SwatchesLegendOptions, RampLegendOptions {
101+
export interface ColorLegendOptions extends BaseLegendOptions, SwatchesLegendOptions, RampLegendOptions {
66102
/** The desired opacity of the color swatches or ramp; defaults to 1. */
67103
opacity?: number;
68104
}
69105

70-
export interface SymbolLegendOptions extends SwatchesLegendOptions {
106+
export interface SymbolLegendOptions extends BaseLegendOptions, SwatchesLegendOptions {
71107
/** The desired fill color of symbols; use *color* for a redundant encoding. */
72108
fill?: string;
73109
/** The desired fill opacity of symbols; defaults to 1. */
@@ -96,39 +132,6 @@ export interface LegendOptions extends ColorLegendOptions, SymbolLegendOptions,
96132
* cannot be changed.
97133
*/
98134
legend?: "ramp" | "swatches";
99-
100-
/** A textual label to place above the legend. */
101-
label?: string | null;
102-
103-
/**
104-
* How to format tick values sampled from the scale’s domain. This may be a
105-
* function, which will be passed the tick value *t* and zero-based index *i*
106-
* and must return the corresponding string. If the domain is numbers, the
107-
* tick format may also be expressed as a [d3-format string][1]; or if the
108-
* domain is dates, the tick format may also be expressed as a [d3-time-format
109-
* string][2].
110-
*
111-
* [1]: https://d3js.org/d3-format#locale_format
112-
* [2]: https://d3js.org/d3-time-format#locale_format
113-
*/
114-
tickFormat?: ScaleOptions["tickFormat"];
115-
116-
/**
117-
* The [CSS font-variant][1] for tick labels. For non-ordinal scales, or
118-
* ordinal scales without an interval, this defaults to *tabular-nums*.
119-
*
120-
* [1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant
121-
*/
122-
fontVariant?: ScaleOptions["fontVariant"];
123-
124-
/** Custom styles to override Plot’s defaults. */
125-
style?: string | Partial<CSSStyleDeclaration> | null;
126-
127-
/**
128-
* The generated element’s class name used for Plot’s default stylesheet; by
129-
* default, a random string prefixed with “plot-”.
130-
*/
131-
className?: string | null;
132135
}
133136

134137
/** Scale definitions and options for a standalone legend. */
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<figure class="plot-d6a7b5-figure" style="max-width: initial;">
2+
<div class="legend-swatches legend-swatches-wrap" style="font-size: 16px;">
3+
<style>
4+
:where(.legend-swatches) {
5+
font-family: system-ui, sans-serif;
6+
font-size: 10px;
7+
margin-bottom: 0.5em;
8+
}
9+
10+
:where(.legend-swatch > svg) {
11+
margin-right: 0.5em;
12+
overflow: visible;
13+
}
14+
15+
:where(.legend-swatches-wrap) {
16+
display: flex;
17+
align-items: center;
18+
min-height: 33px;
19+
flex-wrap: wrap;
20+
}
21+
22+
:where(.legend-swatches-wrap .legend-swatch) {
23+
display: inline-flex;
24+
align-items: center;
25+
margin-right: 1em;
26+
}
27+
</style><span class="legend-swatch"><svg width="15" height="15" fill="rgb(110, 64, 170)" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
28+
<rect width="100%" height="100%"></rect>
29+
</svg>A</span><span class="legend-swatch"><svg width="15" height="15" fill="rgb(191, 60, 175)" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
30+
<rect width="100%" height="100%"></rect>
31+
</svg>B</span><span class="legend-swatch"><svg width="15" height="15" fill="rgb(254, 75, 131)" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
32+
<rect width="100%" height="100%"></rect>
33+
</svg>C</span><span class="legend-swatch"><svg width="15" height="15" fill="rgb(255, 120, 71)" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
34+
<rect width="100%" height="100%"></rect>
35+
</svg>D</span><span class="legend-swatch"><svg width="15" height="15" fill="rgb(226, 183, 47)" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
36+
<rect width="100%" height="100%"></rect>
37+
</svg>E</span><span class="legend-swatch"><svg width="15" height="15" fill="rgb(175, 240, 91)" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
38+
<rect width="100%" height="100%"></rect>
39+
</svg>F</span><span class="legend-swatch"><svg width="15" height="15" fill="rgb(82, 246, 103)" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
40+
<rect width="100%" height="100%"></rect>
41+
</svg>G</span><span class="legend-swatch"><svg width="15" height="15" fill="rgb(29, 223, 163)" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
42+
<rect width="100%" height="100%"></rect>
43+
</svg>H</span><span class="legend-swatch"><svg width="15" height="15" fill="rgb(35, 171, 216)" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
44+
<rect width="100%" height="100%"></rect>
45+
</svg>I</span><span class="legend-swatch"><svg width="15" height="15" fill="rgb(76, 110, 219)" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
46+
<rect width="100%" height="100%"></rect>
47+
</svg>J</span>
48+
</div><svg class="plot" fill="currentColor" font-family="system-ui, sans-serif" font-size="10" text-anchor="middle" width="640" height="60" viewBox="0 0 640 60" style="font-size: 7px;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
49+
<style>
50+
:where(.plot) {
51+
--plot-background: white;
52+
display: block;
53+
height: auto;
54+
height: intrinsic;
55+
max-width: 100%;
56+
}
57+
58+
:where(.plot text),
59+
:where(.plot tspan) {
60+
white-space: pre;
61+
}
62+
</style>
63+
<g aria-label="x-axis tick" aria-hidden="true" fill="none" stroke="currentColor" transform="translate(27,0)">
64+
<path transform="translate(28,30)" d="M0,0L0,6"></path>
65+
<path transform="translate(87,30)" d="M0,0L0,6"></path>
66+
<path transform="translate(146,30)" d="M0,0L0,6"></path>
67+
<path transform="translate(205,30)" d="M0,0L0,6"></path>
68+
<path transform="translate(264,30)" d="M0,0L0,6"></path>
69+
<path transform="translate(323,30)" d="M0,0L0,6"></path>
70+
<path transform="translate(382,30)" d="M0,0L0,6"></path>
71+
<path transform="translate(441,30)" d="M0,0L0,6"></path>
72+
<path transform="translate(500,30)" d="M0,0L0,6"></path>
73+
<path transform="translate(559,30)" d="M0,0L0,6"></path>
74+
</g>
75+
<g aria-label="x-axis tick label" transform="translate(27,9.5)">
76+
<text y="0.71em" transform="translate(28,30)">A</text>
77+
<text y="0.71em" transform="translate(87,30)">B</text>
78+
<text y="0.71em" transform="translate(146,30)">C</text>
79+
<text y="0.71em" transform="translate(205,30)">D</text>
80+
<text y="0.71em" transform="translate(264,30)">E</text>
81+
<text y="0.71em" transform="translate(323,30)">F</text>
82+
<text y="0.71em" transform="translate(382,30)">G</text>
83+
<text y="0.71em" transform="translate(441,30)">H</text>
84+
<text y="0.71em" transform="translate(500,30)">I</text>
85+
<text y="0.71em" transform="translate(559,30)">J</text>
86+
</g>
87+
<g aria-label="cell">
88+
<rect x="28" width="53" y="0" height="30" fill="rgb(110, 64, 170)"></rect>
89+
<rect x="87" width="53" y="0" height="30" fill="rgb(191, 60, 175)"></rect>
90+
<rect x="146" width="53" y="0" height="30" fill="rgb(254, 75, 131)"></rect>
91+
<rect x="205" width="53" y="0" height="30" fill="rgb(255, 120, 71)"></rect>
92+
<rect x="264" width="53" y="0" height="30" fill="rgb(226, 183, 47)"></rect>
93+
<rect x="323" width="53" y="0" height="30" fill="rgb(175, 240, 91)"></rect>
94+
<rect x="382" width="53" y="0" height="30" fill="rgb(82, 246, 103)"></rect>
95+
<rect x="441" width="53" y="0" height="30" fill="rgb(29, 223, 163)"></rect>
96+
<rect x="500" width="53" y="0" height="30" fill="rgb(35, 171, 216)"></rect>
97+
<rect x="559" width="53" y="0" height="30" fill="rgb(76, 110, 219)"></rect>
98+
</g>
99+
</svg>
100+
</figure>

test/plots/legend-color.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,20 @@ test(function colorLegendOrdinalRampInline() {
6767
});
6868
});
6969

70+
test(function colorLegendFontSize() {
71+
return Plot.plot({
72+
color: {
73+
legend: true,
74+
type: "ordinal",
75+
scheme: "rainbow",
76+
className: "legend",
77+
style: {fontSize: "16px"}
78+
},
79+
style: {fontSize: "7px"},
80+
marks: [Plot.cell("ABCDEFGHIJ", {x: Plot.identity, fill: Plot.identity})]
81+
});
82+
});
83+
7084
test(function colorLegendOrdinalRampTickSize() {
7185
return Plot.legend({
7286
color: {

0 commit comments

Comments
 (0)