Added Focused mode as default. Also finally adding the icons correctly.
This commit is contained in:
14
bicorder-app/public/favicon.svg
Normal file
14
bicorder-app/public/favicon.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" style="stop-color:#1a1a2e;stop-opacity:1" />
|
||||||
|
<stop offset="100%" style="stop-color:#16213e;stop-opacity:1" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- Background -->
|
||||||
|
<rect width="128" height="128" fill="url(#bgGrad)" rx="16"/>
|
||||||
|
|
||||||
|
<!-- Large hash symbol -->
|
||||||
|
<text x="64" y="95" font-family="'Courier New', monospace" font-size="100" font-weight="bold" fill="#bbe1fa" text-anchor="middle">#</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 577 B |
BIN
bicorder-app/public/icon-192.png
Normal file
BIN
bicorder-app/public/icon-192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
bicorder-app/public/icon-512.png
Normal file
BIN
bicorder-app/public/icon-512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -14,6 +14,86 @@
|
|||||||
data.metadata.timestamp = new Date().toISOString();
|
data.metadata.timestamp = new Date().toISOString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// View mode and navigation state
|
||||||
|
type ViewMode = 'focused' | 'list';
|
||||||
|
let viewMode: ViewMode = 'focused'; // Focused is default
|
||||||
|
let currentScreen = 0;
|
||||||
|
let refreshKey = 0; // Used to force component refresh in focused mode
|
||||||
|
|
||||||
|
// Screen types
|
||||||
|
type Screen =
|
||||||
|
| { type: 'metadata' }
|
||||||
|
| { type: 'gradient'; setIndex: number; gradientIndex: number; gradient: Gradient; setName: string }
|
||||||
|
| { type: 'analysis'; index: number; gradient: AnalysisGradient }
|
||||||
|
| { type: 'export' };
|
||||||
|
|
||||||
|
// Calculate all screens based on current shortform setting
|
||||||
|
function calculateScreens(): Screen[] {
|
||||||
|
const screens: Screen[] = [];
|
||||||
|
|
||||||
|
// Metadata screen
|
||||||
|
screens.push({ type: 'metadata' });
|
||||||
|
|
||||||
|
// Diagnostic gradient screens
|
||||||
|
data.diagnostic.forEach((diagnosticSet, setIndex) => {
|
||||||
|
diagnosticSet.gradients.forEach((gradient, gradientIndex) => {
|
||||||
|
if (!data.metadata.shortform || gradient.shortform) {
|
||||||
|
screens.push({
|
||||||
|
type: 'gradient',
|
||||||
|
setIndex,
|
||||||
|
gradientIndex,
|
||||||
|
gradient,
|
||||||
|
setName: diagnosticSet.set_name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Analysis screens (not in shortform)
|
||||||
|
if (!data.metadata.shortform) {
|
||||||
|
data.analysis.forEach((gradient, index) => {
|
||||||
|
screens.push({ type: 'analysis', index, gradient });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export screen
|
||||||
|
screens.push({ type: 'export' });
|
||||||
|
|
||||||
|
return screens;
|
||||||
|
}
|
||||||
|
|
||||||
|
$: screens = calculateScreens();
|
||||||
|
$: currentScreenData = screens[currentScreen];
|
||||||
|
$: totalScreens = screens.length;
|
||||||
|
|
||||||
|
function goToNextScreen() {
|
||||||
|
if (currentScreen < totalScreens - 1) {
|
||||||
|
currentScreen++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function goToPrevScreen() {
|
||||||
|
if (currentScreen > 0) {
|
||||||
|
currentScreen--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleViewMode() {
|
||||||
|
viewMode = viewMode === 'focused' ? 'list' : 'focused';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate ASCII progress bar
|
||||||
|
function generateProgressBar(current: number, total: number): string {
|
||||||
|
const filled = '#';
|
||||||
|
const empty = '-';
|
||||||
|
const barLength = Math.min(total, 20); // Cap at 20 characters for display
|
||||||
|
const filledCount = Math.round((current / total) * barLength);
|
||||||
|
const emptyCount = barLength - filledCount;
|
||||||
|
return filled.repeat(filledCount) + empty.repeat(emptyCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
$: progressBar = generateProgressBar(currentScreen + 1, totalScreens);
|
||||||
|
|
||||||
// Load saved state from localStorage
|
// Load saved state from localStorage
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
const saved = localStorage.getItem('bicorder-state');
|
const saved = localStorage.getItem('bicorder-state');
|
||||||
@@ -45,6 +125,27 @@
|
|||||||
console.error('Failed to load saved state:', e);
|
console.error('Failed to load saved state:', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keyboard navigation for focused mode
|
||||||
|
function handleKeyDown(e: KeyboardEvent) {
|
||||||
|
if (viewMode !== 'focused') return;
|
||||||
|
|
||||||
|
// Only navigate if not typing in an input
|
||||||
|
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {
|
||||||
|
e.preventDefault();
|
||||||
|
goToNextScreen();
|
||||||
|
} else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {
|
||||||
|
e.preventDefault();
|
||||||
|
goToPrevScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('keydown', handleKeyDown);
|
||||||
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Save state whenever it changes
|
// Save state whenever it changes
|
||||||
@@ -117,8 +218,13 @@
|
|||||||
<div class="header">
|
<div class="header">
|
||||||
<div class="title">Protocol</div>
|
<div class="title">Protocol</div>
|
||||||
<div class="title">BICORDER</div>
|
<div class="title">BICORDER</div>
|
||||||
|
<button class="mode-toggle" on:click={toggleViewMode} aria-label="Toggle view mode">
|
||||||
|
{viewMode === 'focused' ? '☰' : '⊡'}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{#if viewMode === 'list'}
|
||||||
|
<!-- LIST MODE: Show all sections -->
|
||||||
<MetadataFields
|
<MetadataFields
|
||||||
metadata={data.metadata}
|
metadata={data.metadata}
|
||||||
on:update={handleMetadataUpdate}
|
on:update={handleMetadataUpdate}
|
||||||
@@ -168,6 +274,125 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<ExportControls {data} on:reset={handleReset} />
|
<ExportControls {data} on:reset={handleReset} />
|
||||||
|
|
||||||
|
{:else}
|
||||||
|
<!-- FOCUSED MODE: Show one screen at a time -->
|
||||||
|
<div class="focused-container">
|
||||||
|
{#if currentScreenData.type === 'metadata'}
|
||||||
|
<div class="focused-screen">
|
||||||
|
<MetadataFields
|
||||||
|
metadata={data.metadata}
|
||||||
|
on:update={handleMetadataUpdate}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{:else if currentScreenData.type === 'gradient'}
|
||||||
|
{@const screen = currentScreenData}
|
||||||
|
<div class="focused-screen gradient-screen">
|
||||||
|
<div class="screen-category">{screen.setName.toUpperCase()}</div>
|
||||||
|
|
||||||
|
<div class="gradient-focused">
|
||||||
|
<div class="term-desc left-desc">
|
||||||
|
<div class="term-name">{screen.gradient.term_left}</div>
|
||||||
|
<div class="description-text">{screen.gradient.term_left_description}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#key refreshKey}
|
||||||
|
<GradientSlider
|
||||||
|
gradient={screen.gradient}
|
||||||
|
focusedMode={true}
|
||||||
|
on:change={(e) => {
|
||||||
|
data.diagnostic[screen.setIndex].gradients[screen.gradientIndex].value = e.detail ?? null;
|
||||||
|
data = data;
|
||||||
|
refreshKey++; // Force component refresh
|
||||||
|
}}
|
||||||
|
on:notes={(e) => {
|
||||||
|
data.diagnostic[screen.setIndex].gradients[screen.gradientIndex].notes = e.detail;
|
||||||
|
data = data;
|
||||||
|
refreshKey++; // Force component refresh
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/key}
|
||||||
|
|
||||||
|
<div class="term-desc right-desc">
|
||||||
|
<div class="term-name">{screen.gradient.term_right}</div>
|
||||||
|
<div class="description-text">{screen.gradient.term_right_description}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{:else if currentScreenData.type === 'analysis'}
|
||||||
|
{@const screen = currentScreenData}
|
||||||
|
<div class="focused-screen gradient-screen">
|
||||||
|
<div class="screen-category">ANALYSIS</div>
|
||||||
|
|
||||||
|
<div class="gradient-focused">
|
||||||
|
<div class="term-desc left-desc">
|
||||||
|
<div class="term-name">{screen.gradient.term_left}</div>
|
||||||
|
<div class="description-text">{screen.gradient.term_left_description}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#key refreshKey}
|
||||||
|
<AnalysisDisplay
|
||||||
|
gradient={screen.gradient}
|
||||||
|
focusedMode={true}
|
||||||
|
on:change={(e) => {
|
||||||
|
if (!screen.gradient.automated) {
|
||||||
|
data.analysis[screen.index].value = e.detail ?? null;
|
||||||
|
data = data;
|
||||||
|
refreshKey++; // Force component refresh
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
on:notes={(e) => {
|
||||||
|
data.analysis[screen.index].notes = e.detail;
|
||||||
|
data = data;
|
||||||
|
refreshKey++; // Force component refresh
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/key}
|
||||||
|
|
||||||
|
<div class="term-desc right-desc">
|
||||||
|
<div class="term-name">{screen.gradient.term_right}</div>
|
||||||
|
<div class="description-text">{screen.gradient.term_right_description}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{:else if currentScreenData.type === 'export'}
|
||||||
|
<div class="focused-screen">
|
||||||
|
<ExportControls {data} focusedMode={true} on:reset={handleReset} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Navigation and Progress -->
|
||||||
|
<div class="focused-navigation" class:no-border={currentScreenData.type === 'export'}>
|
||||||
|
<div class="nav-buttons">
|
||||||
|
<button
|
||||||
|
class="nav-btn prev-btn"
|
||||||
|
on:click={goToPrevScreen}
|
||||||
|
disabled={currentScreen === 0}
|
||||||
|
aria-label="Previous screen"
|
||||||
|
>
|
||||||
|
← Previous
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="nav-btn next-btn"
|
||||||
|
on:click={goToNextScreen}
|
||||||
|
disabled={currentScreen === totalScreens - 1}
|
||||||
|
aria-label="Next screen"
|
||||||
|
>
|
||||||
|
Next →
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="progress-indicator">
|
||||||
|
<div class="progress-bar">{progressBar}</div>
|
||||||
|
<div class="progress-numbers">{currentScreen + 1} / {totalScreens}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -175,6 +400,9 @@
|
|||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
@@ -182,6 +410,7 @@
|
|||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
border-bottom: 2px solid var(--border-color);
|
border-bottom: 2px solid var(--border-color);
|
||||||
padding-bottom: 1rem;
|
padding-bottom: 1rem;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
@@ -190,6 +419,27 @@
|
|||||||
letter-spacing: 0.2rem;
|
letter-spacing: 0.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mode-toggle {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
padding: 0.3rem 0.6rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
cursor: pointer;
|
||||||
|
background: var(--bg-color);
|
||||||
|
color: var(--fg-color);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
min-height: auto;
|
||||||
|
opacity: 0.4;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-toggle:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
background-color: var(--input-bg);
|
||||||
|
border-color: var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
.diagnostic-set, .analysis-section {
|
.diagnostic-set, .analysis-section {
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
padding: 1rem 0;
|
padding: 1rem 0;
|
||||||
@@ -211,6 +461,135 @@
|
|||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Focused Mode Styles */
|
||||||
|
.focused-container {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 400px;
|
||||||
|
padding: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focused-screen {
|
||||||
|
animation: fadeIn 0.3s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(10px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.gradient-screen {
|
||||||
|
max-width: 700px;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.screen-category {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
letter-spacing: 0.2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gradient-focused {
|
||||||
|
padding: 2rem;
|
||||||
|
border: 2px solid var(--border-color);
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.term-desc {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.term-desc.left-desc {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.term-desc.right-desc {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.term-name {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
color: var(--fg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.description-text {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
opacity: 0.8;
|
||||||
|
color: var(--fg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.focused-navigation {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1.5rem;
|
||||||
|
padding: 1.5rem 0;
|
||||||
|
margin-top: auto;
|
||||||
|
border-top: 2px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.focused-navigation.no-border {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-btn {
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
min-width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-btn:disabled {
|
||||||
|
opacity: 0.3;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-indicator {
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
font-size: 1rem;
|
||||||
|
letter-spacing: 0.1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--fg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-numbers {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: bold;
|
||||||
|
letter-spacing: 0.1rem;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
main {
|
main {
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
@@ -223,5 +602,34 @@
|
|||||||
.set-header {
|
.set-header {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mode-toggle {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
letter-spacing: 0.05rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-numbers {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focused-container {
|
||||||
|
padding: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gradient-focused {
|
||||||
|
padding: 1rem;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-btn {
|
||||||
|
min-width: 80px;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import Tooltip from './Tooltip.svelte';
|
import Tooltip from './Tooltip.svelte';
|
||||||
|
|
||||||
export let gradient: AnalysisGradient;
|
export let gradient: AnalysisGradient;
|
||||||
|
export let focusedMode: boolean = false;
|
||||||
|
|
||||||
const dispatch = createEventDispatcher<{
|
const dispatch = createEventDispatcher<{
|
||||||
change: number | null;
|
change: number | null;
|
||||||
@@ -98,12 +99,14 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="analysis-gradient">
|
<div class="analysis-gradient">
|
||||||
<div class="gradient-row">
|
<div class="gradient-row" class:focused={focusedMode}>
|
||||||
|
{#if !focusedMode}
|
||||||
<div class="term left">
|
<div class="term left">
|
||||||
<Tooltip text={gradient.term_left_description}>
|
<Tooltip text={gradient.term_left_description}>
|
||||||
{gradient.term_left}
|
{gradient.term_left}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<div class="bar-container">
|
<div class="bar-container">
|
||||||
<button
|
<button
|
||||||
@@ -124,11 +127,13 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{#if !focusedMode}
|
||||||
<div class="term right">
|
<div class="term right">
|
||||||
<Tooltip text={gradient.term_right_description}>
|
<Tooltip text={gradient.term_right_description}>
|
||||||
{gradient.term_right}
|
{gradient.term_right}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="value-display">
|
<div class="value-display">
|
||||||
@@ -200,6 +205,15 @@
|
|||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gradient-row.focused {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gradient-row.focused .bar-container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.term {
|
.term {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
@@ -257,6 +271,11 @@
|
|||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.analysis-gradient .value-display {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.auto-label {
|
.auto-label {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import type { BicorderState } from '../types';
|
import type { BicorderState } from '../types';
|
||||||
|
|
||||||
export let data: BicorderState;
|
export let data: BicorderState;
|
||||||
|
export let focusedMode: boolean = false;
|
||||||
|
|
||||||
const dispatch = createEventDispatcher<{
|
const dispatch = createEventDispatcher<{
|
||||||
reset: void;
|
reset: void;
|
||||||
@@ -121,7 +122,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="export-controls">
|
<section class="export-controls" class:focused={focusedMode}>
|
||||||
<div class="button-group">
|
<div class="button-group">
|
||||||
<button on:click={exportToJSON}>
|
<button on:click={exportToJSON}>
|
||||||
💾 Export JSON
|
💾 Export JSON
|
||||||
@@ -170,6 +171,10 @@
|
|||||||
border-top: 2px solid var(--border-color);
|
border-top: 2px solid var(--border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.export-controls.focused {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
.button-group {
|
.button-group {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import Tooltip from './Tooltip.svelte';
|
import Tooltip from './Tooltip.svelte';
|
||||||
|
|
||||||
export let gradient: Gradient;
|
export let gradient: Gradient;
|
||||||
|
export let focusedMode: boolean = false;
|
||||||
|
|
||||||
const dispatch = createEventDispatcher<{
|
const dispatch = createEventDispatcher<{
|
||||||
change: number;
|
change: number;
|
||||||
@@ -94,12 +95,14 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="gradient-container">
|
<div class="gradient-container">
|
||||||
<div class="gradient-row">
|
<div class="gradient-row" class:focused={focusedMode}>
|
||||||
|
{#if !focusedMode}
|
||||||
<div class="term left">
|
<div class="term left">
|
||||||
<Tooltip text={gradient.term_left_description}>
|
<Tooltip text={gradient.term_left_description}>
|
||||||
{gradient.term_left}
|
{gradient.term_left}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<div class="bar-container">
|
<div class="bar-container">
|
||||||
<button
|
<button
|
||||||
@@ -117,11 +120,13 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{#if !focusedMode}
|
||||||
<div class="term right">
|
<div class="term right">
|
||||||
<Tooltip text={gradient.term_right_description}>
|
<Tooltip text={gradient.term_right_description}>
|
||||||
{gradient.term_right}
|
{gradient.term_right}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="value-display">
|
<div class="value-display">
|
||||||
@@ -179,6 +184,15 @@
|
|||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gradient-row.focused {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gradient-row.focused .bar-container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.term {
|
.term {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
@@ -231,6 +245,11 @@
|
|||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gradient-container .value-display {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.controls {
|
.controls {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Reference in New Issue
Block a user