Whiteboard styling
The board adds only the CSS that it needs to work. Colors, fonts and cursors are up to your app, which styles the board with the data attributes on its elements.
The board's CSS
boardStyles holds the CSS that the board needs to work: the size of the board and the area around it, how shapes hold their text, outline or component, and where their handles show. The rules are in the whiteboard cascade layer, so your app's CSS outside of layers overrides them.
The board adds its CSS when its editor starts, so the whiteboard layer comes after the layers that your app declared before, like Tailwind's, and wins over them. To override the board from those layers, declare the whiteboard layer first:
/* With Tailwind, before @import 'tailwindcss' */
@layer whiteboard, theme, base, components, utilities;A doc frame is as tall as its document. Its height: auto !important also wins over !important rules of your app outside of layers.
The board adds this CSS to the page itself, in a <style data-tiptap-style-whiteboard> element. It uses the editor's injectNonce. An editor with injectCSS: false leaves the CSS to your app:
import { boardStyles } from '@tiptap-pro/extension-whiteboard'
const style = document.createElement('style')
style.textContent = boardStyles
document.head.append(style)Shapes have the size of their attributes. An app that sizes a shape by its content also sets contain: none on it.
Zoom
Set --zoom to the zoom of the camera on the element that holds the editor. The handles read it to keep their size at every zoom. Divide your own outlines and borders by it too:
[data-shape][data-selected] {
outline: calc(2px / var(--zoom, 1)) solid #6a00f5;
outline-offset: calc(2px / var(--zoom, 1));
}Shapes
Every shape element has data-shape, and a data-type with the kind of shape: sticky-note, geo, free-text, freehand, doc-frame or arrow. Custom shapes have the data-type from their shapeNodeView. The board element has data-type="board".
| Attribute | On | Description |
|---|---|---|
data-id | Every shape | The id of the shape |
data-color | Shapes with a color | The name of its color, like blue. Custom shapes have it with a color attribute |
data-font-size | Shapes with text | s, m, l, xl or a name of your own |
data-text-align | Shapes with text | start, center or end |
data-font | Shapes with text | sans, serif, mono or a name of your own |
data-kind | Geometric shapes | rectangle, ellipse, diamond or triangle |
data-selected | Selected shapes | Present while the shape is selected |
data-editing | The edited shape | Present while its text, or the document of a doc frame, is edited |
data-remote-selected | Shapes that other users select | Present while another user selects the shape. That user's color is in --remote-selection |
data-erasing | Every shape | Present while the eraser is about to erase the shape |
The shapeElementAttributes option of WhiteboardKit adds attributes of your own, like the data-suggestion-* attributes of Tracked Changes.
Parts of shapes
| Selector | Description |
|---|---|
[data-shape-content] | The element that holds the text of a shape, or the document of a doc frame |
[data-shape-outline] | The SVG outline behind the text of a geometric shape. It stretches over the whole shape |
[data-shape-handle='resize'] | A resize handle on a corner of a selected shape. data-corner is top-left, top-right, bottom-left or bottom-right |
[data-arrow-handle] | A handle on an end of a selected arrow. Its value is from or to |
[data-shape-component] | The element of a custom shape's node view. It has the size of the shape, and so does a NodeViewWrapper in it |
[data-shape-interactive] | Your mark on parts of a custom shape's component that take their own presses, like the legend of a chart |
Arrows and pen lines are drawn in the current color, so set their color. The outline of a geometric shape is a path that your CSS fills and strokes:
[data-type='arrow'],
[data-type='freehand'] {
color: var(--stroke);
}
[data-shape-outline] path {
fill: var(--fill);
stroke: var(--stroke);
stroke-width: 2px;
vector-effect: non-scaling-stroke;
}Colors
Shapes, text colors and highlights store the name of a board color, so your CSS decides how each one looks. One way is a few variables for each color:
[data-color='blue'] {
--stroke: #0d74ce;
--fill: #ebf5ff;
--note: #bfe0ff;
}
[data-type='sticky-note'] {
background: var(--note);
}Text colors are span elements with data-color, and highlights mark elements with data-color. See the example for the styles of all colors.
To add a color of your own, add its name to the colors option of WhiteboardKit, and style it like the others:
import { shapeColors, WhiteboardKit } from '@tiptap-pro/extension-whiteboard'
WhiteboardKit.configure({ colors: [...shapeColors, 'brand'] })Commands take any name. The list decides which text colors and highlights pasted HTML keeps: other text colors go away, and other highlights become yellow.
Stage
attachStage marks the stage, so your CSS can show the tool and the pan:
| Attribute | Description |
|---|---|
data-tool | The active tool, like select or pen |
data-pan | ready while space is held, and active while the board pans |
While a drag runs, the stage holds a preview element:
| Selector | Description |
|---|---|
[data-selection-box] | The box of a selection drag |
[data-shape-preview] | The box of a shape while a tool draws it. Its value is the tool, like note, and data-color holds the chosen color, if any |
[data-arrow-preview] | The line of an arrow while the arrow tool draws it, in the current color |
[data-pen-preview] | The line of the pen while it draws, in the current color. data-color holds the color of the line |
The previews are not scaled with the board, so they need no --zoom:
[data-selection-box],
[data-shape-preview] {
background: rgba(106, 0, 245, 0.1);
border: 1px dashed #6a00f5;
}
[data-arrow-preview] {
color: #6a00f5;
}Keyboard
While keys act on the board, the editor element has data-keyboard="board". While the text of a shape is edited, it doesn't. It stays while the document of a doc frame is edited.
Read-only
While the board is read-only, the editor element has data-read-only, and selected shapes show no handles. Use it for cursors that promise a change, like a move cursor on shapes:
.tiptap[data-read-only] [data-shape] {
cursor: default;
}