feat: add Toolbar component with active state and formatting buttons
This commit is contained in:
1 parent
9ffa1995a0
commit
e8eee6ce3b
1 file changed
+135
@@ -0,0 +1,135 @@
|
||||
<script lang="ts">
|
||||
import type { Editor } from '@tiptap/core';
|
||||
|
||||
let { editor }: { editor: Editor | null } = $props();
|
||||
</script>
|
||||
|
||||
<div class="toolbar">
|
||||
{#if editor}
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
class:active={editor.isActive('bold')}
|
||||
onclick={() => editor?.chain().focus().toggleBold().run()}
|
||||
title="Bold (Ctrl+B)"
|
||||
>
|
||||
<strong>B</strong>
|
||||
</button>
|
||||
<button
|
||||
class:active={editor.isActive('italic')}
|
||||
onclick={() => editor?.chain().focus().toggleItalic().run()}
|
||||
title="Italic (Ctrl+I)"
|
||||
>
|
||||
<em>I</em>
|
||||
</button>
|
||||
<button
|
||||
class:active={editor.isActive('underline')}
|
||||
onclick={() => editor?.chain().focus().toggleUnderline().run()}
|
||||
title="Underline (Ctrl+U)"
|
||||
>
|
||||
<u>U</u>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="toolbar-separator"></div>
|
||||
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
class:active={editor.isActive('heading', { level: 1 })}
|
||||
onclick={() => editor?.chain().focus().toggleHeading({ level: 1 }).run()}
|
||||
title="Heading 1"
|
||||
>
|
||||
H1
|
||||
</button>
|
||||
<button
|
||||
class:active={editor.isActive('heading', { level: 2 })}
|
||||
onclick={() => editor?.chain().focus().toggleHeading({ level: 2 }).run()}
|
||||
title="Heading 2"
|
||||
>
|
||||
H2
|
||||
</button>
|
||||
<button
|
||||
class:active={editor.isActive('heading', { level: 3 })}
|
||||
onclick={() => editor?.chain().focus().toggleHeading({ level: 3 }).run()}
|
||||
title="Heading 3"
|
||||
>
|
||||
H3
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="toolbar-separator"></div>
|
||||
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
onclick={() => editor?.chain().focus().undo().run()}
|
||||
disabled={!editor.can().undo()}
|
||||
title="Undo (Ctrl+Z)"
|
||||
>
|
||||
↩
|
||||
</button>
|
||||
<button
|
||||
onclick={() => editor?.chain().focus().redo().run()}
|
||||
disabled={!editor.can().redo()}
|
||||
title="Redo (Ctrl+Shift+Z)"
|
||||
>
|
||||
↪
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
padding: 0.5rem 1rem;
|
||||
background: var(--color-toolbar-bg);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.toolbar-group {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.toolbar-separator {
|
||||
width: 1px;
|
||||
height: 1.5rem;
|
||||
background: var(--color-border);
|
||||
margin: 0 0.5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 2rem;
|
||||
height: 2rem;
|
||||
padding: 0 0.5rem;
|
||||
border: none;
|
||||
border-radius: var(--radius);
|
||||
background: transparent;
|
||||
color: var(--color-text);
|
||||
font-size: 0.85rem;
|
||||
font-family: var(--font-sans);
|
||||
cursor: pointer;
|
||||
transition: background 0.15s;
|
||||
}
|
||||
|
||||
button:hover:not(:disabled) {
|
||||
background: var(--color-bg);
|
||||
}
|
||||
|
||||
button.active {
|
||||
background: var(--color-primary);
|
||||
color: white;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
opacity: 0.35;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user