Files
lime/work/activity-workflow-proposal.html
2026-10-02 14:14:47 -05:00

105 lines
5.4 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<div id="lime-activity-workflow-proposal">
<style>
#lime-activity-workflow-proposal .monitor-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
gap: 16px;
margin: 16px 0 8px;
}
#lime-activity-workflow-proposal .monitor { min-width: 0; }
#lime-activity-workflow-proposal svg { display: block; width: 100%; }
#lime-activity-workflow-proposal svg text { fill: var(--foreground); }
#lime-activity-workflow-proposal .monitor-outline {
fill: none;
stroke: var(--border);
}
#lime-activity-workflow-proposal .window {
fill: color-mix(in srgb, var(--viz-series-1) 12%, transparent);
stroke: var(--border);
}
</style>
<div class="viz-controls">
<label class="form-label">Proposed behavior · scenario
<select class="form-select" data-scenario>
<optgroup label="Everyday workflow">
<option value="0">1 · Start: Lime left, Chill right</option>
<option value="1">2 · Open Lime on the right too</option>
<option value="2">3 · Open Docs on the right</option>
<option value="3">4 · Switch right to Chill</option>
<option value="4">5 · Switch left to Work too</option>
<option value="5">6 · Return to Lime on the right</option>
<option value="6">7 · Return to Lime on the left too</option>
<option value="7">8 · Move Docs to the left</option>
<option value="8">9 · Right: away, then back to Lime</option>
</optgroup>
<optgroup label="A separate edge case to decide">
<option value="9">First visit on right; Lime inactive</option>
</optgroup>
</select>
</label>
</div>
<div class="monitor-grid">
<div class="monitor" data-head="left"></div>
<div class="monitor" data-head="right"></div>
</div>
<div class="text-small" data-detail role="status" aria-live="polite"></div>
</div>
<script>
(() => {
const root = document.getElementById('lime-activity-workflow-proposal');
const choose = root.querySelector('[data-scenario]');
const detail = root.querySelector('[data-detail]');
const panels = ['left', 'right'].map(head => root.querySelector(`[data-head="${head}"]`));
const steps = [
{left:['Lime',['Editor']], right:['Chill',['Chat']], detail:'Lime has only been used on the left so far.'},
{left:['Lime',['Editor']], right:['Lime',[]], detail:'Same activity, additional space. Editor stays on the left.'},
{left:['Lime',['Editor']], right:['Lime',['Docs']], detail:'Both windows belong to Lime; each has one current location.'},
{left:['Lime',['Editor']], right:['Chill',['Chat']], detail:'Docs stays open but is not displayed; its right-hand placement is remembered.'},
{left:['Work',['Work browser']], right:['Chill',['Chat']], detail:'Lime is not displayed. Editor and Docs stay open with their positions remembered.'},
{left:['Work',['Work browser']], right:['Lime',['Docs']], detail:'Docs returns on the right. Editor remains out of sight on the left.'},
{left:['Lime',['Editor']], right:['Lime',['Docs']], detail:'Both halves of the live arrangement are back. No saved View was needed.'},
{left:['Lime',['Editor','Docs']], right:['Lime',[]], detail:'The move updates Lime’s live arrangement: Docs no longer belongs in the right-hand layout.'},
{left:['Lime',['Editor','Docs']], right:['Lime',[]], detail:'No reclaim attempt or conflict dialog. The right-hand layout is still empty.'},
{left:['Work',['Work browser']], right:['Lime',[]], detail:'Edge case: Lime’s Editor is remembered on the left, not automatically brought to the right.'}
];
const ns = 'http://www.w3.org/2000/svg';
function element(tag, attributes, text) {
const node = document.createElementNS(ns, tag);
for (const [key,value] of Object.entries(attributes || {})) node.setAttribute(key, value);
if (text !== undefined) node.textContent = text;
return node;
}
function drawMonitor(panel, side, state) {
const width = Math.max(1, panel.getBoundingClientRect().width);
const height = 204;
const svg = element('svg', {viewBox:`0 0 ${width} ${height}`, height,
role:'img', 'aria-label':`${side} monitor showing ${state[0]}: ${state[1].join(' and ') || 'empty'}`});
svg.append(element('rect',{x:1,y:1,width:width-2,height:height-2,rx:4,class:'monitor-outline'}));
svg.append(element('text',{x:12,y:26,'font-weight':500},`${side} · ${state[0]}`));
svg.append(element('line',{x1:1,y1:39,x2:width-1,y2:39,stroke:'var(--border)'}));
const windows = state[1];
if (!windows.length) {
svg.append(element('text',{x:width/2,y:122,'text-anchor':'middle'},'Empty live arrangement'));
} else {
const gap = 8;
const tileWidth = (width-24-gap*(windows.length-1))/windows.length;
windows.forEach((name,index) => {
const x = 12+index*(tileWidth+gap);
svg.append(element('rect',{x,y:51,width:tileWidth,height:140,rx:2,class:'window'}));
svg.append(element('text',{x:x+tileWidth/2,y:126,'text-anchor':'middle'},name));
});
}
panel.replaceChildren(svg);
}
function draw() {
const step = steps[Number(choose.value)];
drawMonitor(panels[0],'Left',step.left);
drawMonitor(panels[1],'Right',step.right);
detail.textContent = step.detail;
}
choose.addEventListener('change', draw);
new ResizeObserver(draw).observe(root);
draw();
})();
</script>