Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
CircularChartProvider,
type CircularChartSpec as CircularChartSpecBase,
} from "@rilldata/web-common/features/components/charts/circular/CircularChartProvider";
import { DEFAULT_LABELS_THRESHOLD } from "@rilldata/web-common/features/components/charts/circular/constants";
import {
ChartSortType,
type ChartFieldsMap,
Expand Down Expand Up @@ -50,6 +51,10 @@ export class CircularChartComponent extends BaseChart<CircularCanvasChartSpec> {
type: "boolean",
label: 'Show "Other" bucket',
},
labels: {
type: "labels",
label: "Data labels",
},
color: {
type: "positional",
label: "Color",
Expand Down Expand Up @@ -148,6 +153,11 @@ export class CircularChartComponent extends BaseChart<CircularCanvasChartSpec> {
metrics_view: metricsViewName,
innerRadius: 50,
show_other: true,
labels: {
show: true,
format: "percent",
threshold: DEFAULT_LABELS_THRESHOLD,
},
color: {
type: "nominal",
field: randomDimension,
Expand Down
108 changes: 108 additions & 0 deletions web-common/src/features/canvas/inspector/LabelsInput.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<script lang="ts">
import Input from "@rilldata/web-common/components/forms/Input.svelte";
import InputLabel from "@rilldata/web-common/components/forms/InputLabel.svelte";
import Select from "@rilldata/web-common/components/forms/Select.svelte";
import Switch from "@rilldata/web-common/components/forms/Switch.svelte";
import {
DEFAULT_LABELS_FORMAT,
DEFAULT_LABELS_THRESHOLD,
type LabelsConfig,
type LabelsFormat,
} from "@rilldata/web-common/features/components/charts/circular/constants";

export let key: string;
export let label: string;
export let value: LabelsConfig | undefined;
export let onChange: (next: LabelsConfig | undefined) => void;

$: show = value?.show === true;

const formatOptions: { value: LabelsFormat; label: string }[] = [
{ value: "percent", label: "Percent" },
{ value: "value", label: "Value" },
];

function toggleShow() {
if (show) {
onChange(undefined);
} else {
onChange({
show: true,
format: DEFAULT_LABELS_FORMAT,
threshold: DEFAULT_LABELS_THRESHOLD,
});
}
}

function setFormat(next: string) {
onChange({
...(value ?? {}),
show: true,
format: next as LabelsFormat,
});
}

function setThreshold(next: number | undefined) {
onChange({
...(value ?? {}),
show: true,
threshold: next,
});
}
</script>

<div class="flex flex-col gap-y-2">
<div class="flex justify-between py-1 items-center">
<InputLabel small {label} id={key} faint={!show} />
<Switch checked={show} onclick={toggleShow} small />
</div>

{#if show}
<div class="flex flex-col gap-y-2 pl-2">
<div class="flex justify-between items-center gap-x-2">
<InputLabel small label="Format" id="{key}-format" />
<div class="control">
<Select
id="{key}-format"
label=""
size="sm"
full={true}
sameWidth
fontSize={12}
options={formatOptions}
value={value?.format ?? DEFAULT_LABELS_FORMAT}
onChange={setFormat}
/>
</div>
</div>
<div class="flex justify-between items-center gap-x-2">
<InputLabel small label="Hide labels below (%)" id="{key}-threshold" />
<div class="control">
<Input
id="{key}-threshold"
label=""
inputType="number"
size="sm"
value={value?.threshold ?? ""}
oninput={(e: Event) => {
const target = e.currentTarget;
if (!(target instanceof HTMLInputElement)) return;
if (target.value === "") {
setThreshold(undefined);
} else {
const n = target.valueAsNumber;
setThreshold(Number.isNaN(n) ? undefined : n);
}
}}
/>
</div>
</div>
</div>
{/if}
</div>

<style lang="postcss">
.control {
@apply w-32 shrink-0;
}
</style>
13 changes: 13 additions & 0 deletions web-common/src/features/canvas/inspector/ParamMapper.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import ComparisonInput from "./ComparisonInput.svelte";
import MultiFieldInput from "./fields/MultiFieldInput.svelte";
import SingleFieldInput from "./fields/SingleFieldInput.svelte";
import LabelsInput from "./LabelsInput.svelte";
import MetricSelectorDropdown from "./MetricSelectorDropdown.svelte";
import SparklineInput from "./SparklineInput.svelte";
import TableTypeSelector from "./TableTypeSelector.svelte";
Expand Down Expand Up @@ -258,6 +259,18 @@
}}
/>

<!-- DATA LABELS INPUT -->
{:else if config.type === "labels"}
<LabelsInput
{key}
label={config.label ?? key}
value={localParamValues[key]}
onChange={(next) => {
localParamValues[key] = next;
component.updateProperty(key, next);
}}
/>

<!-- COMPARISON OPTIONS INPUT -->
{:else if config.type === "comparison_options"}
<ComparisonInput
Expand Down
3 changes: 2 additions & 1 deletion web-common/src/features/canvas/inspector/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ type CustomInputTypes =
| "comparison_options"
| "vega_spec"
| "switcher_tab"
| "ai_generate";
| "ai_generate"
| "labels";
type PositionalInputTypes = "alignment";

export type InputType =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
OTHER_VALUE,
OTHER_VALUE_DOMAIN_KEY,
TOTAL_DOMAIN_KEY,
type LabelsConfig,
} from "./constants";

export type CircularChartSpec = {
Expand All @@ -40,6 +41,7 @@ export type CircularChartSpec = {
color?: FieldConfig<"nominal">;
innerRadius?: number;
show_other?: boolean;
labels?: LabelsConfig;
};

export type CircularChartDefaultOptions = {
Expand Down
16 changes: 13 additions & 3 deletions web-common/src/features/components/charts/circular/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,19 @@ export const OTHER_VALUE_DOMAIN_KEY = "__other_value";
// Synthetic field added by the percent-of-total transform.
export const PERCENT_OF_TOTAL_FIELD = "__percent_of_total";

// Tooltip column title for the percent-of-total entry.
export const PERCENT_OF_TOTAL_TITLE = "% of total";

export type LabelsFormat = "percent" | "value";
export const DEFAULT_LABELS_FORMAT: LabelsFormat = "percent";
export const DEFAULT_LABELS_THRESHOLD = 5;

export type LabelsConfig = {
show?: boolean;
format?: LabelsFormat;
// Hide labels for slices below this percent of total.
threshold?: number;
};
// Synthetic field used to pin the "Other" slice to the end of the arc order
// regardless of how rows sort by measure or category.
export const OTHER_SORT_KEY_FIELD = "__other_sort_key";

// Tooltip column title for the percent-of-total entry.
export const PERCENT_OF_TOTAL_TITLE = "% of total";
Loading
Loading