@domternal/theme 0.2.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/LICENSE +21 -0
- package/README.md +60 -0
- package/dist/domternal-theme.css +1 -0
- package/dist/domternal-theme.expanded.css +1828 -0
- package/index.d.ts +2 -0
- package/package.json +49 -0
- package/src/_base.scss +60 -0
- package/src/_bubble-menu.scss +49 -0
- package/src/_color-palette.scss +89 -0
- package/src/_content.scss +229 -0
- package/src/_details.scss +122 -0
- package/src/_emoji-picker.scss +219 -0
- package/src/_floating-menu.scss +24 -0
- package/src/_image.scss +224 -0
- package/src/_invisible-chars.scss +44 -0
- package/src/_link-popover.scss +144 -0
- package/src/_mention.scss +25 -0
- package/src/_placeholder.scss +16 -0
- package/src/_prosemirror.scss +176 -0
- package/src/_syntax.scss +101 -0
- package/src/_table-controls.scss +271 -0
- package/src/_task-list.scss +51 -0
- package/src/_toolbar.scss +213 -0
- package/src/_variables.scss +150 -0
- package/src/index.scss +53 -0
- package/src/themes/_dark.scss +68 -0
- package/src/themes/_light.scss +43 -0
package/index.d.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@domternal/theme",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Default themes and styles for Domternal editor",
|
|
5
|
+
"author": "https://github.com/ThomasNowHere",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "commonjs",
|
|
8
|
+
"sideEffects": true,
|
|
9
|
+
"types": "index.d.ts",
|
|
10
|
+
"style": "dist/domternal-theme.css",
|
|
11
|
+
"sass": "src/index.scss",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./index.d.ts",
|
|
15
|
+
"sass": "./src/index.scss",
|
|
16
|
+
"style": "./dist/domternal-theme.css",
|
|
17
|
+
"default": "./dist/domternal-theme.css"
|
|
18
|
+
},
|
|
19
|
+
"./css": "./dist/domternal-theme.css",
|
|
20
|
+
"./scss": "./src/index.scss"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"src",
|
|
25
|
+
"index.d.ts"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "sass src/index.scss dist/domternal-theme.css --style=compressed --no-source-map && sass src/index.scss dist/domternal-theme.expanded.css --style=expanded --no-source-map"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"sass": "^1.89.0"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"domternal",
|
|
35
|
+
"editor",
|
|
36
|
+
"theme",
|
|
37
|
+
"css",
|
|
38
|
+
"prosemirror"
|
|
39
|
+
],
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "git+https://github.com/domternal/domternal.git",
|
|
43
|
+
"directory": "packages/theme"
|
|
44
|
+
},
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/domternal/domternal/issues"
|
|
47
|
+
},
|
|
48
|
+
"homepage": "https://domternal.dev"
|
|
49
|
+
}
|
package/src/_base.scss
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Editor Wrapper Styles
|
|
3
|
+
// =============================================================================
|
|
4
|
+
|
|
5
|
+
.dm-editor {
|
|
6
|
+
display: block;
|
|
7
|
+
position: relative;
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
background: var(--dm-editor-bg);
|
|
10
|
+
color: var(--dm-editor-text);
|
|
11
|
+
font-family: var(--dm-editor-font-family);
|
|
12
|
+
font-size: var(--dm-editor-font-size);
|
|
13
|
+
line-height: var(--dm-editor-line-height);
|
|
14
|
+
border: var(--dm-editor-border);
|
|
15
|
+
border-radius: var(--dm-editor-border-radius);
|
|
16
|
+
box-shadow: var(--dm-editor-shadow, none);
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
color-scheme: var(--dm-color-scheme, light);
|
|
19
|
+
|
|
20
|
+
.ProseMirror {
|
|
21
|
+
padding: var(--dm-editor-padding);
|
|
22
|
+
min-height: 6rem;
|
|
23
|
+
|
|
24
|
+
&:focus {
|
|
25
|
+
outline: none;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Focus ring on wrapper when editor is focused
|
|
30
|
+
&:focus-within {
|
|
31
|
+
box-shadow: var(--dm-editor-focus-ring, var(--dm-editor-shadow, none));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Text selection colors
|
|
35
|
+
.ProseMirror ::selection {
|
|
36
|
+
background: var(--dm-selection);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// When toolbar is present above editor, remove top border-radius from editor
|
|
41
|
+
.dm-toolbar + .dm-editor {
|
|
42
|
+
border-top-left-radius: 0;
|
|
43
|
+
border-top-right-radius: 0;
|
|
44
|
+
border-top: none;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// =============================================================================
|
|
48
|
+
// Shared floating element fade-in animation
|
|
49
|
+
// =============================================================================
|
|
50
|
+
// Used by elements conditionally inserted into the DOM (emoji picker,
|
|
51
|
+
// suggestion dropdown, toolbar dropdowns). Uses scale instead of translateY —
|
|
52
|
+
// scale doesn't shift position so it won't conflict with floating-ui.
|
|
53
|
+
// Elements using data-show (bubble menu, floating menu, popovers) use CSS
|
|
54
|
+
// opacity transitions instead — see their respective stylesheets.
|
|
55
|
+
// =============================================================================
|
|
56
|
+
|
|
57
|
+
@keyframes dm-fade-in {
|
|
58
|
+
from { opacity: 0; }
|
|
59
|
+
to { opacity: 1; }
|
|
60
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Bubble Menu Styles
|
|
3
|
+
// =============================================================================
|
|
4
|
+
|
|
5
|
+
.dm-bubble-menu {
|
|
6
|
+
// Button tokens (compact sizing for bubble menu)
|
|
7
|
+
--dm-toolbar-padding: 0.25rem;
|
|
8
|
+
--dm-toolbar-gap: 0.125rem;
|
|
9
|
+
--dm-button-size: 1.75rem;
|
|
10
|
+
--dm-button-border-radius: 0.25rem;
|
|
11
|
+
--dm-button-color: var(--dm-text, #1a1a1a);
|
|
12
|
+
--dm-button-hover-bg: var(--dm-hover, rgba(0, 0, 0, 0.06));
|
|
13
|
+
--dm-button-active-bg: var(--dm-accent-surface, rgba(37, 99, 235, 0.1));
|
|
14
|
+
--dm-button-active-color: var(--dm-accent, #2563eb);
|
|
15
|
+
--dm-button-disabled-opacity: 0.4;
|
|
16
|
+
|
|
17
|
+
// Smaller icons to match compact buttons
|
|
18
|
+
.dm-toolbar-button svg {
|
|
19
|
+
width: 1rem;
|
|
20
|
+
height: 1rem;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.dm-toolbar-separator {
|
|
24
|
+
width: 1px;
|
|
25
|
+
height: 1.125rem;
|
|
26
|
+
background: var(--dm-separator-color, var(--dm-border-color, #e0e0e0));
|
|
27
|
+
margin: 0 0.125rem;
|
|
28
|
+
flex-shrink: 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
position: absolute;
|
|
32
|
+
display: flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
gap: var(--dm-toolbar-gap);
|
|
35
|
+
padding: var(--dm-toolbar-padding);
|
|
36
|
+
background: var(--dm-bg, #fff);
|
|
37
|
+
border: 1px solid var(--dm-border-color, #e5e7eb);
|
|
38
|
+
border-radius: 0.5rem;
|
|
39
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08), 0 1px 3px rgba(0, 0, 0, 0.04);
|
|
40
|
+
visibility: hidden;
|
|
41
|
+
opacity: 0;
|
|
42
|
+
z-index: 50;
|
|
43
|
+
|
|
44
|
+
&[data-show] {
|
|
45
|
+
visibility: visible;
|
|
46
|
+
opacity: 1;
|
|
47
|
+
transition: opacity 0.15s ease;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Color Palette (grid-layout dropdown for TextColor / HighlightColor)
|
|
3
|
+
// =============================================================================
|
|
4
|
+
|
|
5
|
+
.dm-color-palette {
|
|
6
|
+
display: grid;
|
|
7
|
+
grid-template-columns: repeat(var(--dm-palette-columns, 10), 1fr);
|
|
8
|
+
gap: 0.375rem;
|
|
9
|
+
padding: 0.375rem;
|
|
10
|
+
min-width: auto;
|
|
11
|
+
width: max-content;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// "Default" reset button — spans the full width of the grid
|
|
15
|
+
.dm-color-palette-reset {
|
|
16
|
+
grid-column: 1 / -1;
|
|
17
|
+
display: flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
gap: 0.375rem;
|
|
20
|
+
width: 100%;
|
|
21
|
+
padding: 0.375rem 0.5rem;
|
|
22
|
+
margin-bottom: 0.375rem;
|
|
23
|
+
border: none;
|
|
24
|
+
border-radius: 0.375rem;
|
|
25
|
+
background: transparent;
|
|
26
|
+
color: var(--dm-button-color, #1a1a1a);
|
|
27
|
+
cursor: pointer;
|
|
28
|
+
font-size: 0.8125rem;
|
|
29
|
+
line-height: 1.4;
|
|
30
|
+
text-align: left;
|
|
31
|
+
white-space: nowrap;
|
|
32
|
+
transition: background-color 0.15s;
|
|
33
|
+
|
|
34
|
+
&:hover {
|
|
35
|
+
background: var(--dm-button-hover-bg, rgba(0, 0, 0, 0.06));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
svg {
|
|
39
|
+
width: 0.875rem;
|
|
40
|
+
height: 0.875rem;
|
|
41
|
+
flex-shrink: 0;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Individual color swatch
|
|
46
|
+
.dm-color-swatch {
|
|
47
|
+
position: relative;
|
|
48
|
+
width: 1.5rem;
|
|
49
|
+
height: 1.5rem;
|
|
50
|
+
padding: 0;
|
|
51
|
+
border: 1px solid rgba(0, 0, 0, 0.06);
|
|
52
|
+
border-radius: 50%;
|
|
53
|
+
cursor: pointer;
|
|
54
|
+
transition: transform 0.1s, box-shadow 0.1s;
|
|
55
|
+
|
|
56
|
+
&:hover {
|
|
57
|
+
transform: scale(1.15);
|
|
58
|
+
z-index: 1;
|
|
59
|
+
box-shadow: 0 0 0 2px var(--dm-toolbar-bg, #f8f9fa),
|
|
60
|
+
0 0 0 3px var(--dm-accent, #2563eb);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Active state — checkmark indicator
|
|
64
|
+
&--active {
|
|
65
|
+
box-shadow: 0 0 0 2px var(--dm-toolbar-bg, #f8f9fa),
|
|
66
|
+
0 0 0 3px var(--dm-accent, #2563eb);
|
|
67
|
+
|
|
68
|
+
&::after {
|
|
69
|
+
content: '';
|
|
70
|
+
position: absolute;
|
|
71
|
+
inset: 0;
|
|
72
|
+
border-radius: 50%;
|
|
73
|
+
// White checkmark with dark shadow for universal contrast
|
|
74
|
+
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M12 5L6.5 11 4 8.5' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round' opacity='0.3'/%3E%3Cpath d='M12 5L6.5 11 4 8.5' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 80% no-repeat;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Dark theme — adjust swatch border for dark backgrounds
|
|
80
|
+
.dm-theme-dark .dm-color-swatch,
|
|
81
|
+
.dm-theme-auto .dm-color-swatch {
|
|
82
|
+
border-color: rgba(255, 255, 255, 0.15);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@media (prefers-color-scheme: dark) {
|
|
86
|
+
.dm-theme-auto .dm-color-swatch {
|
|
87
|
+
border-color: rgba(255, 255, 255, 0.15);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Content Typography
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// Styles for rendered content inside the editor. Scoped to .dm-editor .ProseMirror
|
|
5
|
+
// so styles don't leak outside.
|
|
6
|
+
// =============================================================================
|
|
7
|
+
|
|
8
|
+
.dm-editor .ProseMirror {
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Paragraphs
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
p {
|
|
14
|
+
margin: 0.4em 0;
|
|
15
|
+
|
|
16
|
+
&:last-child {
|
|
17
|
+
margin-bottom: 0;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Headings
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
h1,
|
|
26
|
+
h2,
|
|
27
|
+
h3,
|
|
28
|
+
h4,
|
|
29
|
+
h5,
|
|
30
|
+
h6 {
|
|
31
|
+
margin: 1.5em 0 0.5em;
|
|
32
|
+
font-weight: 700;
|
|
33
|
+
line-height: 1.25;
|
|
34
|
+
|
|
35
|
+
&:first-child {
|
|
36
|
+
margin-top: 0;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
h1 {
|
|
41
|
+
font-size: 2em;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
h2 {
|
|
45
|
+
font-size: 1.5em;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
h3 {
|
|
49
|
+
font-size: 1.25em;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
h4 {
|
|
53
|
+
font-size: 1.1em;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
h5 {
|
|
57
|
+
font-size: 1em;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
h6 {
|
|
61
|
+
font-size: 0.9em;
|
|
62
|
+
color: var(--dm-muted, #666);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// Inline code
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
code {
|
|
70
|
+
background: var(--dm-code-bg);
|
|
71
|
+
color: var(--dm-code-text);
|
|
72
|
+
font-family: var(--dm-code-font);
|
|
73
|
+
font-size: 0.875em;
|
|
74
|
+
padding: 0.15em 0.35em;
|
|
75
|
+
border: 1px solid var(--dm-border-color);
|
|
76
|
+
border-radius: var(--dm-code-border-radius);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Code blocks (pre > code)
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
|
|
83
|
+
pre {
|
|
84
|
+
background: var(--dm-code-block-bg);
|
|
85
|
+
color: var(--dm-code-block-text);
|
|
86
|
+
font-family: var(--dm-code-font);
|
|
87
|
+
font-size: 0.875em;
|
|
88
|
+
padding: 1em;
|
|
89
|
+
border-radius: 0.375rem;
|
|
90
|
+
overflow-x: auto;
|
|
91
|
+
margin: 0.75em 0;
|
|
92
|
+
|
|
93
|
+
code {
|
|
94
|
+
background: none;
|
|
95
|
+
color: inherit;
|
|
96
|
+
padding: 0;
|
|
97
|
+
border: none;
|
|
98
|
+
border-radius: 0;
|
|
99
|
+
font-size: inherit;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// Blockquote
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
blockquote {
|
|
108
|
+
border-left: var(--dm-blockquote-border);
|
|
109
|
+
color: var(--dm-blockquote-color);
|
|
110
|
+
margin: 0.75em 0;
|
|
111
|
+
padding: 0.25em 0 0.25em 1em;
|
|
112
|
+
|
|
113
|
+
p {
|
|
114
|
+
margin-top: 0;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
// Lists
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
|
|
122
|
+
ul,
|
|
123
|
+
ol {
|
|
124
|
+
margin: 0.75em 0;
|
|
125
|
+
padding-left: 1.5em;
|
|
126
|
+
|
|
127
|
+
li {
|
|
128
|
+
margin: 0.25em 0;
|
|
129
|
+
|
|
130
|
+
> p {
|
|
131
|
+
margin: 0.1em 0;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
ol {
|
|
137
|
+
list-style-type: decimal;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
ul {
|
|
141
|
+
list-style-type: disc;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Nested lists
|
|
145
|
+
ul ul,
|
|
146
|
+
ol ul {
|
|
147
|
+
list-style-type: circle;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
ul ul ul,
|
|
151
|
+
ol ul ul,
|
|
152
|
+
ol ol ul {
|
|
153
|
+
list-style-type: square;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ---------------------------------------------------------------------------
|
|
157
|
+
// Horizontal rule
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
|
|
160
|
+
hr {
|
|
161
|
+
border: none;
|
|
162
|
+
border-top: 2px solid var(--dm-hr-color);
|
|
163
|
+
margin: 1.5em 0;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
// Links
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
|
|
170
|
+
a {
|
|
171
|
+
color: var(--dm-link-color);
|
|
172
|
+
text-decoration: underline;
|
|
173
|
+
cursor: pointer;
|
|
174
|
+
|
|
175
|
+
&:hover {
|
|
176
|
+
color: var(--dm-link-hover-color);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// ---------------------------------------------------------------------------
|
|
181
|
+
// Highlight / mark (fallback for pasted <mark> elements)
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
|
|
184
|
+
mark {
|
|
185
|
+
color: inherit;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ---------------------------------------------------------------------------
|
|
189
|
+
// Images
|
|
190
|
+
// ---------------------------------------------------------------------------
|
|
191
|
+
|
|
192
|
+
img {
|
|
193
|
+
max-width: 100%;
|
|
194
|
+
height: auto;
|
|
195
|
+
display: block;
|
|
196
|
+
margin: 0.75em 0;
|
|
197
|
+
|
|
198
|
+
&.ProseMirror-selectednode {
|
|
199
|
+
outline: 2px solid var(--dm-accent, #2563eb);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// ---------------------------------------------------------------------------
|
|
204
|
+
// Tables
|
|
205
|
+
// ---------------------------------------------------------------------------
|
|
206
|
+
|
|
207
|
+
table {
|
|
208
|
+
border: var(--dm-table-border);
|
|
209
|
+
margin: 0.75em 0;
|
|
210
|
+
|
|
211
|
+
td,
|
|
212
|
+
th {
|
|
213
|
+
border: var(--dm-table-border);
|
|
214
|
+
padding: 0.5em 0.75em;
|
|
215
|
+
min-width: 100px;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
th {
|
|
219
|
+
background: var(--dm-table-header-bg);
|
|
220
|
+
font-weight: 600;
|
|
221
|
+
text-align: left;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
td > p,
|
|
225
|
+
th > p {
|
|
226
|
+
margin: 0;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Details / Accordion Styles
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// The NodeView renders:
|
|
5
|
+
// div[data-type="details"]
|
|
6
|
+
// button[type="button"] ← toggle (chevron)
|
|
7
|
+
// div ← contentDOM
|
|
8
|
+
// summary ← editable header (DetailsSummary)
|
|
9
|
+
// div[data-details-content] ← collapsible body (DetailsContent)
|
|
10
|
+
//
|
|
11
|
+
// Open state: .is-open on the outer div, [hidden] removed from content.
|
|
12
|
+
//
|
|
13
|
+
// Layout: CSS grid places the summary and button side-by-side in row 1,
|
|
14
|
+
// and the content spans full width in row 2. This lets the button
|
|
15
|
+
// stretch to the full summary height for vertical centering.
|
|
16
|
+
// =============================================================================
|
|
17
|
+
|
|
18
|
+
.dm-editor .ProseMirror {
|
|
19
|
+
div[data-type="details"] {
|
|
20
|
+
display: grid;
|
|
21
|
+
grid-template-columns: 1fr auto;
|
|
22
|
+
grid-template-rows: auto 1fr;
|
|
23
|
+
border: var(--dm-details-border);
|
|
24
|
+
border-radius: 0.375rem;
|
|
25
|
+
margin: 0.75em 0;
|
|
26
|
+
|
|
27
|
+
// contentDOM — contains summary (row 1) and content (row 2)
|
|
28
|
+
// Use display:contents so its children participate in the grid
|
|
29
|
+
> div {
|
|
30
|
+
display: contents;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Toggle button — chevron on the right, round hover highlight
|
|
34
|
+
> button[type="button"] {
|
|
35
|
+
grid-column: 2;
|
|
36
|
+
grid-row: 1;
|
|
37
|
+
display: flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
justify-content: center;
|
|
40
|
+
width: 1.5rem;
|
|
41
|
+
height: 1.5rem;
|
|
42
|
+
align-self: center;
|
|
43
|
+
margin-right: 10px;
|
|
44
|
+
border: none;
|
|
45
|
+
background: transparent;
|
|
46
|
+
cursor: pointer;
|
|
47
|
+
color: var(--dm-muted);
|
|
48
|
+
border-radius: 50%;
|
|
49
|
+
|
|
50
|
+
// CSS chevron (pointing right ›)
|
|
51
|
+
&::before {
|
|
52
|
+
content: '';
|
|
53
|
+
display: block;
|
|
54
|
+
width: 0.4em;
|
|
55
|
+
height: 0.4em;
|
|
56
|
+
border-right: 2px solid currentColor;
|
|
57
|
+
border-bottom: 2px solid currentColor;
|
|
58
|
+
transform: rotate(-45deg);
|
|
59
|
+
transition: transform 0.15s ease;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
&:hover {
|
|
63
|
+
color: var(--dm-text);
|
|
64
|
+
background: var(--dm-hover);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
&:focus {
|
|
68
|
+
outline: none;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Summary row background — spans both columns so the button area
|
|
73
|
+
// also gets the surface colour behind the round toggle
|
|
74
|
+
&::before {
|
|
75
|
+
content: '';
|
|
76
|
+
grid-column: 1 / -1;
|
|
77
|
+
grid-row: 1;
|
|
78
|
+
background: var(--dm-details-bg);
|
|
79
|
+
border-radius: 0.375rem;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
&.is-open::before {
|
|
83
|
+
border-radius: 0.375rem 0.375rem 0 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Summary (editable header text)
|
|
87
|
+
summary {
|
|
88
|
+
grid-column: 1;
|
|
89
|
+
grid-row: 1;
|
|
90
|
+
display: block;
|
|
91
|
+
padding: 0.5em 0.5em 0.5em 0.75em;
|
|
92
|
+
font-weight: var(--dm-details-summary-font-weight);
|
|
93
|
+
min-height: 0;
|
|
94
|
+
|
|
95
|
+
// Remove native marker
|
|
96
|
+
&::-webkit-details-marker {
|
|
97
|
+
display: none;
|
|
98
|
+
}
|
|
99
|
+
list-style: none;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Content area (hidden by default via [hidden] attribute from NodeView)
|
|
103
|
+
div[data-details-content] {
|
|
104
|
+
grid-column: 1 / -1;
|
|
105
|
+
grid-row: 2;
|
|
106
|
+
padding: 0.5em 0.75em;
|
|
107
|
+
border-top: var(--dm-details-border);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Disable ProseMirror selected-node outline — the border is enough
|
|
111
|
+
&.ProseMirror-selectednode {
|
|
112
|
+
outline: none;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Open state — rotate chevron to point down
|
|
116
|
+
&.is-open {
|
|
117
|
+
> button[type="button"]::before {
|
|
118
|
+
transform: rotate(45deg);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|