UNPKG

raft-ui

Version:

React UI components for Raft.

256 lines (227 loc) • 8.32 kB
/* Timeline pure CSS styling following pattern/Button.css architecture - Local CSS variables (--r-timeline-*) declared on the list; items inherit them - Modifier classes rebind local variables - Component styles strictly consume local variables - Every marker is a status pixel: a 9px square in the item's colour with a 1.5px sticker-ink edge, strung on a hairline. Titles are 14/20 ink, details and times Space Mono 12 in ink-3, the time on the right of the row. One scale for every size; `lg` only opens the title to 16/24. */ /* ───────────────────────────────────────────────────────────────────────── 1. Local Variable Definitions & Modifier Overrides ───────────────────────────────────────────────────────────────────────── */ .r-timeline { --r-timeline-icon-size: var(--r-timeline-custom-icon-size, 9px); --r-timeline-title-font-size: 14px; --r-timeline-content-font-size: 12px; --r-timeline-time-font-size: 12px; --r-timeline-line-height: 20px; --r-timeline-item-inner-gap: 2px; --r-timeline-title-font-family: var(--font-sans); --r-timeline-title-font-weight: 400; --r-timeline-gap: 12px; --r-timeline-item-gap: 12px; --r-timeline-horizontal-item-gap: 40px; --r-timeline-line-width: 1px; --r-timeline-line-color: var(--line-muted); --r-timeline-marker-border-width: 1.5px; --r-timeline-marker-radius: 2px; /* How much of the variant's fill the marker takes, and its outline. */ --r-timeline-marker-fill: 100%; --r-timeline-marker-border-color: var(--sticker-ink); /* How far each marker sits below the item's top, to center on the title's first line. */ --r-timeline-axis-offset: calc((20px - var(--r-timeline-icon-size)) / 2); &.r-timeline--lg { --r-timeline-title-font-size: 16px; --r-timeline-line-height: 24px; --r-timeline-axis-offset: calc((24px - var(--r-timeline-icon-size)) / 2); } &.r-timeline--horizontal { --r-timeline-axis-offset: 0px; } } /* Markers take the presence colours (default = offline stone, accent = the In Review lavender, since pink only means "do it"); task-status items keep their status colour. */ .r-timeline-item { --r-timeline-item-color: var(--foreground-hint); --r-timeline-item-fill: var(--presence-offline); &.r-timeline-item--information { --r-timeline-item-color: var(--info-strong); --r-timeline-item-fill: var(--info); } &.r-timeline-item--success { --r-timeline-item-color: var(--success-strong); --r-timeline-item-fill: var(--success); } &.r-timeline-item--warning { --r-timeline-item-color: var(--warning-strong); --r-timeline-item-fill: var(--warning); } &.r-timeline-item--danger { --r-timeline-item-color: var(--danger-strong); --r-timeline-item-fill: var(--danger); } /* Accent: the emphasis tone for review-type states, e.g. "in review". */ &.r-timeline-item--accent { --r-timeline-item-color: var(--task-status-in-review-strong); --r-timeline-item-fill: var(--task-status-in-review); } &.r-timeline-item--color { --r-timeline-item-color: var(--r-timeline-custom-color); --r-timeline-item-fill: var(--r-timeline-custom-color); } /* An icon in place of the pixel gets a 14px box. */ &[data-icon] { --r-timeline-icon-size: var(--r-timeline-custom-icon-size, 14px); --r-timeline-axis-offset: calc( (var(--r-timeline-line-height) - var(--r-timeline-icon-size)) / 2 ); } } /* ───────────────────────────────────────────────────────────────────────── 2. Component Styles ───────────────────────────────────────────────────────────────────────── */ .r-timeline { display: flex; flex-direction: column; line-height: var(--r-timeline-line-height); list-style: none; margin: 0; padding: 0; } .r-timeline-item { display: flex; gap: var(--r-timeline-gap); margin: 0; padding: 0; } /* The axis: the marker, centered on the title's first line, then the line down to the next item. */ .r-timeline-item__axis { align-items: center; display: flex; flex: none; flex-direction: column; padding-top: var(--r-timeline-axis-offset); width: var(--r-timeline-icon-size); } .r-timeline-item__marker { background: color-mix( in oklch, var(--r-timeline-item-fill) var(--r-timeline-marker-fill), transparent ); border: var(--r-timeline-marker-border-width) solid var(--r-timeline-marker-border-color, var(--r-timeline-item-color)); border-radius: var(--r-timeline-marker-radius); box-sizing: border-box; flex: none; height: var(--r-timeline-icon-size); width: var(--r-timeline-icon-size); } .r-timeline-item__icon { align-items: center; color: var(--r-timeline-item-color); display: flex; flex: none; font-size: var(--r-timeline-icon-size); height: var(--r-timeline-icon-size); justify-content: center; width: var(--r-timeline-icon-size); & svg { height: 1em; width: 1em; } } .r-timeline-item__line { border-inline-start: var(--r-timeline-line-width) solid var(--r-timeline-line-color); flex: 1; /* Runs on through the next item's offset, stopping 2px short of each marker: a gap of the row's own background cuts the hairline around each pixel. */ margin-bottom: calc(2px - var(--r-timeline-axis-offset)); margin-top: 2px; } .r-timeline-item--dashed > .r-timeline-item__axis > .r-timeline-item__line { border-style: dashed; } .r-timeline-item:last-child > .r-timeline-item__axis > .r-timeline-item__line { visibility: hidden; } .r-timeline-item__body { flex: 1; min-width: 0; padding-bottom: var(--r-timeline-item-gap); } .r-timeline-item:last-child > .r-timeline-item__body { padding-bottom: 0; } .r-timeline-title { color: var(--foreground-strong); font-family: var(--r-timeline-title-font-family); font-size: var(--r-timeline-title-font-size); font-weight: var(--r-timeline-title-font-weight); margin-bottom: var(--r-timeline-item-inner-gap); overflow-wrap: anywhere; } .r-timeline-content { color: var(--foreground-hint); font-family: var(--font-mono); font-size: var(--r-timeline-content-font-size); line-height: 16px; overflow-wrap: anywhere; } .r-timeline-time { color: var(--foreground-hint); font-family: var(--font-mono); font-size: var(--r-timeline-time-font-size); margin-top: var(--r-timeline-item-inner-gap); white-space: nowrap; } /* Markers on the left: the row is [pixel | text | time], the time at the end of the first line. */ .r-timeline--left > .r-timeline-item > .r-timeline-item__body { column-gap: var(--r-timeline-gap); display: grid; grid-template-columns: minmax(0, 1fr) auto; & > * { grid-column: 1; } & > .r-timeline-time { grid-column: 2; grid-row: 1; margin-top: 0; } } /* Markers on the right: the axis moves to the end and the text aligns to it. */ .r-timeline--right > .r-timeline-item { flex-direction: row-reverse; text-align: end; } /* Horizontal: items in a row, each marker followed by a line across to the next. */ .r-timeline--horizontal { flex-direction: row; } .r-timeline--horizontal > .r-timeline-item { flex: none; flex-direction: column; & > .r-timeline-item__axis { flex-direction: row; height: var(--r-timeline-icon-size); padding-top: 0; width: auto; } & > .r-timeline-item__axis > .r-timeline-item__line { border-inline-start: 0; border-top: var(--r-timeline-line-width) solid var(--r-timeline-line-color); margin-bottom: 0; margin-top: 0; } &.r-timeline-item--dashed > .r-timeline-item__axis > .r-timeline-item__line { border-top-style: dashed; } & > .r-timeline-item__body { padding-bottom: 0; padding-inline-end: var(--r-timeline-horizontal-item-gap); } }