@domternal/theme 0.7.0 → 0.7.2

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/src/_image.scss CHANGED
@@ -76,6 +76,9 @@
76
76
  // =============================================================================
77
77
  // Image Insert Popover (appended to document.body - same pattern as link popover)
78
78
  // =============================================================================
79
+ // The popover JS copies the editor's `dm-theme-*` class onto the
80
+ // popover so the dark-tokens cascade applies on the element itself.
81
+ // All colours read from `--dm-*` tokens; no hardcoded theme values.
79
82
 
80
83
  .dm-image-popover {
81
84
  position: fixed;
@@ -83,10 +86,10 @@
83
86
  align-items: center;
84
87
  gap: 0.25rem;
85
88
  padding: 0.25rem;
86
- background: #f8f9fa;
87
- border: 1px solid #e0e0e0;
89
+ background: var(--dm-surface);
90
+ border: 1px solid var(--dm-border-color);
88
91
  border-radius: 0.25rem;
89
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
92
+ box-shadow: var(--dm-popover-shadow, 0 4px 12px rgba(0, 0, 0, 0.12));
90
93
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
91
94
  Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
92
95
  visibility: hidden;
@@ -101,18 +104,18 @@
101
104
  }
102
105
 
103
106
  .dm-image-popover-input {
104
- border: 1px solid #e0e0e0;
107
+ border: 1px solid var(--dm-border-color);
105
108
  border-radius: 0.25rem;
106
109
  padding: 0.25rem 0.5rem;
107
110
  font-size: 0.8125rem;
108
111
  font-family: inherit;
109
112
  min-width: 14rem;
110
113
  outline: none;
111
- background: #fff;
112
- color: #1a1a1a;
114
+ background: var(--dm-bg);
115
+ color: var(--dm-text);
113
116
 
114
117
  &:focus {
115
- border-color: #2563eb;
118
+ border-color: var(--dm-accent);
116
119
  }
117
120
  }
118
121
 
@@ -126,16 +129,16 @@
126
129
  border: none;
127
130
  border-radius: 0.25rem;
128
131
  background: transparent;
129
- color: #1a1a1a;
132
+ color: var(--dm-text);
130
133
  cursor: pointer;
131
134
  transition: background-color 0.15s, color 0.15s;
132
135
 
133
136
  &:hover {
134
- background: rgba(0, 0, 0, 0.06);
137
+ background: var(--dm-hover);
135
138
  }
136
139
 
137
140
  &:focus-visible {
138
- outline: 2px solid var(--dm-accent, #2563eb);
141
+ outline: 2px solid var(--dm-accent);
139
142
  outline-offset: 1px;
140
143
  }
141
144
 
@@ -145,71 +148,9 @@
145
148
  }
146
149
  }
147
150
 
148
- .dm-image-popover-apply:hover {
149
- color: #2563eb;
150
- }
151
-
151
+ .dm-image-popover-apply:hover,
152
152
  .dm-image-popover-browse:hover {
153
- color: #2563eb;
154
- }
155
-
156
- // Dark theme override
157
- [data-theme="dark"] .dm-image-popover,
158
- .dm-theme-dark .dm-image-popover {
159
- background: #2a2a2a;
160
- border-color: #404040;
161
-
162
- .dm-image-popover-input {
163
- background: #1a1a1a;
164
- border-color: #404040;
165
- color: #e0e0e0;
166
-
167
- &:focus {
168
- border-color: #3b82f6;
169
- }
170
- }
171
-
172
- .dm-image-popover-btn {
173
- color: #e0e0e0;
174
-
175
- &:hover {
176
- background: rgba(255, 255, 255, 0.1);
177
- }
178
- }
179
-
180
- .dm-image-popover-apply:hover {
181
- color: #3b82f6;
182
- }
183
- }
184
-
185
- // Auto dark mode - follows system preference
186
- @media (prefers-color-scheme: dark) {
187
- .dm-theme-auto .dm-image-popover {
188
- background: #2a2a2a;
189
- border-color: #404040;
190
-
191
- .dm-image-popover-input {
192
- background: #1a1a1a;
193
- border-color: #404040;
194
- color: #e0e0e0;
195
-
196
- &:focus {
197
- border-color: #3b82f6;
198
- }
199
- }
200
-
201
- .dm-image-popover-btn {
202
- color: #e0e0e0;
203
-
204
- &:hover {
205
- background: rgba(255, 255, 255, 0.1);
206
- }
207
- }
208
-
209
- .dm-image-popover-apply:hover {
210
- color: #3b82f6;
211
- }
212
- }
153
+ color: var(--dm-accent);
213
154
  }
214
155
 
215
156
  // Drag-and-drop overlay - shown when dragging image files over the editor
@@ -1,9 +1,10 @@
1
1
  // =============================================================================
2
2
  // Link Popover Styles
3
3
  // =============================================================================
4
- // The popover is appended to document.body (to escape overflow:hidden on
5
- // .dm-editor), so it can't inherit CSS variables from .dm-editor / .dm-toolbar.
6
- // We hardcode fallback values that match the light theme defaults.
4
+ // The popover is appended to document.body to escape overflow:hidden on
5
+ // .dm-editor. The popover JS copies the editor's `dm-theme-*` class onto
6
+ // the popover so the dark-tokens cascade applies on the element itself.
7
+ // All colours read from `--dm-*` tokens; no hardcoded theme values.
7
8
  // =============================================================================
8
9
 
9
10
  .dm-link-popover {
@@ -12,10 +13,10 @@
12
13
  align-items: center;
13
14
  gap: 0.25rem;
14
15
  padding: 0.25rem;
15
- background: #f8f9fa;
16
- border: 1px solid #e0e0e0;
16
+ background: var(--dm-surface);
17
+ border: 1px solid var(--dm-border-color);
17
18
  border-radius: 0.25rem;
18
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
19
+ box-shadow: var(--dm-popover-shadow, 0 4px 12px rgba(0, 0, 0, 0.12));
19
20
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
20
21
  Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
21
22
  visibility: hidden;
@@ -30,18 +31,18 @@
30
31
  }
31
32
 
32
33
  .dm-link-popover-input {
33
- border: 1px solid #e0e0e0;
34
+ border: 1px solid var(--dm-border-color);
34
35
  border-radius: 0.25rem;
35
36
  padding: 0.25rem 0.5rem;
36
37
  font-size: 0.8125rem;
37
38
  font-family: inherit;
38
39
  min-width: 14rem;
39
40
  outline: none;
40
- background: #fff;
41
- color: #1a1a1a;
41
+ background: var(--dm-bg);
42
+ color: var(--dm-text);
42
43
 
43
44
  &:focus {
44
- border-color: #2563eb;
45
+ border-color: var(--dm-accent);
45
46
  }
46
47
  }
47
48
 
@@ -55,16 +56,16 @@
55
56
  border: none;
56
57
  border-radius: 0.25rem;
57
58
  background: transparent;
58
- color: #1a1a1a;
59
+ color: var(--dm-text);
59
60
  cursor: pointer;
60
61
  transition: background-color 0.15s, color 0.15s;
61
62
 
62
63
  &:hover {
63
- background: rgba(0, 0, 0, 0.06);
64
+ background: var(--dm-hover);
64
65
  }
65
66
 
66
67
  &:focus-visible {
67
- outline: 2px solid var(--dm-accent, #2563eb);
68
+ outline: 2px solid var(--dm-accent);
68
69
  outline-offset: 1px;
69
70
  }
70
71
 
@@ -75,9 +76,11 @@
75
76
  }
76
77
 
77
78
  .dm-link-popover-apply:hover {
78
- color: #2563eb;
79
+ color: var(--dm-accent);
79
80
  }
80
81
 
82
+ // `--dm-danger` is not a semantic token yet, hardcode for now and bump
83
+ // when the design system introduces one.
81
84
  .dm-link-popover-remove:hover {
82
85
  color: #dc2626;
83
86
  }
@@ -85,65 +88,6 @@
85
88
  // Pending-link decoration - highlights the text range while the popover
86
89
  // input has focus (browser hides native selection on editor blur).
87
90
  .dm-link-pending {
88
- background-color: rgba(37, 99, 235, 0.12);
91
+ background-color: color-mix(in srgb, var(--dm-accent) 12%, transparent);
89
92
  border-radius: 1px;
90
93
  }
91
-
92
- // Dark theme override
93
- [data-theme="dark"] .dm-link-popover,
94
- .dm-theme-dark .dm-link-popover {
95
- background: #2a2a2a;
96
- border-color: #404040;
97
-
98
- .dm-link-popover-input {
99
- background: #1a1a1a;
100
- border-color: #404040;
101
- color: #e0e0e0;
102
-
103
- &:focus {
104
- border-color: #3b82f6;
105
- }
106
- }
107
-
108
- .dm-link-popover-btn {
109
- color: #e0e0e0;
110
-
111
- &:hover {
112
- background: rgba(255, 255, 255, 0.1);
113
- }
114
- }
115
-
116
- .dm-link-popover-apply:hover {
117
- color: #3b82f6;
118
- }
119
- }
120
-
121
- // Auto dark mode - follows system preference
122
- @media (prefers-color-scheme: dark) {
123
- .dm-theme-auto .dm-link-popover {
124
- background: #2a2a2a;
125
- border-color: #404040;
126
-
127
- .dm-link-popover-input {
128
- background: #1a1a1a;
129
- border-color: #404040;
130
- color: #e0e0e0;
131
-
132
- &:focus {
133
- border-color: #3b82f6;
134
- }
135
- }
136
-
137
- .dm-link-popover-btn {
138
- color: #e0e0e0;
139
-
140
- &:hover {
141
- background: rgba(255, 255, 255, 0.1);
142
- }
143
- }
144
-
145
- .dm-link-popover-apply:hover {
146
- color: #3b82f6;
147
- }
148
- }
149
- }
@@ -20,10 +20,9 @@
20
20
  max-width: 38rem;
21
21
  margin: 0 auto;
22
22
 
23
- // Generous reading line-height and slightly larger text, similar to
24
- // Notion. Padding is zeroed because the page wrapper already supplies
25
- // the white space around the column.
26
- --dm-editor-font-size: 1.0625rem;
23
+ // Generous reading line-height; padding zeroed because the page wrapper
24
+ // supplies the white space around the column. Body font-size inherits
25
+ // classic 1rem so toggling between modes doesn't shift text size.
27
26
  --dm-editor-line-height: 1.7;
28
27
  --dm-editor-padding: 0;
29
28
 
@@ -44,23 +43,20 @@
44
43
  min-height: 60vh;
45
44
  outline: none;
46
45
 
47
- // Tighter heading rhythm than the default content stylesheet, more
48
- // Notion-like. Sizes are intentionally smaller than the toolbar
49
- // demo's defaults so headings sit closer to body text.
46
+ // Tighter heading rhythm than the default content stylesheet.
47
+ // Sizes inherit classic (browser defaults / `_content.scss`) so the
48
+ // mode toggle shifts layout, not text scale.
50
49
  h1 {
51
- font-size: 2.25rem;
52
50
  font-weight: 700;
53
51
  margin-top: 1.5rem;
54
52
  margin-bottom: 0.75rem;
55
53
  }
56
54
  h2 {
57
- font-size: 1.625rem;
58
55
  font-weight: 600;
59
56
  margin-top: 1.5rem;
60
57
  margin-bottom: 0.5rem;
61
58
  }
62
59
  h3 {
63
- font-size: 1.25rem;
64
60
  font-weight: 600;
65
61
  margin-top: 1.25rem;
66
62
  margin-bottom: 0.375rem;
@@ -68,5 +64,19 @@
68
64
  p {
69
65
  margin: 0.25rem 0;
70
66
  }
67
+
68
+ // Paragraphs inside table cells stay flush; otherwise the higher
69
+ // specificity of the rule above adds 4px top/bottom and visibly puffs
70
+ // up cells compared to classic mode.
71
+ td > p,
72
+ th > p {
73
+ margin: 0;
74
+ }
75
+ }
76
+
77
+ // Slash-command placeholders wrap in narrow table cells; the cell is the editable unit.
78
+ .ProseMirror td .is-empty::before,
79
+ .ProseMirror th .is-empty::before {
80
+ content: none;
71
81
  }
72
82
  }
@@ -246,9 +246,13 @@
246
246
  width: 100%;
247
247
  padding: 0.375rem 0.5rem;
248
248
  border: none;
249
- border-radius: var(--dm-button-border-radius);
249
+ // Component tokens (--dm-button-*) are defined on .dm-editor. This
250
+ // dropdown is portaled to document.body, so those tokens may be
251
+ // undefined here. Fall back to base tokens (which the theme sets via
252
+ // the .dm-theme-dark/.dm-theme-auto class copied onto the dropdown).
253
+ border-radius: var(--dm-button-border-radius, 0.375rem);
250
254
  background: transparent;
251
- color: var(--dm-button-color);
255
+ color: var(--dm-button-color, var(--dm-text));
252
256
  cursor: pointer;
253
257
  font-size: 0.8125rem;
254
258
  line-height: 1.4;
package/src/_toc.scss CHANGED
@@ -5,13 +5,11 @@
5
5
  // =============================================================================
6
6
 
7
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.
8
+ // Positioning wrapper. Inner `.dm-toc-outline-ticks` stacks + clips
9
+ // ticks; card is an absolute sibling, untouched by the clip.
10
10
  display: flex;
11
11
  flex-direction: column;
12
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
13
  z-index: var(--dm-toc-z-index, 10);
16
14
 
17
15
  // No background / no border in collapsed state - just a column of ticks.
@@ -44,6 +42,14 @@
44
42
  &[data-anchor='editor'][data-bottom-visible='true'] {
45
43
  top: var(--dm-toc-editor-top, 1rem);
46
44
  }
45
+ // `scroll-mode='container'`: sticky pins the nav at the host's
46
+ // visible middle, zero JS during scroll. Plugin publishes
47
+ // `--dm-toc-mid-half-height` (= nav.offsetHeight / 2).
48
+ &[data-anchor='editor'][data-scroll-mode='container'] {
49
+ position: sticky;
50
+ top: calc(50% - var(--dm-toc-mid-half-height, 0px));
51
+ right: 0;
52
+ }
47
53
  &[data-anchor='viewport'] {
48
54
  position: fixed;
49
55
  top: 50%;
@@ -94,6 +100,27 @@
94
100
  justify-content: flex-end;
95
101
  }
96
102
 
103
+ // `scroll-mode='container'`: shell spans the host (no top/bottom
104
+ // inset) and is JS-stretched to host.scrollHeight so the sticky's
105
+ // containing block covers the full scroll range.
106
+ .dm-toc-outline-shell[data-anchor='editor'][data-scroll-mode='container'] {
107
+ top: 0;
108
+ bottom: 0;
109
+ }
110
+
111
+ // Ticks column - capped at ~50% (Notion behavior): overflow simply
112
+ // clips, gap stays constant, column doesn't scroll. Defaults to
113
+ // `50vh` (page mode); container mode plugin overrides the var.
114
+ .dm-toc-outline-ticks {
115
+ display: flex;
116
+ flex-direction: column;
117
+ align-items: flex-end;
118
+ gap: var(--dm-toc-tick-gap, 10px);
119
+ padding: var(--dm-toc-padding-block, 12px) var(--dm-toc-padding-inline, 8px);
120
+ max-height: var(--dm-toc-ticks-max-h, 50vh);
121
+ overflow: hidden;
122
+ }
123
+
97
124
  .dm-toc-outline-tick {
98
125
  // Reset button defaults - we draw a solid filled rectangle.
99
126
  appearance: none;
@@ -103,6 +130,9 @@
103
130
  font: inherit;
104
131
  cursor: pointer;
105
132
  background: var(--dm-toc-tick-color, rgba(55, 53, 47, 0.4));
133
+ // Lock tick height so the gap stays constant; overflow is clipped
134
+ // by the wrapper instead of squeezed.
135
+ flex-shrink: 0;
106
136
  height: var(--dm-toc-tick-height, 2px);
107
137
  border-radius: var(--dm-toc-tick-radius, 1px);
108
138
  // Width per heading level - h1 widest, deeper levels narrower.
@@ -173,9 +203,9 @@
173
203
  translateX(var(--dm-toc-card-offset, 8px));
174
204
  min-width: var(--dm-toc-card-min-width, 180px);
175
205
  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));
206
+ // Card matches the ticks wrapper height; the rest of the rows
207
+ // are reachable by scrolling the card itself.
208
+ max-height: var(--dm-toc-ticks-max-h, 50vh);
179
209
  overflow-y: auto;
180
210
  padding: var(--dm-toc-card-padding-block, 6px) 0;
181
211
  background: var(--dm-toc-card-bg, rgba(255, 255, 255, 0.98));
@@ -183,6 +213,26 @@
183
213
  border-radius: var(--dm-toc-card-radius, 6px);
184
214
  box-shadow: var(--dm-toc-card-shadow, 0 8px 24px rgba(0, 0, 0, 0.08));
185
215
 
216
+ // Tokenised slim scrollbar so dark theme overrides keep contrast.
217
+ scrollbar-width: thin;
218
+ scrollbar-color: var(--dm-scrollbar-thumb, rgba(0, 0, 0, 0.18)) transparent;
219
+
220
+ &::-webkit-scrollbar {
221
+ width: 6px;
222
+ }
223
+ &::-webkit-scrollbar-track {
224
+ background: transparent;
225
+ margin: 0.375rem 0;
226
+ }
227
+ &::-webkit-scrollbar-thumb {
228
+ background: var(--dm-scrollbar-thumb, rgba(0, 0, 0, 0.18));
229
+ border-radius: 3px;
230
+ transition: background-color 0.15s;
231
+ }
232
+ &::-webkit-scrollbar-thumb:hover {
233
+ background: var(--dm-scrollbar-thumb-hover, rgba(0, 0, 0, 0.28));
234
+ }
235
+
186
236
  display: flex;
187
237
  flex-direction: column;
188
238
  align-items: stretch;
@@ -216,6 +266,8 @@
216
266
  font-size: var(--dm-toc-row-font-size, 13px);
217
267
  line-height: var(--dm-toc-row-line-height, 1.4);
218
268
  color: var(--dm-toc-row-color, rgba(55, 53, 47, 0.7));
269
+ // Constant row height; long lists scroll the card, no squeeze.
270
+ flex-shrink: 0;
219
271
  padding:
220
272
  var(--dm-toc-row-padding-block, 4px)
221
273
  var(--dm-toc-row-padding-inline-end, 16px)
@@ -122,6 +122,7 @@
122
122
  --dm-editor-font-size: 1rem;
123
123
  --dm-editor-line-height: 1.6;
124
124
  --dm-editor-padding: 1rem;
125
+ --dm-editor-padding-top-extra: 0.5rem;
125
126
  --dm-editor-border: 1px solid var(--dm-border-color);
126
127
  --dm-editor-border-radius: 0.75rem;
127
128
  // Override to add a focus ring, e.g. 0 0 0 1px var(--dm-focus-color)
@@ -100,7 +100,9 @@
100
100
  .dm-theme-dark .dm-mention-suggestion,
101
101
  .dm-theme-dark .dm-table-controls-dropdown,
102
102
  .dm-theme-dark .dm-slash-command-menu,
103
- .dm-theme-dark .dm-block-context-menu {
103
+ .dm-theme-dark .dm-block-context-menu,
104
+ .dm-theme-dark .dm-link-popover,
105
+ .dm-theme-dark .dm-image-popover {
104
106
  @include dark-tokens;
105
107
  }
106
108
 
@@ -116,7 +118,9 @@
116
118
  .dm-theme-auto .dm-mention-suggestion,
117
119
  .dm-theme-auto .dm-table-controls-dropdown,
118
120
  .dm-theme-auto .dm-slash-command-menu,
119
- .dm-theme-auto .dm-block-context-menu {
121
+ .dm-theme-auto .dm-block-context-menu,
122
+ .dm-theme-auto .dm-link-popover,
123
+ .dm-theme-auto .dm-image-popover {
120
124
  @include dark-tokens;
121
125
  }
122
126
  }