@tonycodes-ui/mortar 0.0.0-stage → 0.11.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/AGENTS.md +10 -0
- package/CHANGELOG.md +276 -0
- package/CONTRIBUTING.md +48 -0
- package/DESIGN.md +51 -0
- package/LICENSE +21 -0
- package/README.md +155 -2
- package/TESTING.md +83 -0
- package/baseline-policy.json +16 -0
- package/bin/mortar.mjs +258 -0
- package/catalog.json +9703 -0
- package/cli/audit.mjs +943 -0
- package/cli/data.mjs +176 -0
- package/cli/mcp.mjs +216 -0
- package/cli/migrations.mjs +128 -0
- package/cli/packet.mjs +267 -0
- package/cli/search.mjs +246 -0
- package/cli/tools.mjs +229 -0
- package/design-principles.json +30 -0
- package/dist/agent-data.json +1 -0
- package/dist/application.d.ts +340 -0
- package/dist/application.js +240 -0
- package/dist/auth.d.ts +121 -0
- package/dist/auth.js +97 -0
- package/dist/brand.d.ts +69 -0
- package/dist/brand.js +266 -0
- package/dist/calendar.d.ts +75 -0
- package/dist/calendar.js +310 -0
- package/dist/choice.d.ts +36 -0
- package/dist/choice.js +36 -0
- package/dist/composer.d.ts +28 -0
- package/dist/composer.js +47 -0
- package/dist/display.d.ts +136 -0
- package/dist/display.js +75 -0
- package/dist/docs.d.ts +145 -0
- package/dist/docs.js +141 -0
- package/dist/ecommerce.d.ts +261 -0
- package/dist/ecommerce.js +177 -0
- package/dist/feedback.d.ts +80 -0
- package/dist/feedback.js +98 -0
- package/dist/foundation.d.ts +42 -0
- package/dist/foundation.js +121 -0
- package/dist/heading.d.ts +5 -0
- package/dist/heading.js +9 -0
- package/dist/icons.d.ts +50 -0
- package/dist/icons.js +70 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +17 -0
- package/dist/inspection.d.ts +24 -0
- package/dist/inspection.js +14 -0
- package/dist/internal.d.ts +492 -0
- package/dist/internal.js +273 -0
- package/dist/layout.d.ts +107 -0
- package/dist/layout.js +66 -0
- package/dist/marketing-sections.d.ts +161 -0
- package/dist/marketing-sections.js +58 -0
- package/dist/marketing.d.ts +254 -0
- package/dist/marketing.js +150 -0
- package/dist/navigation.d.ts +35 -0
- package/dist/navigation.js +44 -0
- package/dist/primitives.d.ts +258 -0
- package/dist/primitives.js +244 -0
- package/dist/showcase.d.ts +29 -0
- package/dist/showcase.js +10 -0
- package/dist/workspace.d.ts +80 -0
- package/dist/workspace.js +48 -0
- package/docs/agents.md +127 -0
- package/docs/auth-flows.md +71 -0
- package/docs/migrating-to-0.6.md +94 -0
- package/docs/theming.md +170 -0
- package/package.json +94 -4
- package/skills/mortar/SKILL.md +36 -0
- package/src/application.css +1487 -0
- package/src/application.tsx +1413 -0
- package/src/auth.tsx +452 -0
- package/src/brand.ts +335 -0
- package/src/calendar.css +468 -0
- package/src/calendar.tsx +868 -0
- package/src/choice.tsx +240 -0
- package/src/composer.tsx +158 -0
- package/src/data.css +690 -0
- package/src/display.tsx +452 -0
- package/src/docs.css +704 -0
- package/src/docs.tsx +737 -0
- package/src/ecommerce.css +810 -0
- package/src/ecommerce.tsx +1033 -0
- package/src/feedback.tsx +388 -0
- package/src/foundation.css +1867 -0
- package/src/foundation.tsx +227 -0
- package/src/heading.ts +13 -0
- package/src/icons.tsx +237 -0
- package/src/index.ts +230 -0
- package/src/inspection.tsx +91 -0
- package/src/internal.tsx +614 -0
- package/src/layout.tsx +342 -0
- package/src/marketing-sections.tsx +621 -0
- package/src/marketing.css +2400 -0
- package/src/marketing.tsx +1156 -0
- package/src/navigation.tsx +118 -0
- package/src/overlays.css +350 -0
- package/src/primitives.tsx +1135 -0
- package/src/showcase.tsx +120 -0
- package/src/tokens.css +449 -0
- package/src/workspace.tsx +333 -0
- package/styles.css +56 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ReactNode,
|
|
3
|
+
createContext,
|
|
4
|
+
useContext,
|
|
5
|
+
type AnchorHTMLAttributes,
|
|
6
|
+
type MouseEvent,
|
|
7
|
+
} from "react";
|
|
8
|
+
|
|
9
|
+
/** Return false to leave a route to the browser; otherwise the app owns navigation. */
|
|
10
|
+
export type Navigate = (href: string) => void | false;
|
|
11
|
+
export const NavigationContext = createContext<Navigate | undefined>(undefined);
|
|
12
|
+
|
|
13
|
+
export function followLink(
|
|
14
|
+
event: MouseEvent<HTMLAnchorElement>,
|
|
15
|
+
navigate?: Navigate,
|
|
16
|
+
) {
|
|
17
|
+
const anchor = event.currentTarget;
|
|
18
|
+
if (
|
|
19
|
+
!navigate ||
|
|
20
|
+
event.defaultPrevented ||
|
|
21
|
+
event.button !== 0 ||
|
|
22
|
+
event.metaKey ||
|
|
23
|
+
event.ctrlKey ||
|
|
24
|
+
event.shiftKey ||
|
|
25
|
+
event.altKey ||
|
|
26
|
+
anchor.hasAttribute("download") ||
|
|
27
|
+
(anchor.target && anchor.target !== "_self") ||
|
|
28
|
+
anchor.rel.split(/\s+/).includes("external")
|
|
29
|
+
)
|
|
30
|
+
return;
|
|
31
|
+
const raw = anchor.getAttribute("href");
|
|
32
|
+
if (!raw || raw.startsWith("#")) return;
|
|
33
|
+
const destination = new URL(anchor.href);
|
|
34
|
+
const current = new URL(anchor.ownerDocument.URL);
|
|
35
|
+
if (
|
|
36
|
+
!["http:", "https:"].includes(destination.protocol) ||
|
|
37
|
+
destination.origin !== current.origin
|
|
38
|
+
)
|
|
39
|
+
return;
|
|
40
|
+
if (
|
|
41
|
+
destination.pathname === current.pathname &&
|
|
42
|
+
destination.search === current.search &&
|
|
43
|
+
destination.hash
|
|
44
|
+
)
|
|
45
|
+
return;
|
|
46
|
+
if (
|
|
47
|
+
navigate(destination.pathname + destination.search + destination.hash) !==
|
|
48
|
+
false
|
|
49
|
+
)
|
|
50
|
+
event.preventDefault();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Internal shared anchor: retains native link semantics unless an app router handles it. */
|
|
54
|
+
export function KitLink({
|
|
55
|
+
onClick,
|
|
56
|
+
...props
|
|
57
|
+
}: AnchorHTMLAttributes<HTMLAnchorElement>) {
|
|
58
|
+
const navigate = useContext(NavigationContext);
|
|
59
|
+
return (
|
|
60
|
+
<a
|
|
61
|
+
{...props}
|
|
62
|
+
onClick={(event) => {
|
|
63
|
+
onClick?.(event);
|
|
64
|
+
followLink(event, navigate);
|
|
65
|
+
}}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** A navigation link: sidebar and navbar items, page tabs and flyout entries. */
|
|
71
|
+
export interface LinkItem {
|
|
72
|
+
label: string;
|
|
73
|
+
href: string;
|
|
74
|
+
/** The page being shown; marked aria-current="page". */
|
|
75
|
+
current?: boolean;
|
|
76
|
+
/** Icon shown before the label. */
|
|
77
|
+
icon?: ReactNode;
|
|
78
|
+
/** Shown after the label, e.g. a number of items. */
|
|
79
|
+
count?: number | string;
|
|
80
|
+
description?: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Items gathered under a visible group label. */
|
|
84
|
+
export interface ItemGroup<T> {
|
|
85
|
+
label: string;
|
|
86
|
+
items: T[];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface IconLink {
|
|
90
|
+
/** Accessible name; also the visible text when there is no icon. */
|
|
91
|
+
label: string;
|
|
92
|
+
href: string;
|
|
93
|
+
icon?: ReactNode;
|
|
94
|
+
}
|
|
95
|
+
/** Labelled list of profile or social links; icon links are named by their label. */
|
|
96
|
+
export function IconLinks({
|
|
97
|
+
label,
|
|
98
|
+
links,
|
|
99
|
+
}: {
|
|
100
|
+
label: string;
|
|
101
|
+
links: IconLink[];
|
|
102
|
+
}) {
|
|
103
|
+
return (
|
|
104
|
+
<ul className="m-icon-links" aria-label={label}>
|
|
105
|
+
{links.map((link, index) => (
|
|
106
|
+
<li key={`${link.label}:${link.href}:${index}`}>
|
|
107
|
+
{link.icon ? (
|
|
108
|
+
<KitLink href={link.href} aria-label={link.label}>
|
|
109
|
+
<span aria-hidden="true">{link.icon}</span>
|
|
110
|
+
</KitLink>
|
|
111
|
+
) : (
|
|
112
|
+
<KitLink href={link.href}>{link.label}</KitLink>
|
|
113
|
+
)}
|
|
114
|
+
</li>
|
|
115
|
+
))}
|
|
116
|
+
</ul>
|
|
117
|
+
);
|
|
118
|
+
}
|
package/src/overlays.css
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
/* Workspace overlays: dialogs, panels, palette and toasts.
|
|
2
|
+
Every rule sits in @layer components, so equal-specificity rules resolve by source
|
|
3
|
+
order. styles.css loads tokens, foundation, overlays, application, data, calendar,
|
|
4
|
+
marketing, docs and ecommerce in that order; inside a file each component keeps
|
|
5
|
+
one section, ordered base, then variants and states, then media and container
|
|
6
|
+
queries, except where that would change which equal-specificity rule wins. */
|
|
7
|
+
@layer components {
|
|
8
|
+
/* == Modal == */
|
|
9
|
+
.m-dialog {
|
|
10
|
+
position: fixed;
|
|
11
|
+
inset: 0;
|
|
12
|
+
z-index: var(--m-z-overlay);
|
|
13
|
+
}
|
|
14
|
+
.m-backdrop {
|
|
15
|
+
position: fixed;
|
|
16
|
+
inset: 0;
|
|
17
|
+
background: var(--m-scrim);
|
|
18
|
+
}
|
|
19
|
+
.m-dialog-position {
|
|
20
|
+
position: fixed;
|
|
21
|
+
inset: 0;
|
|
22
|
+
overflow-y: auto;
|
|
23
|
+
display: flex;
|
|
24
|
+
justify-content: center;
|
|
25
|
+
align-items: flex-start;
|
|
26
|
+
padding: 24px;
|
|
27
|
+
}
|
|
28
|
+
.m-dialog-panel {
|
|
29
|
+
margin-block: auto;
|
|
30
|
+
flex-shrink: 0;
|
|
31
|
+
width: 100%;
|
|
32
|
+
max-width: 520px;
|
|
33
|
+
padding: 24px;
|
|
34
|
+
box-shadow: var(--m-float);
|
|
35
|
+
}
|
|
36
|
+
.m-dialog-heading {
|
|
37
|
+
display: flex;
|
|
38
|
+
justify-content: space-between;
|
|
39
|
+
align-items: center;
|
|
40
|
+
gap: 16px;
|
|
41
|
+
margin-bottom: 20px;
|
|
42
|
+
}
|
|
43
|
+
.m-dialog-heading h2 {
|
|
44
|
+
font-size: 20px;
|
|
45
|
+
font-weight: var(--m-weight-semibold);
|
|
46
|
+
}
|
|
47
|
+
.m-dialog-panel > .m-actions {
|
|
48
|
+
margin-top: 24px;
|
|
49
|
+
justify-content: flex-end;
|
|
50
|
+
}
|
|
51
|
+
.m-dialog-panel[data-size="lg"] {
|
|
52
|
+
max-width: 880px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* == ConfirmDialog == */
|
|
56
|
+
.m-confirm {
|
|
57
|
+
padding: 0;
|
|
58
|
+
max-width: 420px;
|
|
59
|
+
overflow: hidden;
|
|
60
|
+
}
|
|
61
|
+
.m-confirm-body {
|
|
62
|
+
display: grid;
|
|
63
|
+
gap: 10px;
|
|
64
|
+
padding: 22px 22px 18px;
|
|
65
|
+
}
|
|
66
|
+
.m-confirm-body > h2 {
|
|
67
|
+
font-size: 18px;
|
|
68
|
+
font-weight: var(--m-weight-semibold);
|
|
69
|
+
letter-spacing: -0.01em;
|
|
70
|
+
}
|
|
71
|
+
.m-confirm-body > div:first-of-type {
|
|
72
|
+
color: var(--m-secondary);
|
|
73
|
+
font-size: var(--m-font-size);
|
|
74
|
+
text-wrap: pretty;
|
|
75
|
+
}
|
|
76
|
+
.m-confirm-actions {
|
|
77
|
+
display: flex;
|
|
78
|
+
justify-content: flex-end;
|
|
79
|
+
flex-wrap: wrap;
|
|
80
|
+
gap: 8px;
|
|
81
|
+
padding: 12px 22px;
|
|
82
|
+
border-top: 1px solid var(--m-line);
|
|
83
|
+
background: var(--m-paper);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* == SlideOver == */
|
|
87
|
+
/* Workspace overlays and lists */
|
|
88
|
+
.m-slide-over {
|
|
89
|
+
position: fixed;
|
|
90
|
+
inset: 0 0 0 auto;
|
|
91
|
+
width: min(420px, 92vw);
|
|
92
|
+
display: flex;
|
|
93
|
+
flex-direction: column;
|
|
94
|
+
background: var(--m-surface);
|
|
95
|
+
border-left: 1px solid var(--m-line);
|
|
96
|
+
box-shadow: var(--m-float);
|
|
97
|
+
}
|
|
98
|
+
.m-slide-over > header {
|
|
99
|
+
display: flex;
|
|
100
|
+
align-items: flex-start;
|
|
101
|
+
gap: 12px;
|
|
102
|
+
padding: 18px 20px;
|
|
103
|
+
border-bottom: 1px solid var(--m-line);
|
|
104
|
+
}
|
|
105
|
+
.m-slide-over > header > div {
|
|
106
|
+
flex: 1;
|
|
107
|
+
}
|
|
108
|
+
.m-slide-over > :where(header > div) > h2 {
|
|
109
|
+
font-size: 17px;
|
|
110
|
+
font-weight: var(--m-weight-semibold);
|
|
111
|
+
}
|
|
112
|
+
.m-slide-over > :where(header > div) > p {
|
|
113
|
+
font-size: 13px;
|
|
114
|
+
color: var(--m-muted);
|
|
115
|
+
}
|
|
116
|
+
.m-slide-over-body {
|
|
117
|
+
flex: 1;
|
|
118
|
+
overflow-y: auto;
|
|
119
|
+
padding: 20px;
|
|
120
|
+
display: flex;
|
|
121
|
+
flex-direction: column;
|
|
122
|
+
gap: 16px;
|
|
123
|
+
}
|
|
124
|
+
.m-slide-over > footer {
|
|
125
|
+
justify-content: flex-end;
|
|
126
|
+
padding: 12px 20px;
|
|
127
|
+
border-top: 1px solid var(--m-line);
|
|
128
|
+
background: var(--m-paper);
|
|
129
|
+
}
|
|
130
|
+
.m-slide-over[data-size="lg"] {
|
|
131
|
+
width: min(640px, 96vw);
|
|
132
|
+
}
|
|
133
|
+
.m-slide-over[data-size="xl"] {
|
|
134
|
+
width: min(880px, 100vw);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* == CommandPalette == */
|
|
138
|
+
.m-palette-position {
|
|
139
|
+
align-items: flex-start;
|
|
140
|
+
padding-top: 12vh;
|
|
141
|
+
}
|
|
142
|
+
.m-palette {
|
|
143
|
+
width: 100%;
|
|
144
|
+
max-width: 600px;
|
|
145
|
+
box-shadow: var(--m-float);
|
|
146
|
+
overflow: hidden;
|
|
147
|
+
}
|
|
148
|
+
.m-palette-input {
|
|
149
|
+
display: flex;
|
|
150
|
+
align-items: center;
|
|
151
|
+
gap: 10px;
|
|
152
|
+
height: 54px;
|
|
153
|
+
padding: 0 16px;
|
|
154
|
+
border-bottom: 1px solid var(--m-line);
|
|
155
|
+
}
|
|
156
|
+
.m-palette-input input {
|
|
157
|
+
flex: 1;
|
|
158
|
+
min-width: 0;
|
|
159
|
+
border: 0;
|
|
160
|
+
background: transparent;
|
|
161
|
+
font-size: 16px;
|
|
162
|
+
outline: none;
|
|
163
|
+
}
|
|
164
|
+
.m-palette-results {
|
|
165
|
+
max-height: 380px;
|
|
166
|
+
overflow-y: auto;
|
|
167
|
+
padding: 6px;
|
|
168
|
+
}
|
|
169
|
+
.m-palette-group {
|
|
170
|
+
padding: 10px 10px 4px;
|
|
171
|
+
font-size: 11px;
|
|
172
|
+
font-weight: var(--m-weight-semibold);
|
|
173
|
+
letter-spacing: var(--m-tracking-caps);
|
|
174
|
+
text-transform: uppercase;
|
|
175
|
+
color: var(--m-muted);
|
|
176
|
+
}
|
|
177
|
+
.m-palette-item {
|
|
178
|
+
display: flex;
|
|
179
|
+
align-items: center;
|
|
180
|
+
justify-content: space-between;
|
|
181
|
+
gap: 12px;
|
|
182
|
+
min-height: var(--m-control);
|
|
183
|
+
padding: 6px 10px;
|
|
184
|
+
border-radius: var(--m-radius);
|
|
185
|
+
font-size: var(--m-font-size);
|
|
186
|
+
cursor: pointer;
|
|
187
|
+
}
|
|
188
|
+
.m-palette-item small {
|
|
189
|
+
display: block;
|
|
190
|
+
font-size: 12px;
|
|
191
|
+
color: var(--m-muted);
|
|
192
|
+
}
|
|
193
|
+
.m-palette-item mark {
|
|
194
|
+
background: none;
|
|
195
|
+
color: inherit;
|
|
196
|
+
font-weight: var(--m-weight-bold);
|
|
197
|
+
text-decoration: underline;
|
|
198
|
+
text-underline-offset: 3px;
|
|
199
|
+
}
|
|
200
|
+
.m-palette-meta {
|
|
201
|
+
font-size: 12px;
|
|
202
|
+
color: var(--m-muted);
|
|
203
|
+
white-space: nowrap;
|
|
204
|
+
}
|
|
205
|
+
.m-palette-empty {
|
|
206
|
+
padding: 32px 10px;
|
|
207
|
+
text-align: center;
|
|
208
|
+
font-size: var(--m-font-size);
|
|
209
|
+
color: var(--m-muted);
|
|
210
|
+
}
|
|
211
|
+
.m-palette-footer {
|
|
212
|
+
display: flex;
|
|
213
|
+
align-items: center;
|
|
214
|
+
gap: 16px;
|
|
215
|
+
padding: 10px 16px;
|
|
216
|
+
border-top: 1px solid var(--m-line);
|
|
217
|
+
background: var(--m-paper);
|
|
218
|
+
font-size: 12px;
|
|
219
|
+
color: var(--m-muted);
|
|
220
|
+
}
|
|
221
|
+
.m-palette-attribution {
|
|
222
|
+
margin-left: auto;
|
|
223
|
+
}
|
|
224
|
+
.m-palette-icon {
|
|
225
|
+
display: inline-grid;
|
|
226
|
+
place-items: center;
|
|
227
|
+
flex-shrink: 0;
|
|
228
|
+
width: 28px;
|
|
229
|
+
height: 28px;
|
|
230
|
+
border-radius: var(--m-radius);
|
|
231
|
+
background: var(--m-sunken);
|
|
232
|
+
color: var(--m-secondary);
|
|
233
|
+
}
|
|
234
|
+
/* With an icon, the label takes the space so it stays beside the icon. */
|
|
235
|
+
.m-palette-icon + span {
|
|
236
|
+
flex: 1;
|
|
237
|
+
min-width: 0;
|
|
238
|
+
}
|
|
239
|
+
/* With no results the empty listbox takes no space above the message. */
|
|
240
|
+
.m-palette-results:empty {
|
|
241
|
+
display: none;
|
|
242
|
+
}
|
|
243
|
+
.m-palette-input:has(input:focus-visible) {
|
|
244
|
+
outline: 2px solid var(--m-focus);
|
|
245
|
+
outline-offset: -2px;
|
|
246
|
+
}
|
|
247
|
+
.m-palette-item[data-focus] {
|
|
248
|
+
background: var(--m-selected);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/* == Toast and Toaster == */
|
|
252
|
+
.m-toast-icon svg {
|
|
253
|
+
width: 12px;
|
|
254
|
+
height: 12px;
|
|
255
|
+
}
|
|
256
|
+
/* Feedback */
|
|
257
|
+
.m-toaster {
|
|
258
|
+
position: fixed;
|
|
259
|
+
right: 20px;
|
|
260
|
+
bottom: 20px;
|
|
261
|
+
z-index: var(--m-z-toast);
|
|
262
|
+
width: min(380px, calc(100vw - 40px));
|
|
263
|
+
}
|
|
264
|
+
.m-toaster ol {
|
|
265
|
+
display: grid;
|
|
266
|
+
gap: 10px;
|
|
267
|
+
}
|
|
268
|
+
.m-toast {
|
|
269
|
+
display: flex;
|
|
270
|
+
align-items: flex-start;
|
|
271
|
+
gap: 12px;
|
|
272
|
+
padding: 12px 14px;
|
|
273
|
+
box-shadow: var(--m-float);
|
|
274
|
+
font-size: 13px;
|
|
275
|
+
}
|
|
276
|
+
.m-toast > div:nth-child(2) {
|
|
277
|
+
flex: 1;
|
|
278
|
+
min-width: 0;
|
|
279
|
+
}
|
|
280
|
+
.m-toast strong {
|
|
281
|
+
display: block;
|
|
282
|
+
font-size: var(--m-font-size);
|
|
283
|
+
}
|
|
284
|
+
.m-toast p {
|
|
285
|
+
color: var(--m-secondary);
|
|
286
|
+
}
|
|
287
|
+
.m-toast .m-actions {
|
|
288
|
+
gap: 2px;
|
|
289
|
+
flex-wrap: nowrap;
|
|
290
|
+
}
|
|
291
|
+
.m-toast .m-button {
|
|
292
|
+
min-height: 28px;
|
|
293
|
+
padding: 2px 8px;
|
|
294
|
+
}
|
|
295
|
+
.m-toast-icon {
|
|
296
|
+
display: grid;
|
|
297
|
+
place-items: center;
|
|
298
|
+
flex-shrink: 0;
|
|
299
|
+
width: 20px;
|
|
300
|
+
height: 20px;
|
|
301
|
+
border-radius: 50%;
|
|
302
|
+
background: var(--m-ink);
|
|
303
|
+
color: var(--m-paper);
|
|
304
|
+
font-size: 11px;
|
|
305
|
+
font-weight: var(--m-weight-bold);
|
|
306
|
+
}
|
|
307
|
+
.m-toast-leading {
|
|
308
|
+
display: inline-flex;
|
|
309
|
+
flex-shrink: 0;
|
|
310
|
+
}
|
|
311
|
+
.m-toast:is(
|
|
312
|
+
[data-tone="success"],
|
|
313
|
+
[data-tone="warning"],
|
|
314
|
+
[data-tone="danger"],
|
|
315
|
+
[data-tone="info"]
|
|
316
|
+
)
|
|
317
|
+
.m-toast-icon {
|
|
318
|
+
background: var(--m-tone);
|
|
319
|
+
color: var(--m-on-feedback);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/* == SaveBar == */
|
|
323
|
+
.m-save-bar {
|
|
324
|
+
position: sticky;
|
|
325
|
+
bottom: 0;
|
|
326
|
+
z-index: var(--m-z-sticky);
|
|
327
|
+
display: flex;
|
|
328
|
+
align-items: center;
|
|
329
|
+
flex-wrap: wrap;
|
|
330
|
+
gap: 12px;
|
|
331
|
+
padding: 12px 20px;
|
|
332
|
+
border-radius: var(--m-radius-lg);
|
|
333
|
+
background: var(--m-ink);
|
|
334
|
+
color: var(--m-paper);
|
|
335
|
+
font-size: var(--m-font-size);
|
|
336
|
+
}
|
|
337
|
+
.m-save-bar > span {
|
|
338
|
+
flex: 1;
|
|
339
|
+
}
|
|
340
|
+
.m-save-bar .m-button-secondary {
|
|
341
|
+
background: transparent;
|
|
342
|
+
color: var(--m-paper);
|
|
343
|
+
border-color: var(--m-secondary);
|
|
344
|
+
}
|
|
345
|
+
.m-save-bar .m-button-primary {
|
|
346
|
+
background: var(--m-paper);
|
|
347
|
+
color: var(--m-ink);
|
|
348
|
+
border-color: var(--m-paper);
|
|
349
|
+
}
|
|
350
|
+
}
|