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
19 changes: 18 additions & 1 deletion core/src/user-components/tags/bigvalue/BigValue.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
const comparison = $derived(model.resolvedComparison);
// Coerce booleans in case they came from variable interpolation as strings
const comparison_delta = $derived(coerceBoolean(comparison?.delta) ?? true);
const comparison_chip = $derived(coerceBoolean(comparison?.chip) ?? false);
const sparkline = $derived(model.resolvedSparkline);
const sparkline_type = $derived((sparkline?.type ?? 'line') as 'line' | 'area' | 'bar');
const sparkline_color = $derived(sparkline?.color);
Expand All @@ -81,9 +82,11 @@
);
const down_is_good = $derived(coerceBoolean(comparison?.down_is_good) ?? false);
const neutralRange = $derived(comparison?.neutral_range ?? [0, 0]);
const isCard = $derived(props.card ?? false);
const max_width = $derived(props.max_width ?? 'none');
const min_width = $derived(props.min_width ?? 'auto');
const title_class = $derived(props.title_class);
const subtitle_class = $derived(props.subtitle_class);
const value_class = $derived(props.value_class);
const text_size = $derived(props.text_size);
const comparison_class = $derived(undefined);
Expand Down Expand Up @@ -148,11 +151,13 @@

// Use resolved props from model (handles variable interpolation)
const resolvedTitle = $derived(model.resolvedTitle);
const resolvedSubtitle = $derived(model.resolvedSubtitle);
const info = $derived(model.resolvedInfo);
const info_link = $derived(model.resolvedInfo_link);
const info_link_title = $derived(model.resolvedInfo_link_title);

const title = $derived(resolvedTitle || (props.value ? valueProcessed.displayAlias : ''));
const subtitle = $derived(resolvedSubtitle || '');

// Extract data points from the single-row query results
const resultRow = $derived.by(() => {
Expand Down Expand Up @@ -280,7 +285,13 @@
</script>

<span
class={cn('block px-0 py-2 font-sans', class_name)}
class={cn(
'block font-sans',
isCard
? 'rounded-xl border bg-card p-4 text-card-foreground shadow-xs transition-all'
: 'px-0 py-2',
class_name
)}
style={`
min-width: ${min_width};
max-width: ${max_width};
Expand All @@ -305,6 +316,11 @@
<Info text={info} link={info_link} link_title={info_link_title} />
{/if}
</span>
{#if subtitle}
<span class={cn('mt-1 block w-full truncate text-left text-xs text-muted-foreground/80', subtitle_class)}>
{subtitle}
</span>
{/if}

<span
class={cn(
Expand Down Expand Up @@ -360,6 +376,7 @@
text={comparison_text}
downIsGood={down_is_good}
{neutralRange}
chip={comparison_chip}
symbolPosition="left"
className="text-xs"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export class BigValueModel extends UserComponentModel<BigValueModelGenerics> {
if (this.metricCompiled) return this.metricCompiled.displayLabel;
return explicit;
});
readonly resolvedSubtitle = $derived(this.resolveText(this.attributes.subtitle));
readonly resolvedInfo = $derived(this.resolveText(this.attributes.info));
readonly resolvedInfo_link = $derived(this.resolveText(this.attributes.info_link));
readonly resolvedInfo_link_title = $derived(this.resolveText(this.attributes.info_link_title));
Expand Down
10 changes: 10 additions & 0 deletions core/src/user-components/tags/bigvalue/bigvalue.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { describe, it, expect } from 'vitest';
import { schema } from './schema';
import { buildBigValueSQL, type BigValueSQLAttrs } from './build-bigvalue-sql';
import { orderCompatibleWithSingleValue } from '../../validators';
import {
Expand Down Expand Up @@ -602,3 +603,12 @@ describe('order × value compatibility (author-time guard for the GROUP BY ALL s
).toEqual([]);
});
});

describe('big_value schema attributes', () => {
it('supports subtitle, card, and comparison.chip', () => {
expect(schema.attributes.title).toBeDefined();
expect(schema.attributes.subtitle).toBeDefined();
expect(schema.attributes.card).toBeDefined();
expect(schema.attributes.comparison).toBeDefined();
});
});
28 changes: 28 additions & 0 deletions core/src/user-components/tags/bigvalue/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ const comparisonSchema = baseComparisonSchema
'Range [min, max] for neutral values. Use null for infinity (e.g., [null, 0] means anything ≤ 0 is neutral)'
),
{ supportsVariables: true }
),
chip: setZodMetadata(
booleanVariableSchema
.optional()
.default(false)
.describe('Whether to display the comparison delta as a chip / pill badge'),
{ supportsVariables: true }
)
})
.optional();
Expand Down Expand Up @@ -205,6 +212,21 @@ const attributes = {
supportsVariables: true,
variableContext: 'text'
},
subtitle: {
type: String,
required: false,
description: 'Subtitle displayed below the title',
affectsQuery: false,
supportsVariables: true,
variableContext: 'text'
},
card: {
type: Boolean,
required: false,
default: false,
description: 'Whether to style the component as an individual card with border and padding',
affectsQuery: false
},
max_width: {
type: String,
required: false,
Expand Down Expand Up @@ -233,6 +255,12 @@ const attributes = {
description: 'Additional CSS classes for the title',
affectsQuery: false
},
subtitle_class: {
type: String,
required: false,
description: 'Additional CSS classes for the subtitle',
affectsQuery: false
},
value_class: {
type: String,
required: false,
Expand Down