@domternal/theme 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -10
- package/dist/domternal-theme.css +1 -1
- package/dist/domternal-theme.expanded.css +1437 -99
- package/package.json +1 -1
- package/src/_base.scss +2 -2
- package/src/_block-colors.scss +178 -0
- package/src/_block-handle.scss +189 -0
- package/src/_bubble-menu.scss +5 -2
- package/src/_color-palette.scss +3 -3
- package/src/_content.scss +51 -1
- package/src/_context-menu.scss +141 -0
- package/src/_details.scss +5 -5
- package/src/_floating-menu.scss +145 -8
- package/src/_image.scss +6 -6
- package/src/_inline-colors.scss +204 -0
- package/src/_invisible-chars.scss +2 -2
- package/src/_link-popover.scss +2 -2
- package/src/_notion-mode.scss +72 -0
- package/src/_prosemirror.scss +1 -1
- package/src/_slash-command.scss +174 -0
- package/src/_table-controls.scss +3 -3
- package/src/_task-list.scss +51 -12
- package/src/_toc.scss +450 -0
- package/src/_toolbar.scss +5 -5
- package/src/_variables.scss +191 -0
- package/src/index.scss +21 -4
- package/src/themes/_dark.scss +118 -3
- package/src/themes/_light.scss +1 -1
package/src/_toc.scss
ADDED
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Table of Contents - Floating Outline
|
|
3
|
+
// Right-rail outline rendered by `@domternal/extension-toc`. Lives OUTSIDE
|
|
4
|
+
// `.dm-editor` (which has `overflow: hidden`), so tokens pull from `:root`.
|
|
5
|
+
// =============================================================================
|
|
6
|
+
|
|
7
|
+
.dm-toc-outline {
|
|
8
|
+
// Stack ticks vertically with even gaps. flex-end keeps the right
|
|
9
|
+
// edge of every tick aligned even though widths differ per level.
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
align-items: flex-end;
|
|
13
|
+
gap: var(--dm-toc-tick-gap, 10px);
|
|
14
|
+
padding: var(--dm-toc-padding-block, 12px) var(--dm-toc-padding-inline, 8px);
|
|
15
|
+
z-index: var(--dm-toc-z-index, 10);
|
|
16
|
+
|
|
17
|
+
// No background / no border in collapsed state - just a column of ticks.
|
|
18
|
+
// The expanded card adds its own chrome.
|
|
19
|
+
background: transparent;
|
|
20
|
+
border: 0;
|
|
21
|
+
margin: 0;
|
|
22
|
+
pointer-events: auto;
|
|
23
|
+
|
|
24
|
+
// Positioning by `data-anchor`:
|
|
25
|
+
//
|
|
26
|
+
// - editor: nav is `position: sticky`. Plugin toggles
|
|
27
|
+
// `data-bottom-visible` via an IntersectionObserver on a sentinel
|
|
28
|
+
// at the shell's bottom edge.
|
|
29
|
+
// - bottom-visible='false' (editor extends below the viewport):
|
|
30
|
+
// nav sticks at `--dm-toc-mid-top` (= `calc(50vh - height/2)`,
|
|
31
|
+
// set from the measured nav height). The BOX is centered around
|
|
32
|
+
// 50vh - no transform - so the visual is fully constrained by
|
|
33
|
+
// the containing block and never escapes the editor's bounds.
|
|
34
|
+
// - bottom-visible='true' (editor's bottom is on screen): sticky
|
|
35
|
+
// offset becomes `1rem`. The nav's natural position is set by
|
|
36
|
+
// the shell (flex-center) or by inline margin-top (frozen mode)
|
|
37
|
+
// so it stays put until the viewport top scrolls past it.
|
|
38
|
+
// - viewport: `position: fixed` to the right edge of the viewport,
|
|
39
|
+
// vertically centered.
|
|
40
|
+
&[data-anchor='editor'] {
|
|
41
|
+
position: sticky;
|
|
42
|
+
top: var(--dm-toc-mid-top, 50vh);
|
|
43
|
+
}
|
|
44
|
+
&[data-anchor='editor'][data-bottom-visible='true'] {
|
|
45
|
+
top: var(--dm-toc-editor-top, 1rem);
|
|
46
|
+
}
|
|
47
|
+
&[data-anchor='viewport'] {
|
|
48
|
+
position: fixed;
|
|
49
|
+
top: 50%;
|
|
50
|
+
right: var(--dm-toc-right-offset, 24px);
|
|
51
|
+
transform: translateY(-50%);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Visibility guards. The plugin sets data-state and data-viewport
|
|
55
|
+
// based on heading count and matchMedia. Hiding via CSS (vs JS
|
|
56
|
+
// `display: none` directly) lets consumers override without
|
|
57
|
+
// monkey-patching the plugin.
|
|
58
|
+
//
|
|
59
|
+
// State machine: hidden | collapsed | expanded
|
|
60
|
+
// hidden - 0 headings / mobile / < minHeadings
|
|
61
|
+
// collapsed - default; ticks visible, card hidden
|
|
62
|
+
// expanded - hover or focus-within; card visible, ticks hidden
|
|
63
|
+
&[data-state='hidden'],
|
|
64
|
+
&[data-viewport='mobile'] {
|
|
65
|
+
display: none;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Editor-mode shell: out-of-flow column running the host's full
|
|
70
|
+
// vertical extent at its right inside edge. Width shrinks to the nav's
|
|
71
|
+
// intrinsic width; the shell itself is invisible. The nav inside
|
|
72
|
+
// uses the shell's height as its sticky range.
|
|
73
|
+
.dm-toc-outline-shell[data-anchor='editor'] {
|
|
74
|
+
position: absolute;
|
|
75
|
+
top: 25px;
|
|
76
|
+
bottom: 25px;
|
|
77
|
+
right: var(--dm-toc-page-offset, 8px);
|
|
78
|
+
z-index: var(--dm-toc-z-index, 10);
|
|
79
|
+
pointer-events: none;
|
|
80
|
+
|
|
81
|
+
&:has(.dm-toc-outline[data-state='hidden']),
|
|
82
|
+
&:has(.dm-toc-outline[data-viewport='mobile']) {
|
|
83
|
+
display: none;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// mode='center': flex-center sets the nav's natural position to host
|
|
88
|
+
// middle (used on mount when the editor fits the viewport). mode='frozen'
|
|
89
|
+
// uses inline margin-top instead (set by the plugin at the B→A
|
|
90
|
+
// transition). mode='middle' uses default block layout.
|
|
91
|
+
.dm-toc-outline-shell[data-anchor='editor'][data-mode='center'] {
|
|
92
|
+
display: flex;
|
|
93
|
+
align-items: center;
|
|
94
|
+
justify-content: flex-end;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.dm-toc-outline-tick {
|
|
98
|
+
// Reset button defaults - we draw a solid filled rectangle.
|
|
99
|
+
appearance: none;
|
|
100
|
+
border: 0;
|
|
101
|
+
margin: 0;
|
|
102
|
+
padding: 0;
|
|
103
|
+
font: inherit;
|
|
104
|
+
cursor: pointer;
|
|
105
|
+
background: var(--dm-toc-tick-color, rgba(55, 53, 47, 0.4));
|
|
106
|
+
height: var(--dm-toc-tick-height, 2px);
|
|
107
|
+
border-radius: var(--dm-toc-tick-radius, 1px);
|
|
108
|
+
// Width per heading level - h1 widest, deeper levels narrower.
|
|
109
|
+
// Default for unmatched levels falls through to h3-width.
|
|
110
|
+
width: var(--dm-toc-tick-h3-width, 8px);
|
|
111
|
+
transition:
|
|
112
|
+
background-color 120ms ease-out,
|
|
113
|
+
width 120ms ease-out;
|
|
114
|
+
|
|
115
|
+
&:hover {
|
|
116
|
+
background: var(--dm-toc-tick-hover-color, rgba(55, 53, 47, 0.7));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Keyboard focus needs a real ring. The hover-only alpha bump
|
|
120
|
+
// (0.4 -> 0.7) is too subtle to act as a focus indicator for users
|
|
121
|
+
// who can't see hover state. Outline-offset 3px keeps the ring
|
|
122
|
+
// clear of the tick body without colliding with the next tick at
|
|
123
|
+
// the default `--dm-toc-tick-gap: 10px`.
|
|
124
|
+
&:focus-visible {
|
|
125
|
+
background: var(--dm-toc-tick-hover-color, rgba(55, 53, 47, 0.7));
|
|
126
|
+
outline: 2px solid var(--dm-accent, #2563eb);
|
|
127
|
+
outline-offset: 3px;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Active state: the tick for the heading the user is reading. Two
|
|
131
|
+
// selectors so consumers can target either the JS class (`--active`)
|
|
132
|
+
// or the a11y attribute (`aria-current="location"`).
|
|
133
|
+
&.dm-toc--active,
|
|
134
|
+
&[aria-current='location'] {
|
|
135
|
+
background: var(--dm-toc-tick-active-color, rgba(55, 53, 47, 0.95));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Per-level width selectors. h1 / h2 / h3 are the canonical Notion
|
|
139
|
+
// levels; we also handle h4-h6 for consumers configuring custom
|
|
140
|
+
// levels via `levels: [1,2,3,4,5,6]`.
|
|
141
|
+
&[data-level='1'] { width: var(--dm-toc-tick-h1-width, 18px); }
|
|
142
|
+
&[data-level='2'] { width: var(--dm-toc-tick-h2-width, 12px); }
|
|
143
|
+
&[data-level='3'] { width: var(--dm-toc-tick-h3-width, 8px); }
|
|
144
|
+
&[data-level='4'] { width: var(--dm-toc-tick-h4-width, 6px); }
|
|
145
|
+
&[data-level='5'] { width: var(--dm-toc-tick-h5-width, 5px); }
|
|
146
|
+
&[data-level='6'] { width: var(--dm-toc-tick-h6-width, 4px); }
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Ticks fade out when the card takes over.
|
|
150
|
+
.dm-toc-outline[data-state='expanded'] .dm-toc-outline-tick {
|
|
151
|
+
opacity: 0;
|
|
152
|
+
pointer-events: none;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// =============================================================================
|
|
156
|
+
// Expanded card
|
|
157
|
+
// =============================================================================
|
|
158
|
+
// The card is absolutely positioned within the nav (which is fixed at
|
|
159
|
+
// the right gutter). Anchored to the nav's right edge and vertically
|
|
160
|
+
// centered against the same midline as the tick column - it visually
|
|
161
|
+
// REPLACES the ticks rather than appearing alongside them. CSS opacity
|
|
162
|
+
// + transform handle the slide-in transition; the plugin only flips
|
|
163
|
+
// the parent's data-state attribute.
|
|
164
|
+
|
|
165
|
+
.dm-toc-outline-card {
|
|
166
|
+
position: absolute;
|
|
167
|
+
right: 0;
|
|
168
|
+
top: 50%;
|
|
169
|
+
// `--dm-toc-card-shift-y` is set by the plugin to nudge the card back
|
|
170
|
+
// into the viewport when the nav sits near the top or bottom edge.
|
|
171
|
+
transform:
|
|
172
|
+
translateY(calc(-50% + var(--dm-toc-card-shift-y, 0px)))
|
|
173
|
+
translateX(var(--dm-toc-card-offset, 8px));
|
|
174
|
+
min-width: var(--dm-toc-card-min-width, 180px);
|
|
175
|
+
max-width: var(--dm-toc-card-max-width, 260px);
|
|
176
|
+
// Long heading lists scroll internally rather than overflowing the
|
|
177
|
+
// viewport; the margin keeps the card off the chrome edges.
|
|
178
|
+
max-height: calc(100vh - 2 * var(--dm-toc-card-viewport-margin, 16px));
|
|
179
|
+
overflow-y: auto;
|
|
180
|
+
padding: var(--dm-toc-card-padding-block, 6px) 0;
|
|
181
|
+
background: var(--dm-toc-card-bg, rgba(255, 255, 255, 0.98));
|
|
182
|
+
border: var(--dm-toc-card-border, 1px solid rgba(0, 0, 0, 0.06));
|
|
183
|
+
border-radius: var(--dm-toc-card-radius, 6px);
|
|
184
|
+
box-shadow: var(--dm-toc-card-shadow, 0 8px 24px rgba(0, 0, 0, 0.08));
|
|
185
|
+
|
|
186
|
+
display: flex;
|
|
187
|
+
flex-direction: column;
|
|
188
|
+
align-items: stretch;
|
|
189
|
+
|
|
190
|
+
// Hidden by default in collapsed state. opacity + transform together
|
|
191
|
+
// let the card softly slide in from the right when expanding. The
|
|
192
|
+
// pointer-events flip prevents interactions with the invisible card.
|
|
193
|
+
opacity: 0;
|
|
194
|
+
pointer-events: none;
|
|
195
|
+
transition:
|
|
196
|
+
opacity var(--dm-toc-card-transition, 180ms) ease-out,
|
|
197
|
+
transform var(--dm-toc-card-transition, 180ms) ease-out;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.dm-toc-outline[data-state='expanded'] .dm-toc-outline-card {
|
|
201
|
+
opacity: 1;
|
|
202
|
+
pointer-events: auto;
|
|
203
|
+
transform:
|
|
204
|
+
translateY(calc(-50% + var(--dm-toc-card-shift-y, 0px)))
|
|
205
|
+
translateX(0);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.dm-toc-outline-row {
|
|
209
|
+
appearance: none;
|
|
210
|
+
border: 0;
|
|
211
|
+
margin: 0;
|
|
212
|
+
background: transparent;
|
|
213
|
+
cursor: pointer;
|
|
214
|
+
text-align: start;
|
|
215
|
+
font: inherit;
|
|
216
|
+
font-size: var(--dm-toc-row-font-size, 13px);
|
|
217
|
+
line-height: var(--dm-toc-row-line-height, 1.4);
|
|
218
|
+
color: var(--dm-toc-row-color, rgba(55, 53, 47, 0.7));
|
|
219
|
+
padding:
|
|
220
|
+
var(--dm-toc-row-padding-block, 4px)
|
|
221
|
+
var(--dm-toc-row-padding-inline-end, 16px)
|
|
222
|
+
var(--dm-toc-row-padding-block, 4px)
|
|
223
|
+
var(--dm-toc-row-padding-inline-start, 12px);
|
|
224
|
+
// Truncate long heading text - it's a navigation aid, not the
|
|
225
|
+
// headings themselves.
|
|
226
|
+
white-space: nowrap;
|
|
227
|
+
overflow: hidden;
|
|
228
|
+
text-overflow: ellipsis;
|
|
229
|
+
border-radius: 3px;
|
|
230
|
+
transition: background-color 120ms ease-out, color 120ms ease-out;
|
|
231
|
+
|
|
232
|
+
&:hover {
|
|
233
|
+
background: var(--dm-toc-row-hover-bg, rgba(0, 0, 0, 0.04));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
&:focus-visible {
|
|
237
|
+
outline: 2px solid var(--dm-accent, #2563eb);
|
|
238
|
+
outline-offset: -2px;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Active row mirrors the active tick. Selector matches both the
|
|
242
|
+
// JS-applied class (`--active`, shared with ticks) and the a11y
|
|
243
|
+
// attribute the plugin sets simultaneously - same convention as ticks.
|
|
244
|
+
&.dm-toc--active,
|
|
245
|
+
&[aria-current='location'] {
|
|
246
|
+
color: var(--dm-toc-row-active-color, rgba(55, 53, 47, 0.95));
|
|
247
|
+
font-weight: var(--dm-toc-row-active-weight, 600);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Per-level indent - h1 sits flush at the start padding, h2 nudges
|
|
251
|
+
// in by one row-indent, h3 by two, etc. Keeps the visual hierarchy
|
|
252
|
+
// legible at a glance even when text is truncated.
|
|
253
|
+
&[data-level='1'] {
|
|
254
|
+
padding-inline-start: var(--dm-toc-row-padding-inline-start, 12px);
|
|
255
|
+
}
|
|
256
|
+
&[data-level='2'] {
|
|
257
|
+
padding-inline-start:
|
|
258
|
+
calc(var(--dm-toc-row-padding-inline-start, 12px) + var(--dm-toc-row-indent, 14px));
|
|
259
|
+
}
|
|
260
|
+
&[data-level='3'] {
|
|
261
|
+
padding-inline-start:
|
|
262
|
+
calc(var(--dm-toc-row-padding-inline-start, 12px) + var(--dm-toc-row-indent, 14px) * 2);
|
|
263
|
+
}
|
|
264
|
+
&[data-level='4'] {
|
|
265
|
+
padding-inline-start:
|
|
266
|
+
calc(var(--dm-toc-row-padding-inline-start, 12px) + var(--dm-toc-row-indent, 14px) * 3);
|
|
267
|
+
}
|
|
268
|
+
&[data-level='5'] {
|
|
269
|
+
padding-inline-start:
|
|
270
|
+
calc(var(--dm-toc-row-padding-inline-start, 12px) + var(--dm-toc-row-indent, 14px) * 4);
|
|
271
|
+
}
|
|
272
|
+
&[data-level='6'] {
|
|
273
|
+
padding-inline-start:
|
|
274
|
+
calc(var(--dm-toc-row-padding-inline-start, 12px) + var(--dm-toc-row-indent, 14px) * 5);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// =============================================================================
|
|
279
|
+
// Inline /toc block
|
|
280
|
+
// Lives INSIDE the editor as a regular content block. NodeView renders
|
|
281
|
+
// the heading list; click on a row routes to scrollToHeading.
|
|
282
|
+
// =============================================================================
|
|
283
|
+
|
|
284
|
+
.dm-toc-block {
|
|
285
|
+
display: block;
|
|
286
|
+
margin-block: var(--dm-toc-block-margin-block, 1rem);
|
|
287
|
+
padding:
|
|
288
|
+
var(--dm-toc-block-padding-block, 12px)
|
|
289
|
+
var(--dm-toc-block-padding-inline, 16px);
|
|
290
|
+
background: var(--dm-toc-block-bg, rgba(0, 0, 0, 0.02));
|
|
291
|
+
border: var(--dm-toc-block-border, 1px solid rgba(0, 0, 0, 0.08));
|
|
292
|
+
border-radius: var(--dm-toc-block-radius, 6px);
|
|
293
|
+
|
|
294
|
+
// Block is contenteditable=false (atom node, NodeView-rendered).
|
|
295
|
+
// Surface a subtle outline ring on PM selection so the user knows
|
|
296
|
+
// the block is selected (e.g. for delete with Backspace on the
|
|
297
|
+
// gap cursor immediately after).
|
|
298
|
+
&.ProseMirror-selectednode {
|
|
299
|
+
outline: 2px solid var(--dm-accent, #2563eb);
|
|
300
|
+
outline-offset: 2px;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.dm-toc-block-empty {
|
|
305
|
+
margin: 0;
|
|
306
|
+
color: var(--dm-toc-block-empty-color, rgba(55, 53, 47, 0.5));
|
|
307
|
+
font-style: var(--dm-toc-block-empty-font-style, italic);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.dm-toc-block-list {
|
|
311
|
+
list-style: none;
|
|
312
|
+
padding: 0;
|
|
313
|
+
margin: 0;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.dm-toc-block-item {
|
|
317
|
+
margin: 0;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.dm-toc-block-link {
|
|
321
|
+
// Reset button defaults for an in-flow link-style affordance.
|
|
322
|
+
appearance: none;
|
|
323
|
+
border: 0;
|
|
324
|
+
background: transparent;
|
|
325
|
+
cursor: pointer;
|
|
326
|
+
font: inherit;
|
|
327
|
+
font-size: var(--dm-toc-block-link-font-size, 0.9375rem);
|
|
328
|
+
line-height: var(--dm-toc-block-link-line-height, 1.5);
|
|
329
|
+
color: var(--dm-toc-block-link-color, rgba(55, 53, 47, 0.8));
|
|
330
|
+
text-align: start;
|
|
331
|
+
width: 100%;
|
|
332
|
+
display: block;
|
|
333
|
+
padding:
|
|
334
|
+
var(--dm-toc-block-link-padding-block, 4px)
|
|
335
|
+
var(--dm-toc-block-link-padding-inline, 8px);
|
|
336
|
+
border-radius: var(--dm-toc-block-link-radius, 3px);
|
|
337
|
+
transition: background-color 120ms ease-out, color 120ms ease-out;
|
|
338
|
+
|
|
339
|
+
&:hover {
|
|
340
|
+
color: var(--dm-toc-block-link-hover-color, rgba(55, 53, 47, 1));
|
|
341
|
+
background: var(--dm-toc-block-link-hover-bg, rgba(0, 0, 0, 0.04));
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
&:focus-visible {
|
|
345
|
+
outline: 2px solid var(--dm-accent, #2563eb);
|
|
346
|
+
outline-offset: -2px;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Active row mirrors the outline's active tick/row contract.
|
|
350
|
+
&.dm-toc-block-link--active,
|
|
351
|
+
&[aria-current='location'] {
|
|
352
|
+
color: var(--dm-toc-block-link-active-color, rgba(55, 53, 47, 0.95));
|
|
353
|
+
font-weight: var(--dm-toc-block-link-active-weight, 600);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Per-level indent. Same shape as outline rows; padding on the
|
|
357
|
+
// link itself so the hover background covers the full visual row
|
|
358
|
+
// including the indent.
|
|
359
|
+
&[data-level='1'] {
|
|
360
|
+
padding-inline-start: var(--dm-toc-block-link-padding-inline, 8px);
|
|
361
|
+
}
|
|
362
|
+
&[data-level='2'] {
|
|
363
|
+
padding-inline-start:
|
|
364
|
+
calc(var(--dm-toc-block-link-padding-inline, 8px) + var(--dm-toc-block-link-indent, 16px));
|
|
365
|
+
}
|
|
366
|
+
&[data-level='3'] {
|
|
367
|
+
padding-inline-start:
|
|
368
|
+
calc(var(--dm-toc-block-link-padding-inline, 8px) + var(--dm-toc-block-link-indent, 16px) * 2);
|
|
369
|
+
}
|
|
370
|
+
&[data-level='4'] {
|
|
371
|
+
padding-inline-start:
|
|
372
|
+
calc(var(--dm-toc-block-link-padding-inline, 8px) + var(--dm-toc-block-link-indent, 16px) * 3);
|
|
373
|
+
}
|
|
374
|
+
&[data-level='5'] {
|
|
375
|
+
padding-inline-start:
|
|
376
|
+
calc(var(--dm-toc-block-link-padding-inline, 8px) + var(--dm-toc-block-link-indent, 16px) * 4);
|
|
377
|
+
}
|
|
378
|
+
&[data-level='6'] {
|
|
379
|
+
padding-inline-start:
|
|
380
|
+
calc(var(--dm-toc-block-link-padding-inline, 8px) + var(--dm-toc-block-link-indent, 16px) * 5);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Reduced-motion guard. Repeated here defensively even though `index.scss`
|
|
385
|
+
// has a global block, in case that block is ever scoped to `.dm-editor`-only.
|
|
386
|
+
@media (prefers-reduced-motion: reduce) {
|
|
387
|
+
.dm-toc-outline-tick,
|
|
388
|
+
.dm-toc-outline-card,
|
|
389
|
+
.dm-toc-outline-row,
|
|
390
|
+
.dm-toc-block-link {
|
|
391
|
+
transition: none;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Card start-state offset becomes 0 too: with no transition, the
|
|
395
|
+
// X translate would jump from `var(--dm-toc-card-offset)` to 0
|
|
396
|
+
// instantly anyway, but resetting the start position to 0 means
|
|
397
|
+
// the card never enters its mid-animation visual state on a fast
|
|
398
|
+
// expand/collapse cycle (which can briefly leak a 1-frame
|
|
399
|
+
// off-position card).
|
|
400
|
+
.dm-toc-outline-card {
|
|
401
|
+
transform:
|
|
402
|
+
translateY(calc(-50% + var(--dm-toc-card-shift-y, 0px)))
|
|
403
|
+
translateX(0);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// Print: hide the floating outline (navigation chrome, not content).
|
|
408
|
+
// Inline `/toc` blocks stay since they belong to the document.
|
|
409
|
+
@media print {
|
|
410
|
+
.dm-toc-outline {
|
|
411
|
+
display: none;
|
|
412
|
+
}
|
|
413
|
+
.dm-toc-block {
|
|
414
|
+
background: transparent;
|
|
415
|
+
border-color: rgba(0, 0, 0, 0.2);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Forced-colors / Windows High Contrast: backgrounds are stripped, so
|
|
420
|
+
// ticks need explicit borders to stay visible. We use `Highlight` /
|
|
421
|
+
// `ButtonText` (OS palette) rather than `forced-color-adjust: none`.
|
|
422
|
+
@media (forced-colors: active) {
|
|
423
|
+
.dm-toc-outline-tick {
|
|
424
|
+
background: ButtonText;
|
|
425
|
+
border: 1px solid ButtonText;
|
|
426
|
+
|
|
427
|
+
&.dm-toc--active,
|
|
428
|
+
&[aria-current='location'] {
|
|
429
|
+
background: Highlight;
|
|
430
|
+
border-color: Highlight;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.dm-toc-outline-card {
|
|
435
|
+
border: 1px solid ButtonText;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
.dm-toc-outline-row,
|
|
439
|
+
.dm-toc-block-link {
|
|
440
|
+
&.dm-toc--active,
|
|
441
|
+
&.dm-toc-block-link--active,
|
|
442
|
+
&[aria-current='location'] {
|
|
443
|
+
color: Highlight;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
.dm-toc-block {
|
|
448
|
+
border: 1px solid ButtonText;
|
|
449
|
+
}
|
|
450
|
+
}
|
package/src/_toolbar.scss
CHANGED
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
color: var(--dm-button-active-color);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
// Expanded state
|
|
53
|
+
// Expanded state - panel/popover is open (same visual as dropdown triggers)
|
|
54
54
|
&[aria-expanded="true"] {
|
|
55
55
|
background: var(--dm-button-hover-bg);
|
|
56
56
|
}
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
// Dropdown trigger
|
|
78
|
+
// Dropdown trigger - wider to fit caret
|
|
79
79
|
.dm-toolbar-dropdown-trigger {
|
|
80
80
|
position: relative;
|
|
81
81
|
width: auto;
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
position: relative;
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
// Dropdown panel
|
|
136
|
+
// Dropdown panel - positioned by floating-ui (strategy: absolute)
|
|
137
137
|
.dm-toolbar-dropdown-panel {
|
|
138
138
|
position: absolute;
|
|
139
139
|
z-index: 50;
|
|
@@ -155,7 +155,7 @@
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
// Display-mode: icon-only
|
|
158
|
+
// Display-mode: icon-only - compact grid-like panel
|
|
159
159
|
.dm-toolbar-dropdown-panel[data-display-mode="icon"] {
|
|
160
160
|
min-width: 0;
|
|
161
161
|
|
|
@@ -166,7 +166,7 @@
|
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
// Display-mode: text-only
|
|
169
|
+
// Display-mode: text-only - shrink to text width, no icon gap
|
|
170
170
|
.dm-toolbar-dropdown-panel[data-display-mode="text"] {
|
|
171
171
|
min-width: 0;
|
|
172
172
|
|