@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/src/_details.scss CHANGED
@@ -24,13 +24,13 @@
24
24
  border-radius: 0.375rem;
25
25
  margin: 0.75em 0;
26
26
 
27
- // contentDOM contains summary (row 1) and content (row 2)
27
+ // contentDOM - contains summary (row 1) and content (row 2)
28
28
  // Use display:contents so its children participate in the grid
29
29
  > div {
30
30
  display: contents;
31
31
  }
32
32
 
33
- // Toggle button chevron on the right, round hover highlight
33
+ // Toggle button - chevron on the right, round hover highlight
34
34
  > button[type="button"] {
35
35
  grid-column: 2;
36
36
  grid-row: 1;
@@ -70,7 +70,7 @@
70
70
  }
71
71
  }
72
72
 
73
- // Summary row background spans both columns so the button area
73
+ // Summary row background - spans both columns so the button area
74
74
  // also gets the surface colour behind the round toggle
75
75
  &::before {
76
76
  content: '';
@@ -108,12 +108,12 @@
108
108
  border-top: var(--dm-details-border);
109
109
  }
110
110
 
111
- // Disable ProseMirror selected-node outline the border is enough
111
+ // Disable ProseMirror selected-node outline - the border is enough
112
112
  &.ProseMirror-selectednode {
113
113
  outline: none;
114
114
  }
115
115
 
116
- // Open state rotate chevron to point down
116
+ // Open state - rotate chevron to point down
117
117
  &.is-open {
118
118
  > button[type="button"]::before {
119
119
  transform: rotate(45deg);
@@ -1,24 +1,161 @@
1
1
  // =============================================================================
2
2
  // Floating Menu Styles
3
+ // Block-insert menu shown on empty paragraphs. Rendered by framework
4
+ // wrappers as a WAI-ARIA menu with role="menu"/"group"/"menuitem".
3
5
  // =============================================================================
4
6
 
5
7
  .dm-floating-menu {
6
8
  position: absolute;
7
9
  display: flex;
8
10
  flex-direction: column;
9
- gap: var(--dm-toolbar-gap);
10
- padding: var(--dm-toolbar-padding);
11
- background: var(--dm-toolbar-bg);
12
- border: var(--dm-toolbar-border);
13
- border-radius: var(--dm-button-border-radius);
14
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
11
+ gap: 0.25rem;
12
+ min-width: 16rem;
13
+ max-height: 22rem;
14
+ overflow-y: auto;
15
+ padding: 0.375rem;
16
+
17
+ // Opaque background - plain color (not translucent) so nested content
18
+ // under the menu is fully occluded. Fallback chain covers cases where
19
+ // the menu is reparented outside `.dm-editor` and loses the variable.
20
+ background: var(--dm-toolbar-bg, var(--dm-bg, #ffffff));
21
+ border: 1px solid var(--dm-border-color, #e5e7eb);
22
+ border-radius: var(--dm-toolbar-border-radius, 0.5rem);
23
+ box-shadow: var(--dm-popover-shadow,
24
+ 0 10px 25px rgba(0, 0, 0, 0.08),
25
+ 0 4px 10px rgba(0, 0, 0, 0.04));
15
26
  visibility: hidden;
16
27
  opacity: 0;
17
- transition: opacity 0.2s ease, visibility 0.2s;
18
- z-index: 50;
28
+ transition: opacity 0.15s ease, visibility 0.15s;
29
+ z-index: var(--dm-z-popover, 50);
30
+
31
+ // Slim, translucent scrollbar - Firefox via scrollbar-* properties,
32
+ // Chrome/Safari/Edge via ::-webkit-scrollbar pseudo-elements. Colors are
33
+ // tokenised so dark theme overrides keep contrast on dark surfaces.
34
+ scrollbar-width: thin;
35
+ scrollbar-color: var(--dm-scrollbar-thumb, rgba(0, 0, 0, 0.18)) transparent;
36
+
37
+ &::-webkit-scrollbar {
38
+ width: 6px;
39
+ }
40
+ &::-webkit-scrollbar-track {
41
+ background: transparent;
42
+ margin: 0.375rem 0;
43
+ }
44
+ &::-webkit-scrollbar-thumb {
45
+ background: var(--dm-scrollbar-thumb, rgba(0, 0, 0, 0.18));
46
+ border-radius: 3px;
47
+ transition: background-color 0.15s;
48
+ }
49
+ &::-webkit-scrollbar-thumb:hover {
50
+ background: var(--dm-scrollbar-thumb-hover, rgba(0, 0, 0, 0.28));
51
+ }
19
52
 
20
53
  &[data-show] {
21
54
  visibility: visible;
22
55
  opacity: 1;
23
56
  }
57
+
58
+ // ---------------------------------------------------------------------------
59
+ // Group heading (e.g. "Basic", "Lists", "Media")
60
+ // ---------------------------------------------------------------------------
61
+ &-group-label {
62
+ padding: 0.375rem 0.5rem 0.125rem;
63
+ font-size: 0.6875rem;
64
+ font-weight: 600;
65
+ letter-spacing: 0.04em;
66
+ text-transform: uppercase;
67
+ color: var(--dm-muted, #999);
68
+ user-select: none;
69
+ }
70
+
71
+ &-group {
72
+ display: flex;
73
+ flex-direction: column;
74
+ gap: 0.125rem;
75
+
76
+ // Visual separator between unlabelled groups; labelled groups get
77
+ // spacing from their label instead.
78
+ & + &:not(:has(+ .dm-floating-menu-group-label)) {
79
+ margin-top: 0.25rem;
80
+ }
81
+ }
82
+
83
+ &-group-wrapper {
84
+ display: flex;
85
+ flex-direction: column;
86
+ }
87
+
88
+ // ---------------------------------------------------------------------------
89
+ // Menu item button (single-line: icon + label + optional shortcut chip)
90
+ // ---------------------------------------------------------------------------
91
+ &-item {
92
+ display: flex;
93
+ align-items: center;
94
+ gap: 0.5rem;
95
+ width: 100%;
96
+ padding: 0.3125rem 0.5rem;
97
+ border: none;
98
+ border-radius: var(--dm-button-border-radius, 0.375rem);
99
+ background: transparent;
100
+ color: var(--dm-button-color, inherit);
101
+ text-align: left;
102
+ font: inherit;
103
+ cursor: pointer;
104
+ transition: background-color 0.12s;
105
+
106
+ &:hover:not([aria-disabled="true"]),
107
+ &:focus:not([aria-disabled="true"]) {
108
+ background: var(--dm-button-hover-bg, rgba(0, 0, 0, 0.04));
109
+ }
110
+
111
+ &:focus-visible {
112
+ outline: 2px solid var(--dm-accent, #2563eb);
113
+ outline-offset: -2px;
114
+ }
115
+
116
+ &[aria-disabled="true"],
117
+ &:disabled {
118
+ opacity: var(--dm-button-disabled-opacity, 0.45);
119
+ cursor: not-allowed;
120
+ }
121
+ }
122
+
123
+ // Icon slot
124
+ &-item-icon {
125
+ display: inline-flex;
126
+ align-items: center;
127
+ justify-content: center;
128
+ width: 1.25rem;
129
+ height: 1.25rem;
130
+ flex-shrink: 0;
131
+ color: var(--dm-editor-text, inherit);
132
+
133
+ svg {
134
+ width: 1.125rem;
135
+ height: 1.125rem;
136
+ }
137
+ }
138
+
139
+ &-item-label {
140
+ flex: 1;
141
+ min-width: 0;
142
+ font-size: 0.875rem;
143
+ color: var(--dm-editor-text, inherit);
144
+ white-space: nowrap;
145
+ overflow: hidden;
146
+ text-overflow: ellipsis;
147
+ }
148
+
149
+ // Shortcut hint chip (e.g. `# `, `> `, `[ ] `)
150
+ &-item-shortcut {
151
+ flex-shrink: 0;
152
+ padding: 0.0625rem 0.375rem;
153
+ font-family: var(--dm-code-font, ui-monospace, monospace);
154
+ font-size: 0.6875rem;
155
+ color: var(--dm-muted, #999);
156
+ background: var(--dm-surface, #f8f9fa);
157
+ border: 1px solid var(--dm-border-color, #e5e7eb);
158
+ border-radius: 0.25rem;
159
+ user-select: none;
160
+ }
24
161
  }
package/src/_image.scss CHANGED
@@ -2,7 +2,7 @@
2
2
  // Image Styles
3
3
  // =============================================================================
4
4
  // Image extension renders as <img> with optional float inline styles.
5
- // Base img styles are in _content.scss this file adds float constraints.
5
+ // Base img styles are in _content.scss - this file adds float constraints.
6
6
  // =============================================================================
7
7
 
8
8
  .dm-editor .ProseMirror {
@@ -45,7 +45,7 @@
45
45
  z-index: 1; // above inline text so clicks always hit the image, not the paragraph behind
46
46
  }
47
47
 
48
- // Selected state accent outline + visible handles
48
+ // Selected state - accent outline + visible handles
49
49
  &.ProseMirror-selectednode {
50
50
  outline: 2px solid var(--dm-accent, #2563eb);
51
51
 
@@ -55,7 +55,7 @@
55
55
  }
56
56
  }
57
57
 
58
- // Resize handles hidden by default, shown on selection
58
+ // Resize handles - hidden by default, shown on selection
59
59
  .dm-image-handle {
60
60
  display: none;
61
61
  position: absolute;
@@ -74,7 +74,7 @@
74
74
  }
75
75
 
76
76
  // =============================================================================
77
- // Image Insert Popover (appended to document.body same pattern as link popover)
77
+ // Image Insert Popover (appended to document.body - same pattern as link popover)
78
78
  // =============================================================================
79
79
 
80
80
  .dm-image-popover {
@@ -182,7 +182,7 @@
182
182
  }
183
183
  }
184
184
 
185
- // Auto dark mode follows system preference
185
+ // Auto dark mode - follows system preference
186
186
  @media (prefers-color-scheme: dark) {
187
187
  .dm-theme-auto .dm-image-popover {
188
188
  background: #2a2a2a;
@@ -212,7 +212,7 @@
212
212
  }
213
213
  }
214
214
 
215
- // Drag-and-drop overlay shown when dragging image files over the editor
215
+ // Drag-and-drop overlay - shown when dragging image files over the editor
216
216
  .dm-editor.dm-dragover {
217
217
  outline: 2px dashed var(--dm-accent);
218
218
  outline-offset: -2px;
@@ -0,0 +1,204 @@
1
+ // =============================================================================
2
+ // Inline Colors
3
+ // =============================================================================
4
+ // Companion to `_block-colors.scss`. The block file's `[data-text-color]`
5
+ // and `[data-bg-color]` rules already apply to inline spans (attribute
6
+ // selectors have no element-type constraint). This file adds the inline
7
+ // span bg-padding override and styles for the Notion color picker popover.
8
+ //
9
+ // Load AFTER `_block-colors.scss` in `index.scss` so the inline override
10
+ // wins on equal specificity.
11
+ // =============================================================================
12
+
13
+ // Block rule applies `padding-block: 0.125rem` to any `[data-bg-color]`,
14
+ // which would push a tinted span's background above/below the line box
15
+ // and overlap neighbouring lines. Spans need INLINE padding only.
16
+ .dm-editor .ProseMirror {
17
+ span[data-bg-color] {
18
+ padding-block: 0;
19
+ padding-inline: 0.2rem;
20
+ border-radius: 0.25rem;
21
+ }
22
+ }
23
+
24
+ // -----------------------------------------------------------------------------
25
+ // Bubble menu "A" trigger
26
+ // -----------------------------------------------------------------------------
27
+
28
+ .dm-ncp-trigger {
29
+ position: relative;
30
+ display: inline-flex;
31
+ flex-direction: column;
32
+ align-items: center;
33
+ justify-content: center;
34
+ gap: 0.125rem;
35
+ }
36
+
37
+ .dm-ncp-trigger-glyph {
38
+ font-family: var(--dm-editor-font-family, system-ui, sans-serif);
39
+ font-size: 0.95rem;
40
+ font-weight: 600;
41
+ line-height: 1;
42
+ transform: translateY(2px);
43
+ }
44
+
45
+ .dm-ncp-trigger-underline {
46
+ width: 0.875rem;
47
+ height: 0.125rem;
48
+ border-radius: 0.0625rem;
49
+ background-color: transparent;
50
+ }
51
+
52
+ // -----------------------------------------------------------------------------
53
+ // Picker popover
54
+ // -----------------------------------------------------------------------------
55
+
56
+ .dm-notion-color-picker {
57
+ // z-index parity with link popover (60), above bubble menu (50).
58
+ position: absolute;
59
+ z-index: 60;
60
+
61
+ display: flex;
62
+ flex-direction: column;
63
+ gap: 0.25rem;
64
+ padding: 0.25rem;
65
+
66
+ background: var(--dm-surface-elevated, var(--dm-surface, #ffffff));
67
+ color: var(--dm-editor-text, inherit);
68
+ border: 1px solid var(--dm-border-color, #e5e7eb);
69
+ border-radius: 0.5rem;
70
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
71
+
72
+ &:not([data-show]) {
73
+ display: none;
74
+ }
75
+ }
76
+
77
+ .dm-ncp-section {
78
+ display: flex;
79
+ flex-direction: column;
80
+ gap: 0.25rem;
81
+ }
82
+
83
+ .dm-ncp-label {
84
+ font-size: 0.75rem;
85
+ line-height: 1;
86
+ font-weight: 500;
87
+ color: var(--dm-muted, #6b7280);
88
+ padding: 0.125rem 0.25rem;
89
+ }
90
+
91
+ .dm-ncp-grid {
92
+ // Fixed 5 columns so every section reads as a 5x2 grid regardless of how
93
+ // many recent entries exist or how wide the popover ends up.
94
+ display: grid;
95
+ grid-template-columns: repeat(5, 1.5rem);
96
+ gap: 0.25rem;
97
+ padding: 0.25rem 0.5rem;
98
+ justify-content: start;
99
+ }
100
+
101
+ // -----------------------------------------------------------------------------
102
+ // Swatch
103
+ // -----------------------------------------------------------------------------
104
+
105
+ .dm-ncp-swatch {
106
+ position: relative;
107
+
108
+ display: inline-flex;
109
+ align-items: center;
110
+ justify-content: center;
111
+
112
+ width: 1.5rem;
113
+ height: 1.5rem;
114
+
115
+ padding: 0;
116
+ border: 1px solid var(--dm-border-color, #e5e7eb);
117
+ border-radius: 50%;
118
+ background: transparent;
119
+ color: var(--dm-editor-text, #333);
120
+
121
+ font-family: var(--dm-editor-font-family, system-ui, sans-serif);
122
+ font-size: 0.75rem;
123
+ font-weight: 600;
124
+ line-height: 1;
125
+
126
+ cursor: pointer;
127
+ transition: transform 0.08s ease, box-shadow 0.08s ease;
128
+
129
+ &:hover {
130
+ transform: scale(1.1);
131
+ box-shadow: 0 0 0 2px var(--dm-accent-surface, rgba(37, 99, 235, 0.15));
132
+ }
133
+
134
+ // OUTSET outline (offset > 0): swatch fill takes the full button surface,
135
+ // so an inset outline would render under the fill.
136
+ &:focus-visible,
137
+ &.dm-ncp-active {
138
+ outline: 2px solid var(--dm-accent, #2563eb);
139
+ outline-offset: 1px;
140
+ }
141
+ }
142
+
143
+ // Strike-through "no color" indicator. Painted via `::after` so it overlays
144
+ // the swatch's content - the text-color "Default" swatch keeps its "A" glyph
145
+ // AND gets the diagonal slash on top, mirroring Notion's letterform-plus-slash
146
+ // signal.
147
+ @mixin ncp-default-slash {
148
+ &::after {
149
+ content: '';
150
+ position: absolute;
151
+ inset: 0;
152
+ border-radius: inherit;
153
+ pointer-events: none;
154
+ background-image: linear-gradient(
155
+ to top right,
156
+ transparent calc(50% - 1px),
157
+ var(--dm-muted, #999) calc(50% - 1px),
158
+ var(--dm-muted, #999) calc(50% + 1px),
159
+ transparent calc(50% + 1px)
160
+ );
161
+ }
162
+ }
163
+
164
+ .dm-ncp-swatch--text {
165
+ background-color: var(--dm-surface, #f8f9fa);
166
+
167
+ &::before {
168
+ content: 'A';
169
+ }
170
+
171
+ &[data-color="null"] {
172
+ @include ncp-default-slash;
173
+ }
174
+
175
+ &[data-color="gray"]::before { color: var(--dm-block-text-gray); }
176
+ &[data-color="brown"]::before { color: var(--dm-block-text-brown); }
177
+ &[data-color="orange"]::before { color: var(--dm-block-text-orange); }
178
+ &[data-color="yellow"]::before { color: var(--dm-block-text-yellow); }
179
+ &[data-color="green"]::before { color: var(--dm-block-text-green); }
180
+ &[data-color="blue"]::before { color: var(--dm-block-text-blue); }
181
+ &[data-color="purple"]::before { color: var(--dm-block-text-purple); }
182
+ &[data-color="pink"]::before { color: var(--dm-block-text-pink); }
183
+ &[data-color="red"]::before { color: var(--dm-block-text-red); }
184
+ }
185
+
186
+ .dm-ncp-swatch--bg {
187
+ &[data-color="null"] { @include ncp-default-slash; }
188
+
189
+ &[data-color="gray"] { background-color: var(--dm-block-bg-gray); }
190
+ &[data-color="brown"] { background-color: var(--dm-block-bg-brown); }
191
+ &[data-color="orange"] { background-color: var(--dm-block-bg-orange); }
192
+ &[data-color="yellow"] { background-color: var(--dm-block-bg-yellow); }
193
+ &[data-color="green"] { background-color: var(--dm-block-bg-green); }
194
+ &[data-color="blue"] { background-color: var(--dm-block-bg-blue); }
195
+ &[data-color="purple"] { background-color: var(--dm-block-bg-purple); }
196
+ &[data-color="pink"] { background-color: var(--dm-block-bg-pink); }
197
+ &[data-color="red"] { background-color: var(--dm-block-bg-red); }
198
+ }
199
+
200
+ @media (max-width: 480px) {
201
+ .dm-notion-color-picker {
202
+ max-width: calc(100vw - 1rem);
203
+ }
204
+ }
@@ -14,7 +14,7 @@
14
14
  user-select: none;
15
15
  }
16
16
 
17
- // Inline space decorations overlay · on the invisible space character
17
+ // Inline space decorations - overlay · on the invisible space character
18
18
  [data-char="space"] {
19
19
  position: relative;
20
20
 
@@ -28,7 +28,7 @@
28
28
  }
29
29
  }
30
30
 
31
- // Inline non-breaking space decorations overlay ° on the nbsp character
31
+ // Inline non-breaking space decorations - overlay ° on the nbsp character
32
32
  [data-char="nbsp"] {
33
33
  position: relative;
34
34
 
@@ -82,7 +82,7 @@
82
82
  color: #dc2626;
83
83
  }
84
84
 
85
- // Pending-link decoration highlights the text range while the popover
85
+ // Pending-link decoration - highlights the text range while the popover
86
86
  // input has focus (browser hides native selection on editor blur).
87
87
  .dm-link-pending {
88
88
  background-color: rgba(37, 99, 235, 0.12);
@@ -118,7 +118,7 @@
118
118
  }
119
119
  }
120
120
 
121
- // Auto dark mode follows system preference
121
+ // Auto dark mode - follows system preference
122
122
  @media (prefers-color-scheme: dark) {
123
123
  .dm-theme-auto .dm-link-popover {
124
124
  background: #2a2a2a;
@@ -0,0 +1,72 @@
1
+ // =============================================================================
2
+ // Notion Mode
3
+ // Opt-in stylistic preset: borderless surface, centered narrow column,
4
+ // generous reading rhythm, BlockHandle in the surrounding gutter.
5
+ // Apply with class `dm-notion-mode` on the editor host element.
6
+ // =============================================================================
7
+
8
+ .dm-editor.dm-notion-mode {
9
+ // Drop the default chrome - Notion pages have no card outline.
10
+ border: none;
11
+ border-radius: 0;
12
+ box-shadow: none;
13
+ background: transparent;
14
+
15
+ // Centered, comfortably narrow reading column. The surrounding margin
16
+ // is where the BlockHandle sits (see token overrides below). Consumers
17
+ // are expected to control the surrounding container width; on viewports
18
+ // narrower than 38rem the column overflows by design (Notion mode is
19
+ // opt-in).
20
+ max-width: 38rem;
21
+ margin: 0 auto;
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;
27
+ --dm-editor-line-height: 1.7;
28
+ --dm-editor-padding: 0;
29
+
30
+ // Handle lives fully OUTSIDE the centered content column. Zeroing the
31
+ // ProseMirror gutter token reclaims the reserved column (the handle no
32
+ // longer overlaps content - there is nothing to reserve). The negative
33
+ // `left` token pulls the handle left of the column with a few px of
34
+ // breathing room before the content's left edge.
35
+ --dm-block-handle-gutter: 0;
36
+ --dm-block-handle-left: -3.5rem;
37
+
38
+ // The `top` checkbox tuning in `_task-list.scss` is for the default
39
+ // 1.6 line-height. Notion mode lifts line-height to 1.7, so nudge the
40
+ // checkbox down to keep it on the x-height of the first label line.
41
+ --dm-task-checkbox-top: 0.45em;
42
+
43
+ .ProseMirror {
44
+ min-height: 60vh;
45
+ outline: none;
46
+
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.
50
+ h1 {
51
+ font-size: 2.25rem;
52
+ font-weight: 700;
53
+ margin-top: 1.5rem;
54
+ margin-bottom: 0.75rem;
55
+ }
56
+ h2 {
57
+ font-size: 1.625rem;
58
+ font-weight: 600;
59
+ margin-top: 1.5rem;
60
+ margin-bottom: 0.5rem;
61
+ }
62
+ h3 {
63
+ font-size: 1.25rem;
64
+ font-weight: 600;
65
+ margin-top: 1.25rem;
66
+ margin-bottom: 0.375rem;
67
+ }
68
+ p {
69
+ margin: 0.25rem 0;
70
+ }
71
+ }
72
+ }
@@ -166,7 +166,7 @@ img.ProseMirror-separator {
166
166
  }
167
167
  }
168
168
 
169
- // Hide native text selection inside selected cells the ::after overlay is sufficient
169
+ // Hide native text selection inside selected cells - the ::after overlay is sufficient
170
170
  .dm-editor .selectedCell,
171
171
  .dm-editor .selectedCell * {
172
172
  &::selection {