style: move extended toolbar button and renome to tools
This commit is contained in:
1 parent
673cafa7a7
commit
c523e34e66
3 files changed
+128
-71
No files matched your search
+120
-56
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { cubicOut } from 'svelte/easing';
|
||||
import type { Editor } from '@tiptap/core';
|
||||
import EditorComponent from './lib/editor/Editor.svelte';
|
||||
import Toolbar from './lib/editor/Toolbar.svelte';
|
||||
@@ -116,6 +117,17 @@
|
||||
saveToolbarExpanded(toolbarExpanded);
|
||||
}
|
||||
|
||||
// Combined height + opacity transition: the extended toolbar slides and fades
|
||||
// in/out as one motion when the toolbar is expanded/collapsed.
|
||||
function expand(node: HTMLElement, { duration = 180 } = {}) {
|
||||
const h = node.scrollHeight;
|
||||
return {
|
||||
duration,
|
||||
easing: cubicOut,
|
||||
css: (t: number) => `overflow: hidden; height: ${t * h}px; opacity: ${t};`,
|
||||
};
|
||||
}
|
||||
|
||||
function clickOutside(node: HTMLElement) {
|
||||
function handler(e: MouseEvent) {
|
||||
if (!node.contains(e.target as Node)) themeOpen = false;
|
||||
@@ -350,7 +362,7 @@
|
||||
<main>
|
||||
<header class:expanded={toolbarExpanded}>
|
||||
<img src="/PrimeText.png" alt="PrimeText" class="app-logo" />
|
||||
<Toolbar editor={activeEditor} tick={activeTick} expanded={toolbarExpanded} />
|
||||
<Toolbar editor={activeEditor} tick={activeTick} />
|
||||
<div class="header-actions">
|
||||
{#snippet saveIcon()}
|
||||
<!-- Floppy disk -->
|
||||
@@ -429,23 +441,6 @@
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-separator"></div>
|
||||
<button
|
||||
class="toolbar-toggle-btn"
|
||||
class:active={toolbarExpanded}
|
||||
onclick={toggleToolbar}
|
||||
title={toolbarExpanded ? 'Hide extended toolbar' : 'Show extended toolbar'}
|
||||
>
|
||||
<!-- Sliders/settings icon -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
||||
<line x1="2" y1="4" x2="14" y2="4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<line x1="2" y1="8" x2="14" y2="8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<line x1="2" y1="12" x2="14" y2="12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<circle cx="5" cy="4" r="1.5" fill="var(--color-toolbar-bg)" stroke="currentColor" stroke-width="1.2"/>
|
||||
<circle cx="10" cy="8" r="1.5" fill="var(--color-toolbar-bg)" stroke="currentColor" stroke-width="1.2"/>
|
||||
<circle cx="7" cy="12" r="1.5" fill="var(--color-toolbar-bg)" stroke="currentColor" stroke-width="1.2"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="theme-wrap" use:clickOutside>
|
||||
<button
|
||||
class="theme-btn"
|
||||
@@ -510,19 +505,44 @@
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
{#if toolbarExpanded}
|
||||
<ToolbarExpanded
|
||||
editor={activeEditor}
|
||||
tick={activeTick}
|
||||
bind:showFormattingMarks
|
||||
bind:pageMargins
|
||||
bind:pageOrientation
|
||||
bind:hfDistances
|
||||
hfActive={hfActive}
|
||||
onEditZone={(zone) => (hfActive = zone)}
|
||||
onDebugDump={handleDebugDump}
|
||||
/>
|
||||
{/if}
|
||||
<div class="toolbar-secondary" class:expanded={toolbarExpanded}>
|
||||
<button
|
||||
class="expand-toggle"
|
||||
class:active={toolbarExpanded}
|
||||
onclick={toggleToolbar}
|
||||
title={toolbarExpanded ? 'Hide extra tools' : 'Show extra tools'}
|
||||
aria-expanded={toolbarExpanded}
|
||||
>
|
||||
<!-- Sliders icon -->
|
||||
<svg class="tools-icon" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
||||
<line x1="2" y1="4" x2="14" y2="4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<line x1="2" y1="8" x2="14" y2="8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<line x1="2" y1="12" x2="14" y2="12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<circle cx="5" cy="4" r="1.5" fill="var(--color-surface)" stroke="currentColor" stroke-width="1.2"/>
|
||||
<circle cx="10" cy="8" r="1.5" fill="var(--color-surface)" stroke="currentColor" stroke-width="1.2"/>
|
||||
<circle cx="7" cy="12" r="1.5" fill="var(--color-surface)" stroke="currentColor" stroke-width="1.2"/>
|
||||
</svg>
|
||||
<span class="expand-label">Tools</span>
|
||||
<svg class="chevron" width="8" height="8" viewBox="0 0 8 8" fill="none" aria-hidden="true">
|
||||
<path d="M2.5 1l3 3-3 3" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
{#if toolbarExpanded}
|
||||
<div class="extended-wrap" transition:expand>
|
||||
<ToolbarExpanded
|
||||
editor={activeEditor}
|
||||
tick={activeTick}
|
||||
bind:showFormattingMarks
|
||||
bind:pageMargins
|
||||
bind:pageOrientation
|
||||
bind:hfDistances
|
||||
hfActive={hfActive}
|
||||
onEditZone={(zone) => (hfActive = zone)}
|
||||
onDebugDump={handleDebugDump}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<EditorComponent
|
||||
bind:editor
|
||||
bind:tick
|
||||
@@ -571,45 +591,37 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Basic toolbar: a complete toolbar with its own divider + elevation. When the
|
||||
extended toolbar opens, those move to .toolbar-secondary so the two rows read
|
||||
as one connected toolbar (border-color/shadow transition for a smooth merge). */
|
||||
header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: var(--color-toolbar-bg);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
box-shadow: var(--shadow);
|
||||
transition: border-color 0.18s, box-shadow 0.18s;
|
||||
}
|
||||
|
||||
/* With the extended toolbar visible the header merges into it: the divider and
|
||||
elevation move to the extended toolbar so they read as one toolbar. */
|
||||
header.expanded {
|
||||
border-bottom: none;
|
||||
border-bottom-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* Anchored to a fixed offset from the header top (align-self + margin-top)
|
||||
instead of vertically centered, so toggling the extended toolbar — which
|
||||
changes the header height — doesn't shift the logo. The offset centers it on
|
||||
the top toolbar's button row (padding-top 0.5rem + half the 2rem button). */
|
||||
.app-logo {
|
||||
height: 17px;
|
||||
width: auto;
|
||||
align-self: flex-start;
|
||||
margin: 0.95rem 0.5rem 0 0.75rem;
|
||||
margin: 0 0.5rem 0 0.75rem;
|
||||
opacity: 1.0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Pinned to the top (like .app-logo) so the changing header height when the
|
||||
extended toolbar toggles doesn't shift it. margin-top matches the top
|
||||
toolbar's padding so the buttons share the same baseline. */
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-left: auto;
|
||||
margin-right: 1rem;
|
||||
align-self: flex-start;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.file-actions {
|
||||
@@ -727,27 +739,79 @@
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.toolbar-toggle-btn {
|
||||
/* Second toolbar row: collapsed it's a transparent strip holding only the
|
||||
floating Tools tab; expanded it becomes the extended-toolbar bar. */
|
||||
.toolbar-secondary {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
/* The toggle is absolute (adds no height): collapsed the bar is 0-height so the
|
||||
document fills up to here; expanded it grows with the extended toolbar.
|
||||
padding-left reserves the tab's column. */
|
||||
padding: 0 1rem 0 6.5rem;
|
||||
background: transparent;
|
||||
border-bottom: 1px solid transparent;
|
||||
transition: background 0.18s, border-color 0.18s, box-shadow 0.18s;
|
||||
}
|
||||
|
||||
.toolbar-secondary.expanded {
|
||||
padding-bottom: 0.4rem;
|
||||
background: var(--color-toolbar-bg);
|
||||
border-bottom-color: var(--color-border);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.extended-wrap {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* "Tools" expander. Overlay (out of flow) so it never reserves row height;
|
||||
top: -1px straddles the basic toolbar's bottom border. Base shape is a normal
|
||||
pill (used when expanded); the bulged tab look is collapsed-only below. */
|
||||
.expand-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 2rem;
|
||||
gap: 5px;
|
||||
height: 2rem;
|
||||
border: none;
|
||||
padding: 0 0.55rem;
|
||||
position: absolute;
|
||||
left: 0.75rem;
|
||||
top: -1px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius);
|
||||
background: transparent;
|
||||
background: var(--color-toolbar-bg);
|
||||
color: var(--color-text);
|
||||
font-size: 0.8rem;
|
||||
font-family: var(--font-sans);
|
||||
cursor: pointer;
|
||||
transition: background 0.15s;
|
||||
transition: border-color 0.15s, background 0.15s, color 0.15s;
|
||||
}
|
||||
|
||||
.toolbar-toggle-btn:hover {
|
||||
background: var(--color-btn-hover);
|
||||
/* Collapsed: the tab hangs from the basic toolbar's bottom edge — drop the top
|
||||
border and round only the bottom so the divider bulges around it, and carry
|
||||
the toolbar's elevation so it reads as part of it. */
|
||||
.toolbar-secondary:not(.expanded) .expand-toggle {
|
||||
border-top-color: transparent;
|
||||
border-radius: 0 0 var(--radius) var(--radius);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.toolbar-toggle-btn.active {
|
||||
background: var(--color-primary);
|
||||
color: white;
|
||||
.expand-toggle:hover {
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
|
||||
.expand-label {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.expand-toggle .chevron {
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.expand-toggle.active .chevron {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.theme-wrap {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import AlignButton from './AlignButton.svelte';
|
||||
import { ORDERED_LIST_TYPES, DEFAULT_ORDERED_TYPE, type OrderedListType } from './orderedListTypes';
|
||||
|
||||
let { editor, tick, expanded = false }: { editor: Editor | null; tick: number; expanded?: boolean } = $props();
|
||||
let { editor, tick }: { editor: Editor | null; tick: number } = $props();
|
||||
|
||||
// $derived re-evaluates whenever `tick` changes (i.e. on every TipTap transaction)
|
||||
let isH1 = $derived(tick >= 0 && !!editor?.isActive('heading', { level: 1 }));
|
||||
@@ -53,7 +53,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="toolbar" class:expanded>
|
||||
<div class="toolbar">
|
||||
{#if editor}
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
@@ -217,21 +217,13 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
padding: 0.5rem 1rem;
|
||||
padding: 0.35rem 1rem;
|
||||
background: var(--color-toolbar-bg);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 200;
|
||||
}
|
||||
|
||||
/* When the extended toolbar is shown the two rows form one toolbar: drop the
|
||||
divider and tighten the bottom padding so the buttons sit at normal spacing. */
|
||||
.toolbar.expanded {
|
||||
border-bottom: none;
|
||||
padding-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
.toolbar-group {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
|
||||
@@ -1159,14 +1159,15 @@
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* Inner content of the second toolbar row; the surrounding .toolbar-secondary
|
||||
(App.svelte) owns the background, divider and elevation. */
|
||||
.toolbar-expanded {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
padding: 0.2rem 1rem 0.4rem;
|
||||
background: var(--color-toolbar-bg);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
box-shadow: var(--shadow);
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Layout sits at the far right (logical separation from the rest). order:1
|
||||
|
||||
Reference in new issue
Block a user