+
- {{
- `Loading ${histogramYAxisLabel}`
- }}
+ {{ `Loading ${histogramYAxisLabel}` }}
@@ -3107,6 +3796,19 @@ const isExemplarViewReady = computed(() => {
id="exemplar-deckgl-canvas"
ref="deckGlContainer"
>
+
+
@@ -3124,4 +3826,24 @@ const isExemplarViewReady = computed(() => {
align-items: center;
gap: 1em;
}
+
+.histogram-tooltip {
+ position: fixed;
+ background: rgba(255, 255, 255, 0.95);
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ padding: 8px 12px;
+ font-size: 12px;
+ color: #333;
+ z-index: 1000;
+ pointer-events: none;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
+ max-width: 200px;
+ white-space: pre-line;
+ font-family: monospace;
+}
+
+.tooltip-content {
+ line-height: 1.4;
+}
diff --git a/apps/client/src/components/exemplarView/ExemplarViewSettingsSidebar.vue b/apps/client/src/components/exemplarView/ExemplarViewSettingsSidebar.vue
index d08c8492..1632e71e 100644
--- a/apps/client/src/components/exemplarView/ExemplarViewSettingsSidebar.vue
+++ b/apps/client/src/components/exemplarView/ExemplarViewSettingsSidebar.vue
@@ -16,6 +16,12 @@ const globalSettings = useGlobalSettings();
const exemplarViewStore = useExemplarViewStore();
const { horizonChartSettings, histogramBinCount} = storeToRefs(exemplarViewStore);
+// Accordion states
+const imageSnippetsOpen = ref(false);
+const histogramsOpen = ref(false);
+const marginsOpen = ref(false);
+const textOpen = ref(false);
+
// Horizon Chart ---------------
const horizonSettingsModal = ref(false);
const colorSchemeOptions = [
@@ -44,21 +50,22 @@ interface SliderMapping {
min: number;
max: number;
step?: number;
+ category: 'imageSnippets' | 'histograms' | 'margins' | 'text';
}
// View Configuration Sliders -------------------
const sliderMappings: Record
= {
- 'Horizon Chart Height': { key: 'horizonChartHeight', min: 4, max: 240 },
- 'Time Bar Height (Outer)': { key: 'timeBarHeightOuter', min: 2, max: 50 },
- 'Snippet Source Size': { key: 'snippetSourceSize', min: 8, max: 320, step: 2 },
- 'Snippet-Horizon Gap': { key: 'snippetHorizonChartGap', min: 0, max: 50 },
- 'Between Exemplar Gap': { key: 'betweenExemplarGap', min: 0, max: 100 },
- 'Between Condition Gap': { key: 'betweenConditionGap', min: 0, max: 200 },
- 'Margin': { key: 'margin', min: 0, max: 500 },
- 'Horizon-Histogram Gap': { key: 'horizonHistogramGap', min: exemplarViewStore.viewConfiguration.histogramFontSize * 2, max: 200 },
- 'Histogram Width': { key: 'histogramWidth', min: 50, max: 800 },
- 'Histogram Font Size': { key: 'histogramFontSize', min: 8, max: 48 },
- 'Histogram Tooltip Font Size': { key: 'histogramTooltipFontSize', min: 8, max: 36 }
+ 'Horizon Chart Height': { key: 'horizonChartHeight', min: 4, max: 240, category: 'imageSnippets' },
+ 'Time Bar Height (Outer)': { key: 'timeBarHeightOuter', min: 2, max: 50, category: 'imageSnippets' },
+ 'Snippet Source Size': { key: 'snippetSourceSize', min: 8, max: 320, step: 2, category: 'imageSnippets' },
+ 'Snippet-Horizon Gap': { key: 'snippetHorizonChartGap', min: 0, max: 50, category: 'margins' },
+ 'Between Exemplar Gap': { key: 'betweenExemplarGap', min: 0, max: 100, category: 'margins' },
+ 'Between Condition Gap': { key: 'betweenConditionGap', min: 0, max: 200, category: 'margins' },
+ 'Margin': { key: 'margin', min: 0, max: 500, category: 'margins' },
+ 'Horizon-Histogram Gap': { key: 'horizonHistogramGap', min: exemplarViewStore.viewConfiguration.histogramFontSize * 2, max: 200, category: 'margins' },
+ 'Histogram Width': { key: 'histogramWidth', min: 50, max: 800, category: 'histograms' },
+ 'Histogram Font Size': { key: 'histogramFontSize', min: 8, max: 48, category: 'text' },
+ 'Histogram Tooltip Font Size': { key: 'histogramTooltipFontSize', min: 8, max: 36, category: 'text' }
};
// Generate slider configs dynamically
@@ -68,6 +75,7 @@ const sliderConfigs = computed((): {
min: number;
max: number;
step: number;
+ category: string;
}[] => [
// Special case for snippet display size (controls both height and width)
{
@@ -75,7 +83,8 @@ const sliderConfigs = computed((): {
model: snippetDisplaySize,
min: 8,
max: 320,
- step: 1
+ step: 1,
+ category: 'imageSnippets'
},
// Generate all other view configuration sliders
...Object.entries(sliderMappings).map(([label, config]) => ({
@@ -86,9 +95,16 @@ const sliderConfigs = computed((): {
}),
min: config.min,
max: config.max,
- step: config.step ?? 1
+ step: config.step ?? 1,
+ category: config.category
}))
]);
+
+// Categorized sliders
+const imageSnippetSliders = computed(() => sliderConfigs.value.filter(config => config.category === 'imageSnippets'));
+const histogramSliders = computed(() => sliderConfigs.value.filter(config => config.category === 'histograms'));
+const marginSliders = computed(() => sliderConfigs.value.filter(config => config.category === 'margins'));
+const textSliders = computed(() => sliderConfigs.value.filter(config => config.category === 'text'));
@@ -194,34 +210,154 @@ const sliderConfigs = computed((): {
v-model="exemplarViewStore.viewConfiguration.spaceKeyFramesEvenly"
:dark="globalSettings.darkMode"
/>
-
-
+
+
+
+
+ {{ config.label }}:
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ config.label }}:
+
+
+
+
+
+
+
+
+
-
-
- {{ config.label }}:
-
-
+
+
+ {{ config.label }}:
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ config.label }}:
+
+
+
+
-
-
-
+
+