diff --git a/apps/client/src/components/exemplarView/ExemplarView.vue b/apps/client/src/components/exemplarView/ExemplarView.vue index 3f8154f8..24c1a040 100644 --- a/apps/client/src/components/exemplarView/ExemplarView.vue +++ b/apps/client/src/components/exemplarView/ExemplarView.vue @@ -1,5 +1,4 @@ @@ -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'));