/* ===== Floating toolbar ===== */ .tm-floating-toolbar { /* We mount on
and rely on `position: fixed` so transformed editor * ancestors cannot anchor the toolbar to themselves. (Position lives in * CSS rather than inline styles; only the dynamic `top`/`left` are set * imperatively by the view plugin.) */ position: fixed; /* Stay above ordinary editor widgets but below Obsidian's modal/popover * layers so a settings dialog (or any other Modal) is never visually * buried by the toolbar. `--layer-popover` is well below `--layer-modal` * in Obsidian, which gives us the right stacking order out of the box. */ z-index: var(--layer-popover, 30); pointer-events: auto; /* Row layout: content groups on the left, collapse toggle on the right. */ display: flex; flex-direction: row; align-items: stretch; gap: 0; padding: 4px; background: var(--background-primary); border: 1px solid var(--background-modifier-border); border-radius: 6px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); font-size: var(--font-ui-smaller); user-select: none; } .tm-floating-toolbar.is-hidden { display: none; } /* Inner wrapper that stacks functional groups vertically. * Has its own overflow:hidden so the collapse animation clips content * without affecting the toggle button. */ .tm-floating-toolbar .tm-toolbar-content { display: flex; flex-direction: column; align-items: stretch; gap: 2px; flex: 0 0 auto; overflow: hidden; transition: width 0.3s ease, opacity 0.25s ease; } /* While the collapse animation is in flight, the JS toggle adds * `is-size-locked` and writes the measured size into CSS custom properties * (`--tm-locked-width` / `--tm-locked-height`) via setCssProps. The class is * removed (and the variables cleared) once the transition settles, so the * content can reflow naturally on subsequent layout changes. */ .tm-floating-toolbar .tm-toolbar-content.is-size-locked { width: var(--tm-locked-width); height: var(--tm-locked-height); } .tm-floating-toolbar.is-collapsed .tm-toolbar-content { width: 0; opacity: 0; padding: 0; gap: 0; } /* Collapse toggle: right edge, vertically centered, same size as toolbar buttons. */ .tm-floating-toolbar .tm-collapse-toggle { display: flex; align-items: center; justify-content: center; min-width: 26px; min-height: 26px; padding: 4px; margin-left: 2px; border-left: 1px solid var(--background-modifier-border); cursor: pointer; flex-shrink: 0; background: transparent; border-top: none; border-right: none; border-bottom: none; border-radius: 4px; color: var(--text-muted); transition: margin 0.25s ease; } .tm-floating-toolbar .tm-collapse-toggle:hover { background: var(--background-modifier-hover); color: var(--text-normal); } /* When collapsed the toolbar slides left past the viewport; content stays in * the DOM to preserve its measured width for the slide calculation. The * viewport edge naturally clips it. */ /* Toggle icon: same size as toolbar button icons + smooth rotation. */ .tm-floating-toolbar .tm-collapse-toggle .tm-icon { width: 16px; height: 16px; transition: transform 0.3s ease; } .tm-floating-toolbar.is-collapsed .tm-collapse-toggle .tm-icon { transform: rotate(180deg); } /* Live Preview merged-cell placeholder: anchors keep their colspan/rowspan * attributes, while the cells they cover are hidden via this class so the * row/column geometry collapses around the anchor. Toggled in JS via * classList instead of writing element.style.display directly. */ table td.tm-merge-placeholder, table th.tm-merge-placeholder { display: none; } .tm-floating-toolbar .tm-group { display: flex; align-items: center; flex-wrap: wrap; gap: 1px; padding: 2px 3px; /* Visual separator between vertically-stacked groups. */ border-bottom: 1px solid var(--background-modifier-border); } .tm-floating-toolbar .tm-group:last-child { border-bottom: none; } .tm-floating-toolbar button.tm-btn { display: inline-flex; align-items: center; justify-content: center; min-width: 26px; height: 26px; padding: 0 6px; background: transparent; border: none; border-radius: 4px; color: var(--text-muted); cursor: pointer; } .tm-floating-toolbar button.tm-btn:hover { background: var(--background-modifier-hover); color: var(--text-normal); } .tm-floating-toolbar button.tm-btn.is-active { background: var(--background-modifier-active-hover); color: var(--text-accent); } .tm-floating-toolbar button.tm-btn .tm-icon { width: 16px; height: 16px; } /* ===== Modal grid editor ===== */ .tm-modal { /* Ensure the modal is wide enough that multi-column tables * are never squeezed down to a single visible column. */ min-width: min(90vw, 600px); } .tm-modal .modal-content { padding: 0; overflow: visible; } .tm-grid-toolbar { display: flex; flex-wrap: wrap; gap: 4px; padding: 8px 12px; border-bottom: 1px solid var(--background-modifier-border); background: var(--background-secondary); } .tm-grid-toolbar button { height: 28px; padding: 0 10px; } .tm-grid-toolbar button.tm-grid-icon-btn { padding: 0 6px; display: inline-flex; align-items: center; justify-content: center; } .tm-grid-toolbar button.tm-grid-icon-btn .svg-icon { width: 16px; height: 16px; } .tm-grid-wrap { max-height: 60vh; overflow: auto; padding: 8px; } table.tm-grid { border-collapse: collapse; /* `table-layout: auto` lets the browser size columns to their content. * `width: 100%` fills the wrapper; wider tables cause `.tm-grid-wrap` * to scroll horizontally. */ table-layout: auto; width: 100%; } table.tm-grid th, table.tm-grid td { border: 1px solid var(--background-modifier-border); padding: 4px 8px; min-width: 80px; vertical-align: top; position: relative; } table.tm-grid th { background: var(--background-secondary); font-weight: 600; } table.tm-grid td.tm-selected, table.tm-grid th.tm-selected { outline: 2px solid var(--interactive-accent); outline-offset: -2px; background: var(--background-modifier-hover); } table.tm-grid .tm-cell-edit { display: block; width: 100%; min-height: 1.4em; outline: none; white-space: pre-wrap; word-break: break-word; } .tm-grid-actions { display: flex; justify-content: flex-end; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--background-modifier-border); background: var(--background-secondary); } /* ===== Reading view & Live Preview rebuilt tables ===== */ /* When the post-processor / live-preview view plugin rewrites a table, * Obsidian's widget-scoped CSS (e.g. `.cm-table-widget td`) no longer matches * because we replace `