04모노스페이스 라벨 리스트
각 기능 앞에 모노스페이스 번호 라벨을 달고, 리스트 줄마다 아래에서 위로 스치듯 나타납니다.
쓰임기능 목록, 변경 로그
ui-monospace 라벨stagger 등장translateY

<main class="stage">
<ul class="list is-demo">
<li class="list__row list__row--1"><span class="list__num">01</span><span class="list__text">실시간 협업 편집</span></li>
<li class="list__row list__row--2"><span class="list__num">02</span><span class="list__text">키보드 전용 커맨드바</span></li>
<li class="list__row list__row--3"><span class="list__num">03</span><span class="list__text">버전별 변경 로그</span></li>
</ul>
</main>@use "../../../../site/static/demo-tokens" as *;
$duration: $dur-loop; // 줄 하나가 스치듯 나타났다 사라지는 한 주기
$easing: $ease-out;
$color: $subject-blue;
@include stage($stage-paper);
.list {
list-style: none;
margin: 0;
padding: $sp-4;
display: flex;
flex-direction: column;
gap: $sp-2;
width: clamp(220px, 76vw, 320px);
background: $subject-ink;
border-radius: $r-card;
box-shadow: $shadow-raised;
}
.list__row {
display: flex;
align-items: center;
gap: $sp-4;
padding: $sp-3 $sp-4;
border-radius: $r-sm;
// 데모 루프는 .is-demo 안에서만 — 정적(실사용) 상태는 opacity 1 이라야 글자 대비가 산다
.list.is-demo & { animation-name: rowSweep; }
animation-duration: $duration;
animation-timing-function: $easing;
animation-iteration-count: infinite;
}
.list__row--1 { animation-delay: 0s; }
.list__row--2 { animation-delay: $duration * -0.67; }
.list__row--3 { animation-delay: $duration * -0.34; }
.list__num {
font: 700 clamp(11px, 2.8vw, 13px)/1 "Courier New", ui-monospace, monospace;
color: $subject-blue-light; // 먹 면 위 파란 글자 — AA 4.5 (blog-design 글자 대비)
}
.list__text {
color: $subject-cream;
font: 600 clamp(11px, 2.8vw, 13px)/1.3 -apple-system, "Segoe UI", "Noto Sans KR", sans-serif;
}
@keyframes rowSweep {
0%, 62%, 100% { opacity: .55; background: transparent; transform: translateY(0); }
17% { opacity: 1; background: rgba($color, .12); transform: translateY(-2px); }
}
@media (prefers-reduced-motion: reduce) {
.list__row { animation: none !important; opacity: .85; background: transparent; transform: none; }
}html, body {
margin: 0;
overflow: hidden;
}
.stage {
box-sizing: border-box;
min-height: 100vh;
display: grid;
place-items: center;
margin: 0;
background: #ffffff;
font-family: -apple-system, "Segoe UI", "Noto Sans KR", sans-serif;
padding: clamp(8px, 4vw, 24px);
}
.list {
list-style: none;
margin: 0;
padding: 16px;
display: flex;
flex-direction: column;
gap: 8px;
width: clamp(220px, 76vw, 320px);
background: #17141a;
border-radius: 16px;
box-shadow: 0 14px 24px rgba(23, 20, 26, 0.32);
}
.list__row {
display: flex;
align-items: center;
gap: 16px;
padding: 12px 16px;
border-radius: 8px;
}
.list.is-demo .list__row {
animation-name: rowSweep;
}
.list__row {
animation-duration: 2s;
animation-timing-function: ease-out;
animation-iteration-count: infinite;
}
.list__row--1 {
animation-delay: 0s;
}
.list__row--2 {
animation-delay: -1.34s;
}
.list__row--3 {
animation-delay: -0.68s;
}
.list__num {
font: 700 clamp(11px, 2.8vw, 13px)/1 "Courier New", ui-monospace, monospace;
color: #5b8cf8;
}
.list__text {
color: #fff7e6;
font: 600 clamp(11px, 2.8vw, 13px)/1.3 -apple-system, "Segoe UI", "Noto Sans KR", sans-serif;
}
@keyframes rowSweep {
0%, 62%, 100% {
opacity: 0.55;
background: transparent;
transform: translateY(0);
}
17% {
opacity: 1;
background: rgba(47, 109, 246, 0.12);
transform: translateY(-2px);
}
}
@media (prefers-reduced-motion: reduce) {
.list__row {
animation: none !important;
opacity: 0.85;
background: transparent;
transform: none;
}
}import type { CSSProperties } from "react";
import styles from "./FeatureListLinear.module.scss";
export type FeatureListLinearProps = {
rows?: [string, string, string];
/** 줄 하나가 스치듯 나타났다 사라지는 한 주기(기본 2000ms) */
duration?: number;
easing?: string;
color?: string;
};
type Vars = CSSProperties & { "--duration"?: string; "--easing"?: string; "--color"?: string };
export default function FeatureListLinear({
rows = ["실시간 협업 편집", "키보드 전용 커맨드바", "버전별 변경 로그"],
duration = 2000,
easing = "ease-out",
color = "#2f6df6",
}: FeatureListLinearProps) {
const vars: Vars = { "--duration": `${duration}ms`, "--easing": easing, "--color": color };
const delays = ["0s", `${-duration * 0.67}ms`, `${-duration * 0.34}ms`];
return (
<ul className={styles.list} style={vars}>
{rows.map((text, i) => (
<li key={text} className={styles.row} style={{ animationDelay: delays[i] }}>
<span className={styles.num}>{String(i + 1).padStart(2, "0")}</span>
<span className={styles.text}>{text}</span>
</li>
))}
</ul>
);
}04 모노스페이스 라벨 리스트 — 측정 누적면적 27.006% · 움직인 프레임 19/23GODRICH 원작 · zip 에 SCSS·React 포함 · 다크 SaaS 랜딩에 스며든 리니어 디자인 시스템 9종
이 데모가 속한 글
다크 SaaS 랜딩에 스며든 리니어 디자인 시스템 9종핀터레스트를 뒤덮은 리니어 디자인 시스템은 이슈 트래커 Linear.app이 쓰는 짙은 잉크 배경에 파란 글로우 하나로 포인트를 주는 다크 스타일입니다. 이 글의 데모 전부 보기


