Full document, spreadsheet, slideshow, and diagram tooling
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request 'fix(sheets): toolbar Google Sheets layout + dark mode font color' (#89) from fix/toolbar-dark-mode into main

scott aa29762e b91059ba

+122 -115
+9
CHANGELOG.md
··· 7 7 8 8 ## [Unreleased] 9 9 10 + ## [0.9.1] — 2026-03-22 11 + 12 + ### Changed 13 + - **Toolbar redesigned to match Google Sheets**: inline alignment buttons (left/center/right), inline $/%/.0/.00 format shortcuts, freeze and insert moved to overflow menu (#198) 14 + 15 + ### Fixed 16 + - **Dark mode font color**: text color picker now tracks theme changes — switching to dark mode updates the default color so text remains visible (#198) 17 + - Cells with theme-default text colors no longer emit inline styles that override the CSS theme (#198) 18 + 10 19 ## [0.9.0] — 2026-03-22 11 20 12 21 ### Fixed
+1 -1
package.json
··· 1 1 { 2 2 "name": "tools", 3 - "version": "0.9.0", 3 + "version": "0.9.1", 4 4 "private": true, 5 5 "type": "module", 6 6 "scripts": {
+47 -77
src/sheets/index.html
··· 53 53 <!-- View-only badge (shown when ?mode=view) --> 54 54 <div class="view-only-badge" id="view-only-badge" style="display:none">View only</div> 55 55 56 - <!-- Formatting toolbar (standard spreadsheet ordering) --> 56 + <!-- Formatting toolbar (Google Sheets layout) --> 57 57 <div class="toolbar gdocs-toolbar" id="toolbar" role="toolbar" aria-label="Formatting toolbar"> 58 58 <!-- Group 1: Undo, Redo, Print, Format Painter --> 59 59 <button class="tb-btn toolbar-mobile-hide" id="tb-undo" title="Undo (Cmd+Z)" aria-label="Undo"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M3 7.5h8a3 3 0 0 1 0 6H9"/><path d="M5.5 5L3 7.5 5.5 10"/></svg></button> ··· 62 62 <button class="tb-btn toolbar-mobile-hide" id="tb-format-painter" title="Format painter (click: one-shot, double-click: sticky, Esc: cancel)" aria-label="Format painter"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M10.5 1.5l2 2-6 6H4.5v-2z"/><path d="M3 11l-1 4 4-1"/><path d="M8.5 3.5l2 2"/></svg></button> 63 63 <span class="toolbar-sep toolbar-mobile-hide"></span> 64 64 65 - <!-- Group 2: Number format --> 65 + <!-- Group 2: Number format + shortcuts --> 66 66 <select class="tb-select toolbar-mobile-hide" id="tb-format" title="Cell number format" aria-label="Cell number format"> 67 67 <option value="auto">Auto</option> 68 - <option value="number">123</option> 69 - <option value="currency">$</option> 70 - <option value="percent">%</option> 68 + <option value="number">Number</option> 69 + <option value="currency">Currency</option> 70 + <option value="percent">Percent</option> 71 71 <option value="date">Date</option> 72 - <option value="text">Text</option> 72 + <option value="text">Plain text</option> 73 73 <option value="custom">Custom...</option> 74 74 </select> 75 + <button class="tb-btn tb-btn-text toolbar-mobile-hide" id="tb-fmt-currency" title="Format as currency" aria-label="Format as currency">$</button> 76 + <button class="tb-btn tb-btn-text toolbar-mobile-hide" id="tb-fmt-percent" title="Format as percent" aria-label="Format as percent">%</button> 77 + <button class="tb-btn tb-btn-text toolbar-mobile-hide" id="tb-dec-decrease" title="Decrease decimal places" aria-label="Decrease decimal places">.0</button> 78 + <button class="tb-btn tb-btn-text toolbar-mobile-hide" id="tb-dec-increase" title="Increase decimal places" aria-label="Increase decimal places">.00</button> 75 79 <span class="toolbar-sep toolbar-mobile-hide"></span> 76 80 77 81 <!-- Group 3: Font family & size --> ··· 94 98 </select> 95 99 <span class="toolbar-sep toolbar-mobile-hide"></span> 96 100 97 - <!-- Group 4: Text formatting (Bold, Italic, Underline, Strikethrough, Colors) --> 101 + <!-- Group 4: Text formatting --> 98 102 <button class="tb-btn" id="tb-bold" title="Bold (Cmd+B)" aria-label="Bold"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M4.5 2.5h4.5a2.5 2.5 0 0 1 0 5h-4.5zM4.5 7.5h5a3 3 0 0 1 0 6h-5z" stroke-width="2"/></svg></button> 99 103 <button class="tb-btn" id="tb-italic" title="Italic (Cmd+I)" aria-label="Italic"><svg class="tb-icon" viewBox="0 0 16 16"><line x1="10" y1="2.5" x2="6" y2="13.5"/><line x1="7" y1="2.5" x2="11" y2="2.5"/><line x1="5" y1="13.5" x2="9" y2="13.5"/></svg></button> 100 104 <button class="tb-btn" id="tb-underline" title="Underline (Cmd+U)" aria-label="Underline"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M4 2v6a4 4 0 0 0 8 0V2"/><line x1="3" y1="14" x2="13" y2="14"/></svg></button> ··· 143 147 <button class="tb-btn toolbar-mobile-hide" id="tb-merge" title="Merge/Unmerge cells" aria-label="Merge cells"><svg class="tb-icon" viewBox="0 0 16 16"><rect x="2" y="2" width="12" height="12" rx="1"/><path d="M5 8h6"/><path d="M6.5 6L5 8l1.5 2"/><path d="M9.5 6l1.5 2-1.5 2"/></svg></button> 144 148 <span class="toolbar-sep toolbar-mobile-hide"></span> 145 149 146 - <!-- Group 6: Alignment & Wrap --> 147 - <div class="toolbar-dropdown toolbar-mobile-hide" id="dd-align"> 148 - <button class="toolbar-dropdown-toggle" id="tb-align-toggle" title="Cell alignment" aria-label="Cell alignment" aria-expanded="false" aria-haspopup="true"> 149 - <span class="dd-icon"><svg class="tb-icon" viewBox="0 0 16 16"><line x1="2" y1="3" x2="14" y2="3"/><line x1="2" y1="6.5" x2="10" y2="6.5"/><line x1="2" y1="10" x2="14" y2="10"/><line x1="2" y1="13.5" x2="10" y2="13.5"/></svg></span><span class="caret">&#9662;</span> 150 - </button> 151 - <div class="toolbar-dropdown-menu" role="menu"> 152 - <button class="toolbar-dropdown-item" data-align="left" title="Align left" role="menuitem"> 153 - <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><line x1="2" y1="3" x2="14" y2="3"/><line x1="2" y1="6.5" x2="10" y2="6.5"/><line x1="2" y1="10" x2="14" y2="10"/><line x1="2" y1="13.5" x2="10" y2="13.5"/></svg></span><span class="item-label">Align left</span> 154 - </button> 155 - <button class="toolbar-dropdown-item" data-align="center" title="Align center" role="menuitem"> 156 - <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><line x1="2" y1="3" x2="14" y2="3"/><line x1="4" y1="6.5" x2="12" y2="6.5"/><line x1="2" y1="10" x2="14" y2="10"/><line x1="4" y1="13.5" x2="12" y2="13.5"/></svg></span><span class="item-label">Align center</span> 157 - </button> 158 - <button class="toolbar-dropdown-item" data-align="right" title="Align right" role="menuitem"> 159 - <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><line x1="2" y1="3" x2="14" y2="3"/><line x1="6" y1="6.5" x2="14" y2="6.5"/><line x1="2" y1="10" x2="14" y2="10"/><line x1="6" y1="13.5" x2="14" y2="13.5"/></svg></span><span class="item-label">Align right</span> 160 - </button> 161 - </div> 162 - </div> 150 + <!-- Group 6: Alignment (inline buttons, Google Sheets style) --> 151 + <button class="tb-btn toolbar-mobile-hide" id="tb-align-left" title="Align left" aria-label="Align left"><svg class="tb-icon" viewBox="0 0 16 16"><line x1="2" y1="3" x2="14" y2="3"/><line x1="2" y1="6.5" x2="10" y2="6.5"/><line x1="2" y1="10" x2="14" y2="10"/><line x1="2" y1="13.5" x2="10" y2="13.5"/></svg></button> 152 + <button class="tb-btn toolbar-mobile-hide" id="tb-align-center" title="Align center" aria-label="Align center"><svg class="tb-icon" viewBox="0 0 16 16"><line x1="2" y1="3" x2="14" y2="3"/><line x1="4" y1="6.5" x2="12" y2="6.5"/><line x1="2" y1="10" x2="14" y2="10"/><line x1="4" y1="13.5" x2="12" y2="13.5"/></svg></button> 153 + <button class="tb-btn toolbar-mobile-hide" id="tb-align-right" title="Align right" aria-label="Align right"><svg class="tb-icon" viewBox="0 0 16 16"><line x1="2" y1="3" x2="14" y2="3"/><line x1="6" y1="6.5" x2="14" y2="6.5"/><line x1="2" y1="10" x2="14" y2="10"/><line x1="6" y1="13.5" x2="14" y2="13.5"/></svg></button> 154 + <span class="toolbar-sep toolbar-mobile-hide"></span> 155 + 156 + <!-- Group 7: Wrap & Vertical align dropdown --> 157 + <button class="tb-btn toolbar-mobile-hide" id="tb-wrap" title="Wrap text" aria-label="Wrap text"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M2 3h12M2 7h9a2 2 0 0 1 0 4H9"/><path d="M10 9.5l-1.5 1.5L10 12.5"/><line x1="2" y1="13" x2="7" y2="13"/></svg></button> 163 158 <div class="toolbar-dropdown toolbar-mobile-hide" id="dd-valign"> 164 159 <button class="toolbar-dropdown-toggle" id="tb-valign-toggle" title="Vertical alignment" aria-label="Vertical alignment" aria-expanded="false" aria-haspopup="true"> 165 160 <span class="dd-icon"><svg class="tb-icon" viewBox="0 0 16 16"><line x1="2" y1="2" x2="14" y2="2" stroke-width="2"/><line x1="8" y1="4" x2="8" y2="14"/><path d="M5.5 6.5L8 4l2.5 2.5"/></svg></span><span class="caret">&#9662;</span> ··· 176 171 </button> 177 172 </div> 178 173 </div> 179 - <button class="tb-btn toolbar-mobile-hide" id="tb-wrap" title="Wrap text" aria-label="Wrap text"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M2 3h12M2 7h9a2 2 0 0 1 0 4H9"/><path d="M10 9.5l-1.5 1.5L10 12.5"/><line x1="2" y1="13" x2="7" y2="13"/></svg></button> 180 174 <span class="toolbar-sep toolbar-mobile-hide"></span> 181 175 182 - <!-- Group 7: Insert --> 183 - <div class="toolbar-dropdown toolbar-mobile-hide" id="dd-insert"> 184 - <button class="toolbar-dropdown-toggle" title="Insert rows or columns" aria-label="Insert" aria-expanded="false" aria-haspopup="true"> 185 - <span class="dd-icon"><svg class="tb-icon" viewBox="0 0 16 16"><rect x="2" y="2" width="12" height="12" rx="1"/><path d="M8 5v6"/><path d="M5 8h6"/></svg></span><span class="caret">&#9662;</span> 176 + <!-- Group 8: Data — Filter, Sort, Chart --> 177 + <button class="tb-btn toolbar-mobile-hide" id="tb-filter" title="Toggle column filters" aria-label="Toggle column filters"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M2 3h12l-4 5v4l-4 2V8z"/></svg></button> 178 + <button class="tb-btn toolbar-mobile-hide" id="tb-sort-asc" title="Sort column A to Z" aria-label="Sort A to Z"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M4 11V3"/><path d="M2 5l2-2 2 2"/><line x1="8" y1="4" x2="14" y2="4"/><line x1="8" y1="8" x2="12" y2="8"/><line x1="8" y1="12" x2="10" y2="12"/></svg></button> 179 + <button class="tb-btn toolbar-mobile-hide" id="tb-sort-desc" title="Sort column Z to A" aria-label="Sort Z to A"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M4 5v8"/><path d="M2 11l2 2 2-2"/><line x1="8" y1="4" x2="10" y2="4"/><line x1="8" y1="8" x2="12" y2="8"/><line x1="8" y1="12" x2="14" y2="12"/></svg></button> 180 + <button class="tb-btn toolbar-mobile-hide" id="tb-chart" title="Insert chart" aria-label="Insert chart"><svg class="tb-icon" viewBox="0 0 16 16"><rect x="2" y="8" width="3" height="6" rx="0.5"/><rect x="6.5" y="4" width="3" height="10" rx="0.5"/><rect x="11" y="6" width="3" height="8" rx="0.5"/></svg></button> 181 + 182 + <!-- Mobile more button (visible only on mobile) --> 183 + <button class="tb-btn toolbar-mobile-more" id="tb-mobile-more" title="More formatting" aria-label="More formatting" aria-expanded="false" aria-haspopup="true"><svg class="tb-icon" viewBox="0 0 16 16"><circle cx="3" cy="8" r="1.25" fill="currentColor" stroke="none"/><circle cx="8" cy="8" r="1.25" fill="currentColor" stroke="none"/><circle cx="13" cy="8" r="1.25" fill="currentColor" stroke="none"/></svg></button> 184 + 185 + <!-- More overflow menu --> 186 + <div class="toolbar-overflow" id="overflow-menu"> 187 + <button class="toolbar-overflow-toggle" id="overflow-toggle" title="More options" aria-label="More options" aria-expanded="false" aria-haspopup="true"> 188 + <svg class="tb-icon" viewBox="0 0 16 16"><circle cx="8" cy="3" r="1.25" fill="currentColor" stroke="none"/><circle cx="8" cy="8" r="1.25" fill="currentColor" stroke="none"/><circle cx="8" cy="13" r="1.25" fill="currentColor" stroke="none"/></svg> 186 189 </button> 187 - <div class="toolbar-dropdown-menu" role="menu"> 190 + <div class="toolbar-overflow-menu" role="menu"> 191 + <!-- Section: Formatting --> 192 + <button class="toolbar-dropdown-item" id="tb-clear-format" title="Clear formatting (Cmd+\)" role="menuitem"> 193 + <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M3 3l10 10"/><path d="M5 2h6l-2 6"/><line x1="3" y1="14" x2="13" y2="14"/></svg></span><span class="item-label">Clear formatting</span> 194 + </button> 195 + <button class="toolbar-dropdown-item" id="tb-striped" title="Toggle striped rows" role="menuitem"> 196 + <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><rect x="2" y="2" width="12" height="3" fill="currentColor" opacity="0.15" stroke="none"/><rect x="2" y="8" width="12" height="3" fill="currentColor" opacity="0.15" stroke="none"/><rect x="2" y="2" width="12" height="12" fill="none"/></svg></span><span class="item-label">Striped rows</span> 197 + </button> 198 + <div class="toolbar-dropdown-divider"></div> 199 + 200 + <!-- Section: Structure --> 188 201 <button class="toolbar-dropdown-item" id="tb-add-row" title="Insert row below" role="menuitem"> 189 - <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M2 8h12"/><path d="M2 2h12v12H2z" fill="none"/><path d="M8 5v6"/></svg></span><span class="item-label">Insert row</span> 202 + <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><rect x="2" y="2" width="12" height="12" rx="1"/><path d="M8 5v6"/><path d="M5 8h6"/></svg></span><span class="item-label">Insert row</span> 190 203 </button> 191 204 <button class="toolbar-dropdown-item" id="tb-add-col" title="Insert column right" role="menuitem"> 192 - <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M8 2v12"/><path d="M2 2h12v12H2z" fill="none"/><path d="M5 8h6"/></svg></span><span class="item-label">Insert column</span> 205 + <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><rect x="2" y="2" width="12" height="12" rx="1"/><path d="M8 5v6"/><path d="M5 8h6"/></svg></span><span class="item-label">Insert column</span> 193 206 </button> 194 - <div class="toolbar-dropdown-divider"></div> 195 207 <button class="toolbar-dropdown-item" id="tb-del-row" title="Delete last row" role="menuitem"> 196 208 <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><rect x="2" y="2" width="12" height="12" rx="1"/><path d="M5 8h6"/></svg></span><span class="item-label">Delete row</span> 197 209 </button> 198 210 <button class="toolbar-dropdown-item" id="tb-del-col" title="Delete last column" role="menuitem"> 199 211 <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><rect x="2" y="2" width="12" height="12" rx="1"/><path d="M5 8h6"/></svg></span><span class="item-label">Delete column</span> 200 212 </button> 201 - </div> 202 - </div> 213 + <div class="toolbar-dropdown-divider"></div> 203 214 204 - <!-- Group 8: Freeze panes --> 205 - <div class="toolbar-dropdown toolbar-mobile-hide" id="dd-freeze"> 206 - <button class="toolbar-dropdown-toggle" id="tb-freeze-toggle" title="Freeze panes" aria-label="Freeze panes" aria-expanded="false" aria-haspopup="true"> 207 - <span class="dd-icon"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M2 5h12"/><path d="M5 2v12"/><path d="M2 2h3v3H2z" fill="currentColor" opacity="0.15" stroke="none"/></svg></span><span class="caret">&#9662;</span> 208 - </button> 209 - <div class="toolbar-dropdown-menu" role="menu"> 215 + <!-- Section: Freeze panes --> 210 216 <button class="toolbar-dropdown-item" id="tb-freeze-rows" title="Freeze rows above cursor" role="menuitem"> 211 217 <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M2 5h12"/><path d="M2 5v-2h12v2" fill="currentColor" opacity="0.15" stroke="none"/><path d="M6 5v8"/><path d="M10 5v8"/></svg></span><span class="item-label">Freeze rows</span> 212 218 </button> 213 219 <button class="toolbar-dropdown-item" id="tb-freeze-cols" title="Freeze columns left of cursor" role="menuitem"> 214 220 <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M5 2v12"/><path d="M5 2h-2v12h2" fill="currentColor" opacity="0.15" stroke="none"/><path d="M5 6h8"/><path d="M5 10h8"/></svg></span><span class="item-label">Freeze columns</span> 215 221 </button> 216 - <div class="toolbar-dropdown-divider"></div> 217 222 <button class="toolbar-dropdown-item" id="tb-unfreeze" title="Unfreeze all panes" role="menuitem"> 218 223 <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M3 3l10 10"/><path d="M13 3L3 13"/></svg></span><span class="item-label">Unfreeze all</span> 219 224 </button> 220 - </div> 221 - </div> 222 - <span class="toolbar-sep toolbar-mobile-hide"></span> 223 - 224 - <!-- Group 9: Data — Filter, Sort, Chart --> 225 - <button class="tb-btn toolbar-mobile-hide" id="tb-filter" title="Toggle column filters" aria-label="Toggle column filters"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M2 3h12l-4 5v4l-4 2V8z"/></svg></button> 226 - <button class="tb-btn toolbar-mobile-hide" id="tb-sort-asc" title="Sort column A to Z" aria-label="Sort A to Z"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M4 11V3"/><path d="M2 5l2-2 2 2"/><line x1="8" y1="4" x2="14" y2="4"/><line x1="8" y1="8" x2="12" y2="8"/><line x1="8" y1="12" x2="10" y2="12"/></svg></button> 227 - <button class="tb-btn toolbar-mobile-hide" id="tb-sort-desc" title="Sort column Z to A" aria-label="Sort Z to A"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M4 5v8"/><path d="M2 11l2 2 2-2"/><line x1="8" y1="4" x2="10" y2="4"/><line x1="8" y1="8" x2="12" y2="8"/><line x1="8" y1="12" x2="14" y2="12"/></svg></button> 228 - <button class="tb-btn toolbar-mobile-hide" id="tb-chart" title="Insert chart" aria-label="Insert chart"><svg class="tb-icon" viewBox="0 0 16 16"><rect x="2" y="8" width="3" height="6" rx="0.5"/><rect x="6.5" y="4" width="3" height="10" rx="0.5"/><rect x="11" y="6" width="3" height="8" rx="0.5"/></svg></button> 229 - 230 - <!-- Mobile more button (visible only on mobile) --> 231 - <button class="tb-btn toolbar-mobile-more" id="tb-mobile-more" title="More formatting" aria-label="More formatting" aria-expanded="false" aria-haspopup="true"><svg class="tb-icon" viewBox="0 0 16 16"><circle cx="3" cy="8" r="1.25" fill="currentColor" stroke="none"/><circle cx="8" cy="8" r="1.25" fill="currentColor" stroke="none"/><circle cx="13" cy="8" r="1.25" fill="currentColor" stroke="none"/></svg></button> 232 - 233 - <!-- More overflow menu (less common actions) --> 234 - <div class="toolbar-overflow" id="overflow-menu"> 235 - <button class="toolbar-overflow-toggle" id="overflow-toggle" title="More options" aria-label="More options" aria-expanded="false" aria-haspopup="true"> 236 - <svg class="tb-icon" viewBox="0 0 16 16"><circle cx="8" cy="3" r="1.25" fill="currentColor" stroke="none"/><circle cx="8" cy="8" r="1.25" fill="currentColor" stroke="none"/><circle cx="8" cy="13" r="1.25" fill="currentColor" stroke="none"/></svg> 237 - </button> 238 - <div class="toolbar-overflow-menu" role="menu"> 239 - <!-- Section: Formatting --> 240 - <button class="toolbar-dropdown-item" id="tb-clear-format" title="Clear formatting (Cmd+\)" role="menuitem"> 241 - <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M3 3l10 10"/><path d="M5 2h6l-2 6"/><line x1="3" y1="14" x2="13" y2="14"/></svg></span><span class="item-label">Clear formatting</span> 242 - </button> 243 - <button class="toolbar-dropdown-item" id="tb-striped" title="Toggle striped rows" role="menuitem"> 244 - <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><rect x="2" y="2" width="12" height="3" fill="currentColor" opacity="0.15" stroke="none"/><rect x="2" y="8" width="12" height="3" fill="currentColor" opacity="0.15" stroke="none"/><rect x="2" y="2" width="12" height="12" fill="none"/></svg></span><span class="item-label">Striped rows</span> 245 - </button> 246 225 <div class="toolbar-dropdown-divider"></div> 247 226 248 227 <!-- Section: Data tools --> ··· 254 233 </button> 255 234 <button class="toolbar-dropdown-item" id="tb-validation" title="Data validation" role="menuitem"> 256 235 <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><path d="M3 8l3 3 7-7"/></svg></span><span class="item-label">Data validation</span> 257 - </button> 258 - <div class="toolbar-dropdown-divider"></div> 259 - 260 - <!-- Section: Decimal controls --> 261 - <button class="toolbar-dropdown-item" id="tb-dec-increase" title="Increase decimal places" role="menuitem"> 262 - <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><text x="1" y="12" font-size="9" fill="currentColor">.0</text><path d="M12 5v6"/><path d="M9 8h6"/></svg></span><span class="item-label">Increase decimals</span> 263 - </button> 264 - <button class="toolbar-dropdown-item" id="tb-dec-decrease" title="Decrease decimal places" role="menuitem"> 265 - <span class="item-icon"><svg class="tb-icon" viewBox="0 0 16 16"><text x="1" y="12" font-size="9" fill="currentColor">.0</text><path d="M9 8h6"/></svg></span><span class="item-label">Decrease decimals</span> 266 236 </button> 267 237 <div class="toolbar-dropdown-divider"></div> 268 238
+65 -37
src/sheets/main.ts
··· 760 760 let style = ''; 761 761 if (cellData?.s) { 762 762 const s = cellData.s; 763 - if (s.color) style += 'color:' + s.color + ';'; 763 + // Skip emitting inline color when it matches a theme default — let CSS variable handle it 764 + if (s.color && s.color !== '#1a1815' && s.color !== '#ddd8ce') style += 'color:' + s.color + ';'; 764 765 // bg is now on the <td>, not .cell-display 765 766 if (s.bold) style += 'font-weight:600;'; 766 767 if (s.italic) style += 'font-style:italic;'; ··· 2057 2058 } 2058 2059 }); 2059 2060 2060 - // --- Alignment dropdown --- 2061 - const alignDropdown = document.getElementById('dd-align'); 2062 - const alignToggle = document.getElementById('tb-align-toggle'); 2063 - const ALIGN_SVGS = { 2064 - left: '<svg class="tb-icon" viewBox="0 0 16 16"><line x1="2" y1="3" x2="14" y2="3"/><line x1="2" y1="6.5" x2="10" y2="6.5"/><line x1="2" y1="10" x2="14" y2="10"/><line x1="2" y1="13.5" x2="10" y2="13.5"/></svg>', 2065 - center: '<svg class="tb-icon" viewBox="0 0 16 16"><line x1="2" y1="3" x2="14" y2="3"/><line x1="4" y1="6.5" x2="12" y2="6.5"/><line x1="2" y1="10" x2="14" y2="10"/><line x1="4" y1="13.5" x2="12" y2="13.5"/></svg>', 2066 - right: '<svg class="tb-icon" viewBox="0 0 16 16"><line x1="2" y1="3" x2="14" y2="3"/><line x1="6" y1="6.5" x2="14" y2="6.5"/><line x1="2" y1="10" x2="14" y2="10"/><line x1="6" y1="13.5" x2="14" y2="13.5"/></svg>', 2067 - }; 2068 - 2069 - alignToggle.addEventListener('click', (e) => { 2070 - e.stopPropagation(); 2071 - toggleDropdown(alignDropdown); 2072 - }); 2073 - 2074 - alignDropdown.querySelectorAll('[data-align]').forEach(btn => { 2075 - btn.addEventListener('click', (e) => { 2076 - e.stopPropagation(); 2077 - const align = btn.dataset.align; 2078 - applyStyleToSelection('align', align); 2079 - alignToggle.querySelector('.dd-icon').innerHTML = ALIGN_SVGS[align] || ALIGN_SVGS.left; 2080 - closeAllDropdowns(); 2081 - }); 2082 - }); 2061 + // --- Inline alignment buttons (Google Sheets style) --- 2062 + document.getElementById('tb-align-left').addEventListener('click', () => applyStyleToSelection('align', 'left')); 2063 + document.getElementById('tb-align-center').addEventListener('click', () => applyStyleToSelection('align', 'center')); 2064 + document.getElementById('tb-align-right').addEventListener('click', () => applyStyleToSelection('align', 'right')); 2083 2065 2084 2066 const sheetsTextColorInput = document.getElementById('tb-text-color'); 2085 2067 const sheetsTextColorSwatch = document.getElementById('tb-text-color-swatch'); 2086 2068 const sheetsBgColorInput = document.getElementById('tb-bg-color'); 2087 2069 const sheetsBgColorSwatch = document.getElementById('tb-bg-color-swatch'); 2088 2070 2071 + // Default text/bg colors per theme (must match CSS --color-text / --color-bg) 2072 + const THEME_DEFAULTS = { 2073 + light: { text: '#1a1815', bg: '#f5f4f1' }, 2074 + dark: { text: '#ddd8ce', bg: '#2a2825' }, 2075 + }; 2076 + 2077 + function getEffectiveTheme(): string { 2078 + const saved = localStorage.getItem('tools-theme'); 2079 + if (saved === 'dark' || saved === 'light') return saved; 2080 + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; 2081 + } 2082 + 2083 + function updateColorPickerDefaults() { 2084 + const theme = getEffectiveTheme(); 2085 + const defaults = THEME_DEFAULTS[theme]; 2086 + // Only update if the user hasn't explicitly picked a custom color 2087 + // (check if the current value matches the OTHER theme's default) 2088 + const otherTheme = theme === 'dark' ? 'light' : 'dark'; 2089 + const otherDefaults = THEME_DEFAULTS[otherTheme]; 2090 + if (sheetsTextColorInput.value === otherDefaults.text) { 2091 + (sheetsTextColorInput as HTMLInputElement).value = defaults.text; 2092 + } 2093 + if (sheetsBgColorInput.value === otherDefaults.bg || sheetsBgColorInput.value === '#ffffff') { 2094 + (sheetsBgColorInput as HTMLInputElement).value = defaults.bg; 2095 + } 2096 + updateSheetsColorSwatches(); 2097 + } 2098 + 2089 2099 function updateSheetsColorSwatches() { 2090 2100 if (sheetsTextColorSwatch) sheetsTextColorSwatch.style.background = sheetsTextColorInput.value; 2091 2101 if (sheetsBgColorSwatch) sheetsBgColorSwatch.style.background = sheetsBgColorInput.value; 2092 2102 } 2103 + 2104 + // Set initial defaults based on current theme 2105 + (function initColorDefaults() { 2106 + const theme = getEffectiveTheme(); 2107 + const defaults = THEME_DEFAULTS[theme]; 2108 + (sheetsTextColorInput as HTMLInputElement).value = defaults.text; 2109 + (sheetsBgColorInput as HTMLInputElement).value = defaults.bg; 2110 + })(); 2093 2111 updateSheetsColorSwatches(); 2094 2112 2113 + // Listen for theme changes (theme toggle dispatches a click that sets data-theme) 2114 + new MutationObserver(() => updateColorPickerDefaults()) 2115 + .observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] }); 2116 + 2095 2117 sheetsTextColorInput.addEventListener('input', (e) => { applyStyleToSelection('color', e.target.value); updateSheetsColorSwatches(); }); 2096 2118 sheetsBgColorInput.addEventListener('input', (e) => { applyStyleToSelection('bg', e.target.value); updateSheetsColorSwatches(); }); 2097 2119 document.getElementById('tb-format').addEventListener('change', (e) => applyStyleToSelection('format', e.target.value)); 2120 + 2121 + // --- Inline format shortcut buttons (Google Sheets style) --- 2122 + document.getElementById('tb-fmt-currency').addEventListener('click', () => { 2123 + applyStyleToSelection('format', 'currency'); 2124 + (document.getElementById('tb-format') as HTMLSelectElement).value = 'currency'; 2125 + }); 2126 + document.getElementById('tb-fmt-percent').addEventListener('click', () => { 2127 + applyStyleToSelection('format', 'percent'); 2128 + (document.getElementById('tb-format') as HTMLSelectElement).value = 'percent'; 2129 + }); 2130 + document.getElementById('tb-dec-decrease').addEventListener('click', () => { 2131 + applyStyleToSelection('format', 'number'); 2132 + (document.getElementById('tb-format') as HTMLSelectElement).value = 'number'; 2133 + }); 2134 + document.getElementById('tb-dec-increase').addEventListener('click', () => { 2135 + applyStyleToSelection('format', 'number'); 2136 + (document.getElementById('tb-format') as HTMLSelectElement).value = 'number'; 2137 + }); 2098 2138 2099 2139 // Sort 2100 2140 document.getElementById('tb-sort-asc').addEventListener('click', () => sortColumn(true)); ··· 2206 2246 renderGrid(); 2207 2247 } 2208 2248 2209 - // --- Frozen panes toolbar (Issue #7) --- 2210 - const freezeDropdown = document.getElementById('dd-freeze'); 2211 - if (freezeDropdown) { 2212 - const freezeToggle = freezeDropdown.querySelector('.toolbar-dropdown-toggle'); 2213 - if (freezeToggle) freezeToggle.addEventListener('click', (e) => { e.stopPropagation(); toggleDropdown(freezeDropdown); }); 2214 - } 2249 + // --- Frozen panes (Issue #7) --- 2215 2250 document.getElementById('tb-freeze-rows').addEventListener('click', () => { const rows = selectedCell.row - 1; setFreezeRows(rows > 0 ? rows : 0); renderGrid(); closeAllDropdowns(); showToast(rows > 0 ? `Froze ${rows} row${rows > 1 ? 's' : ''}` : 'Rows unfrozen'); }); 2216 2251 document.getElementById('tb-freeze-cols').addEventListener('click', () => { const cols = selectedCell.col - 1; setFreezeCols(cols > 0 ? cols : 0); renderGrid(); closeAllDropdowns(); showToast(cols > 0 ? `Froze ${cols} column${cols > 1 ? 's' : ''}` : 'Columns unfrozen'); }); 2217 2252 document.getElementById('tb-unfreeze').addEventListener('click', () => { setFreezeRows(0); setFreezeCols(0); renderGrid(); closeAllDropdowns(); showToast('Panes unfrozen'); }); 2218 - 2219 - // --- Insert dropdown --- 2220 - const insertDropdown = document.getElementById('dd-insert'); 2221 - if (insertDropdown) { 2222 - const insertToggle = insertDropdown.querySelector('.toolbar-dropdown-toggle'); 2223 - if (insertToggle) insertToggle.addEventListener('click', (e) => { e.stopPropagation(); toggleDropdown(insertDropdown); }); 2224 - } 2225 2253 2226 2254 function updateFreezeToolbarState() { 2227 2255 const fr = getFreezeRows();