feat: redesign canvas toolbar with fluid expand and 9-group layout

Toolbar buttons now smoothly widen on hover/click to reveal title text
instead of using CSS tooltips. Reorganized from 7 groups into 9 (Note,
Connect, Media, Embed, AI, Create, Decide, Spend, Travel) with better
categorization. Collapse button uses chevron instead of dots. Mobile
tap targets increased to 48px min-height for accessibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-03-04 20:13:19 -08:00
parent 991c0ed8a5
commit 7443f9df9f
1 changed files with 103 additions and 94 deletions

View File

@ -37,7 +37,7 @@
left: 12px;
display: flex;
flex-direction: column;
align-items: stretch;
align-items: flex-start;
gap: 4px;
padding: 6px 4px;
background: var(--rs-toolbar-bg);
@ -224,56 +224,37 @@
color: white;
}
/* Icon-only toolbar: show only emoji, clip text */
/* Icon-only toolbar: show only emoji, fluid expand on hover/open */
.toolbar-group-toggle {
width: 42px;
max-width: 42px;
overflow: hidden;
text-overflow: clip;
text-align: center;
padding-left: 0;
padding-right: 0;
position: relative;
transition: max-width 0.25s ease, padding 0.2s ease;
}
/* Tooltip on hover */
.toolbar-group-toggle[data-tip]::after {
content: attr(data-tip);
position: absolute;
left: calc(100% + 8px);
top: 50%;
transform: translateY(-50%);
padding: 4px 10px;
border-radius: 6px;
background: var(--rs-toolbar-panel-bg);
color: var(--rs-toolbar-btn-text);
font-size: 12px;
white-space: nowrap;
box-shadow: var(--rs-shadow-md);
opacity: 0;
pointer-events: none;
transition: opacity 0.15s;
z-index: 1002;
/* Fluid expand: show title text on hover or when group is open */
.toolbar-group:hover > .toolbar-group-toggle,
.toolbar-group.open > .toolbar-group-toggle {
max-width: 160px;
padding-left: 10px;
padding-right: 10px;
text-align: left;
}
.toolbar-group-toggle[data-tip]:hover::after {
opacity: 1;
}
/* Hide tooltip when group is open (dropdown is showing) */
.toolbar-group.open > .toolbar-group-toggle[data-tip]::after {
display: none;
}
/* Collapse/expand toggle — small pill at bottom of toolbar */
/* Collapse/expand toggle — chevron at bottom of toolbar */
#toolbar-collapse {
padding: 4px 0 !important;
background: transparent !important;
font-size: 11px !important;
font-size: 16px !important;
line-height: 1;
opacity: 0.4;
transition: opacity 0.2s;
text-align: center;
letter-spacing: 2px;
letter-spacing: 0;
color: var(--rs-text-muted);
order: 999; /* always last */
margin-top: auto;
@ -1531,18 +1512,14 @@
#toolbar .toolbar-group-toggle {
width: 100%;
max-width: none;
text-align: left;
padding: 12px 14px;
font-size: 14px;
min-height: 44px;
padding: 14px 16px;
font-size: 16px;
min-height: 48px;
overflow: visible;
}
/* Hide tooltips on mobile — full text shown */
#toolbar .toolbar-group-toggle[data-tip]::after {
display: none;
}
#toolbar .toolbar-dropdown {
position: static;
box-shadow: none;
@ -1551,16 +1528,17 @@
}
#toolbar .toolbar-dropdown button {
padding: 12px 14px;
font-size: 14px;
min-height: 44px;
padding: 14px 16px;
font-size: 16px;
min-height: 48px;
}
#toolbar > button {
width: 100%;
text-align: left;
padding: 12px 14px;
min-height: 44px;
padding: 14px 16px;
min-height: 48px;
font-size: 16px;
}
#toolbar .toolbar-sep {
@ -1592,6 +1570,12 @@
max-height: 50vh;
}
#toolbar-panel-body button {
padding: 14px 16px;
font-size: 16px;
min-height: 48px;
}
/* Bottom toolbar: compact on mobile */
#bottom-toolbar {
bottom: 8px;
@ -1831,50 +1815,46 @@
</div>
<div id="toolbar">
<!-- 1. Note -->
<div class="toolbar-group">
<button class="toolbar-group-toggle" data-tip="Note">📝 Note</button>
<button class="toolbar-group-toggle">📝 Note</button>
<div class="toolbar-dropdown">
<button id="new-markdown" title="New Note">📝 Note</button>
<button id="new-slide" title="New Slide">🎞️ Slide</button>
</div>
</div>
<!-- 2. Connect -->
<div class="toolbar-group">
<button class="toolbar-group-toggle">🤝 Connect</button>
<div class="toolbar-dropdown">
<button id="new-chat" title="New Chat">💬 Chat</button>
<button id="new-video-chat" title="Video Meet">📹 Video Meet</button>
<button id="new-record" title="Record" class="toolbar-disabled">🔴 Record</button>
</div>
</div>
<!-- 3. Media -->
<div class="toolbar-group">
<button class="toolbar-group-toggle" data-tip="Creative">🔮 Creative</button>
<button class="toolbar-group-toggle">🎵 Media</button>
<div class="toolbar-dropdown">
<button id="new-image-gen" title="New AI Image">🎨 AI Image</button>
<button id="new-video-gen" title="New AI Video">🎬 AI Video</button>
<button id="new-zine-gen" title="Zine Generator">📰 Zine Gen</button>
<button id="new-splat" title="New 3D Splat">🔮 3D Splat</button>
<button id="new-blender" title="New 3D Blender">🧊 3D Blender</button>
<button id="new-drawfast" title="New Drawing">✏️ Drawfast</button>
<button id="new-freecad" title="New FreeCAD">📐 FreeCAD</button>
<button id="new-kicad" title="New KiCAD PCB">🔌 KiCAD PCB</button>
<button id="embed-swag" title="Embed rSwag">🎨 rSwag</button>
<button id="embed-pubs" title="Embed rPubs">📖 rPubs</button>
</div>
</div>
<div class="toolbar-group">
<button class="toolbar-group-toggle" data-tip="Media">🎨 Media</button>
<div class="toolbar-dropdown">
<button id="new-transcription" title="New Transcription">🎤 Transcribe</button>
<button id="new-video-chat" title="New Video Call">📹 Video Call</button>
<button id="new-piano" title="New Piano">🎹 Piano</button>
<button id="embed-photos" title="Embed rPhotos">📸 rPhotos</button>
<button id="new-transcription" title="Transcribe">🎤 Transcribe</button>
<button id="new-stream" title="Stream" class="toolbar-disabled">📡 Stream</button>
<button id="new-piano" title="Piano">🎹 Piano</button>
<button id="embed-tube" title="Embed rTube">🎬 rTube</button>
<button id="embed-photos" title="Embed rPhotos">📸 rPhotos</button>
</div>
</div>
<!-- 4. Embed -->
<div class="toolbar-group">
<button class="toolbar-group-toggle" data-tip="Embed">🔗 Embed</button>
<button class="toolbar-group-toggle">🔗 Embed</button>
<div class="toolbar-dropdown">
<button id="new-embed" title="New Embed">🔗 Web Embed</button>
<button id="new-google-item" title="New Google Item">📎 Google</button>
<button id="new-calendar" title="New Calendar">📅 Calendar</button>
<button id="new-map" title="New Map">🗺️ Map</button>
<button id="new-social-post" title="New Post">📱 Social Post</button>
<button id="new-embed" title="Web Embed">🔗 Web Embed</button>
<button id="new-google-item" title="Google">📎 Google</button>
<button id="new-calendar" title="Calendar">📅 Calendar</button>
<button id="new-map" title="Map">🗺️ Map</button>
<button id="new-social-post" title="Social Post">📱 Social Post</button>
<button id="embed-notes" title="Embed rNotes">📝 rNotes</button>
<button id="embed-books" title="Embed rBooks">📚 rBooks</button>
<button id="embed-forum" title="Embed rForum">💬 rForum</button>
@ -1887,41 +1867,68 @@
</div>
</div>
<!-- 5. AI -->
<div class="toolbar-group">
<button class="toolbar-group-toggle" data-tip="AI">🤖 AI</button>
<button class="toolbar-group-toggle">🤖 AI</button>
<div class="toolbar-dropdown">
<button id="new-prompt" title="New AI Chat">🤖 AI Chat</button>
<button id="new-workflow" title="New Workflow">⚙️ Workflow</button>
<button id="new-prompt" title="AI Chat">🤖 AI Chat</button>
<button id="new-workflow" title="Workflow">⚙️ Workflow</button>
<button id="new-image-gen" title="AI Image">🎨 AI Image</button>
<button id="new-video-gen" title="AI Video">🎬 AI Video</button>
<button id="new-zine-gen" title="Zine Gen">📰 Zine Gen</button>
</div>
</div>
<!-- 6. Create -->
<div class="toolbar-group">
<button class="toolbar-group-toggle" data-tip="Travel">✈️ Travel</button>
<button class="toolbar-group-toggle">🛠️ Create</button>
<div class="toolbar-dropdown">
<button id="new-itinerary" title="New Itinerary">🗓️ Itinerary</button>
<button id="new-destination" title="New Destination">📍 Destination</button>
<button id="new-budget" title="New Budget">💰 Budget</button>
<button id="new-packing-list" title="New Packing List">🎒 Packing List</button>
<button id="new-booking" title="New Booking">✈️ Booking</button>
<button id="new-splat" title="3D Splat">🔮 3D Splat</button>
<button id="new-blender" title="3D Blender">🧊 Blender</button>
<button id="new-drawfast" title="Drawfast">✏️ Drawfast</button>
<button id="new-freecad" title="FreeCAD">📐 FreeCAD</button>
<button id="new-kicad" title="KiCAD PCB">🔌 KiCAD</button>
<button id="embed-swag" title="Embed rSwag">🎨 rSwag</button>
<button id="embed-pubs" title="Embed rPubs">📖 rPubs</button>
</div>
</div>
<!-- 7. Decide -->
<div class="toolbar-group">
<button class="toolbar-group-toggle" data-tip="Decide">📊 Decide</button>
<button class="toolbar-group-toggle">📊 Decide</button>
<div class="toolbar-dropdown">
<button id="new-choice-vote" title="New Poll">☑ Poll</button>
<button id="new-choice-rank" title="New Ranking">📊 Ranking</button>
<button id="new-choice-spider" title="New Scoring">🕸 Scoring</button>
<button id="new-spider-3d" title="3D Spider Plot">📊 3D Spider</button>
<button id="new-conviction" title="Conviction Ranking">⏳ Conviction</button>
<button id="new-token" title="New Token">🪙 Token</button>
<button id="embed-flows" title="Embed rFlows">🌊 rFlows</button>
<button id="embed-wallet" title="Embed rWallet">💰 rWallet</button>
<button id="new-choice-vote" title="Poll">☑ Poll</button>
<button id="new-choice-rank" title="Ranking">📊 Ranking</button>
<button id="new-choice-spider" title="Scoring">🕸 Scoring</button>
<button id="new-spider-3d" title="3D Spider">📊 3D Spider</button>
<button id="new-conviction" title="Conviction">⏳ Conviction</button>
<button id="new-token" title="Token">🪙 Token</button>
<button id="embed-vote" title="Embed rVote">🗳️ rVote</button>
</div>
</div>
<button id="toolbar-collapse" title="Minimize toolbar">···</button>
<!-- 8. Spend -->
<div class="toolbar-group">
<button class="toolbar-group-toggle">💰 Spend</button>
<div class="toolbar-dropdown">
<button id="embed-wallet" title="rWallet">💰 rWallet</button>
<button id="embed-flows" title="rFlows">🌊 rFlows</button>
</div>
</div>
<!-- 9. Travel -->
<div class="toolbar-group">
<button class="toolbar-group-toggle">✈️ Travel</button>
<div class="toolbar-dropdown">
<button id="new-itinerary" title="Itinerary">🗓️ Itinerary</button>
<button id="new-destination" title="Destination">📍 Destination</button>
<button id="new-budget" title="Budget">💰 Budget</button>
<button id="new-packing-list" title="Packing List">🎒 Packing List</button>
<button id="new-booking" title="Booking">✈️ Booking</button>
</div>
</div>
<button id="toolbar-collapse" title="Minimize toolbar"></button>
</div>
<div id="toolbar-panel">
@ -3587,6 +3594,8 @@
document.getElementById("new-prompt").addEventListener("click", () => setPendingTool("folk-prompt"));
document.getElementById("new-transcription").addEventListener("click", () => setPendingTool("folk-transcription"));
document.getElementById("new-video-chat").addEventListener("click", () => setPendingTool("folk-video-chat"));
document.getElementById("new-record").addEventListener("click", () => setPendingTool("folk-record"));
document.getElementById("new-stream").addEventListener("click", () => setPendingTool("folk-stream"));
document.getElementById("new-workflow").addEventListener("click", () => {
setPendingTool("folk-workflow-block", {
blockType: "trigger",
@ -4924,7 +4933,7 @@
const collapseBtn = document.getElementById("toolbar-collapse");
collapseBtn.addEventListener("click", () => {
const isCollapsed = toolbarEl.classList.toggle("collapsed");
collapseBtn.textContent = isCollapsed ? "▶" : "···";
collapseBtn.textContent = isCollapsed ? "" : "";
collapseBtn.title = isCollapsed ? "Expand toolbar" : "Minimize toolbar";
});