3751 lines
120 KiB
HTML
3751 lines
120 KiB
HTML
<!doctype html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<title>D-D0b Layout Preview</title>
|
|
<style>
|
|
:root {
|
|
--bg: #f6f8fa;
|
|
--surface: #ffffff;
|
|
--surface-subtle: #f1f4f7;
|
|
--border: #dce3ea;
|
|
--border-strong: #b8c4cf;
|
|
--text: #172635;
|
|
--muted: #5c6f82;
|
|
--muted-2: #74879a;
|
|
--primary: #2458d3;
|
|
--primary-dark: #1742a6;
|
|
--danger: #b42318;
|
|
--success: #147a46;
|
|
--warning: #9a5b00;
|
|
--padding-viz: rgba(139, 92, 246, 0.2);
|
|
--padding-viz-strong: #7c3aed;
|
|
--gap-viz: rgba(20, 184, 166, 0.18);
|
|
--gap-viz-strong: #0f766e;
|
|
--shadow: 0 16px 40px rgba(20, 35, 55, 0.12);
|
|
--radius: 8px;
|
|
--page-pad: 24px;
|
|
--section-gap: 24px;
|
|
--card-pad: 16px;
|
|
--control-h: 36px;
|
|
--font-body-default-regular-150: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
--font-body-default-regular-0: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
--font-body-small-regular-150: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
--font-body-extra-small-semibold-150: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
--font-body-default-semibold-150: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
--font-heading: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
--text-heading: 24px;
|
|
--text-heading--font-weight: 500;
|
|
--text-heading--line-height: 32px;
|
|
--text-body-default-regular-150: 16px;
|
|
--text-body-default-regular-150--font-weight: 400;
|
|
--text-body-default-regular-150--line-height: 24px;
|
|
--text-body-default-regular-0: 16px;
|
|
--text-body-default-regular-0--font-weight: 400;
|
|
--text-body-default-regular-0--line-height: 17px;
|
|
--text-body-small-regular-150: 14px;
|
|
--text-body-small-regular-150--font-weight: 400;
|
|
--text-body-small-regular-150--line-height: 21px;
|
|
--text-body-small-regular-0: 14px;
|
|
--text-body-small-regular-0--font-weight: 400;
|
|
--text-body-small-regular-0--line-height: 15px;
|
|
--text-body-default-semibold-150: 16px;
|
|
--text-body-default-semibold-150--font-weight: 600;
|
|
--text-body-default-semibold-150--line-height: 24px;
|
|
--text-body-extra-small-semibold-150: 12px;
|
|
--text-body-extra-small-semibold-150--font-weight: 600;
|
|
--text-body-extra-small-semibold-150--line-height: 18px;
|
|
font-family:
|
|
Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
|
"Segoe UI", sans-serif;
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
font-size: 14px;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
button,
|
|
input,
|
|
select,
|
|
textarea {
|
|
font: inherit;
|
|
}
|
|
|
|
.topbar {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 10;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 24px;
|
|
min-height: 56px;
|
|
padding: 0 var(--page-pad);
|
|
border-bottom: 1px solid var(--border);
|
|
background: rgba(255, 255, 255, 0.92);
|
|
backdrop-filter: blur(10px);
|
|
}
|
|
|
|
.brand {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.mark {
|
|
display: grid;
|
|
width: 28px;
|
|
height: 28px;
|
|
place-items: center;
|
|
border-radius: 6px;
|
|
background: var(--text);
|
|
color: #fff;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.topbar-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.marker-toggle {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
min-height: 32px;
|
|
padding: 0 10px;
|
|
border: 1px solid var(--border-strong);
|
|
border-radius: 999px;
|
|
background: #fff;
|
|
color: var(--text);
|
|
font-size: 12px;
|
|
font-weight: 650;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.marker-toggle-switch {
|
|
position: relative;
|
|
width: 32px;
|
|
height: 18px;
|
|
border-radius: 999px;
|
|
background: var(--gap-viz-strong);
|
|
}
|
|
|
|
.marker-toggle-switch::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 3px;
|
|
left: 17px;
|
|
width: 12px;
|
|
height: 12px;
|
|
border-radius: 999px;
|
|
background: #fff;
|
|
transition: left 160ms ease;
|
|
}
|
|
|
|
body.hide-gap-markers .marker-toggle-switch {
|
|
background: var(--border-strong);
|
|
}
|
|
|
|
body.hide-gap-markers .marker-toggle-switch::after {
|
|
left: 3px;
|
|
}
|
|
|
|
.legend {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: 12px;
|
|
margin-top: 16px;
|
|
}
|
|
|
|
.legend-item {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
color: var(--muted);
|
|
font-size: 13px;
|
|
}
|
|
|
|
.legend-dot {
|
|
width: 16px;
|
|
height: 16px;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.legend-dot.padding {
|
|
border: 1px solid var(--padding-viz-strong);
|
|
background: var(--padding-viz);
|
|
}
|
|
|
|
.legend-dot.gap {
|
|
border: 1px solid var(--gap-viz-strong);
|
|
background: var(--gap-viz);
|
|
}
|
|
|
|
.legend-dot.content {
|
|
border: 1px solid var(--border-strong);
|
|
background: #fff;
|
|
}
|
|
|
|
.page {
|
|
max-width: 1440px;
|
|
margin: 0 auto;
|
|
padding: var(--page-pad);
|
|
}
|
|
|
|
.hero {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: 32px;
|
|
}
|
|
|
|
.eyebrow {
|
|
margin: 0 0 8px;
|
|
color: var(--muted-2);
|
|
font-size: 12px;
|
|
font-weight: 700;
|
|
letter-spacing: 0;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
h1,
|
|
h2,
|
|
h3,
|
|
p {
|
|
margin: 0;
|
|
}
|
|
|
|
h1 {
|
|
font-size: 36px;
|
|
line-height: 1.15;
|
|
letter-spacing: 0;
|
|
}
|
|
|
|
.subtitle {
|
|
max-width: 720px;
|
|
margin-top: 8px;
|
|
color: var(--muted);
|
|
font-size: 16px;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.section {
|
|
margin-top: var(--section-gap);
|
|
}
|
|
|
|
.section-head {
|
|
display: flex;
|
|
align-items: flex-end;
|
|
justify-content: space-between;
|
|
gap: 24px;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.section-copy {
|
|
max-width: 760px;
|
|
}
|
|
|
|
h2 {
|
|
font-size: 22px;
|
|
line-height: 1.3;
|
|
}
|
|
|
|
.section-desc {
|
|
margin-top: 6px;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.decision-map {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
gap: 12px;
|
|
}
|
|
|
|
.decision-link {
|
|
display: grid;
|
|
gap: 4px;
|
|
min-height: 92px;
|
|
padding: 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
text-decoration: none;
|
|
color: var(--text);
|
|
}
|
|
|
|
.decision-link strong {
|
|
font-size: 13px;
|
|
}
|
|
|
|
.decision-link span {
|
|
color: var(--muted);
|
|
font-size: 12px;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.decision-panel {
|
|
display: grid;
|
|
gap: 16px;
|
|
margin-bottom: 24px;
|
|
padding: 24px;
|
|
border: 1px solid #c7d2fe;
|
|
border-radius: 8px;
|
|
background: #eef3ff;
|
|
}
|
|
|
|
.decision-kicker {
|
|
color: #2443a8;
|
|
font-size: 12px;
|
|
font-weight: 800;
|
|
letter-spacing: 0;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.decision-panel h3 {
|
|
font-size: 18px;
|
|
line-height: 1.35;
|
|
}
|
|
|
|
.decision-panel p {
|
|
color: #294268;
|
|
}
|
|
|
|
.decision-options {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: 12px;
|
|
}
|
|
|
|
.decision-option {
|
|
padding: 16px;
|
|
border: 1px solid #c7d2fe;
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.decision-option.recommended {
|
|
border-color: var(--primary);
|
|
box-shadow: inset 0 0 0 1px var(--primary);
|
|
}
|
|
|
|
.decision-option strong {
|
|
display: block;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.decision-option span {
|
|
display: block;
|
|
color: var(--muted);
|
|
font-size: 12px;
|
|
line-height: 1.45;
|
|
}
|
|
|
|
.decision-question {
|
|
padding: 12px 16px;
|
|
border-left: 4px solid var(--primary);
|
|
border-radius: 6px;
|
|
background: #fff;
|
|
color: var(--text);
|
|
font-weight: 650;
|
|
}
|
|
|
|
.decision-tag {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
min-height: 24px;
|
|
padding: 0 8px;
|
|
border-radius: 999px;
|
|
background: #dbe4ff;
|
|
color: #2443a8;
|
|
font-size: 12px;
|
|
font-weight: 800;
|
|
}
|
|
|
|
.definition-grid {
|
|
display: grid;
|
|
grid-template-columns: minmax(260px, 0.9fr) minmax(0, 1.4fr);
|
|
gap: 24px;
|
|
}
|
|
|
|
.reference-strip {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
gap: 16px;
|
|
margin-bottom: 24px;
|
|
}
|
|
|
|
.reference-card {
|
|
padding: 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.reference-card strong {
|
|
display: block;
|
|
margin-bottom: 6px;
|
|
}
|
|
|
|
.reference-card ul {
|
|
display: grid;
|
|
gap: 6px;
|
|
margin: 0;
|
|
padding-left: 18px;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.d02-preview-grid {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
|
|
gap: 24px;
|
|
margin-bottom: 24px;
|
|
}
|
|
|
|
.compare-block {
|
|
display: grid;
|
|
gap: 16px;
|
|
margin-bottom: 24px;
|
|
}
|
|
|
|
.compare-head {
|
|
display: grid;
|
|
gap: 4px;
|
|
}
|
|
|
|
.compare-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: 16px;
|
|
}
|
|
|
|
.compare-card {
|
|
padding: 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.compare-card.recommended {
|
|
border-color: var(--primary);
|
|
box-shadow: inset 0 0 0 1px var(--primary);
|
|
}
|
|
|
|
.compare-title {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
gap: 12px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.mini-page {
|
|
--sample-page-pad: 24px;
|
|
--sample-card-pad: 16px;
|
|
--sample-gap: 16px;
|
|
position: relative;
|
|
padding: var(--sample-page-pad);
|
|
border: 1px solid var(--padding-viz-strong);
|
|
border-radius: 8px;
|
|
background:
|
|
repeating-linear-gradient(
|
|
45deg,
|
|
rgba(139, 92, 246, 0.22) 0,
|
|
rgba(139, 92, 246, 0.22) 8px,
|
|
rgba(139, 92, 246, 0.1) 8px,
|
|
rgba(139, 92, 246, 0.1) 16px
|
|
);
|
|
}
|
|
|
|
.mini-page-content {
|
|
display: grid;
|
|
gap: 10px;
|
|
min-height: 96px;
|
|
padding: 12px;
|
|
border: 1px dashed var(--border-strong);
|
|
border-radius: 6px;
|
|
background: #fff;
|
|
}
|
|
|
|
.mini-card {
|
|
position: relative;
|
|
padding: var(--sample-card-pad);
|
|
border: 1px solid var(--padding-viz-strong);
|
|
border-radius: 8px;
|
|
background:
|
|
repeating-linear-gradient(
|
|
45deg,
|
|
rgba(139, 92, 246, 0.2) 0,
|
|
rgba(139, 92, 246, 0.2) 8px,
|
|
rgba(139, 92, 246, 0.1) 8px,
|
|
rgba(139, 92, 246, 0.1) 16px
|
|
);
|
|
}
|
|
|
|
.mini-card-content {
|
|
display: grid;
|
|
gap: 8px;
|
|
min-height: 64px;
|
|
padding: 10px;
|
|
border: 1px dashed var(--border-strong);
|
|
border-radius: 6px;
|
|
background: #fff;
|
|
}
|
|
|
|
.mini-gap-frame {
|
|
display: grid;
|
|
gap: var(--sample-gap);
|
|
padding: 0;
|
|
border-radius: 8px;
|
|
background:
|
|
repeating-linear-gradient(
|
|
-45deg,
|
|
rgba(20, 184, 166, 0.2) 0,
|
|
rgba(20, 184, 166, 0.2) 8px,
|
|
rgba(20, 184, 166, 0.09) 8px,
|
|
rgba(20, 184, 166, 0.09) 16px
|
|
);
|
|
}
|
|
|
|
.mini-gap-item {
|
|
min-height: 42px;
|
|
padding: 10px 12px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 6px;
|
|
background: #fff;
|
|
}
|
|
|
|
.layout-case {
|
|
padding: 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.layout-case.backlog {
|
|
border-style: dashed;
|
|
background: #fafbfc;
|
|
}
|
|
|
|
.layout-case.open {
|
|
border-color: #f5c76b;
|
|
background: #fffaf0;
|
|
}
|
|
|
|
.layout-case-head {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
gap: 16px;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.layout-case-head h3 {
|
|
font-size: 15px;
|
|
line-height: 1.35;
|
|
}
|
|
|
|
.value-row {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 8px;
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.value-chip {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
min-height: 24px;
|
|
padding: 0 8px;
|
|
border-radius: 999px;
|
|
background: var(--surface-subtle);
|
|
color: var(--muted);
|
|
font-size: 12px;
|
|
font-weight: 650;
|
|
}
|
|
|
|
.layout-frame {
|
|
--viz-page-pad: 24px;
|
|
--viz-card-pad: 16px;
|
|
--viz-gap: 16px;
|
|
position: relative;
|
|
display: grid;
|
|
gap: var(--viz-gap);
|
|
padding: var(--viz-page-pad);
|
|
border: 1px solid var(--padding-viz-strong);
|
|
border-radius: 10px;
|
|
background:
|
|
repeating-linear-gradient(
|
|
45deg,
|
|
rgba(139, 92, 246, 0.24) 0,
|
|
rgba(139, 92, 246, 0.24) 8px,
|
|
rgba(139, 92, 246, 0.13) 8px,
|
|
rgba(139, 92, 246, 0.13) 16px
|
|
);
|
|
}
|
|
|
|
.layout-frame.compact {
|
|
--viz-page-pad: 24px;
|
|
--viz-card-pad: 16px;
|
|
--viz-gap: 16px;
|
|
}
|
|
|
|
.layout-frame.editor {
|
|
--viz-card-pad: 32px;
|
|
}
|
|
|
|
.layout-content-shell {
|
|
display: grid;
|
|
gap: var(--viz-gap);
|
|
border: 1px dashed var(--border-strong);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.mock-header {
|
|
display: grid;
|
|
gap: 6px;
|
|
padding: 16px;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
.mock-title {
|
|
width: 44%;
|
|
height: 16px;
|
|
border-radius: 999px;
|
|
background: var(--text);
|
|
}
|
|
|
|
.mock-copy {
|
|
width: 64%;
|
|
height: 10px;
|
|
border-radius: 999px;
|
|
background: var(--border-strong);
|
|
}
|
|
|
|
.mock-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: var(--viz-gap);
|
|
padding: var(--viz-gap);
|
|
}
|
|
|
|
.mock-grid.single {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.mock-card {
|
|
position: relative;
|
|
min-height: 120px;
|
|
padding: var(--viz-card-pad);
|
|
border: 1px solid var(--padding-viz-strong);
|
|
border-radius: 8px;
|
|
background:
|
|
repeating-linear-gradient(
|
|
45deg,
|
|
rgba(139, 92, 246, 0.18) 0,
|
|
rgba(139, 92, 246, 0.18) 8px,
|
|
rgba(139, 92, 246, 0.09) 8px,
|
|
rgba(139, 92, 246, 0.09) 16px
|
|
);
|
|
}
|
|
|
|
.mock-card-inner {
|
|
display: grid;
|
|
gap: 8px;
|
|
min-height: 72px;
|
|
padding: 12px;
|
|
border: 1px dashed var(--border-strong);
|
|
border-radius: 6px;
|
|
background: #fff;
|
|
}
|
|
|
|
.mock-line {
|
|
height: 10px;
|
|
border-radius: 999px;
|
|
background: var(--border-strong);
|
|
}
|
|
|
|
.mock-line.short {
|
|
width: 48%;
|
|
}
|
|
|
|
.mock-line.medium {
|
|
width: 72%;
|
|
}
|
|
|
|
.ownership-note {
|
|
display: grid;
|
|
gap: 8px;
|
|
padding: 16px;
|
|
border: 1px solid #c7d2fe;
|
|
border-radius: 8px;
|
|
background: #eef3ff;
|
|
color: #294268;
|
|
}
|
|
|
|
.ownership-note strong {
|
|
color: #183b7d;
|
|
}
|
|
|
|
.concept-list {
|
|
display: grid;
|
|
gap: 10px;
|
|
margin-bottom: 24px;
|
|
}
|
|
|
|
.concept-row {
|
|
display: grid;
|
|
grid-template-columns: 180px 1fr;
|
|
gap: 16px;
|
|
padding: 12px 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.concept-row strong {
|
|
font-size: 13px;
|
|
}
|
|
|
|
.term-list {
|
|
display: grid;
|
|
gap: 12px;
|
|
}
|
|
|
|
.term {
|
|
padding: 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.term strong {
|
|
display: block;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.padding-showcase {
|
|
display: grid;
|
|
gap: 16px;
|
|
}
|
|
|
|
.padding-sample {
|
|
--pad: 24px;
|
|
position: relative;
|
|
padding: var(--pad);
|
|
border: 1px solid var(--padding-viz-strong);
|
|
border-radius: 10px;
|
|
background:
|
|
repeating-linear-gradient(
|
|
45deg,
|
|
rgba(139, 92, 246, 0.24) 0,
|
|
rgba(139, 92, 246, 0.24) 8px,
|
|
rgba(139, 92, 246, 0.14) 8px,
|
|
rgba(139, 92, 246, 0.14) 16px
|
|
);
|
|
}
|
|
|
|
.padding-content {
|
|
min-height: 72px;
|
|
padding: 16px;
|
|
border: 1px dashed var(--border-strong);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.padding-content.compact {
|
|
min-height: auto;
|
|
padding: 10px 12px;
|
|
}
|
|
|
|
.measure-tag {
|
|
position: absolute;
|
|
top: 8px;
|
|
right: 8px;
|
|
padding: 2px 8px;
|
|
border: 1px solid var(--padding-viz-strong);
|
|
border-radius: 999px;
|
|
background: #fff;
|
|
color: var(--padding-viz-strong);
|
|
font-size: 12px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.gap-sample {
|
|
--gap: 24px;
|
|
display: grid;
|
|
gap: var(--gap);
|
|
padding: 0;
|
|
border-radius: 8px;
|
|
background:
|
|
repeating-linear-gradient(
|
|
-45deg,
|
|
rgba(20, 184, 166, 0.2) 0,
|
|
rgba(20, 184, 166, 0.2) 8px,
|
|
rgba(20, 184, 166, 0.1) 8px,
|
|
rgba(20, 184, 166, 0.1) 16px
|
|
);
|
|
}
|
|
|
|
.gap-item {
|
|
padding: 12px 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.sample-title {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
gap: 16px;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.edge-padding-sample {
|
|
position: relative;
|
|
overflow: hidden;
|
|
padding: 16px;
|
|
border: 1px solid var(--padding-viz-strong);
|
|
border-radius: 10px;
|
|
background: #fff;
|
|
}
|
|
|
|
.edge-padding-sample::before,
|
|
.edge-padding-sample::after {
|
|
position: absolute;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 16px;
|
|
content: "";
|
|
background:
|
|
repeating-linear-gradient(
|
|
45deg,
|
|
rgba(139, 92, 246, 0.28) 0,
|
|
rgba(139, 92, 246, 0.28) 8px,
|
|
rgba(139, 92, 246, 0.16) 8px,
|
|
rgba(139, 92, 246, 0.16) 16px
|
|
);
|
|
}
|
|
|
|
.edge-padding-sample::before {
|
|
left: 0;
|
|
}
|
|
|
|
.edge-padding-sample::after {
|
|
right: 0;
|
|
}
|
|
|
|
.edge-padding-sample .padding-content {
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
.plain-sample {
|
|
position: relative;
|
|
padding: 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 10px;
|
|
background: #fff;
|
|
}
|
|
|
|
.button-padding-viz {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-height: 40px;
|
|
padding: 0 16px;
|
|
border: 1px solid var(--padding-viz-strong);
|
|
border-radius: 6px;
|
|
background:
|
|
repeating-linear-gradient(
|
|
45deg,
|
|
rgba(139, 92, 246, 0.3) 0,
|
|
rgba(139, 92, 246, 0.3) 8px,
|
|
rgba(139, 92, 246, 0.16) 8px,
|
|
rgba(139, 92, 246, 0.16) 16px
|
|
);
|
|
}
|
|
|
|
.button-label-viz {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-height: 38px;
|
|
padding: 0 2px;
|
|
border-radius: 4px;
|
|
background: var(--primary);
|
|
color: #fff;
|
|
font-weight: 650;
|
|
}
|
|
|
|
.grid {
|
|
display: grid;
|
|
gap: 16px;
|
|
}
|
|
|
|
.grid.two {
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
}
|
|
|
|
.grid.three {
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
}
|
|
|
|
.card {
|
|
padding: var(--card-pad);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius);
|
|
background: var(--surface);
|
|
}
|
|
|
|
.card.tight {
|
|
padding: 16px;
|
|
}
|
|
|
|
.card.large {
|
|
padding: 32px;
|
|
}
|
|
|
|
.card h3 {
|
|
margin-bottom: 8px;
|
|
font-size: 16px;
|
|
line-height: 1.35;
|
|
}
|
|
|
|
.muted {
|
|
color: var(--muted);
|
|
}
|
|
|
|
.small {
|
|
color: var(--muted);
|
|
font-size: 12px;
|
|
}
|
|
|
|
.button-row,
|
|
.field-row,
|
|
.toolbar {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: 8px;
|
|
}
|
|
|
|
.button {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-height: var(--control-h);
|
|
padding: 0 16px;
|
|
border: 1px solid transparent;
|
|
border-radius: 6px;
|
|
background: var(--primary);
|
|
color: #fff;
|
|
font-weight: 650;
|
|
text-decoration: none;
|
|
cursor: default;
|
|
}
|
|
|
|
.button.secondary {
|
|
border-color: var(--border-strong);
|
|
background: #fff;
|
|
color: var(--text);
|
|
}
|
|
|
|
.button.ghost {
|
|
background: transparent;
|
|
color: var(--text);
|
|
}
|
|
|
|
.button.danger {
|
|
background: var(--danger);
|
|
}
|
|
|
|
.button.sm {
|
|
min-height: 32px;
|
|
padding: 0 12px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.button.lg {
|
|
min-height: 48px;
|
|
padding: 0 20px;
|
|
}
|
|
|
|
.scale {
|
|
display: grid;
|
|
grid-template-columns: repeat(8, minmax(0, 1fr));
|
|
gap: 12px;
|
|
}
|
|
|
|
.scale-item {
|
|
min-height: 112px;
|
|
padding: 12px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.bar {
|
|
margin-top: 12px;
|
|
border-radius: 4px;
|
|
background: var(--primary);
|
|
}
|
|
|
|
.demo-frame {
|
|
display: grid;
|
|
gap: 16px;
|
|
padding: 24px;
|
|
border: 1px dashed var(--border-strong);
|
|
border-radius: 8px;
|
|
background:
|
|
linear-gradient(rgba(36, 88, 211, 0.05) 1px, transparent 1px),
|
|
linear-gradient(90deg, rgba(36, 88, 211, 0.05) 1px, transparent 1px),
|
|
#fff;
|
|
background-size: 8px 8px;
|
|
}
|
|
|
|
.demo-page-header {
|
|
display: grid;
|
|
gap: 8px;
|
|
padding-bottom: 8px;
|
|
}
|
|
|
|
.rhythm-legend {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 8px;
|
|
margin-top: 12px;
|
|
}
|
|
|
|
.rhythm-comparison {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: 16px;
|
|
}
|
|
|
|
.rhythm-sample {
|
|
display: grid;
|
|
gap: 0;
|
|
padding: 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.rhythm-sample.recommended {
|
|
border-color: var(--primary);
|
|
box-shadow: inset 0 0 0 1px var(--primary);
|
|
}
|
|
|
|
.rhythm-sample-head {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: 12px;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.rhythm-sample-title {
|
|
display: grid;
|
|
gap: 3px;
|
|
}
|
|
|
|
.rhythm-sample-title strong {
|
|
font-size: 15px;
|
|
}
|
|
|
|
.rhythm-page-header-preview,
|
|
.rhythm-section-preview,
|
|
.rhythm-content-preview {
|
|
display: grid;
|
|
gap: 0;
|
|
}
|
|
|
|
.rhythm-eyebrow {
|
|
color: var(--muted);
|
|
font-family: var(--font-body-extra-small-semibold-150);
|
|
font-size: var(--text-body-extra-small-semibold-150);
|
|
font-weight: var(--text-body-extra-small-semibold-150--font-weight);
|
|
line-height: var(--text-body-extra-small-semibold-150--line-height);
|
|
letter-spacing: 0;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.rhythm-title {
|
|
margin: 4px 0 0;
|
|
font-family: var(--font-heading);
|
|
font-size: var(--text-heading);
|
|
font-weight: var(--text-heading--font-weight);
|
|
line-height: var(--text-heading--line-height);
|
|
}
|
|
|
|
.rhythm-desc {
|
|
margin: 0;
|
|
color: var(--muted);
|
|
font-family: var(--font-body-small-regular-150);
|
|
font-size: var(--text-body-small-regular-150);
|
|
font-weight: var(--text-body-small-regular-150--font-weight);
|
|
line-height: var(--text-body-small-regular-150--line-height);
|
|
}
|
|
|
|
.rhythm-section-title {
|
|
margin: 0;
|
|
font-family: var(--font-body-default-semibold-150);
|
|
font-size: var(--text-body-default-semibold-150);
|
|
font-weight: var(--text-body-default-semibold-150--font-weight);
|
|
line-height: var(--text-body-default-semibold-150--line-height);
|
|
}
|
|
|
|
.rhythm-card-row {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: 12px;
|
|
}
|
|
|
|
.rhythm-mini-card {
|
|
min-height: 82px;
|
|
padding: 12px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 6px;
|
|
background: var(--surface-subtle);
|
|
}
|
|
|
|
.rhythm-mini-card strong {
|
|
display: block;
|
|
margin-bottom: 6px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.rhythm-line {
|
|
height: 8px;
|
|
margin-top: 6px;
|
|
border-radius: 999px;
|
|
background: var(--muted-2);
|
|
}
|
|
|
|
.rhythm-line.short {
|
|
width: 60%;
|
|
}
|
|
|
|
.rhythm-list {
|
|
display: grid;
|
|
gap: 8px;
|
|
}
|
|
|
|
.rhythm-list-row {
|
|
display: grid;
|
|
grid-template-columns: 32px minmax(0, 1fr) 64px;
|
|
align-items: center;
|
|
gap: 8px;
|
|
min-height: 36px;
|
|
padding: 0 10px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 6px;
|
|
background: #fff;
|
|
}
|
|
|
|
.rhythm-dot {
|
|
width: 24px;
|
|
height: 24px;
|
|
border-radius: 999px;
|
|
background: var(--border-strong);
|
|
}
|
|
|
|
.rhythm-pill {
|
|
height: 20px;
|
|
border-radius: 999px;
|
|
background: var(--border);
|
|
}
|
|
|
|
.rhythm-detail-grid {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
gap: 16px;
|
|
margin-top: 16px;
|
|
}
|
|
|
|
.rhythm-detail-card {
|
|
display: grid;
|
|
gap: 0;
|
|
padding: 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.rhythm-metric-list {
|
|
display: grid;
|
|
gap: 8px;
|
|
margin-top: 12px;
|
|
}
|
|
|
|
.rhythm-metric {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 12px;
|
|
padding: 8px 10px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 6px;
|
|
background: var(--surface-subtle);
|
|
color: var(--muted);
|
|
font-size: 12px;
|
|
}
|
|
|
|
.rhythm-metric strong {
|
|
color: var(--text);
|
|
}
|
|
|
|
.token-impact {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: 16px;
|
|
margin-top: 16px;
|
|
}
|
|
|
|
.token-impact-card {
|
|
display: grid;
|
|
gap: 12px;
|
|
padding: 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.token-impact-card.warning {
|
|
border-color: #f2c078;
|
|
background: #fffaf1;
|
|
}
|
|
|
|
.token-impact-card.recommended {
|
|
border-color: var(--primary);
|
|
box-shadow: inset 0 0 0 1px var(--primary);
|
|
}
|
|
|
|
.token-impact-card h3,
|
|
.token-impact-card p,
|
|
.token-rule-panel h3,
|
|
.token-rule-panel p,
|
|
.rhythm-detail-card h3,
|
|
.rhythm-detail-card p {
|
|
margin: 0;
|
|
}
|
|
|
|
.token-text-box {
|
|
max-width: 280px;
|
|
padding: 12px;
|
|
border: 1px dashed var(--border-strong);
|
|
border-radius: 6px;
|
|
background:
|
|
linear-gradient(rgba(36, 88, 211, 0.06) 1px, transparent 1px),
|
|
#fff;
|
|
background-size: 100% 8px;
|
|
}
|
|
|
|
.token-text-box.tight {
|
|
font-family: var(--font-body-default-regular-0);
|
|
font-size: var(--text-body-default-regular-0);
|
|
font-weight: var(--text-body-default-regular-0--font-weight);
|
|
line-height: var(--text-body-default-regular-0--line-height);
|
|
}
|
|
|
|
.token-text-box.readable {
|
|
font-family: var(--font-body-default-regular-150);
|
|
font-size: var(--text-body-default-regular-150);
|
|
font-weight: var(--text-body-default-regular-150--font-weight);
|
|
line-height: var(--text-body-default-regular-150--line-height);
|
|
}
|
|
|
|
.token-rule-panel {
|
|
margin-top: 16px;
|
|
padding: 16px;
|
|
border: 1px solid #c7d2fe;
|
|
border-radius: 8px;
|
|
background: #eef3ff;
|
|
}
|
|
|
|
.form {
|
|
display: grid;
|
|
gap: 16px;
|
|
}
|
|
|
|
.field {
|
|
display: grid;
|
|
gap: 8px;
|
|
}
|
|
|
|
label {
|
|
color: var(--text);
|
|
font-size: 13px;
|
|
font-weight: 650;
|
|
}
|
|
|
|
input,
|
|
select,
|
|
textarea {
|
|
width: 100%;
|
|
min-height: var(--control-h);
|
|
padding: 0 12px;
|
|
border: 1px solid var(--border-strong);
|
|
border-radius: 6px;
|
|
background: #fff;
|
|
color: var(--text);
|
|
}
|
|
|
|
textarea {
|
|
min-height: 88px;
|
|
padding-top: 10px;
|
|
resize: vertical;
|
|
}
|
|
|
|
.help {
|
|
color: var(--muted);
|
|
font-size: 12px;
|
|
line-height: 1.45;
|
|
}
|
|
|
|
.error {
|
|
color: var(--danger);
|
|
font-size: 12px;
|
|
line-height: 1.45;
|
|
}
|
|
|
|
.table-shell {
|
|
overflow: hidden;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
th,
|
|
td {
|
|
height: 52px;
|
|
padding: 0 16px;
|
|
border-bottom: 1px solid var(--border);
|
|
text-align: left;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
th {
|
|
color: var(--muted);
|
|
font-size: 12px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
tr:last-child td {
|
|
border-bottom: 0;
|
|
}
|
|
|
|
.pill {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
min-height: 24px;
|
|
padding: 0 8px;
|
|
border-radius: 999px;
|
|
background: #e8f6ee;
|
|
color: var(--success);
|
|
font-size: 12px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.pill.warning {
|
|
background: #fff2d6;
|
|
color: var(--warning);
|
|
}
|
|
|
|
.modal-grid {
|
|
display: grid;
|
|
gap: 24px;
|
|
}
|
|
|
|
.modal-version-grid {
|
|
display: grid;
|
|
gap: 16px;
|
|
}
|
|
|
|
.modal-version {
|
|
display: grid;
|
|
gap: 16px;
|
|
padding: 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.modal-version.recommended {
|
|
border-color: rgba(36, 88, 211, 0.42);
|
|
background: #f7f9ff;
|
|
}
|
|
|
|
.modal-version-head {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: 16px;
|
|
}
|
|
|
|
.modal-size-row {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: 12px;
|
|
}
|
|
|
|
.modal-size-row.four {
|
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
}
|
|
|
|
.modal-size-card {
|
|
display: grid;
|
|
gap: 10px;
|
|
min-width: 0;
|
|
}
|
|
|
|
.modal-size-label {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
gap: 8px;
|
|
color: var(--muted);
|
|
font-size: 12px;
|
|
}
|
|
|
|
.modal-width-track {
|
|
display: flex;
|
|
align-items: center;
|
|
min-height: 64px;
|
|
padding: 12px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background:
|
|
repeating-linear-gradient(
|
|
90deg,
|
|
rgba(20, 184, 166, 0.08) 0,
|
|
rgba(20, 184, 166, 0.08) 8px,
|
|
transparent 8px,
|
|
transparent 16px
|
|
),
|
|
var(--surface-subtle);
|
|
}
|
|
|
|
.modal-width-block {
|
|
display: grid;
|
|
width: var(--preview-pct);
|
|
min-height: 40px;
|
|
place-items: center;
|
|
border: 1px solid var(--border-strong);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
color: var(--text);
|
|
font-size: 12px;
|
|
font-weight: 700;
|
|
box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.08));
|
|
}
|
|
|
|
.viewport-behavior {
|
|
display: grid;
|
|
gap: 12px;
|
|
padding: 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: var(--surface-subtle);
|
|
}
|
|
|
|
.viewport-row {
|
|
display: grid;
|
|
grid-template-columns: 120px 1fr 168px;
|
|
gap: 12px;
|
|
align-items: center;
|
|
}
|
|
|
|
.viewport-track {
|
|
position: relative;
|
|
min-height: 28px;
|
|
overflow: hidden;
|
|
border: 1px solid var(--border);
|
|
border-radius: 999px;
|
|
background: #fff;
|
|
}
|
|
|
|
.viewport-dialog {
|
|
position: absolute;
|
|
inset-block: 5px;
|
|
left: 50%;
|
|
width: var(--dialog-ratio);
|
|
transform: translateX(-50%);
|
|
border-radius: 999px;
|
|
background: var(--primary);
|
|
}
|
|
|
|
.pattern-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
gap: 12px;
|
|
}
|
|
|
|
.pattern-card {
|
|
display: grid;
|
|
gap: 10px;
|
|
padding: 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.pattern-card strong {
|
|
font-size: 14px;
|
|
}
|
|
|
|
.pattern-mini {
|
|
position: relative;
|
|
min-height: 112px;
|
|
overflow: hidden;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: var(--surface-subtle);
|
|
}
|
|
|
|
.pattern-shell {
|
|
position: absolute;
|
|
inset: 0;
|
|
display: grid;
|
|
grid-template-columns: 28% 1fr;
|
|
}
|
|
|
|
.pattern-shell::before {
|
|
content: "";
|
|
border-right: 1px solid var(--border);
|
|
background: #fff;
|
|
}
|
|
|
|
.pattern-page-content {
|
|
margin: 12px;
|
|
border-radius: 6px;
|
|
background: #fff;
|
|
}
|
|
|
|
.pattern-overlay {
|
|
position: absolute;
|
|
inset: 0;
|
|
background: rgba(23, 38, 53, 0.24);
|
|
}
|
|
|
|
.pattern-dialog-box {
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
width: 58%;
|
|
height: 48%;
|
|
transform: translate(-50%, -50%);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
box-shadow: var(--shadow);
|
|
}
|
|
|
|
.pattern-fullscreen-box {
|
|
position: absolute;
|
|
inset: 8px;
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
box-shadow: var(--shadow);
|
|
}
|
|
|
|
.pattern-fullscreen-box::before {
|
|
content: "24px margin";
|
|
position: absolute;
|
|
top: 8px;
|
|
left: 10px;
|
|
color: var(--muted);
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.pattern-drawer-box {
|
|
position: absolute;
|
|
inset-block: 0;
|
|
right: 0;
|
|
width: 46%;
|
|
border-left: 1px solid var(--border);
|
|
background: #fff;
|
|
box-shadow: var(--shadow);
|
|
}
|
|
|
|
.modal-demo {
|
|
--modal-pad: 16px;
|
|
width: min(var(--modal-w), 100%);
|
|
margin: 0 auto;
|
|
overflow: hidden;
|
|
border: 1px solid var(--border);
|
|
border-radius: 10px;
|
|
background: #fff;
|
|
box-shadow: var(--shadow);
|
|
}
|
|
|
|
.modal-header,
|
|
.modal-body,
|
|
.modal-footer {
|
|
padding: var(--modal-pad);
|
|
}
|
|
|
|
.modal-header {
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
.modal-body {
|
|
display: grid;
|
|
gap: 16px;
|
|
}
|
|
|
|
.modal-footer {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 8px;
|
|
border-top: 1px solid var(--border);
|
|
background: var(--surface-subtle);
|
|
}
|
|
|
|
.modal-xs {
|
|
--modal-w: 420px;
|
|
}
|
|
|
|
.modal-small {
|
|
--modal-w: 560px;
|
|
}
|
|
|
|
.modal-medium {
|
|
--modal-w: 720px;
|
|
}
|
|
|
|
.modal-large {
|
|
--modal-w: 1200px;
|
|
}
|
|
|
|
.modal-spacious {
|
|
--modal-pad: 32px;
|
|
}
|
|
|
|
.dialog-gap-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: 16px;
|
|
}
|
|
|
|
.dialog-gap-card {
|
|
display: grid;
|
|
gap: 16px;
|
|
padding: 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.dialog-gap-card.recommended {
|
|
border-color: rgba(36, 88, 211, 0.42);
|
|
background: #f7f9ff;
|
|
}
|
|
|
|
.gap-spec-list {
|
|
display: grid;
|
|
gap: 8px;
|
|
margin: 0;
|
|
padding: 0;
|
|
list-style: none;
|
|
color: var(--muted);
|
|
font-size: 12px;
|
|
}
|
|
|
|
.gap-spec-list li {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
gap: 12px;
|
|
}
|
|
|
|
.gap-spec-list strong {
|
|
color: var(--text);
|
|
}
|
|
|
|
.dialog-gap-demo {
|
|
display: grid;
|
|
width: min(100%, 360px);
|
|
margin: 0 auto;
|
|
overflow: hidden;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
box-shadow: 0 8px 24px rgba(20, 35, 55, 0.1);
|
|
}
|
|
|
|
.dialog-gap-header,
|
|
.dialog-gap-body,
|
|
.dialog-gap-footer {
|
|
padding: 16px;
|
|
}
|
|
|
|
.dialog-gap-header {
|
|
display: grid;
|
|
gap: 0;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
.dialog-gap-title {
|
|
height: 16px;
|
|
width: 48%;
|
|
border-radius: 4px;
|
|
background: var(--text);
|
|
}
|
|
|
|
.dialog-gap-description {
|
|
height: 12px;
|
|
width: 74%;
|
|
border-radius: 4px;
|
|
background: var(--border-strong);
|
|
}
|
|
|
|
.dialog-gap-body {
|
|
display: grid;
|
|
gap: 0;
|
|
}
|
|
|
|
.dialog-gap-field {
|
|
display: grid;
|
|
gap: 8px;
|
|
}
|
|
|
|
.dialog-gap-label {
|
|
height: 10px;
|
|
width: 34%;
|
|
border-radius: 4px;
|
|
background: var(--muted-2);
|
|
}
|
|
|
|
.dialog-gap-input {
|
|
height: 36px;
|
|
border: 1px solid var(--border-strong);
|
|
border-radius: 6px;
|
|
background: #fff;
|
|
}
|
|
|
|
.dialog-gap-section {
|
|
display: grid;
|
|
gap: 8px;
|
|
margin-top: 0;
|
|
}
|
|
|
|
.dialog-gap-row {
|
|
height: 40px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 6px;
|
|
background: var(--surface-subtle);
|
|
}
|
|
|
|
.dialog-gap-footer {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 0;
|
|
border-top: 1px solid var(--border);
|
|
background: var(--surface-subtle);
|
|
}
|
|
|
|
.gap-marker {
|
|
position: relative;
|
|
display: block;
|
|
background:
|
|
repeating-linear-gradient(
|
|
45deg,
|
|
rgba(20, 184, 166, 0.22) 0,
|
|
rgba(20, 184, 166, 0.22) 4px,
|
|
rgba(20, 184, 166, 0.08) 4px,
|
|
rgba(20, 184, 166, 0.08) 8px
|
|
);
|
|
border: 1px dashed var(--gap-viz-strong);
|
|
}
|
|
|
|
.gap-marker.vertical {
|
|
height: var(--gap-size);
|
|
min-height: var(--gap-size);
|
|
}
|
|
|
|
.gap-marker.zero {
|
|
height: 0;
|
|
min-height: 0;
|
|
overflow: visible;
|
|
border: 0;
|
|
border-top: 1px dashed var(--gap-viz-strong);
|
|
background: transparent;
|
|
}
|
|
|
|
.gap-marker.horizontal {
|
|
width: var(--gap-size);
|
|
min-width: var(--gap-size);
|
|
align-self: stretch;
|
|
}
|
|
|
|
.gap-marker::after {
|
|
content: attr(data-label) " " attr(data-size);
|
|
position: absolute;
|
|
z-index: 1;
|
|
right: 4px;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
padding: 1px 4px;
|
|
border: 1px solid rgba(15, 118, 110, 0.28);
|
|
border-radius: 999px;
|
|
background: rgba(255, 255, 255, 0.92);
|
|
color: var(--gap-viz-strong);
|
|
font-size: 10px;
|
|
font-weight: 800;
|
|
line-height: 1.2;
|
|
white-space: nowrap;
|
|
pointer-events: none;
|
|
}
|
|
|
|
body.hide-gap-markers .gap-marker {
|
|
border-color: transparent;
|
|
background: transparent;
|
|
}
|
|
|
|
body.hide-gap-markers .gap-marker::after {
|
|
opacity: 0;
|
|
}
|
|
|
|
.gap-marker.horizontal::after {
|
|
top: -18px;
|
|
right: auto;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
}
|
|
|
|
.gap-marker.zero::after {
|
|
top: 0;
|
|
transform: translateY(-50%);
|
|
}
|
|
|
|
.dialog-gap-button {
|
|
width: 76px;
|
|
height: 32px;
|
|
border-radius: 6px;
|
|
background: var(--border-strong);
|
|
}
|
|
|
|
.dialog-gap-button.primary {
|
|
background: var(--primary);
|
|
}
|
|
|
|
.footer-layout-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: 16px;
|
|
margin-top: 16px;
|
|
}
|
|
|
|
.footer-layout-card {
|
|
display: grid;
|
|
gap: 16px;
|
|
padding: 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.footer-layout-card.recommended {
|
|
border-color: rgba(36, 88, 211, 0.42);
|
|
background: #f7f9ff;
|
|
}
|
|
|
|
.footer-preview {
|
|
display: grid;
|
|
overflow: hidden;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
}
|
|
|
|
.footer-preview-body {
|
|
min-height: 96px;
|
|
padding: 16px;
|
|
}
|
|
|
|
.footer-preview-actions {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 8px;
|
|
padding: 16px;
|
|
border-top: 1px solid var(--border);
|
|
background: var(--surface-subtle);
|
|
}
|
|
|
|
.footer-preview.fill-actions .footer-preview-actions {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
}
|
|
|
|
.footer-preview.fill-actions .dialog-gap-button {
|
|
width: auto;
|
|
}
|
|
|
|
.state {
|
|
display: grid;
|
|
min-height: 220px;
|
|
place-items: center;
|
|
padding: 32px;
|
|
border: 1px dashed var(--border-strong);
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
text-align: center;
|
|
}
|
|
|
|
.state-inner {
|
|
max-width: 420px;
|
|
}
|
|
|
|
.state h3 {
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.note {
|
|
padding: 16px;
|
|
border-left: 4px solid var(--primary);
|
|
border-radius: 6px;
|
|
background: #eef3ff;
|
|
color: #183b7d;
|
|
}
|
|
|
|
@media (max-width: 980px) {
|
|
:root {
|
|
--page-pad: 24px;
|
|
}
|
|
|
|
.grid.two,
|
|
.grid.three,
|
|
.decision-map,
|
|
.decision-options,
|
|
.scale,
|
|
.reference-strip,
|
|
.d02-preview-grid,
|
|
.compare-grid,
|
|
.concept-row,
|
|
.modal-size-row,
|
|
.modal-size-row.four,
|
|
.viewport-row,
|
|
.pattern-grid,
|
|
.definition-grid,
|
|
.rhythm-comparison,
|
|
.rhythm-detail-grid,
|
|
.token-impact,
|
|
.dialog-gap-grid,
|
|
.footer-layout-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.hero,
|
|
.section-head {
|
|
display: grid;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 640px) {
|
|
:root {
|
|
--page-pad: 16px;
|
|
--card-pad: 16px;
|
|
}
|
|
|
|
h1 {
|
|
font-size: 28px;
|
|
}
|
|
|
|
.topbar {
|
|
padding: 0 16px;
|
|
}
|
|
|
|
.topbar-actions {
|
|
display: none;
|
|
}
|
|
|
|
.rhythm-card-row {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header class="topbar">
|
|
<div class="brand">
|
|
<div class="mark">D0b</div>
|
|
<span>D-D0b Layout Preview</span>
|
|
</div>
|
|
<div class="topbar-actions">
|
|
<button class="marker-toggle" id="gapToggle" type="button" aria-pressed="true">
|
|
<span>Spacing Tiles</span>
|
|
<span class="marker-toggle-switch" aria-hidden="true"></span>
|
|
</button>
|
|
<a class="button sm secondary" href="#overview">Uebersicht</a>
|
|
<a class="button sm secondary" href="preview.html">Full Page</a>
|
|
<a class="button sm secondary" href="#d01">D01</a>
|
|
<a class="button sm secondary" href="#d02">D02</a>
|
|
<a class="button sm secondary" href="#d03">D03</a>
|
|
<a class="button sm secondary" href="#d04">D04</a>
|
|
<a class="button sm secondary" href="#d05">D05</a>
|
|
<a class="button sm secondary" href="#d06">D06</a>
|
|
<a class="button sm secondary" href="#d07">D07</a>
|
|
<a class="button sm secondary" href="#d08">D08</a>
|
|
<a class="button sm secondary" href="#d09">D09</a>
|
|
</div>
|
|
</header>
|
|
|
|
<main class="page">
|
|
<section id="overview" class="hero">
|
|
<div>
|
|
<p class="eyebrow">Versioned reference preview</p>
|
|
<h1>Layout, spacing and sizing decisions</h1>
|
|
<p class="subtitle">
|
|
This page preserves the visual examples used for D-D0b. It helps
|
|
review spacing, widths, vertical rhythm and density, but the
|
|
Markdown standards are the source of truth.
|
|
</p>
|
|
</div>
|
|
<div class="note">
|
|
Kept intentionally: this HTML preview is stored with the D-D0b
|
|
planning files for visual review. Final rules live in the Obsidian
|
|
Markdown files and in the Subframe UI Standards.
|
|
</div>
|
|
</section>
|
|
|
|
<section class="section">
|
|
<div class="section-head">
|
|
<div class="section-copy">
|
|
<h2>Was du hier validierst</h2>
|
|
<p class="section-desc">
|
|
Diese Seite ist jetzt als Entscheidungsstrecke aufgebaut. Jede
|
|
Entscheidung hat eine Nummer, eine konkrete Frage und sichtbare
|
|
Beispiele darunter.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="decision-map">
|
|
<a class="decision-link" href="preview.html">
|
|
<strong>Full Page Preview</strong>
|
|
<span>Oeffnet eine eigene Full-Page-Dummyseite mit App Shell und Layout-Umschaltern.</span>
|
|
</a>
|
|
<a class="decision-link" href="#d01">
|
|
<strong>D01 Grundraster</strong>
|
|
<span>Welche Abstandsskala ist unser Standard?</span>
|
|
</a>
|
|
<a class="decision-link" href="#d02">
|
|
<strong>D02 Page & Card Padding</strong>
|
|
<span>Wie viel Luft bekommen Seiten und Panels?</span>
|
|
</a>
|
|
<a class="decision-link" href="#d03">
|
|
<strong>D03 Text-Rhythmus</strong>
|
|
<span>Wie nah stehen Titel, Beschreibung und Inhalt?</span>
|
|
</a>
|
|
<a class="decision-link" href="#d04">
|
|
<strong>D04 Button Ownership</strong>
|
|
<span>Button-Groessen kommen aus der Button-Komponente.</span>
|
|
</a>
|
|
<a class="decision-link" href="#d05">
|
|
<strong>D05 Forms</strong>
|
|
<span>Form-Feldgruppen stehen standardmaessig 16px auseinander.</span>
|
|
</a>
|
|
<a class="decision-link" href="#d06">
|
|
<strong>D06 Table Ownership</strong>
|
|
<span>Tabellen-Dichte kommt aus der Table-Komponente.</span>
|
|
</a>
|
|
<a class="decision-link" href="#d07">
|
|
<strong>D07 Dialoge</strong>
|
|
<span>Welche Breiten gelten fuer kleine, normale und grosse Modale?</span>
|
|
</a>
|
|
<a class="decision-link" href="#d08">
|
|
<strong>D08 Dialog Internal Gaps</strong>
|
|
<span>Welche Abstaende gelten innerhalb normaler Dialoge?</span>
|
|
</a>
|
|
<a class="decision-link" href="#d09">
|
|
<strong>D09 States</strong>
|
|
<span>States sind inline Komponenten-Zustaende, keine eigenen Layout-Screens.</span>
|
|
</a>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="d01" class="section">
|
|
<div class="section-head">
|
|
<div class="section-copy">
|
|
<h2>D01 Grundraster / Spacing Scale</h2>
|
|
<p class="section-desc">
|
|
Validierter 8px-Rhythmus mit erlaubten Zwischenwerten. Nutze
|
|
diese Ansicht als visuelle Referenz fuer die freigegebenen
|
|
Layout-Abstaende.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="decision-panel">
|
|
<div>
|
|
<span class="decision-tag">Entscheidung D01</span>
|
|
</div>
|
|
<div>
|
|
<p class="decision-kicker">Was du festlegst</p>
|
|
<h3>Welche Abstandsskala darf in HiveGrid verwendet werden?</h3>
|
|
<p>
|
|
Das ist die Grundlage fuer alle weiteren Padding- und Gap-Entscheidungen.
|
|
Eine kleine Skala macht Screens konsistenter.
|
|
</p>
|
|
</div>
|
|
<div class="decision-options">
|
|
<div class="decision-option">
|
|
<strong>Sehr streng</strong>
|
|
<span>Nur 8, 16, 24, 32, 48, 64. Sehr sauber, aber manchmal zu grob.</span>
|
|
</div>
|
|
<div class="decision-option recommended">
|
|
<strong>8px Rhythmus + Ausnahmen</strong>
|
|
<span>4, 8, 12, 16, 24, 32, 48, 64. Praktisch fuer echte UI-Arbeit.</span>
|
|
</div>
|
|
<div class="decision-option">
|
|
<strong>Sehr frei</strong>
|
|
<span>Viele Zwischenwerte erlaubt. Flexibel, aber weniger konsistent.</span>
|
|
</div>
|
|
</div>
|
|
<div class="decision-question">
|
|
Entscheidung: Darf HiveGrid den 8px-Rhythmus mit 4px/12px-Ausnahmen nutzen?
|
|
</div>
|
|
</div>
|
|
<div class="scale">
|
|
<div class="scale-item">
|
|
<strong>4px</strong>
|
|
<p class="small">Tiny relation</p>
|
|
<div class="bar" style="height: 4px"></div>
|
|
</div>
|
|
<div class="scale-item">
|
|
<strong>8px</strong>
|
|
<p class="small">Label to field</p>
|
|
<div class="bar" style="height: 8px"></div>
|
|
</div>
|
|
<div class="scale-item">
|
|
<strong>12px</strong>
|
|
<p class="small">Compact groups</p>
|
|
<div class="bar" style="height: 12px"></div>
|
|
</div>
|
|
<div class="scale-item">
|
|
<strong>16px</strong>
|
|
<p class="small">Related items</p>
|
|
<div class="bar" style="height: 16px"></div>
|
|
</div>
|
|
<div class="scale-item">
|
|
<strong>24px</strong>
|
|
<p class="small">Card padding</p>
|
|
<div class="bar" style="height: 24px"></div>
|
|
</div>
|
|
<div class="scale-item">
|
|
<strong>32px</strong>
|
|
<p class="small">Section gap</p>
|
|
<div class="bar" style="height: 32px"></div>
|
|
</div>
|
|
<div class="scale-item">
|
|
<strong>48px</strong>
|
|
<p class="small">Large break</p>
|
|
<div class="bar" style="height: 48px"></div>
|
|
</div>
|
|
<div class="scale-item">
|
|
<strong>64px</strong>
|
|
<p class="small">Major break</p>
|
|
<div class="bar" style="height: 64px"></div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="d02" class="section">
|
|
<div class="section-head">
|
|
<div class="section-copy">
|
|
<h2>D02 Page, Card und Grid Padding</h2>
|
|
<p class="section-desc">
|
|
Lila Flaechen zeigen Innenabstand. Das ist der Abstand zwischen
|
|
dem Rand eines Containers und seinem Inhalt. Tuerkise Flaechen
|
|
zeigen Gap: Abstand zwischen getrennten Elementen.
|
|
</p>
|
|
<div class="legend">
|
|
<span class="legend-item">
|
|
<span class="legend-dot padding"></span>
|
|
Padding / Innenabstand
|
|
</span>
|
|
<span class="legend-item">
|
|
<span class="legend-dot gap"></span>
|
|
Gap / Abstand zwischen Elementen
|
|
</span>
|
|
<span class="legend-item">
|
|
<span class="legend-dot content"></span>
|
|
Inhalt / Content
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="decision-panel">
|
|
<div>
|
|
<span class="decision-tag">Entscheidung D02</span>
|
|
</div>
|
|
<div>
|
|
<p class="decision-kicker">Was du festlegst</p>
|
|
<h3>Wie viel Abstand bekommen Page-Container, Cards/Surfaces und Card-/Grid-Abstaende?</h3>
|
|
<p>
|
|
Diese Entscheidung bestimmt, ob HiveGrid eher kompakt, neutral
|
|
oder luftig wirkt. Es geht um sichtbare Layout-Standards, aber
|
|
Komponenten-Defaults bleiben fuehrend, wenn sie das Padding
|
|
bereits korrekt mitbringen.
|
|
</p>
|
|
</div>
|
|
<div class="decision-options">
|
|
<div class="decision-option">
|
|
<strong>Kompakt</strong>
|
|
<span>Page bleibt 24px min, Card 16px, Grid Gap 12px. Nur fuer enge Teilbereiche.</span>
|
|
</div>
|
|
<div class="decision-option recommended">
|
|
<strong>Entschieden: Admin Standard</strong>
|
|
<span>Page 24px, Card 16px, Grid Gap 16px. Gilt fuer Standard Desktop und kompakte Settings.</span>
|
|
</div>
|
|
<div class="decision-option">
|
|
<strong>Dialog-Variante</strong>
|
|
<span>32px ist kein freier Surface-Standard, aber als eigene Dialog-Variante erlaubt.</span>
|
|
</div>
|
|
</div>
|
|
<div class="decision-question">
|
|
Entschieden: Page Padding ist immer mindestens 24px.
|
|
Card/Surface Padding bleibt 16px. Grid/Card Gap ist standardmaessig
|
|
16px und kann in kompakten Teilbereichen auf 12px reduziert werden.
|
|
Grosse Detail-/Editorflaechen starten ebenfalls mit 16px; 32px ist
|
|
nur ueber die eigene Dialog-Variante erlaubt.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="reference-strip">
|
|
<div class="reference-card">
|
|
<strong>Carbon-Orientierung</strong>
|
|
<ul>
|
|
<li>Carbon arbeitet mit einer kontrollierten Spacing Scale.</li>
|
|
<li>8px ist die zentrale Rhythmik, 16px kommt sehr haeufig vor.</li>
|
|
<li>Layout-Abstaende und Komponenten-Innenabstaende werden getrennt betrachtet.</li>
|
|
</ul>
|
|
</div>
|
|
<div class="ownership-note">
|
|
<strong>HiveGrid-Regel fuer Subframe</strong>
|
|
<p>
|
|
Die Werte unten sind Zielwerte fuer das sichtbare Layout. Wenn
|
|
Dialog, Card, Table, Button oder Input das passende Padding schon
|
|
intern haben, wird dieses Komponenten-Padding genutzt und nicht
|
|
manuell nachgebaut.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="concept-list">
|
|
<div class="concept-row">
|
|
<strong>App Shell</strong>
|
|
<p class="muted">
|
|
Navigation, Sidebar, Topbar und der aeussere Content-Viewport.
|
|
Die App Shell hat nicht einfach einen Page Gap; sie stellt den
|
|
Bereich bereit, in dem die Seite liegt.
|
|
</p>
|
|
</div>
|
|
<div class="concept-row">
|
|
<strong>Page Padding</strong>
|
|
<p class="muted">
|
|
Innenabstand innerhalb des Page-Contents nach der App Shell.
|
|
Dieser Abstand verhindert, dass Inhalt direkt am Shell-Rand oder
|
|
Browserrand klebt.
|
|
</p>
|
|
</div>
|
|
<div class="concept-row">
|
|
<strong>Section / Grid Gap</strong>
|
|
<p class="muted">
|
|
Abstand zwischen getrennten Bereichen, Sections, Karten oder
|
|
Spalten. Das ist kein aeusserer Seitenrand.
|
|
</p>
|
|
</div>
|
|
<div class="concept-row">
|
|
<strong>Schmaler Screen</strong>
|
|
<p class="muted">
|
|
Wenn der verfuegbare Content-Bereich kleiner wird, bleibt der
|
|
Desktop-/Settings-Mindestabstand erstmal bei 24px. Danach muessen
|
|
Layouts umbrechen, stacken oder horizontal scrollen.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="compare-block">
|
|
<div class="compare-head">
|
|
<h3>Vergleich 1: Page Padding</h3>
|
|
<p class="muted">
|
|
Das ist der Abstand vom Page-Content-Rand nach innen. Die App
|
|
Shell selbst ist hier nicht gemeint.
|
|
</p>
|
|
</div>
|
|
<div class="compare-grid">
|
|
<div class="compare-card">
|
|
<div class="compare-title">
|
|
<strong>16px</strong>
|
|
<span class="small">Sonderfall kompakt</span>
|
|
</div>
|
|
<div class="mini-page" style="--sample-page-pad: 16px">
|
|
<span class="measure-tag">16px</span>
|
|
<div class="mini-page-content">
|
|
<div class="mock-line short"></div>
|
|
<div class="mock-line medium"></div>
|
|
<div class="mock-line"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="compare-card recommended">
|
|
<div class="compare-title">
|
|
<strong>24px</strong>
|
|
<span class="small">Empfohlen fuer Admin</span>
|
|
</div>
|
|
<div class="mini-page" style="--sample-page-pad: 24px">
|
|
<span class="measure-tag">24px</span>
|
|
<div class="mini-page-content">
|
|
<div class="mock-line short"></div>
|
|
<div class="mock-line medium"></div>
|
|
<div class="mock-line"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="compare-card">
|
|
<div class="compare-title">
|
|
<strong>32px</strong>
|
|
<span class="small">Ruhigere Flaechen</span>
|
|
</div>
|
|
<div class="mini-page" style="--sample-page-pad: 32px">
|
|
<span class="measure-tag">32px</span>
|
|
<div class="mini-page-content">
|
|
<div class="mock-line short"></div>
|
|
<div class="mock-line medium"></div>
|
|
<div class="mock-line"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="compare-block">
|
|
<div class="compare-head">
|
|
<h3>Vergleich 2: Card / Surface Padding</h3>
|
|
<p class="muted">
|
|
Das ist Innenabstand innerhalb von Cards, Panels oder
|
|
groesseren Surface-Bereichen.
|
|
</p>
|
|
</div>
|
|
<div class="compare-grid">
|
|
<div class="compare-card recommended">
|
|
<div class="compare-title">
|
|
<strong>16px</strong>
|
|
<span class="small">Kompakte Cards</span>
|
|
</div>
|
|
<div class="mini-card" style="--sample-card-pad: 16px">
|
|
<span class="measure-tag">16px</span>
|
|
<div class="mini-card-content">
|
|
<div class="mock-line short"></div>
|
|
<div class="mock-line medium"></div>
|
|
<div class="mock-line"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="compare-card">
|
|
<div class="compare-title">
|
|
<strong>24px</strong>
|
|
<span class="small">Standard Cards</span>
|
|
</div>
|
|
<div class="mini-card" style="--sample-card-pad: 24px">
|
|
<span class="measure-tag">24px</span>
|
|
<div class="mini-card-content">
|
|
<div class="mock-line short"></div>
|
|
<div class="mock-line medium"></div>
|
|
<div class="mock-line"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="compare-card">
|
|
<div class="compare-title">
|
|
<strong>32px</strong>
|
|
<span class="small">Editor / Detail</span>
|
|
</div>
|
|
<div class="mini-card" style="--sample-card-pad: 32px">
|
|
<span class="measure-tag">32px</span>
|
|
<div class="mini-card-content">
|
|
<div class="mock-line short"></div>
|
|
<div class="mock-line medium"></div>
|
|
<div class="mock-line"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="compare-block">
|
|
<div class="compare-head">
|
|
<h3>Vergleich 3: Grid / Card Gap</h3>
|
|
<p class="muted">
|
|
Das ist der Abstand zwischen Karten, Spalten oder
|
|
zusammengehoerigen Layout-Bloecken.
|
|
</p>
|
|
</div>
|
|
<div class="compare-grid">
|
|
<div class="compare-card">
|
|
<div class="compare-title">
|
|
<strong>12px</strong>
|
|
<span class="small">Sehr dicht</span>
|
|
</div>
|
|
<div class="mini-gap-frame" style="--sample-gap: 12px">
|
|
<div class="mini-gap-item">Card A</div>
|
|
<div class="mini-gap-item">Card B</div>
|
|
<div class="mini-gap-item">Card C</div>
|
|
</div>
|
|
</div>
|
|
<div class="compare-card recommended">
|
|
<div class="compare-title">
|
|
<strong>16px</strong>
|
|
<span class="small">Empfohlen</span>
|
|
</div>
|
|
<div class="mini-gap-frame" style="--sample-gap: 16px">
|
|
<div class="mini-gap-item">Card A</div>
|
|
<div class="mini-gap-item">Card B</div>
|
|
<div class="mini-gap-item">Card C</div>
|
|
</div>
|
|
</div>
|
|
<div class="compare-card">
|
|
<div class="compare-title">
|
|
<strong>24px</strong>
|
|
<span class="small">Getrennte Bereiche</span>
|
|
</div>
|
|
<div class="mini-gap-frame" style="--sample-gap: 24px">
|
|
<div class="mini-gap-item">Card A</div>
|
|
<div class="mini-gap-item">Card B</div>
|
|
<div class="mini-gap-item">Card C</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d02-preview-grid">
|
|
<div class="layout-case">
|
|
<div class="layout-case-head">
|
|
<h3>Standard Desktop Page</h3>
|
|
<span class="small">Normale App-/Admin-Seite</span>
|
|
</div>
|
|
<div class="layout-frame">
|
|
<span class="measure-tag">Page 24px</span>
|
|
<div class="layout-content-shell">
|
|
<div class="mock-header">
|
|
<div class="mock-title"></div>
|
|
<div class="mock-copy"></div>
|
|
</div>
|
|
<div class="mock-grid">
|
|
<div class="mock-card">
|
|
<span class="measure-tag">Card 16px</span>
|
|
<div class="mock-card-inner">
|
|
<div class="mock-line short"></div>
|
|
<div class="mock-line medium"></div>
|
|
<div class="mock-line"></div>
|
|
</div>
|
|
</div>
|
|
<div class="mock-card">
|
|
<span class="measure-tag">Card 16px</span>
|
|
<div class="mock-card-inner">
|
|
<div class="mock-line short"></div>
|
|
<div class="mock-line medium"></div>
|
|
<div class="mock-line"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="value-row">
|
|
<span class="value-chip">Page padding 24px</span>
|
|
<span class="value-chip">Card padding 16px</span>
|
|
<span class="value-chip">Card gap 16px</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="layout-case">
|
|
<div class="layout-case-head">
|
|
<h3>Kompakte Settings Page</h3>
|
|
<span class="small">Settings, Admin-Listen, dichter Kontext</span>
|
|
</div>
|
|
<div class="layout-frame compact">
|
|
<span class="measure-tag">Page 24px</span>
|
|
<div class="layout-content-shell">
|
|
<div class="mock-header">
|
|
<div class="mock-title"></div>
|
|
<div class="mock-copy"></div>
|
|
</div>
|
|
<div class="mock-grid single">
|
|
<div class="mock-card">
|
|
<span class="measure-tag">Card 16px</span>
|
|
<div class="mock-card-inner">
|
|
<div class="mock-line short"></div>
|
|
<div class="mock-line medium"></div>
|
|
<div class="mock-line"></div>
|
|
</div>
|
|
</div>
|
|
<div class="mock-card">
|
|
<span class="measure-tag">Card 16px</span>
|
|
<div class="mock-card-inner">
|
|
<div class="mock-line short"></div>
|
|
<div class="mock-line medium"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="value-row">
|
|
<span class="value-chip">Page padding 24px</span>
|
|
<span class="value-chip">Compact card 16px</span>
|
|
<span class="value-chip">Gap 16px</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="layout-case open">
|
|
<div class="layout-case-head">
|
|
<h3>Dialog-Variante: grosse Detail-/Editor-Flaeche</h3>
|
|
<span class="small">Nur ueber Dialog-Komponente</span>
|
|
</div>
|
|
<div class="layout-frame editor">
|
|
<span class="measure-tag">Dialog 32px</span>
|
|
<div class="layout-content-shell">
|
|
<div class="mock-header">
|
|
<div class="mock-title"></div>
|
|
<div class="mock-copy"></div>
|
|
</div>
|
|
<div class="mock-grid single">
|
|
<div class="mock-card">
|
|
<span class="measure-tag">Surface 32px</span>
|
|
<div class="mock-card-inner">
|
|
<div class="mock-line short"></div>
|
|
<div class="mock-line medium"></div>
|
|
<div class="mock-line"></div>
|
|
<div class="mock-line medium"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="value-row">
|
|
<span class="value-chip">Dialog spacious</span>
|
|
<span class="value-chip">32px nur als Dialog-Variante</span>
|
|
<span class="value-chip">D02 final bleibt 16px</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="definition-grid">
|
|
<div class="term-list">
|
|
<div class="term">
|
|
<strong>Padding</strong>
|
|
<p class="muted">
|
|
Fachlich: Innenabstand. Er liegt innerhalb einer Flaeche,
|
|
Karte, Surface oder eines Containers. Padding sorgt dafuer,
|
|
dass Inhalt nicht direkt am Rand klebt.
|
|
</p>
|
|
</div>
|
|
<div class="term">
|
|
<strong>Gap</strong>
|
|
<p class="muted">
|
|
Fachlich: Zwischenraum in einem Layout. Gap liegt zwischen
|
|
mehreren Elementen, zum Beispiel zwischen zwei Karten oder
|
|
zwischen Formularfeldern.
|
|
</p>
|
|
</div>
|
|
<div class="term">
|
|
<strong>Margin</strong>
|
|
<p class="muted">
|
|
Fachlich: Aussenabstand. Margin schiebt ein Element von anderen
|
|
Bereichen weg. In unserem Layout-Lab nutzen wir meistens Gap,
|
|
weil es in Auto Layout besser kontrollierbar ist.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="padding-showcase">
|
|
<div>
|
|
<div class="sample-title">
|
|
<strong>Page Padding</strong>
|
|
<span class="small">Benutzt am aeusseren Seitenrand.</span>
|
|
</div>
|
|
<div class="padding-sample" style="--pad: 24px">
|
|
<span class="measure-tag">24px</span>
|
|
<div class="padding-content">
|
|
<strong>Page content</strong>
|
|
<p class="muted">
|
|
Der Inhalt beginnt nicht direkt am Browser-/Shell-Rand,
|
|
sondern nach dem Page Padding.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<div class="sample-title">
|
|
<strong>Card / Surface Padding</strong>
|
|
<span class="small">Benutzt in Karten, Panels und Surfaces.</span>
|
|
</div>
|
|
<div class="padding-sample" style="--pad: 16px">
|
|
<span class="measure-tag">16px</span>
|
|
<div class="padding-content">
|
|
<strong>Card / surface content</strong>
|
|
<p class="muted">
|
|
Text, Aktionen oder Formularfelder haben Luft zum Rand.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<div class="sample-title">
|
|
<strong>Grid / Card Gap</strong>
|
|
<span class="small">Kein Padding: Abstand zwischen Karten.</span>
|
|
</div>
|
|
<div class="gap-sample" style="--gap: 16px">
|
|
<div class="gap-item">Card 1</div>
|
|
<div class="gap-item">Card 2</div>
|
|
<div class="gap-item">Card 3</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="d03" class="section">
|
|
<div class="section-head">
|
|
<div class="section-copy">
|
|
<h2>D03 Text-Rhythmus</h2>
|
|
<p class="section-desc">
|
|
Text-Rhythmus meint vertikale Abstaende zwischen Textbloecken:
|
|
zum Beispiel Page Title, Beschreibung und erstem Content. Die
|
|
Beispiele nutzen echte Text-Tokens, weil Line-height die sichtbare
|
|
Hoehe eines Textblocks veraendert.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="decision-panel">
|
|
<div>
|
|
<span class="decision-tag">Entscheidung D03</span>
|
|
</div>
|
|
<div>
|
|
<p class="decision-kicker">Was du festlegst</p>
|
|
<h3>Wie eng stehen Textbloecke und der erste Inhalt zusammen?</h3>
|
|
<p>
|
|
D03 ist validiert. Die Regel betrifft die vertikalen Gaps
|
|
zwischen gerenderten Textbloecken und Inhalt. Beschreibende
|
|
Page- und Section-Texte muessen 150%-Texttokens nutzen, weil
|
|
die Line-height die optische Hoehe des Blocks beeinflusst.
|
|
</p>
|
|
<div class="rhythm-legend">
|
|
<span class="value-chip">Title -> Description</span>
|
|
<span class="value-chip">Header -> First content</span>
|
|
<span class="value-chip">Section title -> Section description</span>
|
|
<span class="value-chip">Description -> Section content</span>
|
|
<span class="value-chip">Tokens: Heading / Body 150</span>
|
|
</div>
|
|
</div>
|
|
<div class="decision-options">
|
|
<div class="decision-option">
|
|
<strong>Sehr kompakt</strong>
|
|
<span>0px / 16px / 0px / 8px. Sehr dicht, nur fuer stark verdichtete Teilbereiche.</span>
|
|
</div>
|
|
<div class="decision-option recommended">
|
|
<strong>Token-aware Standard</strong>
|
|
<span>0px / 24px / 0px / 12px. Finaler Vorschlag mit 150%-Texttokens.</span>
|
|
</div>
|
|
<div class="decision-option">
|
|
<strong>Luftig</strong>
|
|
<span>0px / 32px / 0px / 16px. Ruhiger, aber nimmt in Settings mehr Platz weg.</span>
|
|
</div>
|
|
</div>
|
|
<div class="decision-question">
|
|
Validiert: D03 nutzt 0px zwischen Titel und Beschreibung, 24px bis
|
|
zum ersten Content, 0px zwischen Section Title und Beschreibung
|
|
sowie 12px zwischen Section Beschreibung und Inhalt. Page-/Section-
|
|
Beschreibungen muessen dafuer 150%-Texttokens nutzen.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="rhythm-comparison">
|
|
<div
|
|
class="rhythm-sample"
|
|
style="--title-desc-gap: 0px; --header-content-gap: 16px; --section-title-desc-gap: 0px; --section-content-gap: 8px"
|
|
>
|
|
<div class="rhythm-sample-head">
|
|
<div class="rhythm-sample-title">
|
|
<strong>Option A: Sehr kompakt</strong>
|
|
<span class="small">Dicht, scanbar, wenig Ruhe.</span>
|
|
</div>
|
|
<span class="value-chip">A</span>
|
|
</div>
|
|
<div class="rhythm-page-header-preview">
|
|
<span class="rhythm-eyebrow">Settings</span>
|
|
<h3 class="rhythm-title">Mitarbeiter</h3>
|
|
<div class="gap-marker vertical zero" style="--gap-size: var(--title-desc-gap)" data-label="Title -> Desc" data-size="0px"></div>
|
|
<p class="rhythm-desc">
|
|
Verwalte Einladungen, Rollen und Status fuer alle Personen im
|
|
Workspace.
|
|
</p>
|
|
<div class="gap-marker vertical" style="--gap-size: var(--header-content-gap)" data-label="Header -> Content" data-size="16px"></div>
|
|
</div>
|
|
<div class="rhythm-section-preview">
|
|
<h4 class="rhythm-section-title">Aktive Mitarbeiter</h4>
|
|
<div class="gap-marker vertical zero" style="--gap-size: var(--section-title-desc-gap)" data-label="Section -> Desc" data-size="0px"></div>
|
|
<p class="rhythm-desc">
|
|
Die Liste zeigt eingeladene und aktive Nutzer.
|
|
</p>
|
|
<div class="gap-marker vertical" style="--gap-size: var(--section-content-gap)" data-label="Desc -> Content" data-size="8px"></div>
|
|
<div class="rhythm-content-preview">
|
|
<div class="rhythm-card-row">
|
|
<div class="rhythm-mini-card">
|
|
<strong>12 aktiv</strong>
|
|
<div class="rhythm-line"></div>
|
|
<div class="rhythm-line short"></div>
|
|
</div>
|
|
<div class="rhythm-mini-card">
|
|
<strong>3 offen</strong>
|
|
<div class="rhythm-line"></div>
|
|
<div class="rhythm-line short"></div>
|
|
</div>
|
|
</div>
|
|
<div class="rhythm-list" style="margin-top: 12px">
|
|
<div class="rhythm-list-row">
|
|
<span class="rhythm-dot"></span>
|
|
<span class="rhythm-line"></span>
|
|
<span class="rhythm-pill"></span>
|
|
</div>
|
|
<div class="rhythm-list-row">
|
|
<span class="rhythm-dot"></span>
|
|
<span class="rhythm-line"></span>
|
|
<span class="rhythm-pill"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="rhythm-sample recommended"
|
|
style="--title-desc-gap: 0px; --header-content-gap: 24px; --section-title-desc-gap: 0px; --section-content-gap: 12px"
|
|
>
|
|
<div class="rhythm-sample-head">
|
|
<div class="rhythm-sample-title">
|
|
<strong>Option B: Token-aware Standard</strong>
|
|
<span class="small">Finaler Arbeitsstandard mit 150%-Texttokens.</span>
|
|
</div>
|
|
<span class="value-chip">B</span>
|
|
</div>
|
|
<div class="rhythm-page-header-preview">
|
|
<span class="rhythm-eyebrow">Settings</span>
|
|
<h3 class="rhythm-title">Mitarbeiter</h3>
|
|
<div class="gap-marker vertical zero" style="--gap-size: var(--title-desc-gap)" data-label="Title -> Desc" data-size="0px"></div>
|
|
<p class="rhythm-desc">
|
|
Verwalte Einladungen, Rollen und Status fuer alle Personen im
|
|
Workspace.
|
|
</p>
|
|
<div class="gap-marker vertical" style="--gap-size: var(--header-content-gap)" data-label="Header -> Content" data-size="24px"></div>
|
|
</div>
|
|
<div class="rhythm-section-preview">
|
|
<h4 class="rhythm-section-title">Aktive Mitarbeiter</h4>
|
|
<div class="gap-marker vertical zero" style="--gap-size: var(--section-title-desc-gap)" data-label="Section -> Desc" data-size="0px"></div>
|
|
<p class="rhythm-desc">
|
|
Die Liste zeigt eingeladene und aktive Nutzer.
|
|
</p>
|
|
<div class="gap-marker vertical" style="--gap-size: var(--section-content-gap)" data-label="Desc -> Content" data-size="12px"></div>
|
|
<div class="rhythm-content-preview">
|
|
<div class="rhythm-card-row">
|
|
<div class="rhythm-mini-card">
|
|
<strong>12 aktiv</strong>
|
|
<div class="rhythm-line"></div>
|
|
<div class="rhythm-line short"></div>
|
|
</div>
|
|
<div class="rhythm-mini-card">
|
|
<strong>3 offen</strong>
|
|
<div class="rhythm-line"></div>
|
|
<div class="rhythm-line short"></div>
|
|
</div>
|
|
</div>
|
|
<div class="rhythm-list" style="margin-top: 12px">
|
|
<div class="rhythm-list-row">
|
|
<span class="rhythm-dot"></span>
|
|
<span class="rhythm-line"></span>
|
|
<span class="rhythm-pill"></span>
|
|
</div>
|
|
<div class="rhythm-list-row">
|
|
<span class="rhythm-dot"></span>
|
|
<span class="rhythm-line"></span>
|
|
<span class="rhythm-pill"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="rhythm-sample"
|
|
style="--title-desc-gap: 0px; --header-content-gap: 32px; --section-title-desc-gap: 0px; --section-content-gap: 16px"
|
|
>
|
|
<div class="rhythm-sample-head">
|
|
<div class="rhythm-sample-title">
|
|
<strong>Option C: Luftig</strong>
|
|
<span class="small">Ruhiger, aber weniger dicht.</span>
|
|
</div>
|
|
<span class="value-chip">C</span>
|
|
</div>
|
|
<div class="rhythm-page-header-preview">
|
|
<span class="rhythm-eyebrow">Settings</span>
|
|
<h3 class="rhythm-title">Mitarbeiter</h3>
|
|
<div class="gap-marker vertical zero" style="--gap-size: var(--title-desc-gap)" data-label="Title -> Desc" data-size="0px"></div>
|
|
<p class="rhythm-desc">
|
|
Verwalte Einladungen, Rollen und Status fuer alle Personen im
|
|
Workspace.
|
|
</p>
|
|
<div class="gap-marker vertical" style="--gap-size: var(--header-content-gap)" data-label="Header -> Content" data-size="32px"></div>
|
|
</div>
|
|
<div class="rhythm-section-preview">
|
|
<h4 class="rhythm-section-title">Aktive Mitarbeiter</h4>
|
|
<div class="gap-marker vertical zero" style="--gap-size: var(--section-title-desc-gap)" data-label="Section -> Desc" data-size="0px"></div>
|
|
<p class="rhythm-desc">
|
|
Die Liste zeigt eingeladene und aktive Nutzer.
|
|
</p>
|
|
<div class="gap-marker vertical" style="--gap-size: var(--section-content-gap)" data-label="Desc -> Content" data-size="16px"></div>
|
|
<div class="rhythm-content-preview">
|
|
<div class="rhythm-card-row">
|
|
<div class="rhythm-mini-card">
|
|
<strong>12 aktiv</strong>
|
|
<div class="rhythm-line"></div>
|
|
<div class="rhythm-line short"></div>
|
|
</div>
|
|
<div class="rhythm-mini-card">
|
|
<strong>3 offen</strong>
|
|
<div class="rhythm-line"></div>
|
|
<div class="rhythm-line short"></div>
|
|
</div>
|
|
</div>
|
|
<div class="rhythm-list" style="margin-top: 12px">
|
|
<div class="rhythm-list-row">
|
|
<span class="rhythm-dot"></span>
|
|
<span class="rhythm-line"></span>
|
|
<span class="rhythm-pill"></span>
|
|
</div>
|
|
<div class="rhythm-list-row">
|
|
<span class="rhythm-dot"></span>
|
|
<span class="rhythm-line"></span>
|
|
<span class="rhythm-pill"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="rhythm-detail-grid">
|
|
<div class="rhythm-detail-card">
|
|
<p class="decision-kicker">Was D03 regelt</p>
|
|
<h3>Page- und Section-Textbloecke</h3>
|
|
<p class="muted">
|
|
D03 entscheidet die Gaps zwischen Text und Inhalt, damit Screens
|
|
gleich getaktet wirken. Die Inputs, Buttons, Tabellen und Cards
|
|
behalten ihre eigenen Komponentenabstaende.
|
|
</p>
|
|
<div class="rhythm-metric-list">
|
|
<div class="rhythm-metric">
|
|
<span>Page Title zu Beschreibung</span>
|
|
<strong>0px definiert</strong>
|
|
</div>
|
|
<div class="rhythm-metric">
|
|
<span>Page Header zu erstem Content</span>
|
|
<strong>24px</strong>
|
|
</div>
|
|
<div class="rhythm-metric">
|
|
<span>Section Title zu Beschreibung</span>
|
|
<strong>0px definiert</strong>
|
|
</div>
|
|
<div class="rhythm-metric">
|
|
<span>Section Beschreibung zu Inhalt</span>
|
|
<strong>12px</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="rhythm-detail-card">
|
|
<p class="decision-kicker">Nicht Teil von D03</p>
|
|
<h3>Keine Typography- oder Komponentenentscheidung</h3>
|
|
<p class="muted">
|
|
Textgroessen, 150%-Line-height bei mehrzeiligem Text,
|
|
Input-Label-Abstaende, Tabellenzeilen und Button-Hoehen bleiben
|
|
in den jeweiligen Tokens oder Komponenten. D03 soll nur klaeren,
|
|
wie Page-/Section-Text gegen den Content rhythmisiert wird.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="token-impact">
|
|
<div class="token-impact-card warning">
|
|
<div>
|
|
<p class="decision-kicker">Wrap-Risiko</p>
|
|
<h3>`body-default-regular-0`</h3>
|
|
<p class="small">16px Text / 17px Line-height. Gut fuer echte Einzeiler, aber eng sobald Text umbricht.</p>
|
|
</div>
|
|
<div class="token-text-box tight">
|
|
Verwalte Einladungen, Rollen und Status fuer alle Personen im Workspace.
|
|
</div>
|
|
</div>
|
|
<div class="token-impact-card recommended">
|
|
<div>
|
|
<p class="decision-kicker">Wrap-sicher</p>
|
|
<h3>`body-default-regular-150`</h3>
|
|
<p class="small">16px Text / 24px Line-height. Besser fuer Texte, die ein- oder mehrzeilig sein koennen.</p>
|
|
</div>
|
|
<div class="token-text-box readable">
|
|
Verwalte Einladungen, Rollen und Status fuer alle Personen im Workspace.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="token-rule-panel">
|
|
<p class="decision-kicker">Regel-Kandidat fuer Text-Wrapping</p>
|
|
<h3>Wenn Text umbrechen kann, nutzt er einen 150%-Token.</h3>
|
|
<p>
|
|
D03 nutzt bewusst 0px zwischen Titel und Beschreibung, weil der
|
|
150%-Texttoken bereits genug optische Hoehe im Textblock erzeugt.
|
|
Diese 0px sind ein definierter Auto-Layout-Gap und kein fehlender
|
|
Abstand. Wenn ein Description-Text von einer auf zwei Zeilen
|
|
springt, wird nur der Textblock hoeher. Der Gap zum naechsten
|
|
Content bleibt 24px im Page Header oder 12px in Sections.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="d04" class="section">
|
|
<div class="section-head">
|
|
<div class="section-copy">
|
|
<h2>D04 Button Component Ownership</h2>
|
|
<p class="section-desc">
|
|
Button-Hoehen, Innenpadding und Varianten werden durch die
|
|
Button-Komponente abgedeckt, nicht durch Screen-Layout-Regeln.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="decision-panel">
|
|
<div>
|
|
<span class="decision-tag">Komponenten-Ownership</span>
|
|
</div>
|
|
<div>
|
|
<p class="decision-kicker">Was fuer Screens gilt</p>
|
|
<h3>Standardaktionen nutzen die Default-Variante der Button-Komponente.</h3>
|
|
<p>
|
|
Die Default-Variante ist `Medium` und 36px hoch. Screen-Prompts
|
|
sollen Button-Hoehen oder Button-Padding nicht manuell nachbauen.
|
|
</p>
|
|
</div>
|
|
<div class="decision-options">
|
|
<div class="decision-option">
|
|
<strong>Small</strong>
|
|
<span>32px. Kommt aus der Komponente und wird nur genutzt, wenn der Kontext klein/dicht ist.</span>
|
|
</div>
|
|
<div class="decision-option recommended">
|
|
<strong>Medium / Default</strong>
|
|
<span>36px. Standard fuer normale lokale Aktionen in Screens.</span>
|
|
</div>
|
|
<div class="decision-option">
|
|
<strong>Large</strong>
|
|
<span>48px. Kommt aus der Komponente und wird nur bewusst eingesetzt.</span>
|
|
</div>
|
|
</div>
|
|
<div class="decision-question">
|
|
Keine eigene D04-Layoutentscheidung: Button Default/Medium 36px fuer Standardaktionen verwenden.
|
|
</div>
|
|
</div>
|
|
<div class="grid three">
|
|
<div class="card">
|
|
<h3>Small, 32px high</h3>
|
|
<div class="button-row">
|
|
<span class="button sm">Save</span>
|
|
<span class="button sm secondary">Cancel</span>
|
|
<span class="button sm ghost">More</span>
|
|
</div>
|
|
</div>
|
|
<div class="card">
|
|
<h3>Medium / Default, 36px high</h3>
|
|
<div class="button-row">
|
|
<span class="button">Save changes</span>
|
|
<span class="button secondary">Cancel</span>
|
|
</div>
|
|
</div>
|
|
<div class="card">
|
|
<h3>Large, 48px high</h3>
|
|
<div class="button-row">
|
|
<span class="button lg">Create workspace</span>
|
|
<span class="button lg danger">Delete</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="d05" class="section">
|
|
<div class="section-head">
|
|
<div class="section-copy">
|
|
<h2>D05 Form Layout Gap</h2>
|
|
<p class="section-desc">
|
|
Formular-Layout meint hier nur den Abstand zwischen kompletten
|
|
Field-Komponenten. Label, Beschreibung, Control und Message
|
|
gehoeren zur jeweiligen Form-Input-Komponente.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="decision-panel">
|
|
<div>
|
|
<span class="decision-tag">Entscheidung D05</span>
|
|
</div>
|
|
<div>
|
|
<p class="decision-kicker">Was du festlegst</p>
|
|
<h3>Wie dicht stehen komplette Formularfelder bzw. Field-Komponenten?</h3>
|
|
<p>
|
|
Validiert: komplette Field-Komponenten stehen standardmaessig
|
|
16px auseinander. Beschreibung/Help/Error wird innerhalb der
|
|
Komponente ueber deren Props/Slots gepflegt.
|
|
</p>
|
|
</div>
|
|
<div class="decision-options">
|
|
<div class="decision-option">
|
|
<strong>Kompakter Sonderfall</strong>
|
|
<span>12px nur fuer sehr dichte Teilbereiche, nicht als Formularstandard.</span>
|
|
</div>
|
|
<div class="decision-option recommended">
|
|
<strong>Standard</strong>
|
|
<span>16px zwischen kompletten Field-Komponenten.</span>
|
|
</div>
|
|
<div class="decision-option">
|
|
<strong>Luftig</strong>
|
|
<span>24px nur fuer bewusst getrennte Formular-Sections.</span>
|
|
</div>
|
|
</div>
|
|
<div class="decision-question">
|
|
Entschieden: Form Field Gap 16px. Field-Anatomy selbst kommt aus der jeweiligen Komponente.
|
|
</div>
|
|
</div>
|
|
<div class="grid two">
|
|
<div class="card">
|
|
<h3>Standard form density</h3>
|
|
<form class="form">
|
|
<div class="field">
|
|
<label for="name">Workspace name</label>
|
|
<input id="name" value="HiveGrid Demo" />
|
|
<p class="help">Visible to all members in this workspace.</p>
|
|
</div>
|
|
<div class="field">
|
|
<label for="slug">URL shortcut</label>
|
|
<input id="slug" value="hivegrid-demo" />
|
|
</div>
|
|
<div class="field">
|
|
<label for="desc">Description</label>
|
|
<textarea id="desc">Internal demo workspace for layout review.</textarea>
|
|
<p class="error">Use at least 12 characters.</p>
|
|
</div>
|
|
<div class="button-row">
|
|
<span class="button">Save</span>
|
|
<span class="button secondary">Cancel</span>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="card">
|
|
<h3>Compact form density</h3>
|
|
<form class="form" style="gap: 16px">
|
|
<div class="field">
|
|
<label for="first">First name</label>
|
|
<input id="first" value="David" />
|
|
</div>
|
|
<div class="field">
|
|
<label for="last">Last name</label>
|
|
<input id="last" value="Bertram" />
|
|
</div>
|
|
<div class="field">
|
|
<label for="department">Department</label>
|
|
<select id="department">
|
|
<option>Operations</option>
|
|
<option>Sales</option>
|
|
<option>Admin</option>
|
|
</select>
|
|
</div>
|
|
<div class="button-row">
|
|
<span class="button">Update profile</span>
|
|
<span class="button secondary">Reset</span>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="d06" class="section">
|
|
<div class="section-head">
|
|
<div class="section-copy">
|
|
<h2>D06 Table Component Ownership</h2>
|
|
<p class="section-desc">
|
|
Tabellen-Row-Height, Cell Padding und Header-Dichte gehoeren zur
|
|
Table-Komponente. D-D0b dokumentiert nur die Referenzlogik fuer
|
|
Screen-Prompts.
|
|
</p>
|
|
</div>
|
|
<div class="toolbar">
|
|
<input style="width: 260px" value="Search employees" />
|
|
<span class="button secondary">Filter</span>
|
|
<span class="button">Invite</span>
|
|
</div>
|
|
</div>
|
|
<div class="decision-panel">
|
|
<div>
|
|
<span class="decision-tag">Komponenten-Ownership</span>
|
|
</div>
|
|
<div>
|
|
<p class="decision-kicker">Carbon-Referenz</p>
|
|
<h3>Die Table-Komponente fuehrt die Dichte; Screens bauen keine Tabellen-Paddings manuell.</h3>
|
|
<p>
|
|
IBM Carbon arbeitet bei Data Tables mit mehreren Row Sizes. Die
|
|
Werte sind xs 24px, sm 32px, md 40px, lg 48px und xl 64px.
|
|
Columns haben 16px Padding. Die Header Row soll zur
|
|
Tabellen-Row-Groesse passen; sehr grosse Rows sind fuer zwei
|
|
Inhaltszeilen gedacht.
|
|
</p>
|
|
</div>
|
|
<div class="decision-options">
|
|
<div class="decision-option">
|
|
<strong>Carbon kompakt</strong>
|
|
<span>XS/SM fuer sehr dichte Datenlisten, wenn die Table-Komponente das anbietet.</span>
|
|
</div>
|
|
<div class="decision-option recommended">
|
|
<strong>Carbon Standard</strong>
|
|
<span>MD/LG als normale Table-Dichte; Header, Row und Toolbar muessen zusammenpassen.</span>
|
|
</div>
|
|
<div class="decision-option">
|
|
<strong>Carbon gross</strong>
|
|
<span>XL nur, wenn zwei Zeilen Inhalt oder bewusst mehr Leseraum gebraucht wird.</span>
|
|
</div>
|
|
</div>
|
|
<div class="decision-question">
|
|
Keine eigene D06-Layoutentscheidung: Table-Komponente nutzen; Carbon als Referenz fuer passende Row-Size-Systematik.
|
|
</div>
|
|
</div>
|
|
<div class="table-shell">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Role</th>
|
|
<th>Department</th>
|
|
<th>Status</th>
|
|
<th style="text-align: right">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>David Bertram</td>
|
|
<td>Admin</td>
|
|
<td>Operations</td>
|
|
<td><span class="pill">Active</span></td>
|
|
<td style="text-align: right">...</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Anna Keller</td>
|
|
<td>Finance Lead</td>
|
|
<td>Finance</td>
|
|
<td><span class="pill">Active</span></td>
|
|
<td style="text-align: right">...</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Max Hoffmann</td>
|
|
<td>Employee</td>
|
|
<td>Support</td>
|
|
<td><span class="pill warning">Pending</span></td>
|
|
<td style="text-align: right">...</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="d07" class="section">
|
|
<div class="section-head">
|
|
<div class="section-copy">
|
|
<h2>D07 Dialog Sizes</h2>
|
|
<p class="section-desc">
|
|
Validierte Breiten fuer zentrierte Dialoge und Fullscreen
|
|
Dialoge. In Subframe muessen diese Beispiele mit echten Dialog
|
|
Layouts gebaut werden.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="decision-panel">
|
|
<div>
|
|
<span class="decision-tag">Entscheidung D07</span>
|
|
</div>
|
|
<div>
|
|
<p class="decision-kicker">Was du festlegst</p>
|
|
<h3>Welche Breiten bekommen kleine, normale und grosse Dialoge?</h3>
|
|
<p>
|
|
Dialogbreite und Dialogpadding sind getrennte Entscheidungen. Die
|
|
Beispiele unten zeigen Breitenklassen und die zwei validierten
|
|
Dialog-Padding-Varianten.
|
|
</p>
|
|
</div>
|
|
<div class="decision-options">
|
|
<div class="decision-option">
|
|
<strong>XS / S</strong>
|
|
<span>XS 420px fuer kurze Bestaetigung, S 560px fuer kleine Formulare.</span>
|
|
</div>
|
|
<div class="decision-option recommended">
|
|
<strong>M / L</strong>
|
|
<span>M 720px fuer normale Formulare, L 1200px max fuer grosse Editor-Dialoge.</span>
|
|
</div>
|
|
<div class="decision-option">
|
|
<strong>Fullscreen</strong>
|
|
<span>Fill in Breite und Hoehe mit 24px aeusserem Rand, aber maximal 2512px breit.</span>
|
|
</div>
|
|
</div>
|
|
<div class="decision-question">
|
|
Entschieden: XS 420px, S 560px, M 720px, L 1200px max.
|
|
Fullscreen Dialog nutzt Fill mit 24px aeusserem Rand pro Seite und `max-width: 2512px`.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="pattern-grid">
|
|
<div class="pattern-card">
|
|
<div class="pattern-mini">
|
|
<div class="pattern-shell">
|
|
<div class="pattern-page-content"></div>
|
|
</div>
|
|
</div>
|
|
<strong>Page</strong>
|
|
<p class="small">Eigener App-Ort mit Navigation oder Subnavigation. Settings ist eine Page, kein Dialog.</p>
|
|
</div>
|
|
<div class="pattern-card">
|
|
<div class="pattern-mini">
|
|
<div class="pattern-shell">
|
|
<div class="pattern-page-content"></div>
|
|
</div>
|
|
<div class="pattern-overlay"></div>
|
|
<div class="pattern-dialog-box"></div>
|
|
</div>
|
|
<strong>Dialog</strong>
|
|
<p class="small">Temporäres Overlay ueber der Page. Blockiert den Hintergrund und wird wieder geschlossen.</p>
|
|
</div>
|
|
<div class="pattern-card">
|
|
<div class="pattern-mini">
|
|
<div class="pattern-shell">
|
|
<div class="pattern-page-content"></div>
|
|
</div>
|
|
<div class="pattern-overlay"></div>
|
|
<div class="pattern-fullscreen-box"></div>
|
|
</div>
|
|
<strong>Fullscreen Dialog</strong>
|
|
<p class="small">Fill in Breite und Hoehe mit aeusserem Rand und 2512px Maxbreite. Wird geschlossen und ist kein dauerhafter App-Bereich.</p>
|
|
</div>
|
|
<div class="pattern-card">
|
|
<div class="pattern-mini">
|
|
<div class="pattern-shell">
|
|
<div class="pattern-page-content"></div>
|
|
</div>
|
|
<div class="pattern-drawer-box"></div>
|
|
</div>
|
|
<strong>Drawer / Side Panel</strong>
|
|
<p class="small">Seitliche Bearbeitung, waehrend der Kontext sichtbar bleibt. Eigene Breitenregeln, nicht D07.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal-version-grid">
|
|
<div class="modal-version recommended">
|
|
<div class="modal-version-head">
|
|
<div>
|
|
<h3>Validierte zentrierte Dialoggroessen</h3>
|
|
<p class="small">Vier neutrale Groessen fuer Confirm, kleine Formulare, normale Formulare und grosse Editor-Dialoge.</p>
|
|
</div>
|
|
<span class="pill">Validiert</span>
|
|
</div>
|
|
<div class="modal-size-row four">
|
|
<div class="modal-size-card">
|
|
<div class="modal-size-label"><strong>XS</strong><span>420px</span></div>
|
|
<div class="modal-width-track"><div class="modal-width-block" style="--preview-pct: 35%">420</div></div>
|
|
</div>
|
|
<div class="modal-size-card">
|
|
<div class="modal-size-label"><strong>S</strong><span>560px</span></div>
|
|
<div class="modal-width-track"><div class="modal-width-block" style="--preview-pct: 47%">560</div></div>
|
|
</div>
|
|
<div class="modal-size-card">
|
|
<div class="modal-size-label"><strong>M</strong><span>720px</span></div>
|
|
<div class="modal-width-track"><div class="modal-width-block" style="--preview-pct: 60%">720</div></div>
|
|
</div>
|
|
<div class="modal-size-card">
|
|
<div class="modal-size-label"><strong>L</strong><span>1200px max</span></div>
|
|
<div class="modal-width-track"><div class="modal-width-block" style="--preview-pct: 100%">1200</div></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="viewport-behavior">
|
|
<div>
|
|
<h3>Verhalten auf breiten Monitoren</h3>
|
|
<p class="small">
|
|
Dialoge wachsen nicht automatisch mit 4K-Viewports mit. Die Breitenklasse bleibt fix,
|
|
der Dialog bleibt zentriert und der aeussere Overlay-Abstand wird groesser. Fullscreen Dialoge
|
|
nutzen `width: calc(100vw - 48px)`, aber hoechstens 2512px Breite.
|
|
</p>
|
|
</div>
|
|
<div class="viewport-row">
|
|
<strong>1440px</strong>
|
|
<div class="viewport-track"><div class="viewport-dialog" style="--dialog-ratio: 83%"></div></div>
|
|
<span class="small">1200px wirkt gross</span>
|
|
</div>
|
|
<div class="viewport-row">
|
|
<strong>2560px</strong>
|
|
<div class="viewport-track"><div class="viewport-dialog" style="--dialog-ratio: 47%"></div></div>
|
|
<span class="small">1200px bleibt fix</span>
|
|
</div>
|
|
<div class="viewport-row">
|
|
<strong>3840px</strong>
|
|
<div class="viewport-track"><div class="viewport-dialog" style="--dialog-ratio: 31%"></div></div>
|
|
<span class="small">mehr Rand, nicht breiter</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal-grid">
|
|
<div class="modal-demo modal-xs">
|
|
<div class="modal-header">
|
|
<h3>XS - 420px</h3>
|
|
<p class="small">Kurze Bestaetigung oder knapper Hinweis.</p>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>Mitarbeiter deaktivieren?</p>
|
|
<p class="small">Der Zugriff wird sofort gesperrt. Bestehende Daten bleiben erhalten.</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<span class="button secondary">Abbrechen</span>
|
|
<span class="button danger">Deaktivieren</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal-demo modal-small">
|
|
<div class="modal-header">
|
|
<h3>S - 560px</h3>
|
|
<p class="small">Kleines Formular mit wenigen Feldern.</p>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="field">
|
|
<label>Workspace name</label>
|
|
<input value="HiveGrid Demo" />
|
|
</div>
|
|
<div class="field">
|
|
<label>Kategorie</label>
|
|
<select>
|
|
<option>CRM Workspace</option>
|
|
<option>Operations</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<span class="button secondary">Abbrechen</span>
|
|
<span class="button">Anlegen</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal-demo modal-medium">
|
|
<div class="modal-header">
|
|
<h3>M - 720px</h3>
|
|
<p class="small">Normales Formular mit mehreren Feldern oder kurzer Section-Struktur.</p>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="field">
|
|
<label>Role name</label>
|
|
<input value="Finance Lead" />
|
|
</div>
|
|
<div class="field">
|
|
<label>Description</label>
|
|
<textarea>Can approve invoices and review financial records.</textarea>
|
|
</div>
|
|
<div class="field">
|
|
<label>Bereich</label>
|
|
<select>
|
|
<option>Finance</option>
|
|
<option>Sales</option>
|
|
<option>Administration</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<span class="button secondary">Abbrechen</span>
|
|
<span class="button">Weiter</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal-demo modal-large modal-spacious">
|
|
<div class="modal-header">
|
|
<h3>L - 1200px max</h3>
|
|
<p class="small">Grosser Editor mit Navigation, Suche und komplexeren Einstellungen. Nutzt die 32px Dialog-Variante.</p>
|
|
</div>
|
|
<div class="modal-body" style="grid-template-columns: 220px 1fr; align-items: start">
|
|
<div class="card tight" style="background: var(--surface-subtle)">
|
|
<p><strong>Role</strong></p>
|
|
<p class="small">General</p>
|
|
<p class="small">Contacts</p>
|
|
<p class="small">Reports</p>
|
|
<p class="small">Advanced</p>
|
|
</div>
|
|
<div class="form">
|
|
<div class="field">
|
|
<label>Permission search</label>
|
|
<input value="Search permissions" />
|
|
</div>
|
|
<div class="card tight">
|
|
<h3>Contacts</h3>
|
|
<p class="muted">Read, create and update contact records.</p>
|
|
</div>
|
|
<div class="card tight">
|
|
<h3>Reports</h3>
|
|
<p class="muted">View exported reports and analytics.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<span class="button secondary">Abbrechen</span>
|
|
<span class="button">Rolle speichern</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="d08" class="section">
|
|
<div class="section-head">
|
|
<div class="section-copy">
|
|
<h2>D08 Dialog Internal Gaps</h2>
|
|
<p class="section-desc">
|
|
Validierte Entscheidung: Balanced ist der Standard. Diese Werte
|
|
betreffen nur Abstaende zwischen Elementen innerhalb normaler
|
|
Dialoge, nicht die bereits validierte Dialogbreite oder das
|
|
Dialog-Padding.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="decision-panel">
|
|
<div>
|
|
<span class="decision-tag">Entscheidung D08 validiert</span>
|
|
</div>
|
|
<div>
|
|
<p class="decision-kicker">Was du festlegst</p>
|
|
<h3>Welche Gaps gelten zwischen Dialog-Header, Body, Feldern, Sections und Footer?</h3>
|
|
<p>
|
|
Bereits validiert: Dialog Padding 16px Default und 32px Spacious.
|
|
Jetzt validiert: Balanced ist die Standard-Gap-Logik fuer normale
|
|
Dialoge, damit Dialoge nicht je Screen unterschiedlich wirken.
|
|
Mehrzeilige Texte nutzen die 150%-Texttoken; dadurch wird der
|
|
Textblock selbst hoeher, ohne zusaetzlichen Sonder-Gap.
|
|
</p>
|
|
</div>
|
|
<div class="decision-options">
|
|
<div class="decision-option">
|
|
<strong>Kompakt</strong>
|
|
<span>Sehr dicht. Gut fuer kurze Confirm-Dialoge, aber fuer Formulare schnell gedrueckt.</span>
|
|
</div>
|
|
<div class="decision-option recommended">
|
|
<strong>Balanced</strong>
|
|
<span>Orientiert sich an 8px-Rhythmus und Carbon-nahem Modal-Denken: kompakt, aber lesbar.</span>
|
|
</div>
|
|
<div class="decision-option">
|
|
<strong>Ruhig</strong>
|
|
<span>Mehr Luft fuer groessere Dialoge, kann bei XS/S aber zu luftig wirken.</span>
|
|
</div>
|
|
</div>
|
|
<div class="decision-question">
|
|
Entschieden: Balanced wird Standard. Title Gap 8px, Field Gap 16px, Section Gap 24px, Button Gap 8px.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="dialog-gap-grid">
|
|
<div class="dialog-gap-card" style="--title-gap: 4px; --field-gap: 12px; --section-gap-demo: 20px; --button-gap: 8px">
|
|
<div>
|
|
<h3>Kompakt</h3>
|
|
<p class="small">Fuer sehr kurze Dialoge. Spart Hoehe, trennt Inhalte aber weniger stark.</p>
|
|
</div>
|
|
<ul class="gap-spec-list">
|
|
<li><span>Title -> Description</span><strong>4px</strong></li>
|
|
<li><span>Field/Form Row Gap</span><strong>12px</strong></li>
|
|
<li><span>Section Gap</span><strong>20px</strong></li>
|
|
<li><span>Footer Button Gap</span><strong>8px</strong></li>
|
|
</ul>
|
|
<div class="dialog-gap-demo">
|
|
<div class="dialog-gap-header">
|
|
<div class="dialog-gap-title"></div>
|
|
<div class="gap-marker vertical" style="--gap-size: var(--title-gap)" data-label="Title Gap" data-size="4px"></div>
|
|
<div class="dialog-gap-description"></div>
|
|
</div>
|
|
<div class="dialog-gap-body">
|
|
<div class="dialog-gap-field">
|
|
<div class="dialog-gap-label"></div>
|
|
<div class="dialog-gap-input"></div>
|
|
</div>
|
|
<div class="gap-marker vertical" style="--gap-size: var(--field-gap)" data-label="Field Gap" data-size="12px"></div>
|
|
<div class="dialog-gap-field">
|
|
<div class="dialog-gap-label"></div>
|
|
<div class="dialog-gap-input"></div>
|
|
</div>
|
|
<div class="gap-marker vertical" style="--gap-size: var(--section-gap-demo)" data-label="Section Gap" data-size="20px"></div>
|
|
<div class="dialog-gap-section">
|
|
<div class="dialog-gap-row"></div>
|
|
<div class="dialog-gap-row"></div>
|
|
</div>
|
|
</div>
|
|
<div class="dialog-gap-footer">
|
|
<div class="dialog-gap-button"></div>
|
|
<div class="gap-marker horizontal" style="--gap-size: var(--button-gap)" data-label="Button Gap" data-size="8px"></div>
|
|
<div class="dialog-gap-button primary"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="dialog-gap-card recommended" style="--title-gap: 8px; --field-gap: 16px; --section-gap-demo: 24px; --button-gap: 8px">
|
|
<div>
|
|
<h3>Balanced</h3>
|
|
<p class="small">Validierter Default. Passt zu 16px Dialog-Padding und bleibt nah an D02.</p>
|
|
</div>
|
|
<ul class="gap-spec-list">
|
|
<li><span>Title -> Description</span><strong>8px</strong></li>
|
|
<li><span>Field/Form Row Gap</span><strong>16px</strong></li>
|
|
<li><span>Section Gap</span><strong>24px</strong></li>
|
|
<li><span>Footer Button Gap</span><strong>8px</strong></li>
|
|
</ul>
|
|
<div class="dialog-gap-demo">
|
|
<div class="dialog-gap-header">
|
|
<div class="dialog-gap-title"></div>
|
|
<div class="gap-marker vertical" style="--gap-size: var(--title-gap)" data-label="Title Gap" data-size="8px"></div>
|
|
<div class="dialog-gap-description"></div>
|
|
</div>
|
|
<div class="dialog-gap-body">
|
|
<div class="dialog-gap-field">
|
|
<div class="dialog-gap-label"></div>
|
|
<div class="dialog-gap-input"></div>
|
|
</div>
|
|
<div class="gap-marker vertical" style="--gap-size: var(--field-gap)" data-label="Field Gap" data-size="16px"></div>
|
|
<div class="dialog-gap-field">
|
|
<div class="dialog-gap-label"></div>
|
|
<div class="dialog-gap-input"></div>
|
|
</div>
|
|
<div class="gap-marker vertical" style="--gap-size: var(--section-gap-demo)" data-label="Section Gap" data-size="24px"></div>
|
|
<div class="dialog-gap-section">
|
|
<div class="dialog-gap-row"></div>
|
|
<div class="dialog-gap-row"></div>
|
|
</div>
|
|
</div>
|
|
<div class="dialog-gap-footer">
|
|
<div class="dialog-gap-button"></div>
|
|
<div class="gap-marker horizontal" style="--gap-size: var(--button-gap)" data-label="Button Gap" data-size="8px"></div>
|
|
<div class="dialog-gap-button primary"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="dialog-gap-card" style="--title-gap: 8px; --field-gap: 20px; --section-gap-demo: 32px; --button-gap: 12px">
|
|
<div>
|
|
<h3>Ruhig</h3>
|
|
<p class="small">Mehr Luft fuer grosse Dialoge. Koennte eher zur 32px-Spacious-Variante passen.</p>
|
|
</div>
|
|
<ul class="gap-spec-list">
|
|
<li><span>Title -> Description</span><strong>8px</strong></li>
|
|
<li><span>Field/Form Row Gap</span><strong>20px</strong></li>
|
|
<li><span>Section Gap</span><strong>32px</strong></li>
|
|
<li><span>Footer Button Gap</span><strong>12px</strong></li>
|
|
</ul>
|
|
<div class="dialog-gap-demo">
|
|
<div class="dialog-gap-header">
|
|
<div class="dialog-gap-title"></div>
|
|
<div class="gap-marker vertical" style="--gap-size: var(--title-gap)" data-label="Title Gap" data-size="8px"></div>
|
|
<div class="dialog-gap-description"></div>
|
|
</div>
|
|
<div class="dialog-gap-body">
|
|
<div class="dialog-gap-field">
|
|
<div class="dialog-gap-label"></div>
|
|
<div class="dialog-gap-input"></div>
|
|
</div>
|
|
<div class="gap-marker vertical" style="--gap-size: var(--field-gap)" data-label="Field Gap" data-size="20px"></div>
|
|
<div class="dialog-gap-field">
|
|
<div class="dialog-gap-label"></div>
|
|
<div class="dialog-gap-input"></div>
|
|
</div>
|
|
<div class="gap-marker vertical" style="--gap-size: var(--section-gap-demo)" data-label="Section Gap" data-size="32px"></div>
|
|
<div class="dialog-gap-section">
|
|
<div class="dialog-gap-row"></div>
|
|
<div class="dialog-gap-row"></div>
|
|
</div>
|
|
</div>
|
|
<div class="dialog-gap-footer">
|
|
<div class="dialog-gap-button"></div>
|
|
<div class="gap-marker horizontal" style="--gap-size: var(--button-gap)" data-label="Button Gap" data-size="12px"></div>
|
|
<div class="dialog-gap-button primary"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="decision-panel" style="margin-top: 24px">
|
|
<div>
|
|
<span class="decision-tag">Zusatzfrage validiert</span>
|
|
</div>
|
|
<div>
|
|
<p class="decision-kicker">Footer Buttons</p>
|
|
<h3>Sollen Buttons in kleinen Dialogen rechts ausgerichtet bleiben oder die Breite fuellen?</h3>
|
|
<p>
|
|
Das ist getrennt vom Button-Gap. Es geht um die Button-Verteilung
|
|
im Footer: klassische Desktop-Dialoge richten Actions oft rechts
|
|
aus; bei sehr kleinen Dialogen kann Fill ergonomischer wirken.
|
|
</p>
|
|
</div>
|
|
<div class="decision-options">
|
|
<div class="decision-option recommended">
|
|
<strong>Default: rechts</strong>
|
|
<span>Alle Dialoggroessen behalten rechts ausgerichtete Actions. Ruhig und desktop-typisch.</span>
|
|
</div>
|
|
<div class="decision-option">
|
|
<strong>XS/S: Fill</strong>
|
|
<span>Nur kleine Dialoge mit genau zwei Actions duerfen beide Buttons gleich breit fuellen.</span>
|
|
</div>
|
|
<div class="decision-option">
|
|
<strong>Immer Fill</strong>
|
|
<span>Sehr klare Buttonflaechen, aber fuer M/L-Dialoge meistens zu dominant.</span>
|
|
</div>
|
|
</div>
|
|
<div class="decision-question">
|
|
Entschieden: Footer Actions bleiben standardmaessig rechts ausgerichtet. XS/S-Fill bleibt nur eine optionale Sondervariante, falls sie spaeter bewusst gebraucht wird.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="footer-layout-grid">
|
|
<div class="footer-layout-card recommended">
|
|
<div>
|
|
<h3>Default: rechts ausgerichtet</h3>
|
|
<p class="small">Klassischer Desktop-Dialog. Der freie Bereich links ist bewusst, weil die Actions nicht mit dem Inhalt konkurrieren.</p>
|
|
</div>
|
|
<div class="footer-preview">
|
|
<div class="footer-preview-body">
|
|
<div class="dialog-gap-title"></div>
|
|
<div style="height: 8px"></div>
|
|
<div class="dialog-gap-description"></div>
|
|
</div>
|
|
<div class="footer-preview-actions">
|
|
<div class="dialog-gap-button"></div>
|
|
<div class="dialog-gap-button primary"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="footer-layout-card">
|
|
<div>
|
|
<h3>XS/S Sonderfall: Fill Buttons</h3>
|
|
<p class="small">Kann bei sehr kleinen Dialogen mit genau zwei Actions sinnvoll sein. Sollte keine globale M/L-Regel werden.</p>
|
|
</div>
|
|
<div class="footer-preview fill-actions">
|
|
<div class="footer-preview-body">
|
|
<div class="dialog-gap-title"></div>
|
|
<div style="height: 8px"></div>
|
|
<div class="dialog-gap-description"></div>
|
|
</div>
|
|
<div class="footer-preview-actions">
|
|
<div class="dialog-gap-button"></div>
|
|
<div class="dialog-gap-button primary"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="d09" class="section">
|
|
<div class="section-head">
|
|
<div class="section-copy">
|
|
<h2>D09 States / Component Ownership</h2>
|
|
<p class="section-desc">
|
|
Klarstellung: States sind inline Inhaltszustaende und werden ueber
|
|
Komponenten abgedeckt. Sie sind keine Modale und aktuell keine
|
|
eigene Layout-Entscheidung in D-D0b.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="decision-panel">
|
|
<div>
|
|
<span class="decision-tag">Komponenten-Ownership</span>
|
|
</div>
|
|
<div>
|
|
<p class="decision-kicker">Was hier gemeint ist</p>
|
|
<h3>Empty, Error und No-Permission ersetzen inline den betroffenen Inhaltsbereich.</h3>
|
|
<p>
|
|
Beispiel: Eine leere Tabelle zeigt einen Empty State im Tabellen-
|
|
oder Listenbereich. Ein Ladefehler zeigt einen Error State im
|
|
betroffenen Bereich. Das oeffnet nicht automatisch einen Dialog.
|
|
</p>
|
|
</div>
|
|
<div class="decision-options">
|
|
<div class="decision-option">
|
|
<strong>Empty State</strong>
|
|
<span>Im Komponenten-Index vorhanden: Data Display / Empty State.</span>
|
|
</div>
|
|
<div class="decision-option recommended">
|
|
<strong>Error State</strong>
|
|
<span>Im Komponenten-Index vorhanden: Feedback / Error State bzw. Partial page failure.</span>
|
|
</div>
|
|
<div class="decision-option">
|
|
<strong>No Permission</strong>
|
|
<span>Nicht als eigene lokale Komponenten-MD gefunden. Falls noetig als Variante/Komponente klaeren.</span>
|
|
</div>
|
|
</div>
|
|
<div class="decision-question">
|
|
Keine neue D09-Layout-Regel: Screens sollen die vorhandenen State-Komponenten verwenden. No-Permission muss bei Bedarf als Komponentenfrage validiert werden.
|
|
</div>
|
|
</div>
|
|
<div class="grid three">
|
|
<div class="state">
|
|
<div class="state-inner">
|
|
<h3>Empty</h3>
|
|
<p class="muted">No roles have been created yet.</p>
|
|
<div style="height: 16px"></div>
|
|
<span class="button">Create role</span>
|
|
</div>
|
|
</div>
|
|
<div class="state">
|
|
<div class="state-inner">
|
|
<h3>Error</h3>
|
|
<p class="muted">The list could not be loaded.</p>
|
|
<div style="height: 16px"></div>
|
|
<span class="button secondary">Try again</span>
|
|
</div>
|
|
</div>
|
|
<div class="state">
|
|
<div class="state-inner">
|
|
<h3>No permission</h3>
|
|
<p class="muted">You do not have access to this area.</p>
|
|
<div style="height: 16px"></div>
|
|
<span class="button secondary">Back to overview</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
<script>
|
|
const gapToggle = document.getElementById("gapToggle");
|
|
|
|
gapToggle?.addEventListener("click", () => {
|
|
const hidden = document.body.classList.toggle("hide-gap-markers");
|
|
gapToggle.setAttribute("aria-pressed", String(!hidden));
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|