qufox
Design system
qufox, Design System, v0.18.0

A design system for
AI and humans alike
AI와 사람이 함께 쓰는
디자인 시스템

Design system — the single source of truth (SSOT) for tokens, components, and patterns. Dark-first, light-ready, white-label from one seed color. AI fetches llms.txt, components.json to consume tokens, classes, and conventions directly; humans browse the catalog.Design system — 토큰, 컴포넌트, 패턴의 단일 진실원(SSOT)입니다. 다크 우선, 라이트 대응, 색 시드 하나로 화이트라벨. AI는 llms.txt, components.json을 fetch 해 토큰, 클래스, 규약을 그대로 소비하고, 사람은 카탈로그로 봅니다.

164Components컴포넌트
104Generic범용 (generic)
294Design tokens디자인 토큰
2Themes (dark, light)테마 (다크, 라이트)

Two audiences, one source of truth두 청중, 하나의 진실원

AI

Consume machine-readable outputs기계가독 산출물 소비

Agents read conventions from llms.txt, classes/variants/required-tokens/a11y from components.json, and tokens from tokens.json, then apply them to the target app. The web and local outputs are identical.에이전트는 llms.txt로 규약을, components.json으로 클래스, 변형, 필요 토큰, 접근성을, tokens.json으로 토큰을 읽어 작업 대상 앱에 반영합니다. 웹, 로컬 2채널 산출물은 동일합니다.

Agent guide: AGENTS.md →에이전트 가이드: AGENTS.md →
Humans사람

Browse the catalog카탈로그로 탐색

From the left menu, explore one component per page. Each page shows a live preview, variant gallery, required tokens, and accessibility notes. Switch theme (dark/light) and brand color instantly from the top bar.좌측 메뉴에서 컴포넌트를 1개=1페이지로 살펴봅니다. 각 페이지는 라이브 프리뷰, 변형 갤러리, 필요 토큰, 접근성 주의를 함께 보여줍니다. 다크/라이트 테마와 브랜드 색을 상단에서 즉시 전환할 수 있습니다.

Button page example →Button 페이지 예시 →

Apply with AIAI로 적용하기

Point your agent (Claude, Cursor, Copilot, …) at design.qufox.com — it reads llms.txt for conventions, components.json for classes, variants, required tokens, and a11y, and tokens.json for values, then writes qf-* markup with var(--token). Paste a prompt like these:에이전트(Claude, Cursor, Copilot 등)에게 design.qufox.com을 가리키세요 — llms.txt로 규약을, components.json으로 클래스, 변형, 필요 토큰, 접근성을, tokens.json으로 값을 읽어 qf-* + var(--token) 마크업을 만듭니다. 아래 같은 프롬프트를 붙여넣으세요:

Prompt: set up a project프롬프트: 프로젝트 설정

Set up my project using the design system at design.qufox.com.design.qufox.com 의 디자인 시스템을 사용해서 프로젝트 설정을 해줘.

Prompt: build a screen프롬프트: 화면 만들기

Build a login screen with the design.qufox.com design system.design.qufox.com 디자인 시스템으로 로그인 화면을 만들어줘.

Prompt: restyle existing UI프롬프트: 기존 UI 리스타일

Restyle this component with the design.qufox.com design system.이 컴포넌트를 design.qufox.com 디자인 시스템으로 리스타일 해줘.

Tip: for production, ask it to pin a fixed snapshot (e.g. /v0.18.0/tokens.css) instead of the always-latest root. The agent checks its own output against the rules in llms.txt — no raw values, AA contrast, visible focus, 44px touch targets.팁: 프로덕션에서는 항상-최신 루트 대신 고정 스냅샷(예: /v0.18.0/tokens.css)을 핀하도록 요청하세요. 에이전트는 llms.txt의 규칙(raw 값 금지, AA 대비, 포커스 가시, 44px 터치)으로 자기 출력을 검증합니다.

Direct load: for developers직접 로드: 사람 작업자용

Prefer to wire it up by hand? Browse the catalog, copy a component's markup from its page, and load the CSS directly — design.qufox.com outputs are CORS-enabled, so you can pull them from anywhere (like a CDN). <link> tokens.css + components.css, use qf-* classes, and set color, spacing, and radius only via var(--token).직접 연결하고 싶으신가요? 카탈로그에서 컴포넌트 페이지의 마크업을 복사하고 CSS를 직접 로드하세요 — design.qufox.com 산출물은 CORS 허용이라 어디서나 불러올 수 있습니다(CDN 처럼). tokens.css + components.css를 <link> 하고 qf-* 클래스를 쓰며, 색, 간격, radius는 var(--token)으로만 지정합니다.

<!-- Required: tokens + components -->
<link rel="stylesheet" href="https://design.qufox.com/tokens.css">
<link rel="stylesheet" href="https://design.qufox.com/components.css">
<!-- Optional: mobile (qf-m-*) components -->
<link rel="stylesheet" href="https://design.qufox.com/mobile.css">

<button class="qf-btn qf-btn--primary">Save</button>

Icons reference the sprite (icons.svg) via <use>, and the machine-readable outputs (components.json, tokens.json) are fetchable from the same domain.아이콘은 스프라이트(icons.svg)를 <use>로 참조하고, 기계가독 산출물(components.json, tokens.json)도 같은 도메인에서 fetch 할 수 있습니다.

Versions: latest vs pinned버전: 최신 vs 고정

The root (/tokens.css) is always the latest build — handy for prototyping and AI fetch. For production, pin a fixed snapshot — https://design.qufox.com/v0.18.0/tokens.css. See /versions.json for the published list, or vendor (copy) the build outputs.루트(/tokens.css)는 항상 최신 빌드라 프로토타이핑, AI fetch 에 편합니다. 프로덕션은 고정 스냅샷을 핀하세요 — https://design.qufox.com/v0.18.0/tokens.css. 발행 목록은 /versions.json, 또는 빌드 산출물을 벤더링(복사)해도 됩니다.

Catalog카탈로그

Generic core + optional chat module. Component counts by category.범용 코어(generic) + 선택적 채팅 모듈. 카테고리별 컴포넌트 수입니다.

Resources리소스

Foundations

Color, Type, Space

qufox is a dark-first system. Every surface, text, and border derives from a neutral scale generated along the night-lavender axis, while the violet accent carries the brand contrast.qufox는 dark-first 시스템이에요. 모든 서피스, 텍스트, 보더는 night-lavender 축을 따라 생성된 neutral scale에서 파생되고, violet accent가 브랜드 대비를 담당합니다.

Neutral scale

From the app shell to the header — every dark surface layer is drawn from here.앱 쉘부터 헤더까지 — 다크의 서피스 계층을 전부 여기서 뽑습니다.
--n-0#0E0C2A: app shell
--n-1#141232: chat
--n-2#1A1840: panel
--n-3#221F4F: elevated
--n-4#2C285E: hover
--n-5#3A3570: selected
--n-6#4D4780: border
--n-7#6B6599: disabled
--n-8#9892BF: muted
--n-9#C4BFDC: secondary
--n-10#E9D5FF: text
--n-11#F7F1FF: strong

Accent — violet

The brand accent. Links, CTAs, focus rings, and selected states.브랜드 액센트. 링크, CTA, focus ring, 선택 상태.
--a-50#F5EEFF
--a-100#E9DCFF
--a-200#D4B8FF
--a-300#B48EFF
--a-400#9D6FFD: hover
--a-500#8B5CF6: primary
--a-600#7848E0: press
--a-700#5F38B8

Status

--status-onlineonline
--status-idleidle
--status-dndDnD / error
--status-offlineoffline

Typography

Display/body: Pretendard Variable, Mono: Geist Mono
--fs-32 / 60032/1.1Display title
--fs-24 / 60024/1.2Page heading
--fs-20 / 60020/1.2Modal title
--fs-18 / 60018/1.35Section title
--fs-15 / 40015/1.5Message body — the default reading size for chat messages and settings copy.
--fs-13 / 40013/1.5Secondary copy, helper text, metadata.
--fs-11 mono / 600: caps11EYEBROW LABEL

Spacing

4px base. Most steps use 1–8, while 9+ are reserved for page-level spacing.4px base. 대부분 1–8을 사용하고, 9+는 페이지 레벨 여백.
--s-24px
--s-38px
--s-412px
--s-516px
--s-620px
--s-724px
--s-832px
--s-940px
--s-1048px

Radii

--r-xs: 4px
--r-sm: 6px
--r-md: 8px, Button
--r-lg: 10px, Input
--r-xl: 14px, Card
--r-pill: Avatar
Foundations

Elevation, Motion

In dark mode, shadows alone struggle to convey depth. Combine border and shadow to separate surface hierarchy.다크에서는 shadow만으로 깊이를 만들기 어렵습니다. border + shadow를 함께 써서 표면 위계를 분리하세요.

Shadows

--elev-1
--elev-2
--elev-3
--elev-4

--elev-1 topbar, --elev-2 tooltip / toast, --elev-3 dropdown / popover, --elev-4 modal

Motion

Keep transitions short and crisp. Snappy feedback, just like Discord.전환은 짧고 명확하게. Discord처럼 snappy한 피드백.
--dur-fast
140ms
hover, focus, active
--dur-base
220ms
menu open, toast slide
--dur-slow
320ms
modal enter, page transition

Easings

--ease-standard:   cubic-bezier(0.2, 0, 0, 1);     /* default - most UI transitions */
--ease-emphasized: cubic-bezier(0.3, 0, 0, 1);     /* emphasized - modal, page */
--ease-spring:     cubic-bezier(0.34, 1.56, 0.64, 1);  /* overshoot - server button round, switch */
Foundations

Markdown / Prose

When the consuming app converts Markdown to HTML and wraps it in <article class="qf-prose">, the document renders in the design system's tone. Below are the Markdown source (left) and the rendered result (right) of the same document.소비 앱이 마크다운을 HTML 로 변환한 뒤 <article class="qf-prose"> 로 감싸면 문서가 디자인 시스템 톤으로 렌더됩니다. 아래는 같은 문서의 마크다운 소스(좌)와 렌더 결과(우)입니다.

Markdown sourceMarkdown 소스
# Getting Started with the API

This SDK is **simple**. For details, see the [docs](#).

## Installation

Install with `npm i @acme/sdk`.

- Issue a token
- Create a client
  1. Enter the key
  2. Connect

> Keep your key safe.

```js
const c = new Client(key);
await c.connect();
```

| Method | Description |
|---------|------|
| connect | Connect |
| close | Close |

---
End.
Rendered result: .qf-prose렌더 결과: .qf-prose

Getting Started with the APIAPI 시작하기

This SDK is simple. For details, see the docs.이 SDK는 간단합니다. 자세한 건 문서를 보세요.

Installation설치

Install with npm i @acme/sdk.npm i @acme/sdk 로 설치합니다.

  • Issue a token토큰 발급
  • Create a client클라이언트 생성
    1. Enter the key키 입력
    2. Connect연결
Keep your key safe.키는 안전하게 보관하세요.
const c = new Client(key);
await c.connect();
Method메서드Description설명
connectConnect연결
closeClose종료

End.끝.

Usage사용법

<!-- App: convert Markdown → HTML (marked, markdown-it, etc.), then wrap in .qf-prose -->
<article class="qf-prose">{{renderedHtml}}</article>

For the component interface (classes, required tokens, accessibility), see the Display → Prose page (/prose) or components.json.컴포넌트 인터페이스(클래스, 필요 토큰, 접근성)는 Display → Prose 페이지(/prose) 또는 components.json 참조.

Code syntax highlighting코드 구문 강조

The code blocks in this catalog are colored by a dependency-free build-time highlighter. The highlighting engine is the responsibility of the consumer (Prism, Shiki, highlight.js, etc.) or your own builder, while the colors come from the DS's theme-aware, brand-following tokens — map the highlighter's output classes to the qf-syntax__* classes below (or the --syntax-* tokens) for brand-consistent code blocks.이 카탈로그의 코드 블록은 빌드타임 무의존 하이라이터로 칠해집니다. 하이라이트 엔진은 소비처(Prism, Shiki, highlight.js 등)나 자체 빌더가 담당하고, 색은 DS의 테마 인지, 브랜드 추종 토큰이 담당합니다 — 하이라이터 출력 클래스를 아래 qf-syntax__*(또는 --syntax-* 토큰)에 매핑하면 브랜드 일관 코드 블록이 됩니다.

<span class="qf-syntax__punct">&lt;</span><span class="qf-syntax__tag">button</span> <span class="qf-syntax__attr">class</span>=<span class="qf-syntax__string">"qf-btn"</span><span class="qf-syntax__punct">&gt;</span>

--syntax-tag --syntax-attr --syntax-string --syntax-comment --syntax-punct

Layout & structure

Stack

A layout primitive that stacks child elements vertically at a consistent spacing.자식 요소를 세로로 일정 간격으로 쌓는 레이아웃 프리미티브입니다.

.qf-stacklayer: generic

Preview

First
Second
<div class="qf-stack">
  <div>First</div>
  <div>Second</div>
</div>

Variants

First
Second
qf-stack--tight
First
Second
qf-stack--loose

Required tokens

--s-4 --s-2 --s-6

Accessibility

Layout-only, so it carries no semantics of its own. For a meaningful grouping, apply it to an appropriate element such as ul or section. Spacing is controlled via --qf-gap.레이아웃 전용이라 자체 시맨틱이 없습니다. 의미 있는 묶음이면 ul/section 등 적절한 요소에 적용하세요. 간격은 --qf-gap 으로 조절합니다.

Layout & structure

Cluster

A layout primitive that groups elements horizontally and wraps when they overflow (toolbars, tag groups, action rows).요소를 가로로 묶고 넘치면 줄바꿈하는 레이아웃 프리미티브입니다(툴바, 태그군, 액션열).

.qf-clusterlayer: generic

Preview

<div class="qf-cluster">
  <button class="qf-btn qf-btn--primary">Save</button>
  <button class="qf-btn qf-btn--ghost">Cancel</button>
</div>

Variants

qf-cluster--between
qf-cluster--end
qf-cluster--tight

Required tokens

--s-3 --s-2

Accessibility

Layout-only. For an action grouping, use a container element that fits its meaning, and keep visual order in sync with DOM order.레이아웃 전용. 액션 묶음이면 의미에 맞는 컨테이너 요소를 쓰고, 시각 순서와 DOM 순서를 일치시킵니다.

Layout & structure

Grid

A responsive grid layout whose cells fill in automatically.셀이 자동으로 채워지는 반응형 그리드 레이아웃입니다.

.qf-gridlayer: generic

Preview

A
B
<div class="qf-grid">
  <section class="qf-card">
    <div class="qf-card__body">A</div>
  </section>
  <section class="qf-card">
    <div class="qf-card__body">B</div>
  </section>
</div>

Variants

A
B
qf-grid--cols-2
A
B
qf-grid--cols-3
A
B
qf-grid--cols-4

Required tokens

--s-4 --grid-cell-min

Accessibility

Layout-only. Use --qf-grid-min to control the minimum cell width, and preserve DOM order when content order is meaningful.레이아웃 전용. --qf-grid-min 으로 최소 셀폭을 조절하며, 콘텐츠 순서가 의미를 가지면 DOM 순서를 유지합니다.

Layout & structure

Container

A centered body container (max width + side padding). Which one when: --narrow (640px) for forms and a single document body; --reading (720px) for list-style reading pages such as news, issues, or a blog index (fits a one-line title, a three-line summary, and one row of source chips); default (960px) for dashboards, tables, and two-column layouts; --wide (1200px) for wide tables and charts.중앙 정렬 본문 컨테이너입니다(최대폭 + 좌우 여백). 언제 무엇을 쓰나: --narrow(640px)는 폼과 단일 문서 본문. --reading(720px)은 뉴스, 이슈, 블로그 같은 목록형 읽기 화면(제목 한 줄, 요약 3줄, 출처 칩 한 줄이 들어가는 폭). 기본(960px)은 대시보드, 표, 2열 레이아웃. --wide(1200px)는 넓은 표와 차트.

.qf-containerlayer: generic

Preview

Title

<main class="qf-container qf-container--narrow">
  <h1>Title</h1>
</main>

Variants

Title

qf-container--narrow

Title

qf-container--wide

Title

qf-container--reading

Required tokens

--container-w --container-w-narrow --container-w-wide --s-5 --container-w-reading

Accessibility

Layout-only. Keeps page content width and horizontal padding consistent. Typically applied to main or section.레이아웃 전용. 페이지 본문 폭과 좌우 여백을 일관되게 유지합니다. 보통 main/section 에 적용합니다.

Layout & structure

Divider

A horizontal or vertical line that separates content.콘텐츠를 구분하는 수평 또는 수직 선입니다.

.qf-dividerlayer: generic

Preview


<hr class="qf-divider">

Variants


qf-divider--vertical

Required tokens

--divider --s-5 --s-4

Accessibility

Express a meaningful separation with hr or role=separator. If it is purely decorative, consider aria-hidden.의미 있는 구분은 hr 또는 role=separator 로 표현합니다. 순수 장식이면 aria-hidden 을 고려합니다.

Layout & structure

AppShell

A general app shell that lays out a header, sidebar, main content, and an optional right aside. Columns and the header derive from which regions you include — one, two, or three columns, with or without a header, no modifier needed. A container query collapses the sidebar and aside to a single column when the shell gets narrow (mobile). Tune widths with --sidenav-w and --aside-w.헤더, 사이드바, 본문, 우측 보조 패널을 배치하는 범용 앱 셸입니다. 어떤 영역을 넣느냐로 1, 2, 3단과 헤더 유무가 자동 결정됩니다(별도 모디파이어 불필요). 컨테이너 쿼리로 셸 폭이 좁아지면(모바일) 사이드바, aside가 접혀 단일 컬럼이 됩니다. 폭은 --sidenav-w, --aside-w로 조절합니다.

.qf-app-shelllayer: generic

Preview

Dashboard

A general app shell that lays out a header, sidebar, and main content. Columns derive from which regions you include.

<div class="qf-app-shell">
  <header class="qf-app-shell__navbar">
    <nav class="qf-navbar">
      <span class="qf-navbar__brand">Acme</span>
      <span class="qf-navbar__spacer">
      </span>
      <a class="qf-navbar__link" aria-current="page">Dashboard</a>
      <a class="qf-navbar__link">Reports</a>
    </nav>
  </header>
  <nav class="qf-app-shell__sidenav qf-sidenav">
    <div class="qf-sidenav__section">Menu</div>
    <a class="qf-sidenav__item" aria-current="page">Dashboard</a>
    <a class="qf-sidenav__item">Members</a>
    <a class="qf-sidenav__item">Settings</a>
  </nav>
  <main class="qf-app-shell__main">
    <h1>Dashboard</h1>
    <p>A general app shell that lays out a header, sidebar, and main content. Columns derive from which regions you include.</p>
  </main>
</div>

Examples예시

Dashboard

Header plus content — include only the navbar and main.

1 column, with header

Dashboard

Just the content area — include only main.

1 column, no header

Dashboard

Sidebar plus content under a header — the default layout.

2 columns, with header

Dashboard

Sidebar plus content, with no top header.

2 columns, no header

Dashboard

Sidebar, content, and a right aside — a three-column workspace.

3 columns, with header

Dashboard

Three columns without a header bar.

3 columns, no header

Dashboard

The same three-column markup: at a narrow width the sidebar and aside collapse to a single column. The app surfaces them via a drawer or tab bar.

Mobile (≤600px — sidebar & aside collapse)

Variants

qf-app-shell__navbar qf-app-shell__sidenav qf-app-shell__main qf-app-shell__aside qf-app-shell--locked qf-scroll-region

Required tokens

--sidenav-w --aside-w --shell-vh

Accessibility

This is a layout container. Place landmarks (header, nav, main) inside it so assistive technology can recognize each region. Control the sidebar width with --sidenav-w.레이아웃 컨테이너입니다. 내부에 landmark(header, nav, main)를 두어 보조기술이 영역을 인식하게 합니다. 사이드바 폭은 --sidenav-w 로 조절합니다.

Layout & structure

PageHeader

A page header that groups the page title, subtitle, and actions into a single row. --hero is for a site's first screen: a larger title (32px) and a roomier subtitle at body size and reading width.페이지 제목, 부제, 액션을 한 줄로 묶는 페이지 헤더입니다. --hero 는 사이트 첫 화면용으로 제목을 한 단계 크게(32px), 부제를 본문 크기와 가독 폭으로 넉넉히 둡니다.

.qf-page-headerlayer: generic

Preview

Members

12 members

<div class="qf-page-header">
  <div>
    <h1 class="qf-page-header__title">Members</h1>
    <p class="qf-page-header__subtitle">12 members</p>
  </div>
  <div class="qf-page-header__actions">
    <button class="qf-btn qf-btn--primary">Invite</button>
  </div>
</div>

Variants

Members

12 members

qf-page-header--hero

Parts & more: 구성 요소, 기타: qf-page-header__title qf-page-header__subtitle qf-page-header__actions

Required tokens

--s-7 --fs-24 --text-strong --text-muted --tracking-tight --fs-32 --fs-16 --text-secondary --container-w-narrow --s-8 --s-5 --s-2

Accessibility

Make the title an h1 (or a heading appropriate to the page hierarchy) to convey document structure. Keep the action group's visual order in sync with its DOM order.제목은 h1(또는 페이지 계층에 맞는 heading)으로 두어 문서 구조를 전달합니다. 액션 묶음은 시각/DOM 순서를 일치시킵니다.

Layout & structure

TwoCol

A two-column frame for wide screens (main column + aside). Inside qf-container--wide (1200px), from 1100px up the main column (max --container-w-reading, 720px) and the aside (--sz-aside, 300px) sit 40px apart, centered as a pair, so between 1100 and 1200 the main stays at 720 and the aside does not shrink. Below that it is one column — the main column centers like today's reading container and the aside drops below it (gap --s-10). In two columns the aside sticks under the sticky top bar (adjust with --qf-aside-top) and slides to the top when the bar hides (is-hidden). Keep the aside shorter than the viewport — about 560px, up to three sections, sized for a 768px-tall laptop (real viewport ≈ 650–680); a taller aside gets its bottom cut off.넓은 화면의 2열 틀입니다(본문 열 + 사이드 열). qf-container--wide(1200px) 안에 두면 1100px 이상에서 본문 열(최대 --container-w-reading 720px)과 사이드 열(--sz-aside 300px)이 간격 40px 로 가운데 정렬되어, 1100~1200 에서도 본문이 720 을 유지하고 사이드가 좁아지지 않습니다. 그 아래에서는 1열 — 본문 열이 지금의 reading 컨테이너처럼 가운데 오고 사이드는 본문 뒤로 내려갑니다(간격 --s-10). 2열에서 사이드는 고정 상단 바 아래에 sticky 로 붙고(--qf-aside-top 으로 바 높이 조정), 바가 is-hidden 으로 숨으면 맨 위로 미끄러집니다. 사이드는 뷰포트보다 짧게 두세요 — 768px 높이 노트북(실제 뷰포트 ≈ 650~680)을 기준으로 약 560px, 섹션 3개 이내. 길면 아래가 가려집니다.

.qf-twocollayer: generic

Preview

Politics4 communities · 9 posts

Supreme Court admits chief justice filed false expense reports

The court acknowledged on Tuesday that expense reports filed by its chief justice were inaccurate.

<div class="qf-twocol" style="max-width:100%">
  <main class="qf-twocol__main">
    <article class="qf-story">
      <div class="qf-story__kicker">
        <span class="qf-eyebrow">Politics</span>
        <span>4 communities · 9 posts</span>
      </div>
      <h2 class="qf-story__title">Supreme Court admits chief justice filed false expense reports</h2>
      <p class="qf-story__summary">The court acknowledged on Tuesday that expense reports filed by its chief justice were inaccurate.</p>
    </article>
  </main>
  <aside class="qf-twocol__aside qf-aside">
    <section class="qf-aside__section">
      <h2 class="qf-aside__title">Trending now</h2>
      <ol class="qf-ranklist" role="list">
        <li class="qf-ranklist__item">
          <a class="qf-ranklist__link" href="#r1">
            <span class="qf-ranklist__title">Supreme Court admits false expense reports</span>
            <span class="qf-ranklist__meta">8 communities, 51 posts</span>
          </a>
        </li>
        <li class="qf-ranklist__item">
          <a class="qf-ranklist__link" href="#r2">
            <span class="qf-ranklist__title">Central bank holds rates</span>
            <span class="qf-ranklist__meta">3 communities, 5 posts</span>
          </a>
        </li>
      </ol>
    </section>
  </aside>
</div>

Variants

qf-twocol__main qf-twocol__aside

Required tokens

--container-w-reading --sz-aside --s-9 --s-10 --s-6 --h-navbar --dur-base --ease-standard

Accessibility

Put the main element first and the aside after it so reading order stays main → aside in one column too. Make aside section titles h2 so they enter the outline. Keep the aside short enough that every focusable item inside it is visible while stuck.본문(main 요소)을 먼저, 사이드(aside 요소)를 뒤에 두어 1열에서도 읽기 순서가 본문 → 사이드가 되게 합니다. 사이드의 섹션 제목은 h2 로 두어 문서 개요에 들어가게 합니다. sticky 사이드가 가리는 영역이 없도록 사이드 안에는 포커스 대상이 뷰포트 안에 다 보이는 길이만 둡니다.

Layout & structure

Aside

Content of the aside column: a stack of sections (qf-aside__section), each with a title (qf-aside__title — 12px 600 caps, --text-muted, same tone as qf-keypoints__title) and a body. One step quieter than the main column (14px, --text-secondary), --s-6 between sections, no boxes or rules — the column itself is the separation. Inside go qf-ranklist (ranking), a group of qf-stat--sm (numbers), qf-chips with qf-chip__count (per-category counts), and qf-sources with qf-source--link (community links).사이드 열의 내용입니다: 섹션(qf-aside__section) 묶음, 섹션은 제목(qf-aside__title — 12px 600 대문자, --text-muted, qf-keypoints__title 과 같은 톤)과 본문. 본문보다 한 단계 조용한 톤(14px, --text-secondary)이고 섹션 사이 --s-6. 열 자체가 구분이므로 상자·선을 두르지 않습니다. 안에는 qf-ranklist(순위), qf-stat--sm 묶음(숫자), qf-chips + qf-chip__count(분류별 건수), qf-sources + qf-source--link(커뮤니티 링크) 를 둡니다.

.qf-asidelayer: generic

Preview

<aside class="qf-aside" style="max-width:300px">
  <section class="qf-aside__section" aria-labelledby="as1">
    <h2 class="qf-aside__title" id="as1">Today in numbers</h2>
    <div class="qf-cluster" style="--qf-gap:var(--s-6)">
      <div class="qf-stat qf-stat--sm">
        <span class="qf-stat__value">24</span>
        <span class="qf-stat__label">issues today</span>
      </div>
      <div class="qf-stat qf-stat--sm">
        <span class="qf-stat__value">12</span>
        <span class="qf-stat__label">communities</span>
      </div>
      <div class="qf-stat qf-stat--sm">
        <span class="qf-stat__value">3 min</span>
        <span class="qf-stat__label">since update</span>
      </div>
    </div>
  </section>
  <section class="qf-aside__section" aria-labelledby="as2">
    <h2 class="qf-aside__title" id="as2">By category</h2>
    <div class="qf-chips">
      <a class="qf-chip" href="#c1">
        Politics
        <span class="qf-chip__count">7</span>
      </a>
      <a class="qf-chip" href="#c2">
        Society
        <span class="qf-chip__count">5</span>
      </a>
      <a class="qf-chip" href="#c3">
        Sports
        <span class="qf-chip__count">4</span>
      </a>
    </div>
  </section>
  <section class="qf-aside__section" aria-labelledby="as3">
    <h2 class="qf-aside__title" id="as3">Communities</h2>
    <div class="qf-sources">
      <a class="qf-source qf-source--link" href="#s1">Clien</a>
      <a class="qf-source qf-source--link" href="#s2">Ruliweb</a>
      <a class="qf-source qf-source--link" href="#s3">Ppomppu</a>
      <a class="qf-source qf-source--link" href="#s4">82cook</a>
    </div>
  </section>
</aside>

Variants

qf-aside__section qf-aside__title

Required tokens

--s-6 --s-3 --fs-14 --fs-12 --lh-tight --tracking-caps --text-secondary --text-muted

Accessibility

Use the aside element and make section titles h2 (or the heading level that fits the page). Link each section to its title with aria-labelledby so assistive technology names the region. The uppercase transform is visual only.aside 요소에 두고 섹션 제목은 h2(또는 페이지 계층에 맞는 heading)로 둡니다. 섹션마다 aria-labelledby 로 제목을 연결하면 보조기기가 영역 이름을 읽습니다. 대문자 변환은 시각 표현입니다.

Layout & structure

Footer

A footer within the reading width: a top rule, a note paragraph (qf-footer__note, 13px secondary tone, limited measure), and a link row (qf-footer__links). Keep the note to one paragraph — more small print stops being read. Links are 13px with vertical padding for a 24px+ tap target, and the row keeps its spacing when it wraps on phones. Bottom padding includes the safe area. A leading icon (e.g. RSS) inside a link sits with a --s-1 gap.읽기 폭 안의 바닥글입니다: 위 선, 안내 문단(qf-footer__note, 13px 보조 톤, 줄 길이 제한), 링크 줄(qf-footer__links). 안내는 한 문단으로 쓰기를 권합니다 — 둘 이상이면 작은 글씨가 길어져 읽히지 않습니다. 링크는 13px 에 세로 패딩으로 탭 대상 24px 이상이고 폰에서 두 줄로 감싸도 줄 사이 간격이 유지됩니다. 아래 여백은 안전 영역을 더합니다. 링크 앞에 아이콘(RSS 등)을 두면 간격 --s-1 로 붙습니다.

.qf-footerlayer: generic

Preview

<footer class="qf-footer">
  <p class="qf-footer__note">Summaries are written by AI from community posts and may be inaccurate. Check the original posts for details.</p>
  <nav class="qf-footer__links" aria-label="Site">
    <a href="#about">About</a>
    <a href="#removal">Correction and removal requests</a>
    <a href="#privacy">Privacy policy</a>
  </nav>
</footer>

Variants

qf-footer__note qf-footer__links

Required tokens

--s-10 --s-7 --s-6 --safe-bottom --border --text-muted --text-secondary --text --fs-13 --lh-normal --container-w-narrow --s-2 --s-4 --s-5 --s-1 --ring-focus --r-xs

Accessibility

Use the footer element (contentinfo) and group the links in nav[aria-label] or a ul. Links rely on the link-row context plus hover underline rather than a permanent underline, so use this only in a footer link row. 13px is the floor for secondary text; do not make the note smaller.footer 요소(contentinfo)에 두고 링크 줄은 nav[aria-label] 또는 ul 로 묶습니다. 링크는 밑줄 대신 세로 패딩과 hover 밑줄을 쓰므로 바닥글 맥락(링크 줄)에서만 씁니다. 글자 13px 는 보조 정보의 바닥이며 안내 본문을 더 작게 두지 않습니다.

Actions

Button

A primary action button.기본 액션 버튼입니다.

.qf-btnlayer: generic

Preview

<button class="qf-btn qf-btn--primary">Save</button>

Variants

qf-btn--primary
qf-btn--secondary
qf-btn--ghost
qf-btn--danger
qf-btn--link
qf-btn--sm
qf-btn--lg
qf-btn--icon
qf-btn--touch

Required tokens

--accent --text --text-onAccent --border --r-md --s-3 --s-5 --dur-fast --bg-selected --text-strong --m-touch

Accessibility

Make keyboard focus visible and convey the disabled state via disabled or aria-disabled. For icon-only buttons, add meaning with aria-label, and keep text contrast at AA 4.5:1. Ghost/icon buttons used as toggles (aria-pressed) show the pressed state as the selected surface; pair it with an icon or label change so state does not rely on color alone. Button labels do not wrap (white-space: nowrap); shorten long labels or give the button width. Add --touch to a standalone icon button (e.g. share next to a title) to extend a 44px hit area with a transparent ::after on touch devices while keeping its visual size (automatic inside qf-navbar). Do not use it in dense toolbars (gaps under 8px) — it would steal taps from neighbours.키보드 포커스가 보이도록 하고, 비활성은 disabled 또는 aria-disabled 로 전달합니다. 아이콘 전용 버튼은 aria-label 로 의미를 보충하고, 텍스트 대비는 AA 4.5:1 을 지킵니다. 토글(aria-pressed)로 쓰는 ghost/icon 버튼은 눌린 상태가 selected 표면으로 표시됩니다 — 아이콘·라벨 전환과 함께 두어 색에만 기대지 않습니다. 버튼 라벨은 줄바꿈하지 않습니다(white-space: nowrap) — 긴 라벨은 줄이거나 너비를 주세요. 단독으로 선 아이콘 버튼(제목 옆 공유 등)에는 --touch 를 붙이면 터치 환경에서 보이는 크기는 그대로 두고 44px 히트 영역을 투명 ::after 로 넓힙니다(qf-navbar 안은 자동). 밀집 툴바(간격 8px 미만)에는 쓰지 않습니다 — 이웃 버튼의 탭을 가로챕니다.

Actions

IconButton

A clean, icon-only button designed to sit in list rows.리스트 행에 들어가는 군더더기 없는 아이콘 전용 버튼입니다.

.qf-row-iconbtnlayer: generic

Preview

<button class="qf-row-iconbtn" aria-label="Settings">
  <svg class="qf-icon qf-icon--sm" aria-hidden="true">
    <use href="#qf-i-settings"/>
  </svg>
</button>

Examples예시

Settings
Search
More
Edit
Notifications

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--text-muted --text-strong --accent --r-xs

Accessibility

Since only an icon is shown, the action must always be conveyed via aria-label; keep keyboard focus visible and signal the disabled state with disabled. Do not rely on color alone to convey state.아이콘만 표시하므로 aria-label 로 동작을 반드시 전달하고, 키보드 포커스를 보이게 하며 비활성은 disabled 로 알립니다. 색만으로 상태를 전하지 않도록 합니다.

Actions

Link

An inline text link within body content.본문 안의 인라인 텍스트 링크입니다.

.qf-linklayer: generic

Preview

<a class="qf-link" href="/docs">View docs</a>

Examples예시

Default
Unresolved wikilink

Variants

qf-link--muted
qf-link--unresolved

Required tokens

--link --link-hover --r-xs --text-secondary --text-muted

Accessibility

Built as a real a[href] to preserve keyboard and screen reader navigation, with a hover underline and sufficient contrast so meaning is not carried by color alone. The focus ring is visible. An unresolved wikilink (qf-link--unresolved) has no href and is marked aria-disabled="true", conveying the unresolved state with a dotted underline and color rather than color alone.실제 a[href] 로 만들어 키보드/스크린리더 탐색을 보존하고, hover 밑줄과 충분한 대비로 색 단독 의존을 피합니다. 포커스 ring 이 보입니다. 미해결 위키링크(qf-link--unresolved)는 href 를 비우고 aria-disabled="true" 로 표시하며, 점선 밑줄과 색으로 미해결을 색 단독이 아니게 전달합니다.

Actions

ButtonGroup

A group that joins adjacent buttons into a single unit (split actions, segments).인접한 버튼들을 한 덩어리로 결합한 그룹입니다(분할 액션, 세그먼트).

.qf-btn-grouplayer: generic

Preview

<div class="qf-btn-group" role="group" aria-label="Sort">
  <button class="qf-btn qf-btn--secondary" aria-pressed="true">List</button>
  <button class="qf-btn qf-btn--secondary">Grid</button>
</div>

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--r-md

Accessibility

Convey the unit's meaning with role=group and aria-label. For toggle segments, set aria-pressed on each button.role=group 과 aria-label 로 묶음의 의미를 전달합니다. 토글 세그먼트면 각 버튼에 aria-pressed 를 둡니다.

Actions

CopyButton

A standalone button that copies an id, path, URL, or similar to the clipboard. Copy completion is reflected via data-copied=true (the consumer handles the toggle).id, 경로, URL 등을 클립보드에 복사하는 독립 버튼입니다. 복사 완료는 data-copied=true 로 상태를 표시합니다(토글은 소비처).

.qf-copy-btnlayer: generic

Preview

<button class="qf-copy-btn" type="button">
  <svg class="qf-icon qf-icon--sm" aria-hidden="true">
    <use href="#qf-i-copy"/>
  </svg>
  Copy
</button>

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--bg-elevated --border --text-secondary --bg-hover --ok-400 --r-sm --font-mono

Accessibility

Convey the action and result with text next to the icon (Copy/Copied), and announce completion not just with color but with text and aria-live.아이콘 옆 텍스트(복사/복사됨)로 동작과 결과를 전달하고, 완료는 색뿐 아니라 텍스트, aria-live 로 알립니다.

Actions

ToTop

A round "back to top" icon button floating at the bottom right (qf-i-chevron-up). Hidden by default; consumer JS adds is-shown once the page is scrolled more than a screen. 44px tap target, with the phone safe area added. Set --qf-totop-bottom (default --safe-bottom) to lift it above a bottom ad or a mobile tab bar (qf-m-tabbar, which has a higher z-index).오른쪽 아래에 떠 있는 둥근 "맨 위로" 아이콘 버튼입니다(qf-i-chevron-up). 기본은 숨겨져 있고, 한 화면 넘게 내려갔을 때 소비처 JS 가 is-shown 을 붙이면 나타납니다. 44px 탭 대상이며 폰의 안전 영역을 더합니다. 바닥 광고나 모바일 탭바(qf-m-tabbar, z-index 가 더 높음) 위로 올릴 때는 --qf-totop-bottom 을 지정합니다(기본 --safe-bottom).

.qf-totoplayer: generic

Preview

<div style="position:relative;height:120px">
  <button class="qf-totop is-shown" type="button" aria-label="Back to top" style="position:absolute">
    <svg class="qf-icon qf-icon--md" aria-hidden="true">
      <use href="#qf-i-chevron-up"/>
    </svg>
  </button>
</div>

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--s-5 --safe-bottom --z-sticky --m-touch --border --border-strong --r-pill --bg-elevated --bg-hover --text --elev-3 --s-3 --dur-fast --ease-standard --ring-focus

Accessibility

Give the button aria-label="Back to top". While hidden it is visibility: hidden, so it leaves the focus order and is only tappable/focusable when shown. The focus ring is visible. On press the consumer scrolls to top and ideally moves focus to the first element of the content.button 에 aria-label="맨 위로" 를 둡니다. 숨김 상태는 visibility: hidden 이라 포커스 순서에서 빠지고, 보일 때만 탭·포커스됩니다. 포커스 링이 보입니다. 누르면 소비처가 window.scrollTo 로 올리고 포커스를 본문 첫 요소로 옮기면 좋습니다.

Forms & inputs

Input

A single-line text input field.한 줄 텍스트 입력 필드입니다.

.qf-inputlayer: generic

Preview

<input class="qf-input" type="text" aria-label="Search" placeholder="Search">

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--bg-input --text --border --border-strong --text-muted --r-lg --s-4 --ring-danger

Accessibility

Convey the error state with aria-invalid="true", reinforced by the border and focus ring. Associate the label via a label element or aria-label, and tie helper text together with aria-describedby.오류 상태는 aria-invalid="true" 로 전달하며 보더와 링으로 함께 표시합니다. 라벨은 label 요소나 aria-label 로 연결하고, 안내문은 aria-describedby 로 묶습니다.

Forms & inputs

InputGroup

Groups an input with icon buttons on either side as one unit (no wrapping; the input may shrink). Example: previous/next-day arrows (qf-btn--ghost qf-btn--icon qf-btn--sm qf-btn--touch + qf-i-chevron-left/right) around a date input.입력과 양옆 아이콘 버튼을 한 덩어리로 묶습니다(줄바꿈 없음, 입력은 줄어들 수 있음). 예: 날짜 입력 양옆의 이전 날/다음 날 화살표(qf-btn--ghost qf-btn--icon qf-btn--sm qf-btn--touch + qf-i-chevron-left/right).

.qf-input-grouplayer: generic

Preview

<div class="qf-input-group">
  <button class="qf-btn qf-btn--ghost qf-btn--icon qf-btn--sm qf-btn--touch" type="button" aria-label="Previous day">
    <svg class="qf-icon qf-icon--sm" aria-hidden="true">
      <use href="#qf-i-chevron-left"/>
    </svg>
  </button>
  <input class="qf-input" type="date" value="2026-10-03" aria-label="Go to date">
  <button class="qf-btn qf-btn--ghost qf-btn--icon qf-btn--sm qf-btn--touch" type="button" aria-label="Next day">
    <svg class="qf-icon qf-icon--sm" aria-hidden="true">
      <use href="#qf-i-chevron-right"/>
    </svg>
  </button>
</div>

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--s-1

Accessibility

Give the arrow buttons an aria-label (previous day, next day) and the input a label or aria-label. Disable a button at the end of the range. The 28px arrows carry qf-btn--touch so they get a 44px hit area on touch devices (overlapping the input by 8px is acceptable).화살표 버튼에는 aria-label(이전 날, 다음 날)을 두고 입력에는 label 이나 aria-label 을 둡니다. 범위 끝에서는 버튼을 disabled 로. 화살표는 28px 라 qf-btn--touch 를 붙여 터치 환경에서 44px 히트 영역을 받습니다(입력 위로 8px 겹치는 정도는 허용).

Forms & inputs

Textarea

A multi-line text input field that adds height and vertical resizing on top of qf-input. --mono is for prompts and code (--font-mono, 12px).여러 줄 텍스트를 입력하는 입력 필드입니다. qf-input 위에 높이, 세로 리사이즈를 더합니다. --mono 는 지시문·코드 편집용(--font-mono 12px).

.qf-textarealayer: generic

Preview

<textarea class="qf-input qf-textarea" rows="3" aria-label="Notes" placeholder="Enter a note">
</textarea>

Variants

qf-textarea--mono

Required tokens

--bg-input --border --text --r-lg --s-3 --s-4 --ring-accent --font-mono --fs-12 --lh-normal

Accessibility

Associate the label via for/id or a wrapping label, and indicate errors with aria-invalid=true. Allow vertical-only resizing to prevent layout breakage.label 을 for/id 또는 감싼 라벨로 연결하고, 오류는 aria-invalid=true 로 표시합니다. 리사이즈는 세로만 허용해 레이아웃 깨짐을 막습니다.

Forms & inputs

Field

A form field wrapper that groups the label, control, helper text, and error message.라벨, 컨트롤, 도움말, 오류 메시지를 묶는 폼 필드 래퍼입니다.

.qf-fieldlayer: generic

Preview

<label class="qf-field">
  <span class="qf-field__label">Email</span>
  <input class="qf-input" type="email" placeholder="you@example.com">
  <span class="qf-field__hint">Enter your work email.</span>
</label>

Variants

qf-field__label qf-field__hint qf-field__error

Required tokens

--s-2 --fs-12 --text-secondary --text-muted --danger-400 --tracking-caps

Accessibility

Associate the label with the control (by wrapping it or via for/id), and link error text with aria-describedby. Convey errors with text, not color alone.라벨을 컨트롤과 연결하고(감싸거나 for/id), 오류 텍스트는 aria-describedby 로 연결합니다. 색뿐 아니라 텍스트로 오류를 전달합니다.

Forms & inputs

DateRange

A range input that groups a start and end date, using the browser's native date picker for calendar selection.시작, 종료 날짜를 묶는 범위 입력입니다. 달력 선택은 브라우저 native date picker 를 사용합니다.

.qf-daterangelayer: generic

Preview

~
<div class="qf-daterange">
  <input class="qf-input" type="date" aria-label="Start date" value="2026-06-01">
  <span class="qf-daterange__sep">~</span>
  <input class="qf-input" type="date" aria-label="End date" value="2026-06-16">
</div>

Variants

qf-daterange__sep

Required tokens

--s-3 --text-muted --bg-input --border --r-lg

Accessibility

Associate each input with a from/to label via aria-label, and also convey the range meaning (start to end).각 input 에 from/to 라벨을 aria-label 로 연결하고, 범위 의미(시작~종료)를 함께 전달합니다.

Forms & inputs

ToggleRow

A settings toggle row that groups a title, description, and a control on the right into a single line.제목과 설명, 우측 컨트롤을 한 줄로 묶는 설정 토글 행입니다.

.qf-toggle-rowlayer: generic

Preview

Notifications
Receive desktop notifications
<div class="qf-toggle-row">
  <div class="qf-toggle-row__text">
    <div class="qf-toggle-row__title" id="r1">Notifications</div>
    <div class="qf-toggle-row__desc">Receive desktop notifications</div>
  </div>
  <button class="qf-switch" role="switch" aria-checked="true" aria-labelledby="r1">
  </button>
</div>

Variants

qf-toggle-row__text qf-toggle-row__title qf-toggle-row__desc

Required tokens

--s-5 --divider --fs-15 --fs-13 --text-strong --text-muted --font-sans

Accessibility

Associate the row's title text as the label for the switch on the right so screen readers know what is being turned on and off.행의 제목 텍스트를 우측 스위치의 라벨로 연결해 무엇을 켜고 끄는지 화면 낭독기에 전달합니다.

Forms & inputs

Switch

A switch that toggles between on and off states.켜짐, 꺼짐 상태를 토글하는 스위치입니다.

.qf-switchlayer: generic

Preview

<button class="qf-switch" role="switch" aria-checked="true" aria-label="Turn on notifications">
</button>

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--bg-track --accent --r-pill --dur-fast --dur-base --ease-spring

Accessibility

Convey state with role=switch and aria-checked, and associate a label. Make it togglable via keyboard and keep focus visible.role=switch와 aria-checked로 상태를 전달하고 라벨을 연결합니다. 키보드로 토글 가능하며 포커스가 보이게 합니다.

Forms & inputs

OtpInput

A one-time code input field where a verification code is entered one digit per box.인증 코드를 자리별로 입력하는 일회용 코드 입력란입니다.

.qf-otp-inputlayer: generic

Preview

<div class="qf-otp-input" role="group" aria-label="6-digit verification code">
  <input class="qf-otp-input__digit" inputmode="numeric" maxlength="1" aria-label="Digit 1">
  <input class="qf-otp-input__digit" inputmode="numeric" maxlength="1" aria-label="Digit 2">
  <input class="qf-otp-input__digit" inputmode="numeric" maxlength="1" aria-label="Digit 3">
  <input class="qf-otp-input__digit" inputmode="numeric" maxlength="1" aria-label="Digit 4">
  <input class="qf-otp-input__digit" inputmode="numeric" maxlength="1" aria-label="Digit 5">
  <input class="qf-otp-input__digit" inputmode="numeric" maxlength="1" aria-label="Digit 6">
</div>

Variants

qf-otp-input__digit

Required tokens

--s-2 --s-10 --fs-24 --font-mono --accent --ring-accent --danger-400 --ring-danger

Accessibility

Each digit box shows an accent ring on focus for visible focus, and errors are conveyed beyond color with aria-invalid and a danger ring. inputMode=numeric brings up the numeric keypad, and a label communicates the field's purpose.각 자리 입력은 포커스 시 accent ring으로 가시하고, 오류는 aria-invalid와 danger ring으로 색 외 상태를 함께 전합니다. inputMode=numeric로 숫자 키패드를 제공하고 라벨로 용도를 안내합니다.

Forms & inputs

PasswordStrengthMeter

Displays password strength in real time using a bar and a label.비밀번호 강도를 막대와 라벨로 실시간 표시합니다.

.qf-strength-meterlayer: generic

Preview

Strong

<div class="qf-strength-meter" data-strength="strong">
  <div class="qf-strength-meter__track">
    <span class="qf-strength-meter__bar is-on">
    </span>
    <span class="qf-strength-meter__bar is-on">
    </span>
    <span class="qf-strength-meter__bar is-on">
    </span>
  </div>
  <p class="qf-strength-meter__label" aria-live="polite">Strong</p>
</div>

Examples예시

Weak

Weak

Medium

Medium

Strong

Strong

Variants

qf-strength-meter__track qf-strength-meter__bar qf-strength-meter__label

Required tokens

--s-1 --s-2 --bg-hover --danger-400 --warn-400 --ok-400 --ok-600 --r-sm

Accessibility

Strength is conveyed through label text (weak, fair, strong) alongside the data-strength bar color, avoiding reliance on color alone. aria-live announces changes in strength.강도는 data-strength 막대 색과 함께 라벨 텍스트(약함, 보통, 강함)로 전달해 색 단독 의존을 피합니다. aria-live로 강도 변화를 알립니다.

Forms & inputs

BackupCodes

A list that displays one-time recovery codes for two-factor authentication.2단계 인증의 일회용 복구 코드를 보여주는 목록입니다.

.qf-backup-codeslayer: generic

Preview

  • A1B2-C3D4
  • E5F6-G7H8
  • J9K0-L1M2
  • N3P4-Q5R6
  • S7T8-U9V0
  • W1X2-Y3Z4
  • B5C6-D7E8
  • F9G0-H1J2
<ul class="qf-backup-codes" aria-label="Backup codes">
  <li class="qf-backup-codes__code">A1B2-C3D4</li>
  <li class="qf-backup-codes__code is-used">E5F6-G7H8</li>
  <li class="qf-backup-codes__code">J9K0-L1M2</li>
  <li class="qf-backup-codes__code">N3P4-Q5R6</li>
  <li class="qf-backup-codes__code">S7T8-U9V0</li>
  <li class="qf-backup-codes__code">W1X2-Y3Z4</li>
  <li class="qf-backup-codes__code">B5C6-D7E8</li>
  <li class="qf-backup-codes__code">F9G0-H1J2</li>
</ul>

Variants

qf-backup-codes__code

Required tokens

--s-2 --s-4 --bg-input --border --r-md --font-mono --text-strong --text-muted

Accessibility

Used codes are distinguished with a strikethrough and dimmed color; it is best to also convey their state through text and not visuals alone. A monospace alignment keeps the codes legible.사용한 코드는 취소선과 함께 흐린 색으로 구분하며, 상태를 시각만이 아니라 텍스트로 함께 안내하면 좋습니다. mono 정렬로 코드 가독성을 확보합니다.

Forms & inputs

Checkbox

A checkbox for confirmations such as agreeing to terms.약관 동의 등 확인을 받는 체크박스입니다.

.qf-checkboxlayer: generic

Preview

<label class="qf-checkbox">
  <input class="qf-checkbox__input" type="checkbox">
  <span class="qf-checkbox__label">I agree to the terms</span>
</label>

Variants

qf-checkbox__input qf-checkbox__label

Required tokens

--s-3 --s-5 --accent --fs-13 --text-secondary --lh-normal

Accessibility

Only accent-color is layered onto the native input to preserve focus-visible focus visibility. The label and input are associated so that clicking the label works and screen readers read it correctly.네이티브 input 위에 accent-color만 얹어 focus-visible 포커스 가시를 보존합니다. label과 input을 연결해 라벨 클릭과 스크린리더 읽기를 보장합니다.

Forms & inputs

Select

A dropdown select field that wraps a native select to match the design.네이티브 select 를 디자인에 맞춰 감싸는 드롭다운 선택 필드입니다.

.qf-selectlayer: generic

Preview

<span class="qf-select">
  <select aria-label="Country">
    <option>Korea</option>
    <option>Japan</option>
  </select>
</span>

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--bg-input --border --text --r-lg --s-4 --s-8 --text-muted --ring-accent

Accessibility

Because the core is a native select, keyboard and screen reader behavior is preserved as-is. Associate the label via for/id, and indicate errors with aria-invalid=true.내부는 네이티브 select 라 키보드/스크린리더 동작을 그대로 보존합니다. label 을 for/id 로 연결하고, 오류는 aria-invalid=true 로 표시합니다.

Forms & inputs

Radio

Pairs a single-select radio button with its label on one row.단일 선택 라디오 버튼과 라벨을 한 행으로 묶습니다.

.qf-radiolayer: generic

Preview

<div class="qf-stack" style="gap:var(--s-2)">
  <label class="qf-radio">
    <input class="qf-radio__input" type="radio" name="plan" checked>
    <span class="qf-radio__label">Free</span>
  </label>
  <label class="qf-radio">
    <input class="qf-radio__input" type="radio" name="plan">
    <span class="qf-radio__label">Pro</span>
  </label>
  <label class="qf-radio">
    <input class="qf-radio__input" type="radio" name="plan">
    <span class="qf-radio__label">Team</span>
  </label>
</div>

Variants

qf-radio__input qf-radio__label

Required tokens

--s-3 --s-5 --accent --fs-13 --text-secondary

Accessibility

Group options under the same name and wrap them in qf-choice-list. Only accent-color is layered onto the native input to preserve focus visibility.같은 name 으로 그룹을 묶고 qf-choice-list 로 감쌉니다. 네이티브 input 위에 accent-color 만 얹어 포커스 가시를 보존합니다.

Forms & inputs

ChoiceList

A container that groups a set of checkboxes or radios together with a title.체크박스나 라디오 그룹을 제목과 함께 묶는 컨테이너입니다.

.qf-choice-listlayer: generic

Preview

Notifications
<fieldset class="qf-choice-list">
  <legend class="qf-choice-list__legend">Notifications</legend>
  <label class="qf-checkbox">
    <input class="qf-checkbox__input" type="checkbox" checked>
    <span class="qf-checkbox__label">Email</span>
  </label>
  <label class="qf-checkbox">
    <input class="qf-checkbox__input" type="checkbox">
    <span class="qf-checkbox__label">Push</span>
  </label>
  <label class="qf-checkbox">
    <input class="qf-checkbox__input" type="checkbox">
    <span class="qf-checkbox__label">SMS</span>
  </label>
</fieldset>

Variants

qf-choice-list__legend

Required tokens

--s-3 --s-1 --fs-12 --text-secondary --tracking-caps

Accessibility

Build it as a fieldset and convey the group title with legend (qf-choice-list__legend). Use radio for single selection and checkbox for multiple selection.fieldset 으로 만들고 legend(qf-choice-list__legend)로 그룹 제목을 전달합니다. 단일 선택은 radio, 다중 선택은 checkbox 를 씁니다.

Forms & inputs

FormLayout

A layout that arranges form fields vertically and provides horizontal rows and an action row.폼 필드를 세로로 배치하고 가로 행과 액션열을 제공하는 레이아웃입니다.

.qf-formlayer: generic

Preview

<form class="qf-form">
  <div class="qf-form__row">
    <label class="qf-field">
      <span class="qf-field__label">Name</span>
      <input class="qf-input">
    </label>
  </div>
  <div class="qf-form__actions">
    <button class="qf-btn qf-btn--primary">Save</button>
  </div>
</form>

Variants

qf-form__row qf-form__actions

Required tokens

--s-5 --s-4 --s-3 --grid-cell-min

Accessibility

Apply it to a form element, and associate each field's label/hint/error via qf-field. __row wraps automatically at narrow widths.form 요소에 적용하고 각 필드는 qf-field 로 라벨/힌트/에러를 연결합니다. __row 는 좁은 폭에서 자동 줄바꿈됩니다.

Forms & inputs

Search

A search input field with an icon and a clear button.아이콘과 클리어 버튼을 갖춘 검색 입력 필드입니다.

.qf-searchlayer: generic

Preview

<div class="qf-search">
  <span class="qf-search__icon" aria-hidden="true">
    <svg class="qf-icon qf-icon--sm">
      <use href="#qf-i-search"/>
    </svg>
  </span>
  <input class="qf-search__input" type="search" aria-label="Search" placeholder="Search">
  <button class="qf-search__clear" aria-label="Clear search">×</button>
</div>

Variants

qf-search__icon qf-search__input qf-search__clear

Required tokens

--bg-input --border --accent --r-lg --s-4 --text --text-muted

Accessibility

Give the input[type="search"] an aria-label or an associated label. Mark the icon aria-hidden, and give the clear button an aria-label (e.g. "Clear search").input[type=search] 에 aria-label 또는 연결된 label 을 둡니다. 아이콘은 aria-hidden, 클리어 버튼에는 aria-label(예: 검색어 지우기).

Forms & inputs

Slider

A slider for selecting a value from a range.범위 값을 선택하는 슬라이더입니다.

.qf-sliderlayer: generic

Preview

<input class="qf-slider" type="range" min="0" max="100" value="40" aria-label="Volume">

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--s-2 --r-pill --bg-hover --accent --ring-focus

Accessibility

Because it's a native input[type="range"], keyboard operation and value communication come for free. Associate a label, and use aria-valuetext to supplement units when needed.네이티브 input[type=range] 라 키보드 조작과 값 전달이 기본 제공됩니다. label 을 연결하고 필요 시 aria-valuetext 로 단위를 보충합니다.

Forms & inputs

NumberInput

A numeric input field with increment and decrement buttons.증감 버튼이 있는 숫자 입력 필드입니다.

.qf-number-inputlayer: generic

Preview

<div class="qf-number-input">
  <button class="qf-number-input__btn" aria-label="Decrease">−</button>
  <input class="qf-number-input__field" type="number" value="1" aria-label="Quantity">
  <button class="qf-number-input__btn" aria-label="Increase">+</button>
</div>

Variants

qf-number-input__field qf-number-input__btn

Required tokens

--bg-input --border --r-lg --text --font-mono --bg-hover --text-secondary

Accessibility

The field is an input[type="number", inputmode="numeric"] with an associated label. Give the stepper buttons an aria-label (e.g. "Increment" / "Decrement"), and let the input remain the source of truth for the value.field 는 input[type=number, inputmode=numeric] 에 label 연결. 증감 버튼에는 aria-label(예: 1 증가/감소)을 두고, 값은 input 이 권위를 가집니다.

Forms & inputs

FileDrop

A general-purpose upload zone for dropping files via drag-and-drop or clicking to browse.파일을 끌어다 놓거나 클릭해 올리는 범용 업로드 영역입니다.

.qf-file-droplayer: generic

Preview

<label class="qf-file-drop">
  <span class="qf-file-drop__title">Drop files here</span>
  <span>or click to browse</span>
  <input type="file" hidden>
</label>

Variants

qf-file-drop--active

Parts & more: 구성 요소, 기타: qf-file-drop__title

Required tokens

--border-strong --r-lg --bg-input --text-muted --accent --accent-bg --text-strong --s-8

Accessibility

Connect a real input[type="file"] to the zone (via label or click delegation) to preserve keyboard access. Convey the drag state with text in addition to --active.실제 input[type=file] 을 영역에 연결(label 또는 클릭 위임)해 키보드 접근을 보존합니다. 드래그 상태는 --active 와 함께 텍스트로도 안내합니다.

Forms & inputs

Composer

A composer that wraps an auto-expanding textarea and inline actions (send, etc.) in a focus-within pill, with a leading slot (__lead) and size variants (--sm/--lg). The rich-text format bar (__formatbar, --rich) is a chat-layer extension.focus-within 필 안에 자동확장 textarea와 인라인 액션(전송 등)을 묶는 컴포저입니다. 선행 슬롯(__lead)과 크기 변형(--sm/--lg)을 지원합니다. 리치 텍스트 포맷바(__formatbar, --rich)는 챗 확장입니다.

.qf-composerlayer: generic

Preview

<div class="qf-composer">
  <div class="qf-composer__row">
    <button class="qf-composer__attach" aria-label="Attach">
      <svg class="qf-icon" aria-hidden="true">
        <use href="#qf-i-plus"/>
      </svg>
    </button>
    <textarea class="qf-composer__input" rows="1" aria-label="Message" placeholder="Type a message">
    </textarea>
    <button class="qf-composer__send" aria-label="Send">
      <svg class="qf-icon" aria-hidden="true">
        <use href="#qf-i-send"/>
      </svg>
    </button>
  </div>
</div>

Variants

qf-composer--rich
qf-composer--sm
qf-composer--lg

Parts & more: 구성 요소, 기타: qf-composer__formatbar qf-composer__format-btn qf-composer__format-sep qf-composer__row qf-composer__attach qf-composer__input qf-composer__actions qf-composer__send qf-composer__hint qf-composer__hint-count--over qf-composer__lead

Required tokens

--bg-input --border --accent --r-lg --s-3 --s-5 --text --text-onAccent --composer-max-h --composer-font-min --s-10

Accessibility

Because focus-within highlights the field with an accent border, the inner textarea disables its own outline. Formatting buttons convey their toggle state via aria-pressed. Keep the send button disabled when the input is empty, and signal a hint character-count overflow with text as well as color.focus-within 시 accent 보더로 강조하므로 내부 textarea 는 자체 outline 을 끕니다. 포맷 버튼은 aria-pressed 로 토글 상태를 전합니다. 전송 버튼은 입력이 비면 disabled 로 두고, 힌트 글자수 초과는 색만이 아니라 텍스트로도 알립니다.

Forms & inputs

Pick

An image-choice tile that behaves like a radio: pick one from a row of thumbnails. A <label class="qf-pick"> holds input[type=radio].qf-pick__input (laid transparently over the tile so the whole tile is the hit area), a frame qf-pick__frame (4:3, --bg-media, img uses object-fit: contain because the whole picture must be visible — not cover), a bottom-left tag qf-pick__tag (on-media glass, short text), and a one-line label qf-pick__label (12px, ellipsis). States: checked draws an accent outline outside the frame (2px, offset 2), focus-visible shows --ring-focus, disabled dims, hover shows a --border-strong outline. Variants: qf-pick__frame--none (dashed frame with a single word, "None"), qf-pick--muted (not a candidate — desaturated, darker image and a warning-colored tag), qf-pick--current (what is shown now — bolder label). The row is qf-picks: horizontal scroll with scroll-snap, inner padding so outlines and rings are not clipped, and the same right-edge fade as qf-chips--scroll (only when overflowing, clears at the end, is-end fallback). Tile width --sz-pick (160px; 2.1 tiles at 390px).축소 사본을 보고 하나를 고르는 이미지 선택 타일입니다(라디오 동작). <label class="qf-pick"> 안에 input[type=radio].qf-pick__input(투명하게 깔려 타일 전체가 히트), 틀 qf-pick__frame(4:3, --bg-media, img 는 object-fit: contain — 이미지 전체를 봐야 하므로 cover 가 아님), 왼쪽 아래 태그 qf-pick__tag(미디어 위 글래스, 짧은 글자), 한 줄 라벨 qf-pick__label(12px, 말줄임)을 둡니다. 상태: checked 는 틀 바깥 액센트 외곽선(2px, offset 2), focus-visible 은 --ring-focus, disabled 는 흐림, hover 는 --border-strong 외곽선. 변형: qf-pick__frame--none(점선 틀에 글자 하나, "없음"), qf-pick--muted(후보가 아닌 것 — 이미지 채도·밝기 낮춤 + 태그 경고색), qf-pick--current(지금 보이는 것 — 라벨 진하게). 줄은 qf-picks: 가로 스크롤 + scroll-snap, 안쪽 여백으로 외곽선·링이 잘리지 않고, 오른쪽 페이드는 qf-chips--scroll 과 같습니다(넘칠 때만, 끝에서 걷힘, 미지원은 is-end). 타일 폭 --sz-pick(160px, 390px 에서 2.1장).

.qf-picklayer: generic

Preview

<div class="qf-picks" role="radiogroup" aria-label="Image to show">
  <label class="qf-pick qf-pick--current">
    <input class="qf-pick__input" type="radio" name="pick" value="1" checked>
    <span class="qf-pick__frame">
      <img src="brand-assets/png/og-image.png" alt="">
      <span class="qf-pick__tag">Shown</span>
    </span>
    <span class="qf-pick__label">Clien, photo</span>
  </label>
  <label class="qf-pick">
    <input class="qf-pick__input" type="radio" name="pick" value="2">
    <span class="qf-pick__frame">
      <img src="brand-assets/png/icon-512.png" alt="">
      <span class="qf-pick__tag">AI</span>
    </span>
    <span class="qf-pick__label">AI image</span>
  </label>
  <label class="qf-pick qf-pick--muted">
    <input class="qf-pick__input" type="radio" name="pick" value="3">
    <span class="qf-pick__frame">
      <img src="brand-assets/png/og-image.png" alt="">
      <span class="qf-pick__tag">Screenshot</span>
    </span>
    <span class="qf-pick__label">Ruliweb, screenshot of an article</span>
  </label>
  <label class="qf-pick">
    <input class="qf-pick__input" type="radio" name="pick" value="none">
    <span class="qf-pick__frame qf-pick__frame--none">None</span>
    <span class="qf-pick__label">No image</span>
  </label>
</div>

Variants

qf-pick__input qf-pick__frame qf-pick__frame--none qf-pick__tag qf-pick__label qf-pick--muted qf-pick--current qf-picks

Required tokens

--sz-pick --aspect-4x3 --bg-media --r-md --r-xs --s-1 --s-2 --s-3 --s-4 --s-10 --fs-12 --fs-11 --lh-normal --lh-snug --tracking-normal --text-muted --text-strong --border-strong --accent --ring-focus --on-media-glass-bg --on-media-text --warn-400 --dur-fast --ease-standard --font-sans --on-media-glass-bg-strong --text-disabled

Accessibility

Wrap the row in role="radiogroup" with an aria-label; each tile is label > input[type=radio], so click, Space and arrow-key movement work natively (arrow focus scrolls the tile into view via scroll-padding). The radio's accessible name is the label text (tag + label); add a title or aria-describedby for more. Use alt="" for decorative thumbnails, a description when the content matters. The tag sits on an on-media glass (--on-media-glass-bg + --on-media-text), AA on any image; the muted tag uses --warn-400 on the strong glass (--on-media-glass-bg-strong): 6.8:1 even over a white image or the light letterbox (the .68 glass would be 4.1). Tiles are 160×120, an ample touch target, and the gap widens to --s-4 on touch devices. When the checked outline and the focus ring overlap they read as a 4px accent band — both are accent, so it reads as "the selected one is focused". A disabled tile only dims its image; the label stays readable in --text-disabled and the tile does not react to hover. Checked, focus and disabled styling rely on :has(), so browsers without it (Firefox < 121, Safari < 15.4) show no state.줄을 role="radiogroup" + aria-label 로 묶고 타일은 label > input[type=radio] 라 클릭·Space·화살표 이동이 네이티브로 동작합니다(화살표로 옮기면 scroll-padding 으로 타일이 줄 안에 들어옵니다). 라디오의 접근 가능한 이름은 label 의 텍스트(태그 + 라벨)이며, 설명이 더 필요하면 label 의 title 이나 aria-describedby 로. img 는 장식이면 alt="", 내용이 중요하면 설명. 태그는 미디어 위 글래스(--on-media-glass-bg + --on-media-text)라 어떤 이미지 위에서도 AA. muted 태그는 진한 글래스(--on-media-glass-bg-strong) 위 --warn-400 — 흰 이미지·라이트 레터박스 위에서도 6.8:1(.68 글래스는 4.1 로 미달). 타일 160×120 이라 터치 대상이 충분하고 터치 환경에서는 타일 간격이 --s-4 로 넓어집니다. checked 외곽선과 포커스 링이 겹치면 4px 액센트 띠로 보이며 둘 다 액센트라 "선택된 것에 포커스" 로 읽힙니다. disabled 타일은 이미지만 흐려지고 라벨은 --text-disabled 로 읽히며 hover 에 반응하지 않습니다. 선택·포커스·disabled 표시는 :has() 에 기대므로 미지원 브라우저(Firefox < 121, Safari < 15.4)에서는 상태가 보이지 않습니다.

Display & data

Avatar

A circular avatar that represents a user (with an optional status dot).사용자를 나타내는 원형 아바타입니다(상태 점은 옵션).

.qf-avatarlayer: generic

Preview

M
<span class="qf-avatar qf-avatar--md">
  M
  <span class="qf-avatar__status qf-avatar__status--online">
  </span>
</span>

Examples예시

M
Online
H
Idle
J
Do not disturb
S
Offline

Variants

M
qf-avatar--xs
M
qf-avatar--sm
M
qf-avatar--md
M
qf-avatar--lg
M
qf-avatar--xl

Parts & more: 구성 요소, 기타: qf-avatar__status qf-avatar__status--online qf-avatar__status--idle qf-avatar__status--dnd qf-avatar__status--offline

Required tokens

--bg-elevated --r-pill --sz-status-dot --sz-status-dot-ring --status-online --status-offline --avatar-ring

Accessibility

Provide meaningful alt text for the image, and do not convey the status dot by color alone, supplementing it with text or aria-label such as online or away.이미지에는 의미 있는 alt 를 제공하고, 상태 점은 색만으로 전하지 않도록 온라인, 자리 비움 등 텍스트나 aria-label 로 보충합니다.

Display & data

Badge

A small badge for a label, a status, or a notification count. Status tones: --success (healthy), --warn (resting, delayed), --danger (stopped, failed), --muted (paused, inactive). Marking AI-written text: put a default qf-badge with qf-i-sparkle reading "AI summary" in the kicker line above the title (neutral tone, 11px), and shorten the closing qf-notice--info to one line ("Tell us if something is wrong"). An svg inside a badge scales with the text (an explicit size modifier such as qf-icon--sm keeps its size).라벨, 상태, 알림 개수를 나타내는 작은 배지입니다. 상태는 --success(정상) --warn(쉬는 중, 지연) --danger(중단, 실패) --muted(멈춤, 비활성)로 구분합니다. AI 가 쓴 글의 표시: 제목 위 kicker 줄에 기본 qf-badge + qf-i-sparkle 로 "AI 요약" 을 두고(중립 톤, 11px), 글 끝의 qf-notice--info 는 "틀린 곳이 있으면 알려 주세요" 한 줄로 줄입니다. 배지 안 svg 는 글자 크기에 맞춰집니다(qf-icon--sm 같은 크기 변형을 명시하면 그 크기 유지).

.qf-badgelayer: generic

Preview

3
<span class="qf-badge qf-badge--count" aria-label="3 new notifications">3</span>

Examples예시

Healthy Resting Stopped Paused Neutral
Status set
3
Notification count (only)
Clien 2 2 posts
Neutral count (not red)
Politics4 communities · 9 posts · 9 min agoAI summary
AI-written marker (in a kicker line)

Variants

3
qf-badge--accent
3
qf-badge--success
3
qf-badge--warn
3
qf-badge--danger
3
qf-badge--muted
3
qf-badge--dot
3
qf-badge--count

Required tokens

--bg-hover --text-secondary --accent-subtle --ok-bg --text-ok --warn-bg --text-warn --danger-bg --text-danger --border --text-muted --danger-600 --r-xs --r-pill --s-2 --fs-11

Accessibility

Include text so meaning is not conveyed by color alone. qf-badge--count (red) is for notification counts only. Do not use it for neutral counts such as post or community totals; use the default qf-badge or qf-source__count (gray number) instead. Supplement count badges with an aria-label such as N unread.색만으로 의미를 전하지 않도록 텍스트를 함께 둡니다. qf-badge--count(빨강)는 알림 개수 전용입니다. 글 수, 커뮤니티 수 같은 중립 개수에는 쓰지 말고 기본 qf-badge 나 qf-source__count(회색 숫자)를 쓰세요. 개수 배지는 읽지 않음 N건 처럼 aria-label 로 보충합니다.

Display & data

CodeBlock

A code block that displays code in a monospace font.코드를 모노스페이스로 표시하는 코드 블록입니다.

.qf-codeblocklayer: generic

Preview

tsconst a = 1;
<pre class="qf-codeblock">
  <span class="qf-codeblock__lang">ts</span>
  <code>const a = 1;</code>
</pre>

Variants

tsconst a = 1;
qf-codeblock--with-header

Parts & more: 구성 요소, 기타: qf-codeblock__lang qf-codeblock__header qf-codeblock__header-lang qf-codeblock__copy qf-code-inline

Required tokens

--bg-code --text-code --divider --r-md --s-4 --fs-13 --font-mono --ok-400

Accessibility

Use a button element for the copy button and signal copy completion with 'Copied' text, not color alone. Wrap code in pre and code markup to convey its meaning.복사 버튼은 button 요소로 두고 복사 완료는 색만이 아니라 'Copied' 텍스트로 함께 알립니다. 코드는 pre, code 마크업으로 감싸 의미를 전달합니다.

Display & data

Prose

A body (prose) style that renders long-form documents such as Markdown in the design system's tone. The body measure defaults to a readable ~640px and is overridable via --qf-prose-max (e.g., none or var(--container-w-wide)). --article is for article bodies of several 3–6 sentence paragraphs (news write-ups): 16px body, one-line paragraph spacing (--s-6), and keep-all word breaking for Korean. Inside --article, h2/h3 are article subheadings (17px, 600, no underline, --s-6 above and --s-2 below) — when the body runs four paragraphs or more, put a short h2 (about 12 characters) where the thread changes.마크다운 등 장문 문서를 디자인 시스템 톤으로 렌더하는 본문(prose) 스타일입니다. 본문 폭은 기본 가독성 measure(약 640px)이며, --qf-prose-max 로 오버라이드합니다(예: none, var(--container-w-wide)). --article 은 뉴스 전말처럼 3~6문장 문단이 이어지는 기사 본문용으로 본문 16px, 문단 간격 한 줄(--s-6), 한국어 어절 유지(keep-all)를 적용합니다. --article 안의 h2/h3 는 기사 소제목(17px, 600, 밑선 없음, 위 --s-6 아래 --s-2)입니다 — 전말이 네 문단 이상이면 흐름이 바뀌는 곳에 12자 안의 h2 를 둡니다.

.qf-proselayer: generic

Preview

Document title

The body uses emphasis, a link, and inline code.

  • First item
  • Second item
Blockquotes are highlighted with the accent bar.
<article class="qf-prose">
  <h2>Document title</h2>
  <p>
    The body uses
    <strong>emphasis</strong>
    , a
    <a href="#prose">link</a>
    , and
    <code>inline</code>
    code.
  </p>
  <ul>
    <li>First item</li>
    <li>Second item</li>
  </ul>
  <blockquote>Blockquotes are highlighted with the accent bar.</blockquote>
</article>

Examples예시

The Supreme Court acknowledged on Tuesday that expense reports filed by its chief justice were inaccurate, and issued a formal apology. The admission followed a week of reporting that traced dozens of receipts to restaurants closed on the dates listed.

Community reaction spread quickly across several Korean forums. Threads on Clien and Bobaedream questioned why the internal audit had taken years, while posters on 82cook focused on the apology itself.

The court said it would publish a corrected ledger and refer the matter to an outside review. No timeline was given.

--article (news write-up)

Variants

Document title

The body uses emphasis, a link, and inline code.

  • First item
  • Second item
Blockquotes are highlighted with the accent bar.
qf-prose--article

Required tokens

--text --text-strong --link --accent --divider --bg-panel --font-mono --container-w-narrow --fs-16 --s-6 --fs-17 --lh-snug

Accessibility

Maintain the semantic HTML hierarchy (h1→h6 order, ul/ol/blockquote/table structure), and underline links to provide a cue beyond color. Keep body contrast at AA, and use token colors for code and tables.시맨틱 HTML 계층(h1→h6 순서, ul/ol/blockquote/table 구조)을 유지하고, 링크는 밑줄로 색 외 단서를 함께 줍니다. 본문 대비 AA, 코드/표는 토큰 색을 사용합니다.

Display & data

Lede

A lede (standfirst) paragraph under the title. A two-to-three-sentence summary set one step larger than body text (18px, so the line pitch widens too) in a secondary tone (--text-secondary), apart from the article body (qf-prose--article, 16px). --rule draws a short accent line underneath to mark where the body begins. Use --rule when nothing sits between lede and body; use the plain form when a picture separates them. Margins: --s-2 above, --s-6 below (inside a qf-stack the stack gap is added on both sides). Same measure as qf-prose; when overriding --qf-prose-max, set it on a common ancestor of lede and body.제목 아래 리드(standfirst) 문단입니다. 2~3문장 요약을 본문보다 한 단계 큰 글자(18px, 줄 간격도 따라 넓어짐)와 보조 톤(--text-secondary)으로 두어 본문(qf-prose--article, 16px)과 구분합니다. --rule 은 아래에 짧은 액센트 선을 그려 본문의 시작을 알립니다. 리드와 본문 사이에 그림이 없으면 --rule 을 쓰고, 그림이 사이를 가르면 기본형을 씁니다. 위 여백 --s-2, 아래 여백 --s-6(qf-stack 안에서는 stack 의 gap 이 양쪽에 더해집니다). 폭은 qf-prose 와 같은 measure 이며, --qf-prose-max 를 바꿀 때는 리드와 본문의 공통 조상에 둡니다.

.qf-ledelayer: generic

Preview

Supreme Court admits chief justice filed false expense reports

The court acknowledged on Tuesday that expense reports filed by its chief justice were inaccurate and issued a formal apology, after a week of reporting traced dozens of receipts to restaurants closed on the dates listed.

The admission followed an investigation by a nonprofit newsroom. Community reaction spread quickly across several Korean forums, with threads questioning why the internal audit had taken years.

The court said it would publish a corrected ledger and refer the matter to an outside review. No timeline was given.

<article>
  <h1 class="qf-page-header__title">Supreme Court admits chief justice filed false expense reports</h1>
  <p class="qf-lede qf-lede--rule">The court acknowledged on Tuesday that expense reports filed by its chief justice were inaccurate and issued a formal apology, after a week of reporting traced dozens of receipts to restaurants closed on the dates listed.</p>
  <section class="qf-prose qf-prose--article">
    <p>The admission followed an investigation by a nonprofit newsroom. Community reaction spread quickly across several Korean forums, with threads questioning why the internal audit had taken years.</p>
    <p>The court said it would publish a corrected ledger and refer the matter to an outside review. No timeline was given.</p>
  </section>
</article>

Examples예시

Supreme Court admits chief justice filed false expense reports

The court acknowledged on Tuesday that expense reports filed by its chief justice were inaccurate and issued a formal apology.

The admission followed an investigation by a nonprofit newsroom. Community reaction spread quickly across several Korean forums.

--rule (no picture between lede and body)

Supreme Court admits chief justice filed false expense reports

The court acknowledged on Tuesday that expense reports filed by its chief justice were inaccurate and issued a formal apology.

The admission followed an investigation by a nonprofit newsroom. Community reaction spread quickly across several Korean forums.

Plain (a figure separates lede and body)

Variants

Supreme Court admits chief justice filed false expense reports

The court acknowledged on Tuesday that expense reports filed by its chief justice were inaccurate and issued a formal apology, after a week of reporting traced dozens of receipts to restaurants closed on the dates listed.

The admission followed an investigation by a nonprofit newsroom. Community reaction spread quickly across several Korean forums, with threads questioning why the internal audit had taken years.

The court said it would publish a corrected ledger and refer the matter to an outside review. No timeline was given.

qf-lede--rule

Required tokens

--fs-18 --lh-loose --text-secondary --font-sans --s-2 --s-5 --s-6 --s-9 --accent --container-w-narrow

Accessibility

Use a p so it is read as the paragraph right after the heading (h1). Two cues separate it from the body independently of color: size (18 vs 16px) and the --rule line; the secondary tone is an extra cue (its contrast against body text is only 1.3–1.5:1). So when no picture sits between lede and body, always use --rule. The line is ::after decoration (drawn as a border so it survives forced-colors mode) and is not exposed to assistive technology. Weight is fixed at 400 (in Korean fallback fonts 500 may render like 400, so weight is not a reliable cue). Contrast: --text-secondary on --bg-app 10.7:1 (dark) / 10.2:1 (light); the --accent line 4.49 / 4.07.p 로 두어 제목(h1) 바로 다음 문단으로 낭독되게 합니다. 본문과의 구분은 크기(18 vs 16px)와 --rule 의 선, 두 가지가 색과 무관한 단서이고 보조 톤은 덧붙는 단서입니다(본문색과의 대비는 1.3~1.5:1 로 약함). 그래서 리드와 본문 사이에 그림이 없으면 반드시 --rule 을 씁니다. 선은 ::after 장식(border 로 그려 강제 색상 모드에서도 남음)이라 보조기기에 노출되지 않습니다. 굵기는 400 으로 고정합니다(한국어 폴백 글꼴에서 500 은 400 과 같게 렌더될 수 있어 단서가 되지 못함). 대비: --text-secondary on --bg-app 10.7:1(다크) / 10.2:1(라이트), 선 --accent 4.49 / 4.07.

Display & data

KeyPoints

An article's key points. A box placed between the lede and the body (after the picture if there is one), holding a label ("Key points", 12px caps tone) and two to four one-sentence items (under about 40 characters). Bullets are short accent bars, not dots (order carries no meaning, so no numbers). It has a --bg-panel background and a border but no left rule, so it does not read as a qf-notice. When it is the lede's immediate next sibling under the same parent, the qf-lede--rule line hides automatically (:has adjacent sibling); if the lede is wrapped in another element this does not fire, so leave --rule off then. Place the box outside qf-prose (inside, qf-prose's h2 style would override the label). Same measure as qf-prose.기사의 핵심 묶음입니다. 리드와 전말 사이(그림이 있으면 그림 다음)에 두는 상자로, 라벨("핵심", 12px 대문자 톤)과 한 문장짜리 항목 2~4개(40자 안)를 담습니다. 글머리는 점이 아니라 액센트의 짧은 막대(순서가 의미가 아니라 번호를 쓰지 않습니다). 바탕 --bg-panel 과 테두리만 있고 왼쪽 선이 없어 qf-notice 와 같은 종류로 보이지 않습니다. 리드와 같은 부모의 바로 다음 형제로 오면 qf-lede--rule 의 선이 자동으로 숨습니다(:has 인접 형제). 리드가 다른 요소에 감싸여 있으면 발동하지 않으니 그때는 --rule 을 붙이지 마세요. 상자는 qf-prose 밖에 둡니다(안에 두면 qf-prose 의 h2 스타일이 라벨을 덮습니다). 폭은 qf-prose 와 같은 measure 입니다.

.qf-keypointslayer: generic

Preview

Key points

  • The court admitted its expense reports were inaccurate and apologized.
  • Dozens of receipts named restaurants closed on the dates listed.
  • A corrected ledger and an outside review were promised, with no timeline.
<section class="qf-keypoints" aria-labelledby="kp-title">
  <h2 class="qf-keypoints__title" id="kp-title">Key points</h2>
  <ul class="qf-keypoints__list">
    <li class="qf-keypoints__item">The court admitted its expense reports were inaccurate and apologized.</li>
    <li class="qf-keypoints__item">Dozens of receipts named restaurants closed on the dates listed.</li>
    <li class="qf-keypoints__item">A corrected ledger and an outside review were promised, with no timeline.</li>
  </ul>
</section>

Examples예시

The court acknowledged on Tuesday that expense reports filed by its chief justice were inaccurate and issued a formal apology.

Key points

  • The court admitted its expense reports were inaccurate and apologized.
  • A corrected ledger and an outside review were promised.

What the reporting found

The admission followed an investigation by a nonprofit newsroom that traced dozens of receipts to restaurants closed on the dates listed.

Community reaction

Threads on several Korean forums questioned why the internal audit had taken years.

After a lede (lede rule hides)

Variants

qf-keypoints__title qf-keypoints__list qf-keypoints__item

Required tokens

--s-5 --s-6 --s-4 --s-3 --s-2 --container-w-narrow --bg-panel --border --r-lg --r-pill --fs-12 --fs-15 --lh-tight --lh-normal --tracking-caps --text-muted --text --accent --font-sans

Accessibility

Use section[aria-labelledby] to name the region and make the label an h2 so "Key points" enters the document outline, and mark items up as ul/li (the bar is ::before decoration). Bar --accent on --bg-panel 3.97 dark / 3.79 light (graphics 3:1). Text --text on --bg-panel passes AA. More than four items makes the box heavier than the lede — keep it to four.section[aria-labelledby] 로 영역 이름을 주고 라벨을 h2 로 두어 "핵심" 이 문서 구조에 들어가게 하고, 항목은 ul/li 로 둡니다(막대는 ::before 장식). 막대 --accent on --bg-panel 다크 3.97 / 라이트 3.79(그래픽 3:1). 글자 --text on --bg-panel AA. 항목이 다섯 개를 넘으면 상자가 리드보다 무거워집니다 — 네 개까지.

Display & data

Mark

Search-term highlight. Use <mark class="qf-mark"> inside titles (qf-story__title) and summaries (qf-story__summary). Background is the subtle accent (--accent-subtle); the text color is inherited, so it stays calm in both 600-weight titles and 400-weight summaries. The 2px side padding is offset by a negative margin so text does not shift, and when it spans two lines each end is rounded (box-decoration-break: clone).검색어 강조입니다. <mark class="qf-mark"> 로 제목(qf-story__title)과 요약(qf-story__summary) 안에서 씁니다. 바탕은 액센트의 옅은 톤(--accent-subtle), 글자색은 상속이라 제목(600)과 요약(400) 어디서도 과하지 않습니다. 좌우 2px 패딩은 음수 margin 으로 상쇄되어 글자 흐름이 밀리지 않고, 두 줄에 걸치면 양 끝이 각각 둥급니다(box-decoration-break: clone).

.qf-marklayer: generic

Preview

Politics4 communities · 9 posts

Supreme Court admits chief justice filed false expense reports

The court acknowledged on Tuesday that expense reports filed by its chief justice were inaccurate.

<article class="qf-story">
  <div class="qf-story__kicker">
    <span class="qf-eyebrow">Politics</span>
    <span>4 communities · 9 posts</span>
  </div>
  <h2 class="qf-story__title">
    Supreme
    <mark class="qf-mark">Court</mark>
    admits chief justice filed false expense reports
  </h2>
  <p class="qf-story__summary">
    The
    <mark class="qf-mark">court</mark>
    acknowledged on Tuesday that expense reports filed by its chief justice were inaccurate.
  </p>
</article>

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--accent-subtle --r-xs --s-1

Accessibility

A mark element, which assistive technology may announce as highlighted (some do not). Inherited text color: --text-strong on --accent-subtle 13.1:1 dark / 14.6:1 light, --text-secondary 8.2 / 8.2 — AA. Use it only for matched search terms so the highlight does not change meaning. When a card hover turns the title accent-colored, text inside the mark stays --text-strong (accent text would be 4.25:1 in light). Because of the negative margin, a mark at the start of a line may lose its left 2px inside qf-clamp (overflow hidden) — only the decorative end flattens.mark 요소라 보조기기가 강조로 알립니다(일부는 낭독하지 않음). 글자색 상속: --text-strong on --accent-subtle 다크 13.1:1 / 라이트 14.6:1, --text-secondary 8.2 / 8.2 — AA. 강조가 의미를 바꾸지 않도록 검색어 외에는 쓰지 않습니다. 카드 hover 로 제목이 accent 색이 되어도 mark 안 글자는 --text-strong 을 유지합니다(라이트에서 accent 글자는 4.25:1). 음수 margin 때문에 줄 첫머리의 mark 는 왼쪽 2px 이 qf-clamp(overflow hidden) 안에서 잘릴 수 있습니다 — 장식 끝만 평평해집니다.

Display & data

Footnotes

A Markdown footnotes list — footnotes and back-reference links below a divider at the end of the body. In-body reference superscripts (sup>a) are accented via --accent-text within qf-prose.마크다운 각주 목록 — 본문 하단 구분선 아래 각주와 역참조 링크입니다. 본문 내 참조 위첨자(sup>a)는 qf-prose 스코프에서 --accent-text 로 강조됩니다.

.qf-footnoteslayer: generic

Preview

  1. 디자인 시스템은 사람과 AI가 함께 씁니다. ↩
<section class="qf-footnotes">
  <ol>
    <li id="fn1">
      디자인 시스템은 사람과 AI가 함께 씁니다.
      <a class="qf-footnotes__backref" href="#fnref1" aria-label="본문으로 돌아가기">↩</a>
    </li>
  </ol>
</section>

Variants

qf-footnotes__backref

Required tokens

--divider --fs-13 --text-secondary --text-muted --accent-text --accent-bg-faint --r-xs --s-5 --s-6 --s-8

Accessibility

Footnotes use an ol to convey order, and back-reference links carry an aria-label (e.g., back to content) so meaning is not carried by an icon or glyph alone. In-body references are real a[href] anchors enabling round-trip navigation.각주는 ol 로 순서를 전달하고, 역참조 링크에는 aria-label(예: 본문으로 돌아가기)을 두어 아이콘, 기호 단독 의존을 피합니다. 본문 참조는 실제 a[href] 앵커로 왕복 이동이 가능합니다.

Display & data

Transclude

A transclusion card that quotes another note inline within the body, with a left --border-strong accent, --bg-panel surface, and a __source link to the original at the top. Named qf-transclude to avoid colliding with the chat embed qf-embed.다른 노트를 본문에 인라인 인용하는 트랜스클루전 카드입니다. 좌측 --border-strong 액센트 + --bg-panel 배경, 상단 __source 원문 링크. 채팅 임베드 qf-embed 와 이름 충돌을 피해 qf-transclude 로 명명했습니다.

.qf-transcludelayer: generic

Preview

Embedded content from another note is quoted inline here.

<blockquote class="qf-transclude">
  <div class="qf-transclude__source">
    <svg class="qf-icon qf-icon--sm" aria-hidden="true">
      <use href="#qf-i-link"/>
    </svg>
    <a href="/notes/api">notes/api</a>
  </div>
  <p>Embedded content from another note is quoted inline here.</p>
</blockquote>

Variants

qf-transclude__source

Required tokens

--border --border-strong --bg-panel --divider --text-secondary --text-muted --link --r-md --s-4 --s-5 --fs-12

Accessibility

Convey the quotation with blockquote semantics, and provide a real a[href] source link for navigation to the origin. The left accent is decorative, with source text supplying context.인용 의미를 blockquote 시맨틱으로 전달하고, 원문 링크는 실제 a[href] 로 출처 이동을 보장합니다. 좌측 액센트는 장식이며 출처 텍스트로 맥락을 함께 제공합니다.

Display & data

EmptyState

An empty-state area that provides guidance when there is no content. Pages such as a 404 are built from the same parts: title, body, a search form (qf-search), and an action button as children (no variant needed).내용이 없을 때 안내하는 빈 상태 영역입니다. 404 같은 안내 화면도 제목, 본문, 찾기 입력(qf-search), 행동 버튼을 자식으로 두면 됩니다(변형 불필요).

.qf-emptylayer: generic

Preview

No items yet
Add your first item to get started.
<div class="qf-empty">
  <svg class="qf-icon qf-icon--xl" aria-hidden="true" style="color:var(--text-muted)">
    <use href="#qf-i-inbox"/>
  </svg>
  <div class="qf-empty__title">No items yet</div>
  <div class="qf-empty__body">Add your first item to get started.</div>
  <button class="qf-btn qf-btn--primary qf-btn--sm">New item</button>
</div>

Examples예시

Page not found
The address may be wrong, or the issue may have been removed.
Back to the front page
404 page (title + body + search + action)

Variants

qf-empty__title qf-empty__body

Required tokens

--s-12 --s-7 --s-4 --text-muted --text-strong --fs-18 --fs-14

Accessibility

Convey the guidance through title and body text rather than the icon. When it appears dynamically, placing it in an aria-live region is recommended.안내 의미를 아이콘이 아닌 제목, 본문 텍스트로 전달합니다. 동적으로 나타날 때는 aria-live 영역에 넣는 것을 권장합니다.

Display & data

Skeleton

A placeholder skeleton shown while content is loading.콘텐츠 로딩 중에 보여 주는 자리표시자 스켈레톤입니다.

.qf-skellayer: generic

Preview

<div class="qf-skel" aria-hidden="true" style="width: 60%; height: var(--s-4)">
</div>

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--bg-hover --bg-selected --r-sm

Accessibility

Mark the loading area with aria-busy="true" to tell screen readers it is not meaningful content. Respecting prefers-reduced-motion for motion-sensitive users is recommended.로딩 영역을 aria-busy="true"로 표시하고 의미 있는 콘텐츠가 아님을 화면 낭독기에 알립니다. 모션 민감 사용자를 위해 prefers-reduced-motion을 존중하는 것을 권장합니다.

Display & data

Eyebrow

A small uppercase label placed above a section.섹션 위에 올리는 작은 대문자 레이블입니다.

.qf-eyebrowlayer: generic

Preview

New feature
<span class="qf-eyebrow">New feature</span>

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--fs-12 --font-sans --tracking-caps --accent-text

Accessibility

The uppercase transform is visual presentation only, so keep the actual text in normal casing so screen readers read it correctly. Do not carry meaning in the accent color alone.대문자 변환은 시각 표현이며 실제 텍스트는 정상 표기로 두어 화면 낭독기가 올바르게 읽도록 합니다. 강조 색에만 의미를 싣지 않습니다.

Display & data

KeyboardShortcutSheet

A sheet that presents a list of keyboard shortcuts grouped by category.단축키 목록을 그룹별로 보여 주는 시트입니다.

.qf-kbd-sheetlayer: generic

Preview

Navigation
Open searchCtrl+K
<div class="qf-kbd-sheet">
  <div class="qf-kbd-sheet__group">
    <div class="qf-kbd-sheet__group-title">Navigation</div>
    <div class="qf-kbd-sheet__row">
      <span>Open search</span>
      <span class="qf-kbd-sheet__keys">
        <kbd class="qf-kbd">Ctrl</kbd>
        <span class="qf-kbd-sheet__plus">+</span>
        <kbd class="qf-kbd">K</kbd>
      </span>
    </div>
  </div>
</div>

Variants

qf-kbd-sheet__group qf-kbd-sheet__group-title qf-kbd-sheet__row qf-kbd-sheet__keys qf-kbd-sheet__plus qf-kbd

Required tokens

--s-6 --s-8 --s-2 --fs-11 --fs-14 --text-muted --text-secondary --tracking-caps

Accessibility

Mark each keycap with a kbd element to convey its meaning, and manage focus within the dialog context when placed inside a modal.각 키캡은 kbd 요소로 표기해 의미를 전달하고 모달 안에 둘 때는 dialog 컨텍스트에서 포커스를 관리합니다.

Display & data

Card

A surface container that groups content (with header, body, and footer slots).콘텐츠를 묶는 표면 컨테이너입니다(헤더, 본문, 푸터 슬롯).

.qf-cardlayer: generic

Preview

Title

This is the content.
<section class="qf-card">
  <div class="qf-card__header">
    <h3 class="qf-card__title">Title</h3>
  </div>
  <div class="qf-card__body">This is the content.</div>
</section>

Variants

Title

This is the content.
qf-card--interactive

Parts & more: 구성 요소, 기타: qf-card__header qf-card__title qf-card__body qf-card__footer

Required tokens

--bg-panel --border --divider --r-xl --s-6 --text-strong --border-strong

Accessibility

An interactive card (--interactive) should be wrapped in a keyboard-accessible element (a/button) or given an appropriate role and tabindex, with visible focus.상호작용 카드(--interactive)는 키보드 접근 가능한 요소(a/button)로 감싸거나 적절한 role 과 tabindex 를 부여하고 포커스를 보이게 합니다.

Display & data

Tag

A chip that represents a label or category (a text label, distinct from Badge which is used for counts and status). As <a class="qf-tag"> it becomes a clickable tag (hover = selected surface; 40px tall with a 44px hit area on touch). Show counts such as post totals with qf-tag__count (a lighter-weight number) — qf-badge--count (red) is for notifications only. It stays clickable inside a qf-story--stretched card.라벨이나 카테고리를 나타내는 칩입니다(카운트, 상태용 Badge 와 구분되는 텍스트 라벨). <a class="qf-tag"> 로 두면 눌리는 태그가 됩니다(hover 는 selected 표면, 터치 환경 40px + 44px 히트). 글 수 같은 개수는 qf-tag__count(가는 숫자)로 — qf-badge--count(빨강)는 알림 전용입니다. qf-story--stretched 카드 안에서도 눌립니다.

.qf-taglayer: generic

Preview

Design
<span class="qf-tag qf-tag--accent">
  Design
  <button class="qf-tag__remove" aria-label="Remove Design tag">×</button>
</span>

Examples예시

Link tags with counts (tag index)

Variants

Design
qf-tag--accent
Design
qf-tag--outline

Parts & more: 구성 요소, 기타: qf-tag__remove qf-tag__count

Required tokens

--bg-hover --text-secondary --accent-subtle --accent-on-subtle --r-sm --s-3 --fs-12 --bg-selected --text --text-muted --ring-focus --s-9 --m-touch --dur-fast --ease-standard --s-2 --border-strong --r-xs

Accessibility

Give the remove button (qf-tag__remove) an aria-label (e.g., Remove design tag). Pair label text with color so meaning is never conveyed by color alone. A link tag is an a[href] with a visible focus ring; supplement a count with an aria-label such as "powershell, 24 posts". Do not put qf-tag__remove inside a link tag (a button inside an a). Inline tags inside qf-prose keep the line height and do not grow on touch. The count uses --text-secondary at weight 400 (tag text is 500): 9.5 / 9.5 on --bg-hover and still AA on the --bg-selected hover surface (--text-muted would be 4.48 in light, so it is not used).제거 버튼(qf-tag__remove)에는 aria-label(예: 디자인 태그 제거)을 둡니다. 색만으로 의미를 전하지 않고 라벨 텍스트를 함께 둡니다. 링크 태그는 a[href] 라 포커스 링이 보이고, 개수는 숫자 뒤에 단위를 aria-label 로 보충할 수 있습니다(예: "powershell, 글 24건"). 링크 태그에는 qf-tag__remove 를 넣지 않습니다(a 안의 button). 본문(qf-prose) 안 인라인 태그는 줄 높이를 지키며 터치 성장이 없습니다. 개수는 --text-secondary(굵기 400, 태그 글자는 500)라 바탕 --bg-hover 위 9.5 / 9.5, hover 표면 --bg-selected 위에서도 AA 입니다(--text-muted 는 라이트 4.48 로 미달이라 쓰지 않음).

Display & data

Stat

Displays a dashboard metric (KPI) with a large value, a label, and a trend delta. A hint line under the value (qf-stat__hint, e.g. "limit 300") is optional. --sm is for short figures in an aside or summary row (value 18px 600, label 12px).대시보드 지표(KPI)를 큰 값, 라벨, 추세 델타로 표시합니다. 값 아래 보조 텍스트(qf-stat__hint, 예: 상한 300장)를 둘 수 있습니다. --sm 은 사이드·요약 줄의 짧은 숫자(값 18px 600, 라벨 12px)입니다.

.qf-statlayer: generic

Preview

Monthly active users12,840▲ 8.2%
<div class="qf-stat">
  <span class="qf-stat__label">Monthly active users</span>
  <span class="qf-stat__value">12,840</span>
  <span class="qf-stat__delta qf-stat__delta--up">▲ 8.2%</span>
</div>

Examples예시

Monthly active users12,840▲ 8.2%
Increase
Churn rate3.1%▼ 1.4%
Decrease
Pending tasks27
No delta
Images kept212limit 300
With hint

Variants

Monthly active users12,840▲ 8.2%
qf-stat--sm

Parts & more: 구성 요소, 기타: qf-stat__label qf-stat__value qf-stat__delta qf-stat__delta--up qf-stat__delta--down qf-stat__hint

Required tokens

--text-strong --text-muted --fs-32 --fs-13 --tracking-tight --ok-600 --danger-400 --fs-12 --fs-18 --lh-snug --tracking-normal

Accessibility

Trend is conveyed not just by color but with an arrow/sign (▲▼ or +/-) and text, avoiding reliance on color alone. Pair the value with its unit and meaning.추세는 색뿐 아니라 화살표/부호(▲▼ 또는 +/-)와 텍스트로 전달해 색 단독 의존을 피합니다. 값에는 단위/의미를 함께 둡니다.

Display & data

Sparkline

A mini chart that shows a time-series trend within a small area. The consumer generates points/path from the data, and the DS provides token-based styling (line and area colors).시계열 추세를 작은 영역에 보여주는 미니 차트입니다. 데이터→points/path 는 소비처가 생성하고 DS 는 토큰 기반 스타일(선, 영역 색)을 제공합니다.

.qf-sparklinelayer: generic

Preview

<span class="qf-sparkline qf-sparkline--ok">
  <svg viewBox="0 0 100 32" preserveAspectRatio="none" role="img" aria-label="Recent throughput trend, rising">
    <polyline class="qf-sparkline__area" points="0,28 12,24 24,26 36,18 48,20 60,12 72,14 84,6 100,8 100,32 0,32">
  </polyline>
  <polyline class="qf-sparkline__line" points="0,28 12,24 24,26 36,18 48,20 60,12 72,14 84,6 100,8">
</polyline>
</svg>
</span>

Variants

qf-sparkline--ok
qf-sparkline--warn
qf-sparkline--danger

Parts & more: 구성 요소, 기타: qf-sparkline__line qf-sparkline__area

Required tokens

--accent --ok-400 --warn-400 --danger-400

Accessibility

Unless decorative, provide a trend summary via role=img + aria-label (e.g., "Throughput over the last 24 hours, rising"), and pair color with numeric labels.장식이 아니면 role=img + aria-label 로 추세 요약(예: "최근 24시간 처리량, 상승")을 제공하고, 색뿐 아니라 수치 라벨을 함께 둡니다.

Display & data

Table

A table that presents data in rows and columns, offering a sort caret (aria-sort), a sticky header, row selection, and toolbar affordances (the consumer handles sort and selection logic).행과 열로 데이터를 보여주는 표입니다. 정렬 캐럿(aria-sort), sticky 헤더, 행 선택, 툴바 affordance 를 제공합니다(정렬/선택 로직은 소비처).

.qf-tablelayer: generic

Preview

Jobs
NameStatus
sync-skulkRunning
backfillQueued
<div class="qf-table-wrap">
  <div class="qf-table__toolbar">
    <span class="qf-table__toolbar-title">Jobs</span>
    <span class="qf-table__toolbar-spacer">
    </span>
    <button class="qf-btn qf-btn--secondary qf-btn--sm">Retry</button>
  </div>
  <table class="qf-table qf-table--sticky">
    <thead>
      <tr>
        <th>
          <input type="checkbox" class="qf-checkbox__input" aria-label="Select all">
        </th>
        <th class="qf-table__th--sortable" aria-sort="ascending">
          <span class="qf-table__sort">Name</span>
        </th>
        <th class="qf-table__th--sortable">
          <span class="qf-table__sort">Status</span>
        </th>
      </tr>
    </thead>
    <tbody>
      <tr class="is-selected">
        <td>
          <input type="checkbox" class="qf-checkbox__input" checked aria-label="Select row">
        </td>
        <td>sync-skulk</td>
        <td>Running</td>
      </tr>
      <tr>
        <td>
          <input type="checkbox" class="qf-checkbox__input" aria-label="Select row">
        </td>
        <td>backfill</td>
        <td>Queued</td>
      </tr>
    </tbody>
  </table>
</div>

Variants

Jobs
NameStatus
sync-skulkRunning
backfillQueued
qf-table--striped
Jobs
NameStatus
sync-skulkRunning
backfillQueued
qf-table--sticky

Parts & more: 구성 요소, 기타: qf-table-wrap qf-table__th--sortable qf-table__sort qf-table__toolbar qf-table__toolbar-title qf-table__toolbar-spacer

Required tokens

--divider --s-3 --s-4 --text-muted --text --bg-hover --fs-14 --accent --accent-bg --bg-panel --z-sticky

Accessibility

Convey header relationships with a thead/th(scope=col)/tbody structure, and describe the table's purpose with a caption or aria-label. At narrow widths, qf-table-wrap enables horizontal scrolling.thead/th(scope=col)/tbody 구조로 헤더 관계를 전달하고, 표 용도는 caption 또는 aria-label 로 설명합니다. 좁은 폭은 qf-table-wrap 으로 가로 스크롤합니다.

Display & data

DescriptionList

A list that presents term-and-description (key-value) pairs in an aligned layout.용어와 설명(키-값) 쌍을 정렬해 보여주는 목록입니다.

.qf-dllayer: generic

Preview

Plan
Pro
Joined
2026-01-01
<dl class="qf-dl">
  <dt>Plan</dt>
  <dd>Pro</dd>
  <dt>Joined</dt>
  <dd>2026-01-01</dd>
</dl>

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--s-2 --s-5 --text-muted --text --fs-13 --fs-14

Accessibility

Convey key-value relationships with dl/dt/dd semantics. The grid handles the visual two-column alignment while the markup preserves the meaning.dl/dt/dd 시맨틱으로 키-값 관계를 전달합니다. 시각적 2열 정렬은 grid 가 담당하고 의미는 마크업이 보존합니다.

Display & data

AvatarGroup

Stacks multiple avatars in an overlapping cluster to compactly represent a set of participants.여러 아바타를 겹쳐 쌓아 참여자를 압축 표시합니다.

.qf-avatar-grouplayer: generic

Preview

MHJ+2
<span class="qf-avatar-group" aria-label="5 participants">
  <span class="qf-avatar qf-avatar--sm">M</span>
  <span class="qf-avatar qf-avatar--sm">H</span>
  <span class="qf-avatar qf-avatar--sm">J</span>
  <span class="qf-avatar qf-avatar--sm">+2</span>
</span>

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--avatar-ring --r-pill --s-3

Accessibility

Provide alt text (the user's name) on each avatar image, and supplement the group's overall meaning (e.g. "5 participants") with aria-label. The ring is separated from the surface via --avatar-ring (surface).각 아바타 이미지에 alt(사용자명)를 제공하고, 그룹 전체 의미(예: 참여자 5명)는 aria-label 로 보충합니다. ring 은 --avatar-ring(표면) 으로 표면과 분리됩니다.

Display & data

List

A general-purpose vertical list with dividers (settings rows, item lists).구분선이 있는 범용 세로 목록입니다(설정 행, 항목 리스트).

.qf-listlayer: generic

Preview

  • NotificationsOn
  • LanguageEnglish
<ul class="qf-list">
  <li class="qf-list__item">
    <span class="qf-list__text">Notifications</span>
    <span class="qf-list__trailing">On</span>
  </li>
  <li class="qf-list__item">
    <span class="qf-list__text">Language</span>
    <span class="qf-list__trailing">English</span>
  </li>
</ul>

Variants

qf-list__item qf-list__text qf-list__trailing qf-list__item--interactive

Required tokens

--s-3 --s-4 --divider --text --bg-hover --text-muted --s-9

Accessibility

Build it with ul/li, and make interactive items (--interactive) an a/button to preserve keyboard access and visible focus. Interactive rows are at least 40px tall, and a link or button inside (.qf-list__text) extends its tap target into the row padding (about 37px, WCAG 2.5.8). Inline content inside the link (icon + text, qf-clamp) keeps flowing as usual.ul/li 로 만들고, 상호작용 항목(--interactive)은 a/button 으로 두어 키보드 접근과 포커스 가시를 보존합니다. 상호작용 행은 최소 40px 이고, 행 안의 링크나 버튼(.qf-list__text)은 행 패딩까지 탭 대상으로 가져갑니다(약 37px, WCAG 2.5.8). 링크 안의 내용은 인라인 흐름 그대로 둘 수 있습니다(아이콘 + 텍스트, qf-clamp).

Display & data

RankList

A ranked list (e.g. trending issues 1–5). Numbers come from a CSS counter so there is no digit in the markup (rank carries meaning: accent, tabular-nums). Each item is a link (qf-ranklist__link) holding a title (qf-ranklist__title, 14px 600, two-line clamp) and a meta line (qf-ranklist__meta, 12px muted), with hover tint, visited tone and focus ring. Meant for the aside but works unchanged when the layout drops to one column.순위 목록입니다(지금 뜨는 이슈 1~5). 번호는 CSS counter 로 그려 마크업에 숫자가 없고(순위가 의미라 번호, 액센트, tabular-nums), 항목 전체가 링크(qf-ranklist__link)이며 제목(qf-ranklist__title, 14px 600, 두 줄 clamp)과 메타(qf-ranklist__meta, 12px muted)로 이루어집니다. hover 틴트, 방문 톤, 포커스 링. 사이드 열에서 쓰지만 1열로 내려가도 그대로 동작합니다.

.qf-ranklistlayer: generic

Preview

<ol class="qf-ranklist" role="list" style="max-width:300px">
  <li class="qf-ranklist__item">
    <a class="qf-ranklist__link" href="#r1">
      <span class="qf-ranklist__title">Supreme Court admits chief justice filed false expense reports, apologizes</span>
      <span class="qf-ranklist__meta">8 communities, 51 posts</span>
    </a>
  </li>
  <li class="qf-ranklist__item">
    <a class="qf-ranklist__link" href="#r2">
      <span class="qf-ranklist__title">Central bank holds rates, signals a cut before year end</span>
      <span class="qf-ranklist__meta">3 communities, 5 posts</span>
    </a>
  </li>
  <li class="qf-ranklist__item">
    <a class="qf-ranklist__link" href="#r3">
      <span class="qf-ranklist__title">City council reverses late-night bus cuts</span>
      <span class="qf-ranklist__meta">2 communities, 4 posts</span>
    </a>
  </li>
</ol>

Variants

qf-ranklist__item qf-ranklist__link qf-ranklist__title qf-ranklist__meta

Required tokens

--s-7 --s-3 --s-2 --s-1 --r-md --fs-14 --fs-12 --lh-snug --accent-text --text-strong --text-secondary --text-muted --bg-row-hover --ring-focus --dur-fast --ease-standard

Accessibility

Use ol/li, and add role="list" to the ol because list-style: none can drop list semantics in WebKit. The CSS counter number is ::before generated text, so it becomes part of the link name and is read as "1 title meta" (the rank is conveyed). For titles cut by the two-line clamp, provide the full text via title or aria-label. Number --accent-text on --bg-app 7.5 / 5.3 — AA.ol/li 로 두되 list-style: none 이라 WebKit 에서 목록 의미가 떨어질 수 있으니 ol 에 role="list" 를 둡니다. CSS counter 번호는 ::before 생성 텍스트라 링크 이름에 포함되어 "1 제목 메타" 로 읽힙니다(순위가 전달됨). 두 줄 clamp 로 잘린 제목은 title 속성이나 aria-label 로 전체를 줄 수 있습니다. 번호 --accent-text on --bg-app 7.5 / 5.3 — AA.

Display & data

Story

One item of a content list such as news, issues, or a blog. It fixes the hierarchy of kicker (category + meta), title, summary, source chips, and a 4:3 thumbnail. The whole item may be the link (a.qf-story) or only the title. --pictured places text in column 1 and the thumbnail in column 2 (on narrow screens it only shrinks, it does not move); --lead emphasizes the first item (24px title, wider thumbnail; on narrow screens a 16:9 thumbnail sits above the text); --compact shows only kicker and title (summary and sources are hidden even if present). Visited items get a quieter title. Place the list inside qf-container--reading (720px): narrow overflows titles and source chips, the default width makes summary lines too long. Source chips inside an item are automatically one step smaller (11px). --skeleton is a placeholder card shown while the next page loads (bars in the empty slots, same height as a real card; if real cards are --stretched, add --stretched to the skeleton too so the sources row matches on touch devices). --stretched stretches the title link over the whole card when the card is an article with only the title linked, so source chips (qf-source--link) and tag links (a.qf-tag) inside can be real links — sources use qf-source, categories and topics use qf-tag.뉴스, 이슈, 블로그 같은 콘텐츠 목록의 한 항목입니다. 분류와 메타(kicker), 제목, 요약, 출처 칩, 4:3 썸네일의 위계를 구성요소로 고정합니다. 항목 전체가 링크(a.qf-story)이거나 제목만 링크일 수 있습니다. --pictured 는 텍스트 1열 + 썸네일 2열(좁은 폭에서는 크기만 줄고 자리는 유지), --lead 는 첫 항목 강조(제목 24px, 썸네일 확대. 좁은 폭에서는 16:9 썸네일이 텍스트 위로), --compact 는 제목과 kicker 만(요약, 출처는 마크업이 있어도 숨김). 방문한 항목은 제목이 한 톤 낮아집니다. 목록은 qf-container--reading(720px) 안에 두는 것을 권합니다(narrow 는 제목과 출처 칩이 넘치고 기본 폭은 요약 행이 깁니다). 항목 안의 출처 칩은 자동으로 한 단계 작아집니다(11px). --skeleton 은 다음 화면을 불러오는 동안 자리를 지키는 카드(빈 슬롯에 막대, 실제 카드와 같은 높이. 실제 카드가 --stretched 면 스켈레톤에도 --stretched 를 붙여 터치 환경의 출처 행 높이를 맞춥니다). --stretched 는 카드가 article 이고 제목만 링크일 때 제목 링크를 카드 전체로 늘려, 카드 안의 출처 칩(qf-source--link)과 태그 링크(a.qf-tag)를 눌리는 링크로 둘 수 있게 합니다 — 출처는 qf-source, 분류·주제는 qf-tag.

.qf-storylayer: generic

Preview

<a class="qf-story qf-story--pictured" href="#story">
  <img class="qf-story__media" src="brand-assets/png/og-image.png" alt="" width="180" height="135">
  <div class="qf-story__kicker">
    <span class="qf-eyebrow">Politics</span>
    <span>4 communities · 9 posts · 9 min ago</span>
  </div>
  <h2 class="qf-story__title">Supreme Court admits chief justice filed false expense reports, apologizes</h2>
  <p class="qf-story__summary qf-clamp qf-clamp--3">Reporting by an investigative outlet traced dozens of receipts to restaurants that were closed on the dates listed. The court issued a formal apology and said a corrected ledger would follow.</p>
  <div class="qf-sources qf-story__sources">
    <span class="qf-source">82cook</span>
    <span class="qf-source">Inven</span>
    <span class="qf-source">Clien</span>
    <span class="qf-source">Bobaedream</span>
  </div>
</a>

Examples예시

Text only, title is the link
--pictured without summary/sources (spacer rows keep kicker↔title tight)
--skeleton (loading placeholder)
--stretched (article, title link stretched, source chips are links)

Variants

qf-story__kicker qf-story__title qf-story__summary qf-story__sources qf-story__media qf-story--pictured qf-story--lead qf-story--compact qf-story--skeleton qf-story--stretched

Required tokens

--text-strong --text-secondary --text-muted --accent-text --bg-row-hover --bg-media --aspect-4x3 --aspect-16x9 --sz-story-media --sz-story-media-sm --sz-story-media-lead --fs-18 --fs-24 --fs-14 --r-md --s-5 --ring-focus --fs-12 --fs-15 --s-1 --s-2 --s-3 --s-4 --lh-snug --lh-tight --lh-normal --tracking-tight --dur-fast --ease-standard --border --bg-hover --bg-selected --r-xs --r-pill --m-touch

Accessibility

Use h2/h3 for the title to convey list structure. When the whole item is a link, do not nest other links inside it (no source --link chips). Give decorative thumbnails alt="" and width/height to avoid layout shift. Focus is shown as a ring around the whole item. The visited tone is a secondary cue; meaning never relies on color alone. When the whole item is a link, the kicker, title, summary, and sources all become the link name and it gets long; if summaries are long, consider linking only the title (see the Text only example). To shorten the link name to the title only, aria-labelledby="<title id>" can be set on a.qf-story. With --stretched, text inside the card cannot be selected by dragging and the context menu is the title link's — in return the link name is just the title. Give skeletons aria-hidden="true" and replace them wholesale when real cards arrive.제목은 h2/h3 로 두어 목록의 문서 구조를 전달합니다. 항목 전체를 링크로 만들 때는 안에 다른 링크(출처 칩 --link 등)를 넣지 않습니다(중첩 링크 금지). 장식 썸네일은 alt="" 로 두고 width/height 를 적어 레이아웃 점프를 막습니다. 포커스는 항목 전체에 링으로 보입니다. 방문 톤은 보조 단서일 뿐 의미를 색에만 싣지 않습니다. 항목 전체가 링크면 kicker, 제목, 요약, 출처가 모두 링크 이름이 되어 길어집니다. 요약이 길면 제목만 링크로 두는 형태(Text only 예제)를 고려하세요. 링크 이름을 제목만으로 줄이려면 a.qf-story 에 aria-labelledby="제목 id" 를 둘 수 있습니다. --stretched 에서는 카드 안 텍스트를 드래그로 선택할 수 없고 우클릭 메뉴가 제목 링크의 것입니다 — 그 대신 링크 이름이 제목만으로 짧습니다. 스켈레톤은 aria-hidden="true" 로 두고 실제 카드가 오면 통째로 바꿉니다.

Display & data

Source

A small, neutral chip naming one source (a community or outlet). An outline pill, distinct from Tag (labels) and Badge (status, notifications). qf-source__count shows a count as a gray number (instead of a red count badge); qf-source__mark holds an initial or favicon. --link makes it a link to the original list; qf-sources is the wrapping group container. Inside qf-story__sources and qf-timeline__body they are secondary information and shrink automatically by one step (11px, matching the body line height).출처(커뮤니티, 매체) 이름 하나를 나타내는 중립 톤의 작은 칩입니다. 태그(라벨)나 배지(상태, 알림)와 구분되는 outline pill 입니다. qf-source__count 는 회색 숫자로 개수를(빨간 count 배지 대신), qf-source__mark 는 이니셜이나 파비콘을 넣습니다. --link 는 눌러서 원문 목록으로 가는 링크형, qf-sources 는 줄바꿈되는 묶음 컨테이너입니다. qf-story__sources 와 qf-timeline__body 안에서는 보조 정보라 자동으로 한 단계 작아집니다(11px, 본문 줄 높이와 같음).

.qf-sourcelayer: generic

Preview

82cookInven 3Clien 2
<div class="qf-sources">
  <span class="qf-source">82cook</span>
  <span class="qf-source">
    Inven
    <span class="qf-source__count">3</span>
  </span>
  <a class="qf-source qf-source--link" href="#source">
    <span class="qf-source__mark" aria-hidden="true">C</span>
    Clien
    <span class="qf-source__count">2</span>
  </a>
</div>

Examples예시

Bobaedream
Plain
Bobaedream 2
With count (gray, not red)
Ruliweb
With mark (initial)
--link
82cookInvenClienBobaedreamPpomppuRuliwebDC Inside
Group (qf-sources, wraps)

Variants

82cookInven 3Clien 2
qf-source--link

Parts & more: 구성 요소, 기타: qf-sources qf-source__count qf-source__mark

Required tokens

--border --border-strong --text-secondary --text-muted --text --r-pill --fs-12 --fs-11 --s-2 --s-3 --s-5 --m-touch --ring-focus --bg-selected --bg-hover --s-4 --lh-snug --dur-fast --ease-standard

Accessibility

Counts are gray numbers, so they do not read as warnings; add an aria-label when needed (e.g. "2 posts on Bobaedream"). --link is an anchor with a visible focus ring. On touch devices (any-pointer: coarse, including touch laptops) only --link chips grow to 44px; static chips and chips inside a linked qf-story stay as they are. Do not use --link inside a qf-story that is itself a link.개수는 회색 숫자라 경고로 읽히지 않습니다. 필요하면 aria-label 로 뜻을 보충합니다(예: 보배드림 글 2건). --link 는 a 로 두고 포커스 링이 보입니다. 터치 환경(any-pointer: coarse, 터치 노트북 포함)에서는 --link 칩만 44px 로 커지고, 정적 칩과 카드 안 칩은 그대로입니다. 항목 전체가 링크인 qf-story 안에서는 --link 를 쓰지 않습니다.

Display & data

DayRule

A date or section rule placed between list items: an eyebrow-toned label plus a line, used as an li (with role="separator", also provide the label via aria-label). --sticky pins it to the top while scrolling and paints the app background (--bg-app) so items do not show through. Knobs: --qf-dayrule-top (offset under a fixed header, default 0; the rule sits at --z-sticky, so with a fixed header you must set this to the header height, e.g. var(--h-navbar)) and --qf-dayrule-bg (background when used inside a panel). Give items a scroll-margin-top so a sticky rule does not cover the top of a focused item. When a sticky top bar (qf-navbar--sticky) hides with is-hidden, the rule automatically moves up to top: 0.목록 사이에 끼우는 날짜, 구간 구분줄입니다. eyebrow 톤 라벨과 선으로 이루어지며 li 로 씁니다(role="separator" 를 쓰면 aria-label 로 라벨을 함께 줍니다). --sticky 는 스크롤 시 상단에 붙고 앱 배경(--bg-app)을 깔아 아래 항목이 비치지 않습니다. 노브: --qf-dayrule-top(고정 헤더 아래 오프셋, 기본 0. z-index 가 --z-sticky 라 고정 헤더가 있으면 반드시 헤더 높이, 예: var(--h-navbar), 를 지정), --qf-dayrule-bg(패널 안에서 쓸 때 배경). sticky 구분줄이 포커스된 항목의 윗부분을 가리지 않게 항목에 scroll-margin-top 을 주는 것을 권합니다. 고정 상단 바(qf-navbar--sticky)가 is-hidden 으로 숨으면 날짜줄은 자동으로 맨 위(top: 0)로 올라붙습니다.

.qf-dayrulelayer: generic

Preview

  • First item of the day
  • Second item
  • An older item
<ul class="qf-stack qf-stack--tight" style="list-style:none;margin:0;padding:0;width:100%">
  <li class="qf-dayrule" role="separator" aria-label="Today, Wednesday, Sep 30">
    <span class="qf-dayrule__label">Today · Wednesday, Sep 30</span>
  </li>
  <li class="qf-list__item" style="padding-inline:0">First item of the day</li>
  <li class="qf-list__item" style="padding-inline:0">Second item</li>
  <li class="qf-dayrule" role="separator" aria-label="Yesterday, Tuesday, Sep 29">
    <span class="qf-dayrule__label">Yesterday · Tuesday, Sep 29</span>
  </li>
  <li class="qf-list__item" style="padding-inline:0">An older item</li>
</ul>

Variants

  • First item of the day
  • Second item
  • An older item
qf-dayrule--sticky

Parts & more: 구성 요소, 기타: qf-dayrule__label

Required tokens

--accent-text --text-muted --bg-app --z-sticky --fs-12 --tracking-caps --s-3 --s-4 --lh-tight --border --dur-base --ease-standard

Accessibility

In ARIA, separator has presentational children, so text inside it is not exposed to assistive technology. If you use role="separator", always duplicate the label in aria-label (e.g. aria-label="Today, Wednesday, Sep 30"); if counting it among the items is acceptable, use a plain li without the role so the label is read as-is. Keep the label as real text; the uppercase transform is visual only. The --sticky background must stay opaque so text does not show through; do not set a translucent value.ARIA 의 separator 는 자식 요소가 presentational 이라 안의 텍스트가 보조기기에 노출되지 않습니다. role="separator" 를 쓰려면 같은 텍스트를 aria-label 로 반드시 함께 두고(예: aria-label="오늘, 9월 30일 수요일"), 항목 수에 섞여도 괜찮으면 role 없이 일반 li 로 두어 라벨이 그대로 낭독되게 합니다. 라벨은 실제 텍스트로 두고 대문자 변환은 시각 표현입니다. --sticky 의 배경은 아래 텍스트가 겹쳐 보이지 않게 불투명해야 하므로 반투명 값을 넣지 않습니다.

Display & data

Timeline

A vertical timeline of events in time order (unlike qf-steps, which shows progress through stages). Each item has a time (qf-timeline__time), a marker (qf-timeline__marker), and a body (qf-timeline__body: source chip + title link + meta); qf-timeline__day marks a date change. The marker color is exposed through one custom property, --qf-timeline-marker, which consumers set with a token (e.g. var(--viz-2)) to tell sources apart (default --text-muted). The time column (--sz-timeline-time) survives narrow widths; for very narrow layouts, --stacked moves the time above the body.시간순 기록을 세로로 보여 주는 타임라인입니다(진행 단계를 나타내는 qf-steps 와 다릅니다). 항목은 시각(qf-timeline__time), 마커(qf-timeline__marker), 본문(qf-timeline__body: 출처 칩 + 제목 링크 + 메타)로 이루어지고, 날짜가 바뀌는 곳에 qf-timeline__day 를 둡니다. 마커 색은 커스텀 프로퍼티 --qf-timeline-marker 하나로 열어 두어 소비처가 토큰(예: var(--viz-2))으로 출처를 구분합니다(기본 --text-muted). 좁은 폭에서도 시각 칸(--sz-timeline-time)이 유지되며, 더 좁게 써야 하면 --stacked 로 시각을 본문 위로 올립니다.

.qf-timelinelayer: generic

Preview

<ol class="qf-timeline">
  <li class="qf-timeline__day">Sep 30</li>
  <li class="qf-timeline__item" style="--qf-timeline-marker: var(--viz-1)">
    <time class="qf-timeline__time" datetime="2026-09-30T09:12">09:12</time>
    <span class="qf-timeline__marker" aria-hidden="true">
    </span>
    <div class="qf-timeline__body">
      <span class="qf-source">Clien</span>
      <a class="qf-link" href="#post">The chief justice's expense reports do not add up</a>
      <span class="qf-timeline__meta">4 comments</span>
    </div>
  </li>
  <li class="qf-timeline__item" style="--qf-timeline-marker: var(--viz-2)">
    <time class="qf-timeline__time" datetime="2026-09-30T09:40">09:40</time>
    <span class="qf-timeline__marker" aria-hidden="true">
    </span>
    <div class="qf-timeline__body">
      <span class="qf-source">82cook</span>
      <a class="qf-link" href="#post">So the Supreme Court apologized. Now what?</a>
      <span class="qf-timeline__meta">31 comments</span>
    </div>
  </li>
  <li class="qf-timeline__item" style="--qf-timeline-marker: var(--viz-3)">
    <time class="qf-timeline__time" datetime="2026-09-30T11:05">11:05</time>
    <span class="qf-timeline__marker" aria-hidden="true">
    </span>
    <div class="qf-timeline__body">
      <span class="qf-source">Bobaedream</span>
      <a class="qf-link" href="#post">Court to publish a corrected ledger, refers case to outside review</a>
      <span class="qf-timeline__meta">12 comments</span>
    </div>
  </li>
  <li class="qf-timeline__day">Sep 29</li>
  <li class="qf-timeline__item">
    <time class="qf-timeline__time" datetime="2026-09-29T22:48">22:48</time>
    <span class="qf-timeline__marker" aria-hidden="true">
    </span>
    <div class="qf-timeline__body">
      <span class="qf-source">Inven</span>
      <a class="qf-link" href="#post">First report surfaces on the expense records</a>
      <span class="qf-timeline__meta">2 comments</span>
    </div>
  </li>
</ol>

Examples예시

Variants

Parts & more: 구성 요소, 기타: qf-timeline__item qf-timeline__time qf-timeline__marker qf-timeline__body qf-timeline__meta qf-timeline__day

Required tokens

--text --text-strong --text-secondary --text-muted --accent-text --sz-timeline-time --sz-timeline-marker --fs-14 --fs-12 --lh-normal --r-pill --s-3 --s-4 --border-strong --s-1 --s-2 --tracking-caps --lh-tight --border

Accessibility

Convey order with an ol and mark times with time[datetime]. Markers are decorative (aria-hidden); the source is conveyed by the qf-source text, not by color. Titles are qf-link anchors with a visible focus ring and a light underline so they read as links next to the meta text on the same line, and visited links are toned down. Date dividers (qf-timeline__day) are read as list item text.ol 로 순서를 전달하고 시각은 time[datetime] 으로 둡니다. 마커는 장식(aria-hidden)이며 출처는 색이 아니라 qf-source 텍스트로 전달합니다. 제목은 qf-link 로 두어 포커스 링이 보이고, 같은 줄의 메타 텍스트와 구분되게 옅은 밑줄로 링크 단서를 함께 줍니다. 방문한 링크는 한 톤 낮아집니다. 날짜 구분(qf-timeline__day)은 li 텍스트로 낭독됩니다.

Display & data

Clamp

A utility that truncates text to N lines with an ellipsis — keeps card titles and descriptions uniform.텍스트를 N줄에서 말줄임하는 유틸리티입니다. 카드 제목, 설명을 균일하게 자릅니다.

.qf-clamplayer: generic

Preview

This is a longer description that clamps to two lines with an ellipsis when it overflows its container width, keeping cards uniform.

<p class="qf-clamp" style="max-width:320px;margin:0">This is a longer description that clamps to two lines with an ellipsis when it overflows its container width, keeping cards uniform.</p>

Examples예시

This variant clamps to three lines instead of two. Useful for denser cards where a little more context fits before the ellipsis truncates the remaining overflow text.

3 lines (--3)

A single-line clamp behaves like a truncating ellipsis on overflow.

1 line (--1)

Variants

This is a longer description that clamps to two lines with an ellipsis when it overflows its container width, keeping cards uniform.

qf-clamp--1

This is a longer description that clamps to two lines with an ellipsis when it overflows its container width, keeping cards uniform.

qf-clamp--3

This is a longer description that clamps to two lines with an ellipsis when it overflows its container width, keeping cards uniform.

qf-clamp--reserve

Required tokens

--lh-snug

Accessibility

Visual truncation only — the full text stays in the accessibility tree (never aria-hidden the clamp node). When text may be cut, pair it with a title attribute or qf-tooltip.시각적 절단만이며 전체 텍스트는 접근성 트리에 유지합니다(클램프 노드에 aria-hidden 금지). 잘릴 수 있으면 title 이나 qf-tooltip 을 함께 제공합니다.

Display & data

SortToggle

A three-state sort toggle that cycles ascending↔descending↔off — used as a table header (th[aria-sort]) or a button, with a direction glyph.오름차순↔내림차순↔off를 순환하는 3상태 정렬 토글입니다. 테이블 헤더(th[aria-sort]) 또는 버튼으로 쓰며 방향을 글리프로 표시합니다.

.qf-sort-togglelayer: generic

Preview

<button class="qf-sort-toggle is-active" type="button" data-direction="asc" aria-label="Sort by name, ascending">
  <span>Name</span>
  <span class="qf-sort-toggle__indicator" aria-hidden="true">▲</span>
</button>

Examples예시

Descending (active)
Off (inactive)

Variants

qf-sort-toggle--lg

Parts & more: 구성 요소, 기타: qf-sort-toggle__indicator

Required tokens

--text-secondary --text-strong --accent --bg-hover --sort-indicator-size --ring-accent --r-sm --s-1 --s-2 --fs-13

Accessibility

Table headers use th[aria-sort='ascending|descending|none']; standalone buttons use role=button with an accessible name. Cycle with Enter/Space, convey direction via aria-sort/glyph (not color alone), and keep headers at a 44px tap target.테이블 헤더는 th[aria-sort='ascending|descending|none'], 독립 버튼은 role=button + 접근명입니다. Enter/Space로 순환하고 방향은 색이 아니라 aria-sort/글리프로 전달하며 헤더는 44px 탭 타깃을 유지합니다.

Charts & data viz

Chart

A multi-series time-series line/area chart. The consumer computes coordinates (points/path) and tick values from the data (same contract as Sparkline); the DS provides token-based styling for axes, grid, series, hover guide, and value tooltip. Set series color on the parent group via style="color:var(--viz-N)" (1–8).멀티시리즈 시계열 라인/영역 차트입니다. 좌표(points/path)와 눈금 값은 소비처가 데이터에서 계산하고(sparkline 과 동일 계약), DS 는 축, 그리드, 시리즈, 호버 가이드, 값 툴팁의 토큰 기반 스타일을 제공합니다. 시리즈 색은 부모 그룹에 style="color:var(--viz-N)"(1~8) 로 지정합니다.

.qf-chartlayer: generic

Preview

300200100000:0012:0024:00
Downloaded 268
Failed 12
No data
  • Downloaded
  • Failed
<div class="qf-chart" style="--chart-h:200px">
  <svg class="qf-chart__svg" viewBox="0 0 320 200" role="img" aria-label="Downloads vs failures over 24h, both rising">
    <g class="qf-chart__grid">
      <line x1="36" y1="20" x2="312" y2="20">
    </line>
    <line x1="36" y1="60" x2="312" y2="60">
  </line>
  <line x1="36" y1="100" x2="312" y2="100">
</line>
<line x1="36" y1="140" x2="312" y2="140">
</line>
</g>
<text class="qf-chart__label qf-chart__label--y" x="30" y="20">300</text>
<text class="qf-chart__label qf-chart__label--y" x="30" y="60">200</text>
<text class="qf-chart__label qf-chart__label--y" x="30" y="100">100</text>
<text class="qf-chart__label qf-chart__label--y" x="30" y="140">0</text>
<line class="qf-chart__axis" x1="36" y1="20" x2="36" y2="140">
</line>
<line class="qf-chart__axis" x1="36" y1="140" x2="312" y2="140">
</line>
<g style="color:var(--viz-1)">
  <polygon class="qf-chart__area" points="36,120 105,96 174,104 243,64 312,48 312,140 36,140">
</polygon>
<polyline class="qf-chart__series" points="36,120 105,96 174,104 243,64 312,48">
</polyline>
</g>
<g style="color:var(--viz-3)">
  <polyline class="qf-chart__series" points="36,132 105,128 174,118 243,112 312,96">
</polyline>
</g>
<text class="qf-chart__label qf-chart__label--x" x="36" y="158">00:00</text>
<text class="qf-chart__label qf-chart__label--x" x="174" y="158">12:00</text>
<text class="qf-chart__label qf-chart__label--x" x="312" y="158">24:00</text>
<line class="qf-chart__guide" x1="243" y1="20" x2="243" y2="140">
</line>
<circle class="qf-chart__dot" cx="243" cy="64" r="3.5" style="color:var(--viz-1)">
</circle>
</svg>
<div class="qf-chart__tooltip" style="left:196px;top:24px">
  <div class="qf-chart__tooltip-row">
    <span class="qf-chart__tooltip-swatch" style="color:var(--viz-1)">
    </span>
    Downloaded 268
  </div>
  <div class="qf-chart__tooltip-row">
    <span class="qf-chart__tooltip-swatch" style="color:var(--viz-3)">
    </span>
    Failed 12
  </div>
</div>
<div class="qf-chart__state">No data</div>
</div>
<ul class="qf-legend" style="margin-top:var(--s-3)">
  <li class="qf-legend__item">
    <span class="qf-legend__swatch" style="color:var(--viz-1)">
    </span>
    Downloaded
  </li>
  <li class="qf-legend__item">
    <span class="qf-legend__swatch" style="color:var(--viz-3)">
    </span>
    Failed
  </li>
</ul>

Variants

qf-chart__svg qf-chart__grid qf-chart__axis qf-chart__label qf-chart__series qf-chart__area qf-chart__dot qf-chart__guide qf-chart__tooltip qf-chart__state qf-chart--loading qf-chart--empty

Required tokens

--viz-1 --viz-2 --viz-3 --chart-grid --chart-axis --chart-label --chart-tooltip-bg --chart-tooltip-text --border --bg-panel

Accessibility

Summarize the trend with role="img" + aria-label on the svg (e.g., "Downloads vs failures over the last 24h, rising"). The hover guide/tooltip is a pointer affordance; pair color with a legend and numeric labels to avoid color-only reliance. Offer an equivalent data table for keyboard/screen-reader users.svg 에 role="img" + aria-label 로 추세를 요약합니다(예: "최근 24시간 다운로드 대 실패, 상승"). 호버 가이드/툴팁은 포인터 보조 수단이며, 색 단독 의존을 피하도록 범례와 수치 라벨을 함께 둡니다. 키보드/스크린리더 사용자에게는 동일 데이터의 표 대체본 제공을 권장합니다.

Charts & data viz

BarChart

A grouped or stacked bar chart. The consumer computes bar coordinates/heights for a category axis (site/category) plus values. Groups place bars side by side; stacks pile them at the same x (both expressed via coordinates). Use --horizontal to switch label alignment for horizontal bars. Set bar color via style="color:var(--viz-N)".그룹 또는 스택 막대 차트입니다. 카테고리축(사이트/카테고리) + 값, 막대 좌표/높이는 소비처가 계산합니다. 그룹은 막대를 나란히, 스택은 같은 x 에 쌓아 배치합니다(둘 다 좌표로 표현). --horizontal 로 가로 막대 레이블 정렬을 전환합니다. 막대 색은 style="color:var(--viz-N)".

.qf-barchartlayer: generic

Preview

apicdnweb
<div class="qf-barchart" style="--chart-h:200px">
  <svg class="qf-barchart__svg" viewBox="0 0 320 200" role="img" aria-label="Downloaded vs failed by site, grouped">
    <g class="qf-barchart__grid">
      <line x1="40" y1="40" x2="312" y2="40">
    </line>
    <line x1="40" y1="100" x2="312" y2="100">
  </line>
  <line x1="40" y1="160" x2="312" y2="160">
</line>
</g>
<line class="qf-barchart__axis" x1="40" y1="20" x2="40" y2="160">
</line>
<line class="qf-barchart__axis" x1="40" y1="160" x2="312" y2="160">
</line>
<rect class="qf-barchart__bar" x="60" y="56" width="22" height="104" style="color:var(--viz-1)">
</rect>
<rect class="qf-barchart__bar" x="86" y="132" width="22" height="28" style="color:var(--viz-7)">
</rect>
<rect class="qf-barchart__bar" x="150" y="40" width="22" height="120" style="color:var(--viz-1)">
</rect>
<rect class="qf-barchart__bar" x="176" y="120" width="22" height="40" style="color:var(--viz-7)">
</rect>
<rect class="qf-barchart__bar" x="240" y="84" width="22" height="76" style="color:var(--viz-1)">
</rect>
<rect class="qf-barchart__bar" x="266" y="146" width="22" height="14" style="color:var(--viz-7)">
</rect>
<text class="qf-barchart__label" x="84" y="178">api</text>
<text class="qf-barchart__label" x="174" y="178">cdn</text>
<text class="qf-barchart__label" x="264" y="178">web</text>
</svg>
</div>

Variants

qf-barchart__svg qf-barchart__grid qf-barchart__axis qf-barchart__label qf-barchart__track qf-barchart__bar qf-barchart__value qf-barchart--horizontal

Required tokens

--viz-1 --viz-7 --chart-grid --chart-axis --chart-label --chart-track --text-secondary

Accessibility

Provide a comparison summary via role="img" + aria-label, and include value-label text so the chart does not rely on color alone. Reinforce the category×series breakdown with a legend.svg 에 role="img" + aria-label 로 비교 요약을 제공하고, 값 레이블 텍스트를 함께 둬 색 단독 의존을 피합니다. 카테고리×시리즈 분해는 범례로 보강합니다.

Charts & data viz

Donut

A multi-segment donut chart (an N-segment distribution, unlike the single-gauge Radial). Each segment is expressed with stroke-dasharray/stroke-dashoffset against the circle circumference, with lengths computed by the consumer. Place a total/label in the center and reinforce the distribution with a legend. Set segment color via style="color:var(--viz-N)".다세그먼트 도넛 차트입니다(단일 게이지인 Radial 과 달리 N 세그먼트 분포). 각 세그먼트는 원 둘레 기준 stroke-dasharray/stroke-dashoffset 로 표현하며 길이는 소비처가 계산합니다. 중앙에 합계/라벨을 두고 분포는 범례로 보강합니다. 세그먼트 색은 style="color:var(--viz-N)".

.qf-donutlayer: generic

Preview

412failures
<div class="qf-donut">
  <svg class="qf-donut__svg" viewBox="0 0 128 128" role="img" aria-label="Failure reasons: timeout 60%, auth 28%, other 12%">
    <circle class="qf-donut__track" cx="64" cy="64" r="54" stroke-width="16">
  </circle>
  <circle class="qf-donut__segment" cx="64" cy="64" r="54" stroke-width="16" stroke-dasharray="203.58 135.71" stroke-dashoffset="0" style="color:var(--viz-1)">
</circle>
<circle class="qf-donut__segment" cx="64" cy="64" r="54" stroke-width="16" stroke-dasharray="95 244.29" stroke-dashoffset="-203.58" style="color:var(--viz-5)">
</circle>
<circle class="qf-donut__segment" cx="64" cy="64" r="54" stroke-width="16" stroke-dasharray="40.71 298.58" stroke-dashoffset="-298.58" style="color:var(--viz-7)">
</circle>
</svg>
<div class="qf-donut__center">
  <span class="qf-donut__total">412</span>
  <span class="qf-donut__label">failures</span>
</div>
</div>

Variants

qf-donut__svg qf-donut__track qf-donut__segment qf-donut__center qf-donut__total qf-donut__label

Required tokens

--viz-1 --viz-5 --viz-7 --chart-track --text-strong --text-muted --fs-24

Accessibility

State the segment proportions with role="img" + aria-label on the svg (e.g., "Failure reasons: timeout 60%, auth 28%, other 12%"). Pair the centered total text and a legend to avoid color-only reliance.svg 에 role="img" + aria-label 로 세그먼트 비율을 명시합니다(예: "실패 사유: 타임아웃 60%, 인증 28%, 기타 12%"). 중앙 합계 텍스트와 범례로 색 단독 의존을 피합니다.

Charts & data viz

Heatmap

A site×time or site×category density heatmap (throughput/failures). Cells are a CSS grid; pass per-cell intensity via inline style --qf-heat (0–1) and the color interpolates between --heat-empty and currentColor. The consumer sets the column count (grid-template-columns) and cell values. Set color via style="color:var(--viz-N)".사이트×시간 또는 사이트×카테고리 밀도(처리량/실패) 히트맵입니다. CSS 그리드 셀로, 강도는 셀마다 --qf-heat(0~1) 를 인라인 style 로 전달하면 색이 --heat-empty 와 currentColor 사이를 보간합니다. 그리드 열 수(grid-template-columns)와 셀 값은 소비처가 지정합니다. 색은 style="color:var(--viz-N)".

.qf-heatmaplayer: generic

Preview

<div class="qf-heatmap" style="grid-template-columns:auto repeat(6,1fr);max-width:300px" role="img" aria-label="Throughput density by site and 4-hour bucket">
  <div class="qf-heatmap__row">
    <span class="qf-heatmap__label">api</span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.2" title="api 00:00 — 21">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.5" title="api 04:00 — 58">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.8" title="api 08:00 — 92">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:1" title="api 12:00 — 114">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.6" title="api 16:00 — 67">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.3" title="api 20:00 — 33">
    </span>
  </div>
  <div class="qf-heatmap__row">
    <span class="qf-heatmap__label">cdn</span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.5" title="cdn 00:00 — 54">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.7" title="cdn 04:00 — 78">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.9" title="cdn 08:00 — 101">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.6" title="cdn 12:00 — 64">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.4" title="cdn 16:00 — 41">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.2" title="cdn 20:00 — 19">
    </span>
  </div>
  <div class="qf-heatmap__row">
    <span class="qf-heatmap__label">web</span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.1" title="web 00:00 — 9">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.3" title="web 04:00 — 28">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.6" title="web 08:00 — 63">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.8" title="web 12:00 — 88">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.7" title="web 16:00 — 71">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.5" title="web 20:00 — 52">
    </span>
  </div>
  <div class="qf-heatmap__row">
    <span class="qf-heatmap__label">db</span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.4" title="db 00:00 — 44">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.5" title="db 04:00 — 51">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.4" title="db 08:00 — 47">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.6" title="db 12:00 — 62">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:0.9" title="db 16:00 — 103">
    </span>
    <span class="qf-heatmap__cell" style="--qf-heat:1" title="db 20:00 — 118">
    </span>
  </div>
</div>

Variants

qf-heatmap__row qf-heatmap__cell qf-heatmap__label

Required tokens

--viz-2 --heat-empty --text-muted

Accessibility

Because this is a grid (not an svg), give the container role="img" + aria-label summarizing what the density represents, and provide the exact value per cell via title (or aria-label) so it does not rely on color/brightness alone.svg 가 아닌 그리드이므로 컨테이너에 role="img" + aria-label 로 무엇의 밀도인지 요약하고, 각 셀에는 title(또는 aria-label)로 정확한 수치를 제공해 색/명도 단독 의존을 피합니다.

Charts & data viz

Legend

A legend shared by the charts (color swatch + label + optional value). Match the swatch to the series color via style="color:var(--viz-N)". The --toggle variant turns items into button[aria-pressed] to convey series show/hide state.차트들이 공유하는 범례입니다(색칩 + 라벨 + 선택적 수치). 색칩은 style="color:var(--viz-N)" 로 시리즈 색과 맞춥니다. --toggle 변형은 항목을 button[aria-pressed] 로 만들어 시리즈 표시 on/off 를 전달합니다.

.qf-legendlayer: generic

Preview

  • Downloaded 3,248
  • Skipped 412
  • Failed 96
<ul class="qf-legend">
  <li class="qf-legend__item">
    <span class="qf-legend__swatch" style="color:var(--viz-1)">
    </span>
    Downloaded
    <span class="qf-legend__value">3,248</span>
  </li>
  <li class="qf-legend__item">
    <span class="qf-legend__swatch" style="color:var(--viz-5)">
    </span>
    Skipped
    <span class="qf-legend__value">412</span>
  </li>
  <li class="qf-legend__item">
    <span class="qf-legend__swatch" style="color:var(--viz-7)">
    </span>
    Failed
    <span class="qf-legend__value">96</span>
  </li>
</ul>

Examples예시

Toggle (show/hide series)

Variants

qf-legend__item qf-legend__swatch qf-legend__value qf-legend--toggle

Required tokens

--viz-1 --viz-5 --viz-7 --text-secondary --text-muted --bg-hover --text-disabled

Accessibility

Use ul/li for the non-toggle form. For the toggle form, make each item a button + aria-pressed (true/false) so screen readers announce the visibility state, and ensure dimmed items are distinguished by state (aria-pressed), not color alone.비토글형은 ul/li 로 의미를 전달합니다. 토글형은 각 항목을 button + aria-pressed(true/false) 로 만들어 표시 상태를 스크린리더에 알리고, 흐려진 항목도 색 외 상태(aria-pressed)로 구분되게 합니다.

Media

MediaCard

A thumbnail card with an aspect-ratio-locked media slot (letterbox) plus overlay badges and toggles — for video, image, and poster grids.종횡비 고정 미디어 슬롯(레터박스)에 오버레이 배지, 토글을 얹는 썸네일 카드입니다. 비디오, 이미지, 포스터 그리드에 씁니다.

.qf-media-cardlayer: generic

Preview

12:34
Sunset over the harbor, extended cut
1080p248 MB2 days ago
<div class="qf-media-card qf-media-card--interactive" style="max-width:260px">
  <div class="qf-media-card__media">
    <div class="qf-media-card__overlay qf-media-card__overlay--start">
      <span class="qf-badge">12:34</span>
    </div>
    <div class="qf-media-card__overlay qf-media-card__overlay--end">
      <button class="qf-btn qf-btn--icon qf-btn--ghost" aria-label="Favorite" aria-pressed="false">
        <svg class="qf-icon qf-icon--md" aria-hidden="true">
          <use href="#qf-i-star"/>
        </svg>
      </button>
    </div>
  </div>
  <div class="qf-media-card__body">
    <div class="qf-media-card__title qf-clamp">Sunset over the harbor, extended cut</div>
    <div class="qf-media-card__meta">
      <span>1080p</span>
      <span>248 MB</span>
      <span>2 days ago</span>
    </div>
  </div>
</div>

Examples예시

NEW
The Lighthouse
2019Drama
Poster (--2x3)
Loading (--loading + qf-skel)
Couldn't load preview
Broken asset
Error (--error + __fallback)

Variants

qf-media-card__media qf-media-card__overlay qf-media-card__overlay--start qf-media-card__overlay--end qf-media-card__body qf-media-card__title qf-media-card__meta qf-media-card__skeleton qf-media-card__fallback qf-media-card--2x3 qf-media-card--auto qf-media-card--interactive qf-media-card--error

Required tokens

--bg-media --media-overlay-scrim --aspect-16x9 --aspect-2x3 --r-lg --border --border-strong --bg-panel --elev-3 --ring-accent --s-2 --s-3 --fs-13 --fs-12 --text --text-muted --dur-fast --ease-standard

Accessibility

Make activatable media slots operable with role=button, tabindex=0, Enter/Space, and aria-label. Overlay toggles are real buttons with aria-pressed and a 44px target; badge text keeps 4.5:1 over the scrim; skeletons set aria-busy; truncated titles carry a title attribute.활성화 가능한 미디어 슬롯은 role=button, tabindex=0, Enter/Space, aria-label 로 동작을 전달합니다. 오버레이 토글은 실제 button + aria-pressed + 44px, 배지 텍스트는 스크림 위에서 4.5:1, 스켈레톤은 aria-busy, 잘린 제목은 title 속성을 둡니다.

Media

Figure

A picture (or video) with a one-line caption below. The caption is 13px in a secondary tone; a link inside is underlined and carries a qf-i-external icon so it reads as a link beyond color. Non-link notes such as "Image: AI generated" sit in the same place without an icon. Limit the image height with --qf-figure-max-h (none by default).그림(또는 영상)과 그 아래 한 줄 캡션입니다. 캡션은 13px 보조 톤이고, 안의 링크는 밑줄과 qf-i-external 아이콘으로 링크임이 색 외에도 드러납니다. "이미지 출처: AI 생성" 같은 비링크 문구도 같은 자리에 아이콘 없이 둡니다. 그림 최대 높이는 --qf-figure-max-h 로 제한할 수 있습니다(기본 없음).

.qf-figurelayer: generic

Preview

<figure class="qf-figure" style="max-width:420px">
  <img src="brand-assets/png/og-image.png" alt="qufox brand card">
  <figcaption class="qf-figure__caption">
    Image:
    <a href="#source" target="_blank" rel="noopener">
      Ruliweb post
      <svg class="qf-icon qf-icon--sm" aria-hidden="true">
        <use href="#qf-i-external"/>
      </svg>
    </a>
  </figcaption>
</figure>

Examples예시

Linked source
Illustration of the issue
Image: AI generated
AI generated (no link)

Variants

qf-figure__caption

Required tokens

--s-2 --s-1 --r-lg --bg-media --fs-13 --lh-snug --text-muted --text-secondary --text --border-strong

Accessibility

Use figure/figcaption so image and caption are associated, and give the img an alt that describes the content (caption = source, alt = content). External links use target=_blank with rel=noopener, the icon is aria-hidden, and opening in a new window is conveyed in the link text or aria-label. Caption links are inline text links, so only vertical padding is added to help tapping.figure/figcaption 으로 두어 그림과 설명이 묶이게 하고, img 에는 내용을 설명하는 alt 를 둡니다(캡션은 출처, alt 는 내용). 외부 링크는 target=_blank 와 rel=noopener 를 쓰고 아이콘은 aria-hidden, 새 창 열림은 링크 텍스트나 aria-label 로 알립니다. 캡션 링크는 본문 안 인라인 링크라 세로 패딩만 더해 탭을 돕습니다.

Media

MediaOverlay

Glass control and status chrome that floats over a video or image stage. Stays light regardless of theme, avoids the safe area, and passes pointer events through so it never blocks native controls.영상이나 이미지 스테이지 위에 떠서 컨트롤과 상태를 보여주는 글래스 크롬입니다. 테마와 무관하게 항상 밝고, safe-area를 피하며, pointer-events 패스스루로 네이티브 컨트롤을 가리지 않습니다.

.qf-media-overlaylayer: generic

Preview

LIVE
12:34 / 48:02
<div style="position:relative;aspect-ratio:var(--aspect-16x9);max-width:440px;background:var(--bg-media);border-radius:var(--r-lg);overflow:hidden">
  <div class="qf-media-overlay">
    <div class="qf-media-overlay__top">
      <span class="qf-media-overlay__pill">LIVE</span>
      <span style="flex:1">
      </span>
      <button class="qf-media-overlay__pill qf-media-overlay__pill--button" aria-label="Settings">
        <svg class="qf-icon qf-icon--md" aria-hidden="true">
          <use href="#qf-i-settings"/>
        </svg>
      </button>
    </div>
    <div class="qf-media-overlay__bottom">
      <button class="qf-media-overlay__pill qf-media-overlay__pill--button" aria-label="Play">
        <svg class="qf-icon qf-icon--md" aria-hidden="true">
          <use href="#qf-i-video"/>
        </svg>
      </button>
      <span class="qf-media-overlay__pill">12:34 / 48:02</span>
    </div>
  </div>
</div>

Examples예시

Buffering…Reconnecting to stream
Buffering HUD (role=status)
Error HUD (role=alert)

Variants

qf-media-overlay__top qf-media-overlay__bottom qf-media-overlay__pill qf-media-overlay__pill--button qf-media-overlay__pill--danger qf-media-overlay__hud qf-media-overlay__hud--error qf-media-overlay__title qf-media-overlay__body

Required tokens

--on-media-text --on-media-text-muted --on-media-glass-bg --on-media-glass-bg-strong --on-media-border --on-media-border-hover --on-media-danger-text --on-media-danger-border --safe-top --safe-bottom --z-media-overlay --r-pill --r-lg --ring-focus --scrim-blur --fs-13 --fs-15

Accessibility

__pill--button is a real button with a focus ring visible over video and a 44px target. __hud uses role=status + aria-live=polite while buffering and role=alert on error. The container's pointer-events:none must not trap focus or block keyboard access to native controls.__pill--button은 실제 button + 영상 위에서 보이는 포커스 링 + 44px 입니다. __hud는 버퍼링 시 role=status, aria-live=polite, 에러 시 role=alert 를 둡니다. 컨테이너 pointer-events:none이 포커스를 가두거나 네이티브 컨트롤 키보드 접근을 막지 않아야 합니다.

Feedback & status

Toast

A notification message that appears briefly in a corner of the screen. --brief shows briefly and fades out (--dur-toast-brief, 2.4 s; under reduced motion it simply disappears after 2.4 s without motion. No live disappearing example is kept in the catalog). Pattern: a share button (qf-btn--ghost qf-btn--icon + qf-i-share) calls navigator.share, or falls back to copying the link and showing a qf-toast--brief "Link copied".화면 모서리에 잠깐 뜨는 알림 메시지입니다. --brief 는 짧게 떠 있다 사라집니다(--dur-toast-brief, 2.4초. 축소 모션에서는 모션 없이 2.4초 뒤 사라짐. 카탈로그에는 사라지는 라이브 예제를 두지 않습니다). 패턴: 공유 버튼(qf-btn--ghost qf-btn--icon + qf-i-share)은 navigator.share 를 쓰고, 없으면 링크를 복사한 뒤 qf-toast--brief 로 "링크를 복사했습니다" 를 띄웁니다.

.qf-toastlayer: generic

Preview

Saved
<div class="qf-toast qf-toast--success" role="status" aria-live="polite">
  <div class="qf-toast__title">Saved</div>
</div>

Variants

Saved
qf-toast--success
Saved
qf-toast--danger
Saved
qf-toast--warn
Saved
qf-toast--brief

Parts & more: 구성 요소, 기타: qf-toast__title qf-toast__body

Required tokens

--bg-elevated --border --accent --ok-400 --danger-400 --warn-400 --r-md --elev-3 --dur-toast-brief --ease-standard --s-2

Accessibility

Announce with role="status" and aria-live="polite", and use role="alert" for errors. Include title and body text so meaning is not conveyed by the left color bar alone. Remove a --brief toast on animationend, and give the toast region role="status" (aria-live=polite) so it is announced.role="status" 와 aria-live="polite" 로 알리고 오류는 role="alert" 를 씁니다. 좌측 색 막대만으로 의미를 전하지 않도록 제목과 본문 텍스트를 함께 둡니다. --brief 는 animationend 에서 요소를 제거하고, 토스트 영역을 role="status"(aria-live=polite) 로 두어 낭독되게 합니다.

Feedback & status

ToastRegion

A fixed container that stacks multiple qf-toast elements, defaulting to the top right and repositionable with --bottom/--left.여러 qf-toast 를 쌓아 올리는 고정 컨테이너입니다. 기본 우상단, --bottom/--left 로 위치를 바꿉니다.

.qf-toast-regionlayer: generic

Preview

Saved
Sync delayed
<div class="qf-toast-region" aria-live="polite">
  <div class="qf-toast qf-toast--success" role="status">
    <div class="qf-toast__title">Saved</div>
  </div>
  <div class="qf-toast qf-toast--warn" role="status">
    <div class="qf-toast__title">Sync delayed</div>
  </div>
</div>

Variants

Saved
Sync delayed
qf-toast-region--bottom
Saved
Sync delayed
qf-toast-region--left

Required tokens

--z-toast --s-5 --s-3

Accessibility

Set aria-live=polite (assertive for urgent) on the region so screen readers announce toasts as they are added. Apply pointer-events to the toasts only.region 에 aria-live=polite(긴급은 assertive)를 두어 추가되는 토스트를 스크린리더가 읽게 합니다. pointer-events 는 토스트에만.

Feedback & status

Callout

Obsidian-style callouts — 13 typed notice blocks rendered inside qf-prose body, with optional collapsing via details/summary.Obsidian 스타일 콜아웃 — qf-prose 본문 안에 렌더하는 13종 안내 블록입니다. 접기(details/summary)를 지원합니다.

.qf-calloutlayer: generic

Preview

Tip
Use tokens and dark, light adapt automatically.
<div class="qf-callout qf-callout--tip">
  <div class="qf-callout__title">
    <span class="qf-callout__icon">
      <svg class="qf-icon qf-icon--sm" aria-hidden="true">
        <use href="#qf-i-sparkle"/>
      </svg>
    </span>
    Tip
  </div>
  <div class="qf-callout__body">Use tokens and dark, light adapt automatically.</div>
</div>

Examples예시

Note
A general note in body flow.
note
Abstract
A short summary of what follows.
abstract
Info
Contextual information.
info
Todo
Something still to do.
todo
Tip
Use tokens and dark, light adapt automatically.
tip
Success
The step completed.
success
Question
Is this the right approach?
question
Warning
Double-check before continuing.
warning
Failure
The check did not pass.
failure
Danger
This action cannot be undone.
danger
Bug
Known issue, tracked in #142.
bug
Example
A worked example follows.
example
Quote
Design is how it works.
quote
Collapsible
Click the summary to fold and unfold.
collapsible (details/summary)

Variants

Tip
Use tokens and dark, light adapt automatically.
qf-callout--note
Tip
Use tokens and dark, light adapt automatically.
qf-callout--abstract
Tip
Use tokens and dark, light adapt automatically.
qf-callout--info
Tip
Use tokens and dark, light adapt automatically.
qf-callout--todo
Tip
Use tokens and dark, light adapt automatically.
qf-callout--tip
Tip
Use tokens and dark, light adapt automatically.
qf-callout--success
Tip
Use tokens and dark, light adapt automatically.
qf-callout--question
Tip
Use tokens and dark, light adapt automatically.
qf-callout--warning
Tip
Use tokens and dark, light adapt automatically.
qf-callout--failure
Tip
Use tokens and dark, light adapt automatically.
qf-callout--danger
Tip
Use tokens and dark, light adapt automatically.
qf-callout--bug
Tip
Use tokens and dark, light adapt automatically.
qf-callout--example
Tip
Use tokens and dark, light adapt automatically.
qf-callout--quote

Parts & more: 구성 요소, 기타: qf-callout__title qf-callout__icon qf-callout__body

Required tokens

--text-info --text-ok --text-warn --text-danger --accent-text --text-muted --border --border-strong --bg-elevated --text-strong --r-md --s-1 --ring-focus

Accessibility

Convey the type via the title text in addition to the left accent bar and icon color, avoiding reliance on color alone (WCAG 1.4.1). Icons are aria-hidden; collapsing uses native details/summary to preserve keyboard and screen reader behavior, with a focus ring on the summary.타입 의미를 좌측 강조선과 아이콘 색뿐 아니라 제목 텍스트로 함께 전달해 색 단독 의존을 피합니다(WCAG 1.4.1). 아이콘은 aria-hidden, 접기는 네이티브 details/summary 로 키보드, 스크린리더 동작을 보존하고 summary 에 포커스 링을 둡니다.

Feedback & status

Banner

A banner that displays a notice at the top of the page or inline.상단 또는 본문에 알림을 표시하는 배너입니다.

.qf-bannerlayer: generic

Preview

Your connection is unstable.
<div class="qf-banner qf-banner--warn" role="status">
  <span class="qf-banner__msg">Your connection is unstable.</span>
  <button class="qf-banner__close" aria-label="Close">×</button>
</div>

Variants

Your connection is unstable.
qf-banner--info
Your connection is unstable.
qf-banner--warn
Your connection is unstable.
qf-banner--danger
Your connection is unstable.
qf-banner--accent

Parts & more: 구성 요소, 기타: qf-banner__icon qf-banner__msg qf-banner__actions qf-banner__close

Required tokens

--accent --accent-subtle --info-400 --warn-400 --danger-400 --bg-panel --s-3 --text-strong

Accessibility

Assign role=status or role=alert to match its nature, and convey the informational meaning with an icon and text, not color alone. Give the close button an aria-label.성격에 맞춰 role=status 또는 role=alert를 부여하고 정보 의미를 색뿐 아니라 아이콘과 텍스트로 전달합니다. 닫기 버튼에는 aria-label을 둡니다.

Feedback & status

Notice

An inline message box that surfaces info, warning, or danger states.정보, 경고, 위험을 알리는 인라인 안내 박스입니다.

.qf-noticelayer: generic

Preview

<div class="qf-notice qf-notice--warn" role="alert">
  <span class="qf-notice__icon">
    <svg class="qf-icon qf-icon--md" aria-hidden="true">
      <use href="#qf-i-alert"/>
    </svg>
  </span>
  <div class="qf-notice__body">
    <p class="qf-notice__title">Caution</p>
    You have unsaved changes.
  </div>
</div>

Examples예시

Load failed + retry (end of an infinite list)

Variants

qf-notice--info
qf-notice--warn
qf-notice--danger

Parts & more: 구성 요소, 기타: qf-notice__icon qf-notice__body qf-notice__title

Required tokens

--border --s-1 --info-400 --warn-400 --danger-400 --r-md --bg-elevated --text-secondary

Accessibility

Meaning is carried by a title and body text in addition to the left border color and icon, avoiding reliance on color alone. Warning and danger use role=alert, while info uses role=status to announce to screen readers.좌측 보더 색과 아이콘에 더해 제목, 본문 텍스트로 의미를 전달해 색 단독 의존을 피합니다. 경고, 위험은 role=alert로, 정보는 role=status로 스크린리더에 알립니다.

Feedback & status

Spinner

A spinning loader that indicates work is in progress.작업이 진행 중임을 나타내는 회전 로더입니다.

.qf-spinnerlayer: generic

Preview

<span class="qf-spinner" role="status" aria-label="Loading">
</span>

Variants

qf-spinner--sm
qf-spinner--lg

Required tokens

--bg-selected --accent --r-pill

Accessibility

Announce progress with role=status and an aria-label (e.g., Loading). prefers-reduced-motion is honored by the global guard in tokens.css.role=status 와 aria-label(예: 불러오는 중)로 진행을 알립니다. prefers-reduced-motion 은 tokens.css 전역 가드가 존중합니다.

Feedback & status

Progress

Displays task progress as a bar.작업 진행률을 막대로 표시합니다.

.qf-progresslayer: generic

Preview

<div class="qf-progress" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100">
  <span class="qf-progress__bar" style="width: 60%">
  </span>
</div>

Variants

qf-progress--success
qf-progress--danger
qf-progress--indeterminate

Parts & more: 구성 요소, 기타: qf-progress__bar

Required tokens

--bg-hover --accent --ok-400 --danger-400 --r-pill --s-2 --dur-base

Accessibility

Convey the value with role=progressbar and aria-valuenow/valuemin/valuemax. Express an indeterminate state with aria-busy=true or by omitting the value attributes.role=progressbar 와 aria-valuenow/valuemin/valuemax 로 값을 전달합니다. 진행률 미정 상태는 aria-busy=true 또는 값 속성 생략으로 표현합니다.

Feedback & status

Radial

Shows a single value such as capacity or utilization as a radial gauge. Pass --qf-radial-value (0–100) via inline style.용량, 사용률 등 단일 값을 방사형(게이지)으로 보여줍니다. --qf-radial-value(0~100) 를 인라인 style 로 전달합니다.

.qf-radiallayer: generic

Preview

72%
<div class="qf-radial qf-radial--warn" style="--qf-radial-value:72" role="progressbar" aria-valuenow="72" aria-valuemin="0" aria-valuemax="100" aria-label="Disk usage">
  <span class="qf-radial__value">72%</span>
</div>

Variants

72%
qf-radial--ok
72%
qf-radial--warn
72%
qf-radial--danger

Parts & more: 구성 요소, 기타: qf-radial__value

Required tokens

--accent --bg-hover --bg-elevated --text-strong --ok-400 --warn-400 --danger-400 --fs-18

Accessibility

Convey the value with role=progressbar + aria-valuenow/min/max, and use the centered numeric text to avoid reliance on color alone.role=progressbar + aria-valuenow/min/max 로 값을 전달하고, 중앙 수치 텍스트로 색 단독 의존을 피합니다.

Feedback & status

Nudge

A pill button floating centered under the top bar that says something like "3 new issues" and, when pressed, scrolls to the top and refreshes. The consumer inserts it only when there is something new (short slide-down mount motion) and removes it on press or when handled — no state classes. If the top bar is not --h-navbar tall, set --qf-nudge-top. 44px on phones. It may be a button or an a (no underline).상단 바 아래 가운데에 떠서 "새 이슈 3건" 처럼 알리고, 누르면 맨 위로 가며 새로 고치는 알약 버튼입니다. 새 항목이 있을 때만 소비처가 DOM 에 넣고(위에서 내려오는 짧은 마운트 모션), 누르거나 처리되면 제거합니다 — 상태 클래스가 없습니다. 상단 바 높이가 기본(--h-navbar)과 다르면 --qf-nudge-top 으로 맞춥니다. 폰에서는 44px. button 또는 a 로 쓸 수 있습니다(밑줄 없음).

.qf-nudgelayer: generic

Preview

<div style="position:relative;height:88px">
  <button class="qf-nudge" type="button" style="position:absolute;top:var(--s-3)">
    <svg class="qf-icon qf-icon--sm" aria-hidden="true">
      <use href="#qf-i-chevron-up"/>
    </svg>
    3 new issues
  </button>
</div>

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--h-navbar --s-3 --s-2 --s-5 --s-6 --s-9 --z-sticky --r-pill --accent-solid --accent-solid-hover --accent-solid-press --text-onAccent --elev-3 --fs-13 --dur-base --ease-emphasized --m-touch --ring-focus

Accessibility

A button whose text is its name (icon aria-hidden). Place it inside an aria-live=polite region so its appearance is announced. White text on the solid accent passes AA. The mount motion is disabled under prefers-reduced-motion.button 이며 문구 자체가 이름입니다(아이콘은 aria-hidden). 새로 나타났음을 알리려면 aria-live=polite 영역 안에 넣습니다. 흰 글자는 solid accent 위에서 AA 를 넘습니다. 마운트 모션은 prefers-reduced-motion 에서 꺼집니다.

Feedback & status

Steps

Displays the progress steps of a multi-step flow.다단계 흐름의 진행 단계를 표시합니다.

.qf-stepslayer: generic

Preview

  1. ✓Account
  2. 2Profile
<ol class="qf-steps">
  <li class="qf-steps__step qf-steps__step--done">
    <span class="qf-steps__marker">✓</span>
    Account
  </li>
  <li class="qf-steps__bar" aria-hidden="true">
  </li>
  <li class="qf-steps__step" aria-current="step">
    <span class="qf-steps__marker">2</span>
    Profile
  </li>
</ol>

Variants

qf-steps__step qf-steps__marker qf-steps__bar qf-steps__step--done

Required tokens

--s-2 --r-pill --bg-hover --accent --text-onAccent --ok-400 --divider --text-muted

Accessibility

Convey order with an ol and set aria-current="step" on the current step. Communicate the completed/current state with marker numbers and text, not color alone.ol 로 순서를 전달하고 현재 단계에 aria-current=step 을 둡니다. 완료/현재 상태를 색뿐 아니라 마커 숫자, 텍스트로 함께 전달합니다.

Feedback & status

TypingDots

A three-dot staggered bounce that signals 'generating' or 'typing' — semantically distinct from a spinner (working) or progress (quantified).standalone 3점 staggered bounce로 '생성 중'/입력 중을 표시합니다. spinner(작업 중), progress(정량)와 의미가 다릅니다.

.qf-typing-dotslayer: generic

Preview

<span class="qf-typing-dots" role="status" aria-label="Generating">
  <span class="qf-typing-dots__dot" aria-hidden="true">
  </span>
  <span class="qf-typing-dots__dot" aria-hidden="true">
  </span>
  <span class="qf-typing-dots__dot" aria-hidden="true">
  </span>
</span>

Examples예시

On accent surface (--onAccent)
Large (--lg)

Variants

qf-typing-dots--onAccent
qf-typing-dots--sm
qf-typing-dots--lg

Parts & more: 구성 요소, 기타: qf-typing-dots__dot

Required tokens

--size-typing-dot --motion-typing --text-muted --accent --s-1 --r-pill --ease-standard

Accessibility

Give the root role=status, aria-live=polite, and an accessible name (e.g. aria-label='Generating'); the dots are aria-hidden. Under prefers-reduced-motion, replace the bounce with an opacity fade — never freeze it at scale(0).루트에 role=status, aria-live=polite, 접근명(예: aria-label='생성 중')을 두고 점은 aria-hidden 입니다. prefers-reduced-motion 에서 bounce를 opacity 페이드로 대체하고 scale(0)로 얼려 안 보이게 두지 않습니다.

Navigation

Menu

A dropdown menu that presents a list of actions.동작 목록을 보여주는 드롭다운 메뉴입니다.

.qf-menulayer: generic

Preview

<div class="qf-menu" role="menu">
  <button class="qf-menu__item" role="menuitem">
    Edit
    <kbd class="qf-menu__kbd">⌘E</kbd>
  </button>
  <button class="qf-menu__item" role="menuitem">
    Copy
    <kbd class="qf-menu__kbd">⌘C</kbd>
  </button>
  <div class="qf-menu__separator" role="separator">
  </div>
  <button class="qf-menu__item qf-menu__item--danger" role="menuitem">Delete</button>
</div>

Variants

qf-menu__item qf-menu__item--danger qf-menu__separator qf-menu__kbd

Required tokens

--bg-elevated --border --bg-hover --r-lg --r-sm --divider --s-2 --elev-3

Accessibility

Set role="menu" and role="menuitem", navigate with the up and down arrows, and close on Esc. Show shortcuts as text so meaning is not conveyed by color alone.role="menu" 와 role="menuitem" 을 지정하고, 위아래 화살표로 이동하며 Esc 로 닫습니다. 단축키는 텍스트로 함께 보여 색만으로 의미를 전하지 않습니다.

Navigation

Tabs

A set of tabs for switching between multiple views.여러 뷰를 전환하는 탭 모음입니다.

.qf-tabslayer: generic

Preview

<div class="qf-tabs" role="tablist">
  <button class="qf-tabs__item" role="tab" aria-selected="true">All</button>
  <button class="qf-tabs__item" role="tab" aria-selected="false">Mentions</button>
  <button class="qf-tabs__item" role="tab" aria-selected="false">Unread</button>
</div>

Variants

qf-tabs__item

Required tokens

--divider --text-secondary --text-strong --accent --s-3 --s-4 --fs-14

Accessibility

Set role="tablist" and role="tab", and mark the active tab with aria-selected="true". Navigate with the left and right arrows, and convey state with text in addition to the underline indicator.role="tablist" 과 role="tab" 을 지정하고 선택 탭은 aria-selected="true" 로 알립니다. 좌우 화살표로 이동하며 밑줄 표시 외에 상태를 텍스트로도 전합니다.

Navigation

TableOfContents

An 'on this page' table of contents that sticks to the right (qf-app-shell__aside) of a blog or doc page.블로그, 문서 우측(qf-app-shell__aside)에 sticky 로 붙는 '이 페이지에서' 목차입니다.

.qf-toclayer: generic

Preview

<nav class="qf-toc" aria-label="On this page">
  <div class="qf-toc__title">On this page</div>
  <ul>
    <li class="qf-toc__item">
      <a class="qf-toc__link qf-toc__link--active" href="#intro">Introduction</a>
    </li>
    <li class="qf-toc__item qf-toc__item--d2">
      <a class="qf-toc__link" href="#setup">Setup</a>
    </li>
    <li class="qf-toc__item qf-toc__item--d3">
      <a class="qf-toc__link" href="#install">Install the CLI</a>
    </li>
  </ul>
</nav>

Variants

qf-toc__title qf-toc__item qf-toc__item--d2 qf-toc__item--d3 qf-toc__link qf-toc__link--active

Required tokens

--accent --text-strong --text-secondary --text-muted --fs-11 --fs-13 --tracking-caps --s-4 --s-7 --lh-snug

Accessibility

Give the nav an aria-label to convey the landmark, and mark the active item with a left vertical indicator (--accent) plus text emphasis so meaning is not carried by color alone. Links meet a 44px touch target and long titles are truncated with an ellipsis.nav 에 aria-label 을 두어 랜드마크 의미를 전달하고, 활성 항목은 좌측 세로 인디케이터(--accent) + 텍스트 강조로 색 단독 의존을 피합니다. 링크는 44px 터치 타깃을 확보하고 긴 제목은 말줄임합니다.

Navigation

Breadcrumb

A breadcrumb trail that shows the path to the current location.현재 위치까지의 경로를 보여주는 이동 경로 내비게이션입니다.

.qf-breadcrumblayer: generic

Preview

<nav aria-label="Breadcrumb">
  <ol class="qf-breadcrumb">
    <li>
      <a class="qf-breadcrumb__item" href="/">Home</a>
    </li>
    <li class="qf-breadcrumb__sep" aria-hidden="true">/</li>
    <li>
      <a class="qf-breadcrumb__item" aria-current="page">Settings</a>
    </li>
  </ol>
</nav>

Variants

qf-breadcrumb__item qf-breadcrumb__sep

Required tokens

--s-2 --link --text-muted --fs-13

Accessibility

Build it as an ol inside nav[aria-label="breadcrumb"], and set aria-current="page" on the current page's item. Mark the separator (__sep) as decorative with aria-hidden.nav[aria-label=경로] 안의 ol 로 만들고, 현재 페이지 항목에 aria-current=page 를 둡니다. 구분 기호(__sep)는 aria-hidden 으로 장식 처리합니다.

Navigation

Pagination

Pagination controls for moving between pages.페이지 사이를 이동하는 페이지네이션입니다.

.qf-paginationlayer: generic

Preview

<nav aria-label="Pagination">
  <ul class="qf-pagination">
    <li>
      <button class="qf-pagination__item" aria-label="Previous">‹</button>
    </li>
    <li>
      <button class="qf-pagination__item" aria-current="page">1</button>
    </li>
    <li>
      <button class="qf-pagination__item">2</button>
    </li>
  </ul>
</nav>

Variants

qf-pagination__item

Required tokens

--s-1 --r-sm --text-secondary --bg-hover --bg-selected --text-strong --fs-14

Accessibility

Wrap it in nav[aria-label="pagination"] and set aria-current="page" on the current page. Give the previous/next buttons an aria-label, and signal unavailable states with disabled.nav[aria-label=페이지] 로 감싸고 현재 페이지에 aria-current=page 를 둡니다. 이전/다음 버튼에는 aria-label 을 주고, 불가 상태는 disabled 로 알립니다.

Navigation

Navbar

A top app bar that holds branding, navigation links, and actions. --sticky pins the bar to the top; use it on long lists and reading pages where search and a way back up must stay reachable. Class contract: consumer JS toggles is-stuck when scrolled past 0 (shadow and line) and is-hidden while scrolling down (slides up out of view). Narrow-width contract: the bar stays one line — the brand truncates with an ellipsis, the link group (qf-navbar__nav) scrolls horizontally when it overflows, icon buttons never shrink, and gaps/padding step down at ≤600px. On phones keep to brand + two links + three icon buttons; move a select or long links into a drawer or menu on the consumer side (the DS hides nothing).브랜드, 내비 링크, 액션을 담는 상단 앱 바입니다. --sticky 는 위에 붙는 고정 상단 바입니다 — 긴 목록이나 읽기 페이지처럼 내려간 뒤에도 찾기와 맨 위로 가는 길이 필요할 때 씁니다. 클래스 계약: 소비처 JS 가 스크롤이 0 이 아니면 is-stuck(그림자·선), 아래로 스크롤 중이면 is-hidden(위로 숨음)을 붙였다 뗍니다. 좁은 폭 계약: 바는 한 줄을 지킵니다 — 브랜드는 말줄임, 링크 묶음(qf-navbar__nav)은 넘치면 가로 스크롤, 아이콘 버튼은 줄지 않음, ≤600px 에서 간격·여백 한 단계 축소. 폰에 둘 것은 브랜드 + 링크 2개 + 아이콘 버튼 3개까지이고 select·긴 링크는 소비처가 드로어나 메뉴로 옮깁니다(DS 는 아무것도 숨기지 않습니다).

.qf-navbarlayer: generic

Preview

<nav class="qf-navbar" aria-label="Main menu">
  <span class="qf-navbar__brand">Acme</span>
  <div class="qf-navbar__nav">
    <a class="qf-navbar__link" aria-current="page">Dashboard</a>
    <a class="qf-navbar__link" href="/r">Reports</a>
  </div>
  <span class="qf-navbar__spacer">
  </span>
  <button class="qf-btn qf-btn--ghost qf-btn--icon" type="button" aria-pressed="true" aria-label="Light theme">
    <svg class="qf-icon qf-icon--md" aria-hidden="true">
      <use href="#qf-i-sun"/>
    </svg>
  </button>
  <button class="qf-btn qf-btn--primary qf-btn--sm">New</button>
</nav>

Variants

qf-navbar--sticky

Parts & more: 구성 요소, 기타: qf-navbar__brand qf-navbar__nav qf-navbar__link qf-navbar__spacer

Required tokens

--h-navbar --bg-panel --divider --s-5 --text-strong --bg-hover --bg-selected --z-header-sticky --elev-2 --border --dur-base --ease-standard --dur-fast --m-touch --s-4 --s-3 --s-2 --s-1 --fs-16 --fs-14 --tracking-tight --text-secondary --r-sm --text

Accessibility

Wrap it in header > nav[aria-label] and set aria-current="page" on the link for the current location. Use a[href] for links, with a visible keyboard focus. A theme toggle is a qf-btn--ghost qf-btn--icon with aria-pressed (light mode = true); consumer JS swaps the sun (qf-i-sun) / moon (qf-i-moon) icon. The pressed state shows as the selected surface. A pinned bar covers part of the viewport: place in-page sticky elements (qf-dayrule) below it with --qf-dayrule-top: var(--h-navbar) and give focus targets a scroll-margin-top. The hide transition becomes instant under prefers-reduced-motion. For --sticky, put the nav directly under body (or make the header itself the bar); a nav inside a header only sticks within the header box. If keyboard focus enters a hidden bar it reappears. Icon buttons inside the bar get a 44px hit area on touch devices automatically. If the brand is icon + text, put the ellipsis styling on the text span (an inline-flex brand needs text-overflow on the text element) and give the full name via title. __nav shows no overflow hint, so keep to two links on phones (keyboard focus scrolls automatically).header > nav[aria-label] 로 감싸고, 현재 위치 링크에 aria-current=page 를 둡니다. 링크는 a[href], 키보드 포커스 가시. 밝기 토글은 qf-btn--ghost qf-btn--icon 에 aria-pressed(밝은 모드 = true)를 두고 해(qf-i-sun)/달(qf-i-moon) 아이콘을 소비처 JS 가 바꿉니다. 눌린 상태는 selected 표면으로 보입니다. 고정 바는 뷰포트를 가리므로 페이지 안 sticky(qf-dayrule)는 --qf-dayrule-top: var(--h-navbar) 로 그 아래에 두고, 포커스 이동 대상에는 scroll-margin-top 을 줍니다. 숨김 전환은 prefers-reduced-motion 에서 즉시 바뀝니다. --sticky 는 nav 를 body 직하(또는 header 자체)에 두어야 뷰포트에 붙습니다(header 안의 nav 는 header 박스 안에서만 붙음). 숨은 바 안으로 키보드 포커스가 들어오면 다시 보입니다. 바 안의 아이콘 버튼은 터치 환경에서 44px 히트 영역을 자동으로 받습니다. 브랜드가 아이콘 + 글자면 글자 span 에 말줄임 스타일을 두고(inline-flex 브랜드는 text-overflow 가 글자 요소에 걸려야 함) title 로 전체 이름을 줍니다. __nav 는 넘침 단서가 없으므로 폰에서 링크 2개까지(키보드 포커스는 자동 스크롤).

Navigation

SideNav

A general-purpose vertical navigation organized into sections and items (unrelated to a chat channel list).섹션과 항목으로 구성된 범용 세로 내비게이션입니다(채팅 채널 목록과 무관).

.qf-sidenavlayer: generic

Preview

<nav class="qf-sidenav" aria-label="Sections">
  <div class="qf-sidenav__section">Workspace</div>
  <a class="qf-sidenav__item" aria-current="page">Overview</a>
  <a class="qf-sidenav__item" href="/m">Members</a>
</nav>

Variants

qf-sidenav__section qf-sidenav__item

Required tokens

--bg-panel --divider --s-3 --r-sm --text-secondary --bg-hover --bg-selected --text-muted

Accessibility

Wrap it in nav[aria-label] and set aria-current="page" on the current item. Distinguish groups with section headings (qf-sidenav__section).nav[aria-label] 로 감싸고, 현재 항목에 aria-current=page 를 둡니다. 섹션 제목(qf-sidenav__section)으로 그룹을 구분합니다.

Navigation

PostNav

Previous / next post links at the end of an article (end of the reading column, before the footer — the "after reading" slot). Two cells; at ≤600px they stack so titles do not wrap into many lines. Each cell is a card-toned block link (qf-postnav__link, --prev / --next) holding an eyebrow (qf-postnav__eyebrow: "← Previous" / "Next →") and a title (qf-postnav__title, 15px 600, two-line clamp); the next cell is right-aligned. If only one neighbour exists, render just that cell.글 끝의 이전 글 / 다음 글입니다(읽기 열 끝, 바닥글 앞 — "읽은 다음"의 자리). 두 칸이며 ≤600px 에서는 한 칸씩 세로로 쌓여 제목이 여러 줄로 감기지 않습니다. 각 칸은 카드 톤의 블록 링크(qf-postnav__link, --prev / --next)로 머리말(qf-postnav__eyebrow: "← 이전 글" / "다음 글 →")과 제목(qf-postnav__title, 15px 600, 두 줄 clamp)을 담고, 다음 글은 오른쪽 정렬입니다. 한쪽만 있으면 그 칸만 둡니다.

.qf-postnavlayer: generic

Preview

<nav class="qf-postnav" aria-label="Adjacent posts">
  <a class="qf-postnav__link qf-postnav__link--prev" href="#prev">
    <span class="qf-postnav__eyebrow">← Previous</span>
    <span class="qf-postnav__title">.NET - WPF JumpList</span>
  </a>
  <a class="qf-postnav__link qf-postnav__link--next" href="#next">
    <span class="qf-postnav__eyebrow">Next →</span>
    <span class="qf-postnav__title">PowerShell - Creating a Credential for remote access</span>
  </a>
</nav>

Variants

qf-postnav__link qf-postnav__link--prev qf-postnav__link--next qf-postnav__eyebrow qf-postnav__title

Required tokens

--s-9 --s-4 --s-5 --s-2 --border --border-strong --r-lg --bg-panel --bg-elevated --fs-12 --fs-15 --lh-tight --lh-snug --tracking-caps --text-muted --text-strong --accent-text --ring-focus --dur-fast --ease-standard

Accessibility

Wrap in nav[aria-label="Adjacent posts"]; each cell is an a[href]. The eyebrow arrows are text and are read, so the link name reads like "Previous post, title". The focus ring surrounds the whole cell. Provide clamped titles in full via a title attribute.nav[aria-label="앞뒤 글"] 로 감싸고 각 칸은 a[href] 입니다. 머리말의 화살표는 텍스트라 낭독되며 링크 이름은 "이전 글 제목" 처럼 읽힙니다. 포커스 링이 칸 전체에 보입니다. 두 줄 clamp 로 잘린 제목은 title 속성으로 전체를 줄 수 있습니다.

Navigation

Chip

Desktop filter chips and their group (qf-chips). Works as links (a + aria-current="page") or buttons (button + aria-pressed="true"); the selected state uses an accent-subtle background, accent border, and a bold label. The group wraps by default; --scroll makes a single horizontally scrolling row on narrow screens (scrollbar hidden). Shares tokens with the mobile qf-m-filter-chip (--r-pill, --accent-subtle, --accent) for visual consistency; only the label color is --accent-on-subtle for AA. --scroll fades its right edge into the background to hint there is more, only when the row overflows, and the fade clears at the end (automatically where scroll-driven animations are supported; otherwise consumer JS adds is-end). On touch devices chips are 40px tall with a transparent 44px hit area. qf-picks (image pick rows) shares the same fade.데스크톱 필터 칩과 그 묶음(qf-chips)입니다. 링크(a + aria-current="page")와 버튼(button + aria-pressed="true") 모두 지원하며 선택 상태는 accent-subtle 배경, accent 테두리, 굵은 라벨로 표시합니다. 기본은 줄바꿈(wrap), --scroll 은 좁은 폭에서 한 줄 가로 스크롤(스크롤바 숨김)입니다. 모바일 qf-m-filter-chip 과 같은 토큰(--r-pill, --accent-subtle, --accent)을 써서 시각이 일관되며, 라벨 색만 AA 를 위해 --accent-on-subtle 입니다. --scroll 은 오른쪽 끝을 배경으로 녹아들게 페이드해 더 있음을 암시하고, 넘칠 때만 생기며 끝까지 스크롤하면 걷힙니다(스크롤 타임라인 지원 브라우저는 자동, 그 밖은 소비처 JS 가 is-end 를 붙임). 터치 환경에서 칩은 40px 이고 투명 영역으로 44px 히트를 확보합니다. 같은 페이드를 qf-picks(이미지 선택 타일 줄)도 씁니다.

.qf-chiplayer: generic

Preview

<nav class="qf-chips" aria-label="Category">
  <a class="qf-chip" href="#all" aria-current="page">All</a>
  <a class="qf-chip" href="#politics">Politics</a>
  <a class="qf-chip" href="#society">Society</a>
  <a class="qf-chip" href="#economy">Economy</a>
  <a class="qf-chip" href="#culture">Culture</a>
  <a class="qf-chip" href="#sports">Sports</a>
  <a class="qf-chip" href="#tech">Tech</a>
  <a class="qf-chip" href="#world">World</a>
</nav>

Examples예시

Buttons (aria-pressed) with counts
--scroll (single row, scrolls sideways)

Variants

qf-chips qf-chips--scroll qf-chip__count

Required tokens

--bg-panel --bg-hover --border --border-strong --text-secondary --text --text-muted --accent-subtle --accent --accent-on-subtle --r-pill --fs-13 --s-2 --s-3 --s-4 --m-touch --ring-focus --s-1 --lh-tight --dur-fast --ease-standard --s-9 --s-10

Accessibility

Link chips are anchors inside nav[aria-label] with aria-current="page" on the current one; button chips use aria-pressed. The selected state is conveyed by border and weight as well as color. The focus ring stays visible (--scroll keeps a 4px inner padding for the halo and a matching negative margin to stay aligned, so the parent needs at least 4px of horizontal room), and on touch devices (any-pointer: coarse, including touch laptops) chips are 40px tall with a transparent 44px hit area (hit areas of adjacent rows touch but do not overlap). In --scroll, tabbing brings each chip into view. The --scroll fade appears only when the row overflows (with scroll-driven animation support), and tabbing to a chip stops left of the fade via scroll-padding. Without support, consumer JS adds is-end on load, resize and scroll when the row is at its end or does not overflow.링크 칩은 nav[aria-label] 안의 a 로 두고 현재 항목에 aria-current="page" 를, 버튼 칩은 aria-pressed 를 씁니다. 선택 상태는 색과 함께 테두리와 굵기로도 전달합니다. 포커스 링이 보이고(--scroll 은 halo 까지 보이도록 4px 여백을 안쪽에 두고 같은 크기의 음수 margin 으로 정렬을 유지하므로, 부모에 4px 이상 좌우 여백이 필요합니다), 터치 환경(any-pointer: coarse, 터치 노트북 포함)에서는 칩이 40px 이고 투명 영역으로 44px 히트를 확보합니다(인접 행의 히트 영역은 맞닿기만 함). --scroll 은 키보드로 Tab 이동 시 브라우저가 칩을 뷰로 스크롤합니다. --scroll 의 페이드는 넘칠 때만 생기고(스크롤 타임라인 지원 시), Tab 으로 칩에 가면 scroll-padding 으로 페이드 왼쪽에 멈춥니다. 미지원 브라우저는 소비처 JS 가 load·resize·scroll 에서 끝에 닿았거나 넘치지 않으면 is-end 를 붙입니다.

Overlays

Tooltip

A bubble that shows a short description when an element is pointed at.요소를 가리킬 때 짧은 설명을 띄우는 말풍선입니다.

.qf-tooltiplayer: generic

Preview

Open settings
<span class="qf-tooltip" role="tooltip" id="tt-1">Open settings</span>

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--bg-inverse --text-inverse --r-sm --fs-12 --elev-2

Accessibility

Mark it with role="tooltip" and associate it with the target via aria-describedby. Since it has no pointer-events, ensure the content is also reachable via keyboard focus.role="tooltip" 으로 표시하고 대상에 aria-describedby 로 연결합니다. pointer-events 가 없으므로 키보드 포커스로도 내용을 접근할 수 있게 합니다.

Overlays

Modal

A modal dialog presented over the screen.화면 위에 띄우는 모달 대화상자입니다.

.qf-modallayer: generic

Preview

<div class="qf-modal" role="dialog" aria-modal="true" aria-labelledby="m-t">
  <div class="qf-modal__header">
    <h2 class="qf-modal__title" id="m-t">Delete project</h2>
    <button class="qf-btn qf-btn--icon qf-btn--lg qf-btn--ghost" aria-label="Close">
      <svg class="qf-icon qf-icon--md" aria-hidden="true">
        <use href="#qf-i-x"/>
      </svg>
    </button>
  </div>
  <div class="qf-modal__body">This action cannot be undone. The project and all its data will be permanently deleted.</div>
  <div class="qf-modal__footer">
    <button class="qf-btn qf-btn--ghost">Cancel</button>
    <button class="qf-btn qf-btn--danger">Delete</button>
  </div>
</div>

Variants

qf-modal-backdrop qf-modal__header qf-modal__title qf-modal__body qf-modal__footer

Required tokens

--bg-elevated --border --r-xl --elev-4 --s-7 --divider --z-modal --z-modal-bg

Accessibility

Set role="dialog" and aria-modal="true", and associate the title via aria-labelledby. Trap focus within the modal, close on Esc, and move focus into it when it opens.role="dialog" 와 aria-modal="true" 를 지정하고 aria-labelledby 로 제목과 연결합니다. 포커스를 모달 안에 가두고 Esc 로 닫으며, 열릴 때 포커스를 옮깁니다.

Overlays

SettingsLayout

A settings layout split into a left navigation and a main content area.좌측 내비게이션과 본문 영역으로 나뉜 설정 레이아웃입니다.

.qf-settingslayer: generic

Preview

Content
<div class="qf-settings">
  <nav class="qf-settings__nav">
    <a class="qf-settings__nav-item" aria-selected="true">General</a>
  </nav>
  <div class="qf-settings__main">Content</div>
</div>

Variants

qf-settings__nav qf-settings__nav-head qf-settings__nav-item qf-settings__main

Required tokens

--bg-panel --divider --s-4 --s-8 --r-sm --text-secondary --bg-selected

Accessibility

Express the current selection on nav items with aria-selected and keep keyboard focus visible. Convey the selected state via aria attributes, not background color alone.내비 항목은 aria-selected로 현재 선택을 표현하고 키보드 포커스가 보이게 합니다. 선택 상태는 배경색뿐 아니라 aria 속성으로 함께 전달합니다.

Overlays

SettingsOverlay

A settings overlay presented over the full screen.전체 화면 위에 띄우는 설정 오버레이입니다.

.qf-settings-overlaylayer: generic

Preview

<div class="qf-settings-overlay__backdrop">
</div>
<div class="qf-settings-overlay__card" role="dialog" aria-modal="true" aria-label="Settings">
  <button class="qf-settings-overlay__close" aria-label="Close">×</button>
  <div class="qf-stack" style="padding:var(--s-8)">
    <h2>Settings</h2>
    <p style="color:var(--text-secondary);max-width:560px">Edit app-wide settings such as account, notifications, and theme in a full-screen overlay. Lay it out with navigation on the left and a content area on the right.</p>
  </div>
</div>

Variants

qf-settings-overlay__backdrop qf-settings-overlay__card qf-settings-overlay__close

Required tokens

--z-settings --z-settings-bg --bg-app --r-xl --elev-4 --s-8 --dur-base

Accessibility

Mark the card as a modal with role=dialog and aria-modal="true", trap focus, and close on Esc. Give the close button an aria-label.카드는 role=dialog와 aria-modal="true"로 모달임을 알리고 포커스를 가두며 Esc로 닫습니다. 닫기 버튼에는 aria-label을 둡니다.

Overlays

CommandPalette

A command and search palette opened via a keyboard shortcut.단축키로 여는 명령, 검색 팔레트입니다.

.qf-cmd-palettelayer: generic

Preview

<div class="qf-cmd-palette" role="dialog" aria-label="Command palette">
  <div class="qf-cmd-palette__search">
    <input class="qf-cmd-palette__input" role="combobox" aria-expanded="true" aria-controls="cmd-list" placeholder="Search commands">
  </div>
  <ul id="cmd-list" class="qf-cmd-palette__list" role="listbox">
    <li class="qf-cmd-palette__row" role="option" aria-selected="true">
      <span class="qf-cmd-palette__label">New document</span>
    </li>
  </ul>
</div>

Variants

qf-cmd-palette-backdrop qf-cmd-palette__search qf-cmd-palette__input qf-cmd-palette__list qf-cmd-palette__section qf-cmd-palette__row qf-cmd-palette__row-icon qf-cmd-palette__label qf-cmd-palette__path qf-cmd-palette__kbd qf-cmd-palette__empty

Required tokens

--bg-elevated --border --r-xl --elev-4 --accent --bg-selected --s-4

Accessibility

Indicate the current selection on result rows with aria-selected, and provide a cue beyond color via a left accent bar on the selected row. Ensure up and down keyboard navigation and visible focus, and convey empty results with text.결과 행은 aria-selected로 현재 선택을 알리고 선택 행은 좌측 accent bar로 색 외 단서를 함께 제공합니다. 키보드 위아래 이동과 포커스 가시를 보장하고, 빈 결과는 텍스트로 안내합니다.

Overlays

EmojiPicker

A picker for searching emoji and choosing them by category.이모지를 검색, 카테고리별로 골라 넣는 선택기입니다.

.qf-emoji-pickerlayer: generic

Preview

<div class="qf-emoji-picker" role="dialog" aria-label="Select emoji">
  <div class="qf-emoji-picker__search">
    <div class="qf-emoji-picker__search-field">
      <span class="qf-emoji-picker__search-icon">
        <svg class="qf-icon qf-icon--sm" aria-hidden="true">
          <use href="#qf-i-search"/>
        </svg>
      </span>
      <input class="qf-emoji-picker__search-input" type="search" aria-label="Search emoji" placeholder="Search">
    </div>
  </div>
  <div class="qf-emoji-picker__tabs" role="tablist">
    <button class="qf-emoji-picker__tab" role="tab" aria-selected="true" aria-label="Smileys">😀</button>
    <button class="qf-emoji-picker__tab" role="tab" aria-selected="false" aria-label="Animals">🐶</button>
    <button class="qf-emoji-picker__tab" role="tab" aria-selected="false" aria-label="Food">🍔</button>
    <button class="qf-emoji-picker__tab" role="tab" aria-selected="false" aria-label="Activities">⚽</button>
    <button class="qf-emoji-picker__tab" role="tab" aria-selected="false" aria-label="Symbols">🎵</button>
  </div>
  <div class="qf-emoji-picker__grid">
    <div class="qf-emoji-picker__category-label">Smileys</div>
    <div class="qf-emoji-picker__row">
      <button class="qf-emoji-picker__cell" aria-selected="true" aria-label="Emoji">😀</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">😃</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">😄</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">😁</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">😆</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">😅</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">😂</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">🤣</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">😊</button>
    </div>
    <div class="qf-emoji-picker__row">
      <button class="qf-emoji-picker__cell" aria-label="Emoji">😇</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">🙂</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">🙃</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">😉</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">😌</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">😍</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">🥰</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">😘</button>
      <button class="qf-emoji-picker__cell" aria-label="Emoji">😗</button>
    </div>
  </div>
  <div class="qf-emoji-picker__preview">
    <span class="qf-emoji-picker__preview-emoji">😀</span>
    <span class="qf-emoji-picker__preview-shortcode">:grinning:</span>
  </div>
</div>

Variants

qf-emoji-picker__search qf-emoji-picker__search-field qf-emoji-picker__search-input qf-emoji-picker__tabs qf-emoji-picker__tab qf-emoji-picker__grid qf-emoji-picker__category-label qf-emoji-picker__row qf-emoji-picker__cell qf-emoji-picker__preview qf-emoji-picker__preview-shortcode qf-emoji-picker__preview--empty

Required tokens

--bg-elevated --border --r-xl --elev-4 --accent --bg-hover --bg-selected --s-3

Accessibility

Convey state on category tabs and emoji cells with aria-selected, and add a cue beyond color via a bottom accent indicator on the selected tab. Surface the shortcode text in the bottom preview and ensure visible focus.카테고리 탭과 이모지 셀은 aria-selected로 상태를 전하고, 선택 탭은 하단 accent 표시로 색 외 단서를 더합니다. 하단 미리보기에 shortcode 텍스트를 함께 노출하고 포커스 가시를 보장합니다.

Overlays

UploadOverlay

A drag-and-drop guidance overlay shown while files are being dragged over a drop target.파일을 끌어다 놓는 동안 표시되는 드래그 앤 드롭 안내 오버레이입니다.

.qf-upload-overlaylayer: generic

Preview

Drop here to upload

Up to 50MB

<div class="qf-upload-overlay" role="status" aria-live="polite">
  <div class="qf-upload-overlay__icon">
    <svg class="qf-icon" aria-hidden="true">
      <use href="#qf-i-upload"/>
    </svg>
  </div>
  <p class="qf-upload-overlay__title">Drop here to upload</p>
  <p class="qf-upload-overlay__hint">Up to 50MB</p>
</div>

Variants

qf-upload-overlay__icon qf-upload-overlay__title qf-upload-overlay__hint

Required tokens

--accent-bg --accent --r-xl --s-3 --s-4 --text-strong --text-secondary

Accessibility

The overlay is purely visual with no pointer-events, conveying its action through a title and hint text. A dashed border is paired with guidance text so meaning is not carried by color alone.오버레이는 pointer-events 없이 시각 안내만 담당하며, 제목과 힌트 텍스트로 동작을 명확히 전달합니다. 점선 테두리와 함께 안내 문구를 두어 색 단독 의존을 피합니다.

Overlays

Popover

A floating panel of arbitrary content anchored to a trigger (free-form content, unlike a menu).트리거 기준으로 떠 있는 임의 콘텐츠 패널입니다(메뉴와 달리 자유 콘텐츠).

.qf-popoverlayer: generic

Preview

<div class="qf-popover" role="dialog" aria-label="Filter">
  <p>This is floating content.</p>
</div>

Variants

No variants — single style.변형 없음 — 단일 스타일.

Required tokens

--bg-floating --border --r-lg --elev-3 --s-4 --z-dropdown

Accessibility

Set aria-haspopup/aria-expanded on the trigger and link it to the panel with aria-controls. Close on Esc and restore focus to the trigger, and move focus into the panel when it opens.트리거에 aria-haspopup/aria-expanded 를 두고 패널과 aria-controls 로 연결합니다. Esc 로 닫고 포커스를 트리거로 복원하며, 열릴 때 포커스를 패널로 옮깁니다.

Overlays

Drawer

A panel that slides in from the edge of the screen (right by default, with a left variant).화면 측면에서 슬라이드되는 패널입니다(우측 기본, 좌측 변형).

.qf-drawerlayer: generic

Preview

<div class="qf-drawer-backdrop">
</div>
<aside class="qf-drawer" role="dialog" aria-modal="true" aria-label="Settings">
  <div class="qf-drawer__header">
    <h2 class="qf-drawer__title">Settings</h2>
  </div>
  <div class="qf-drawer__body">Content</div>
</aside>

Variants

qf-drawer--left

Parts & more: 구성 요소, 기타: qf-drawer-backdrop qf-drawer__header qf-drawer__title qf-drawer__body qf-drawer__footer

Required tokens

--bg-elevated --border --elev-4 --z-modal --z-modal-bg --scrim --s-6 --divider

Accessibility

Announce it with role="dialog" and aria-modal="true", and trap focus inside the panel. Close on Esc and backdrop click, and restore focus to where it was before opening.role=dialog 와 aria-modal=true 로 알리고 포커스를 패널 안에 가둡니다. Esc 와 backdrop 클릭으로 닫고, 열기 전 포커스를 복원합니다.

Overlays

Lightbox

A chrome-free fullscreen contain-fit media viewer (zoom) or a full-bleed scrolling contact sheet. Unlike a dialog (qf-modal), it holds only media — no panel chrome.크롬 없는 풀스크린 contain-fit 미디어 뷰어(줌) 또는 풀블리드 스크롤 컨택트 시트입니다. 다이얼로그(qf-modal)와 달리 패널 크롬 없이 미디어만 담습니다.

.qf-lightboxlayer: generic

Preview

<div class="qf-lightbox">
  <button class="qf-lightbox__close" aria-label="Close">
    <svg class="qf-icon qf-icon--md" aria-hidden="true">
      <use href="#qf-i-x"/>
    </svg>
  </button>
  <div class="qf-lightbox__stage">
    <div class="qf-lightbox__media" style="width:260px;aspect-ratio:3 / 2;background:var(--bg-media)">
    </div>
  </div>
</div>

Examples예시

Contact sheet (--sheet)

Variants

qf-lightbox__close qf-lightbox__stage qf-lightbox__media qf-lightbox__sheet qf-lightbox__frame qf-lightbox__caption qf-lightbox--dim qf-lightbox--sheet

Required tokens

--scrim --scrim-strong --scrim-blur --z-modal --on-media-glass-bg --on-media-border --on-media-text --r-md --safe-top --ring-focus --s-8

Accessibility

role=dialog + aria-modal=true + aria-label. Trap focus, move focus to the close button on open, and restore it to the trigger on close. Close on Esc and scrim click (stop propagation on media clicks); the close button is 44px; respect prefers-reduced-motion.role=dialog + aria-modal=true + aria-label. 포커스를 가두고 열 때 닫기 버튼으로 포커스 이동, 닫을 때 트리거로 복원. Esc와 스크림 클릭으로 닫고(미디어 클릭은 stopPropagation), 닫기 버튼은 44px, prefers-reduced-motion을 존중합니다.

Disclosure

Accordion

A disclosure list whose sections expand and collapse when you click their header.제목을 눌러 내용을 펼치고 접는 디스클로저 목록입니다.

.qf-accordionlayer: generic

Preview

Shipping policy
Ships within 3 days.
<div class="qf-accordion">
  <details class="qf-accordion__item" open>
    <summary class="qf-accordion__trigger">Shipping policy</summary>
    <div class="qf-accordion__panel">Ships within 3 days.</div>
  </details>
</div>

Variants

qf-accordion__item qf-accordion__trigger qf-accordion__panel

Required tokens

--border --divider --r-lg --s-4 --s-5 --text-strong --bg-hover

Accessibility

Built on native details/summary, so keyboard toggling and expanded-state communication come for free. Put meaningful header text in the summary (qf-accordion__trigger).네이티브 details/summary 기반이라 키보드 토글과 펼침 상태 전달이 기본 제공됩니다. summary(qf-accordion__trigger)에 의미 있는 제목 텍스트를 둡니다.

Pattern

Full chat mockup

A real screen assembled entirely from the components above. The same 3-column layout as Discord.위 컴포넌트로만 조립한 실제 화면. Discord와 동일한 3-column 레이아웃.

qufox team
▾ PRODUCT
announcements 2
general
design
voice-lounge
▾ ENGINEERING
frontend
backend 12
general
Announcements, General chat공지, 일반 대화
dev_leeMOD2:34 PM오후 2:34

All the brand assets are in. @designer_kim please take a look!브랜드 에셋 다 반영했습니다. @designer_kim 확인 부탁!

🦊5
🚀2
designer_kim2:38 PM오후 2:38

Looks good! Just double-check that the --r-xl value is applied to the cards.좋아요! --r-xl 값 카드에 적용했는지만 확인해주세요.

And the favicon looks great too 👀그리고 파비콘도 잘 보이네요 👀
pm_choi is typing…pm_choi 입력 중…
ONLINE — 3
founder_park
dev_lee
designer_kim
OFFLINE — 8
eng_jung
ops_han
Assets

Icon pack: 100+

All the icons your chat UI needs in one set. Every icon is drawn as 24×24 viewBox, SVG path, stroke=currentColor and covers Discord/Slack patterns. Set the color via CSS color and the size via the size modifier.채팅 UI에 필요한 아이콘을 한 세트로. 모두 24×24 viewBox, SVG path, stroke=currentColor로 그려졌고, Discord/Slack 패턴을 덮습니다. 색상은 CSS color로, 크기는 사이즈 modifier로 조절해요.

Usage

<!-- 1. Load once in the document -->
<link rel="stylesheet" href="icons.css">

<!-- 2. Reference by symbol ID -->
<svg class="qf-icon"><use href="icons.svg#qf-i-send"/></svg>

<!-- Size / color modifiers -->
<svg class="qf-icon qf-icon--sm">...</svg>      /* 16 */
<svg class="qf-icon qf-icon--lg qf-icon--accent">...</svg>

Sizes

sm: 16
md: 20
lg: 24
xl: 28

Colors

currentColor
--accent
--muted
success
danger

In-context examples

in buttons
message hover toolbar
Message #general
composer
voice controls
Online
Idle
Do not disturb
presence
Edit message
Pin message
Copy link
Delete
dropdown menu

Full list전체 목록

Click to copy the <use href="#..."/> string.클릭하면 <use href="#..."/> 문자열이 복사돼요.
copied
Pattern

Auth — Login & sign-up

Drop-in authentication screens built only from generic components — qf-card, qf-field, qf-input, qf-btn, qf-notice, qf-strength-meter. Accent and surfaces follow the active brand — switch Brand or theme in the top bar to watch them re-skin — and the symbol comes from brand.config.json, so every white-label customer gets these screens for free.범용 컴포넌트(qf-card, qf-field, qf-input, qf-btn, qf-notice, qf-strength-meter)만으로 구성한 즉시 사용 가능한 인증 화면입니다. accent와 표면은 활성 브랜드를 따라 — 상단에서 Brand나 테마를 바꾸면 다시 칠해집니다 — 심볼은 brand.config.json에서 와서, 모든 화이트라벨 고객이 이 화면을 그대로 쓸 수 있습니다.

Log in

qufox: sign in

Welcome back다시 만나 반가워요

Pick up right where you left off.바로 이어서 시작하세요.

No account yet? 계정이 없으신가요? Sign up가입하기

Forgot your password?비밀번호를 잊으셨나요?

Sign up

qufox: sign up

Create your account계정을 만들어요

It only takes a minute to get started.1분이면 시작할 수 있어요.

Password

Strong강함

Already have an account? 이미 계정이 있으신가요? Log in로그인

States & messaging상태와 메시지

Form feedback uses the same notice and field-error patterns, so the affordance never relies on color alone — each message carries an icon and text, and live regions announce errors to screen readers.폼 피드백은 동일한 notice와 field-error 패턴을 써서 색에만 의존하지 않습니다 — 각 메시지는 아이콘과 텍스트를 함께 두고, 라이브 영역이 오류를 스크린리더에 통지합니다.
Your session expired, so you were signed out. Please log in again.세션이 만료되어 로그아웃되었습니다. 다시 로그인해 주세요.
App screens

Workspace, Discover

New workspace creation flow and browsing public workspaces. Category metadata (emoji, labels) follows WORKSPACE_CATEGORY_META.새 워크스페이스 생성 플로우와 공개 워크스페이스 둘러보기. 카테고리 메타(이모지, 라벨)는 WORKSPACE_CATEGORY_META를 따릅니다.

Discover: Desktop

Top search + category segment + card grid. The join button is .qf-btn--primary.상단 검색 + 카테고리 segment + 카드 그리드. 참여 버튼은 .qf-btn--primary.

Public workspaces공개 워크스페이스

Q
qufox Design Guildqufox 디자인 길드
🎨 Art, 248 members🎨 예술, 248명

A space where designers gather to share their process and exchange feedback.디자이너들이 모여 작업 과정을 공유하고 피드백을 주고받는 공간.

F
Frontend KoreaFrontend 한국
💻 Dev, 1,204 members💻 개발, 1,204명

A community studying modern frontend together — React, Vue, Svelte, and more.React, Vue, Svelte 등 모던 프론트엔드를 함께 공부하는 커뮤니티.

G
Game Dev Lounge
🎮 Gaming, 87 members🎮 게임, 87명

A small gathering where indie game developers share their work and trade feedback.인디 게임 개발자들이 작업물 공유하고 피드백하는 작은 모임.

Create workspace: Desktop modal

Create a new workspace새 워크스페이스 만들기

Create a space to chat with your friends and team. You can change this later.내 친구들, 팀과 대화할 공간을 만들어보세요. 나중에 변경할 수 있어요.

qufox.app/w/
Lowercase letters, numbers, and hyphens only소문자, 숫자, 하이픈만 가능
Public workspace공개 워크스페이스
Listed in Discover so anyone can request to joinDiscover에 노출되어 누구나 참여 요청 가능

Mobile

Discover찾기
Public workspaces공개 워크스페이스
New workspace새 워크스페이스
/w/
Public공개
Listed in DiscoverDiscover에 노출
App screens

Channel settings

Split into Overview, Members, and Permissions tabs. A Discord-style left nav pattern, but on mobile it collapses into a single scroll plus a segment control.개요, 멤버, 권한 탭으로 분리. Discord와 같은 좌측 nav 패턴이지만 모바일에서는 단일 스크롤 + segment로 압축.

Desktop: Overview tab

Overview개요

Configure the channel's basic information.채널의 기본 정보를 설정합니다.

Shown in the channel header.채널 헤더에 표시됩니다.
Private channel비공개 채널
Only invited members can view it.초대된 멤버만 볼 수 있어요.
Slow mode슬로우 모드
Minimum 5-second interval between messages메시지 사이 최소 5초 간격

Desktop: Members tab

Members멤버 42

Member멤버
Role역할
Joined가입
Y유
Yujin유진
@yujin
Owner소유자
2024.01.12
M민
Minseo민서
@minseo
Admin관리자
2024.02.03
J지
Jiho지호
@jiho
Member멤버
2024.03.18
S소
Soyoung소영
@soyoung
Member멤버
2024.04.02

Mobile

#general
Channel settings채널 설정
Private비공개
Invited members only초대된 멤버만
Slow mode슬로우 모드
5-second interval5초 간격
Members: 42멤버: 42
#general
Admins: 3관리자: 3
Members: 39멤버: 39
App screens

Channel, Category modals

New channel, new category, creating a channel inside a category. All use the same modal component + .qf-toggle-row pattern.새 채널, 새 카테고리, 카테고리 안에 채널 만들기. 모두 같은 modal 컴포넌트 + .qf-toggle-row 패턴.

Desktop: Create Channel

Create Channel채널 만들기

Add a new channel to the PRODUCT category.PRODUCT 카테고리에 새 채널을 추가합니다.

Private channel비공개 채널
Only selected members and roles can see it.선택한 멤버와 역할만 볼 수 있어요.

Desktop: Create Category

Create Category카테고리 만들기

Group related channels together to keep things organized.관련된 채널들을 묶어서 정리할 수 있어요.

Private category비공개 카테고리
All sub-channels are synced to private.하위 채널이 모두 비공개로 동기화됩니다.

Mobile: Bottom sheet

Create Channel채널 만들기
Private비공개
ENGINEERING categoryENGINEERING 카테고리
App screens

Threads

Split follow-up conversations off a message inline. Desktop uses a right-hand side panel, mobile uses a full-screen route.메시지의 후속 대화를 인라인으로 분리. 데스크톱은 우측 사이드 패널, 모바일은 풀스크린 라우트.

Desktop: Thread panel beside chat

qufox team
▾ PRODUCT
general
design
announcements 2
general
Team-wide announcements팀 전체 공지
E유
Eugene유진Today 10:42 AM오늘 오전 10:42
It would be good to write up the major changes going into the next release. Please review the PR below 🙏다음 릴리즈에 들어갈 큰 변경사항 정리해두면 좋을 것 같아요. 아래 PR 리뷰 부탁드립니다 🙏
M민
Minseo민서10:48 AM오전 10:48
This behaves the same on mobile too, right? I added test cases.이거 모바일에서도 같은 동작 맞죠? 테스트 케이스 추가했어요.
7 replies7개의 답글 , Latest: 12 minutes ago, 가장 최근: 12분 전
J지
Jiho지호11:02 AM오전 11:02
I think we should merge the design token PR along with it.디자인 토큰 PR도 같이 머지하면 좋을 것 같아요.

Mobile: Full-screen thread

Thread스레드
#general, 7 replies7개의 답글
Minseo민서 10:48 AM오전 10:48
This behaves the same on mobile too, right? I added test cases.이거 모바일에서도 같은 동작 맞죠? 테스트 케이스 추가했어요.
7 replies7개의 답글
E유
Eugene유진11:05
Right. Please double-check once more on iOS Safari.맞아요. iOS Safari에서 한 번 더 확인 부탁드려요.
Please look at the scroll performance too 🙏스크롤 성능도 같이 봐주세요 🙏
M민
Minseo민서11:14
Tests passed ✅테스트 통과했습니다 ✅
J지
Jiho지호11:22
I think you can go ahead and merge!머지하셔도 될 것 같아요!
App screens

DM shell

One-on-one conversations with friends, no workspace required. DM list on the left plus the main conversation area. On mobile, the list and conversation are separate routes.워크스페이스 없이도 친구와 1:1 대화. 좌측 DM 리스트 + 메인 대화 영역. 모바일은 리스트와 대화가 별도 라우트.

Desktop: DM list + active conversation

Friends친구 Activity활동
Direct Messages다이렉트 메시지
M민
Minseo민서
All tests passed ✅테스트 통과했습니다 ✅
J지
Jiho 3지호 3
Merged the design tokens PR디자인 토큰 PR 머지했어요
S소
Soyoung, Gunwoo소영, 건우
Gunwoo: How about tomorrow afternoon?건우: 내일 오후 어때요?
G건
Gunwoo건우
See you tomorrow!내일 봬요!
M민
Minseo민서
@minseo, Online@minseo, 온라인
Wednesday, May 22, 20242024년 5월 22일 수요일
M민
Minseo민서10:14 AM오전 10:14
Finished the PR review. I left a few comments.PR 리뷰 끝났어요. 코멘트 몇 개 남겨놨습니다.
Y유
Yujin유진10:32 AM오전 10:32
Thank you! I'll make the changes and let you know.감사합니다! 반영하고 다시 알려드릴게요.
M민
Minseo민서11:14 AM오전 11:14
All tests passed ✅테스트 통과했습니다 ✅
I think it's good to merge머지해도 될 것 같아요

Mobile

Messages메시지
M민
Minseo민서
Direct message, Online다이렉트 메시지, 온라인
Wednesday, May 225월 22일 수요일
M민
Minseo민서10:14
Finished the PR review. I left a few comments.PR 리뷰 끝났어요. 코멘트 몇 개 남겨놨습니다.
Y유
Yujin유진10:32
Thank you! I'll make the changes and let you know.감사합니다! 반영하고 다시 알려드릴게요.
M민
Minseo민서11:14
All tests passed ✅테스트 통과했습니다 ✅
I think it's good to merge머지해도 될 것 같아요
App screens

Friends

Friends list + incoming/outgoing requests + user blocking. The 4-tab segment pattern is identical on desktop and mobile.친구 목록 + 받은/보낸 요청 + 사용자 차단. 4-탭 segment 패턴은 데스크톱, 모바일 동일.

Desktop: All friends

Friends친구
All friends — 8전체 친구 — 8
M민
Minseo민서
@minseo, Online@minseo, 온라인
J지
Jiho지호
@jiho, Away@jiho, 자리 비움
S소
Soyoung소영
@soyoung, Offline@soyoung, 오프라인
G건
Gunwoo건우
@gunwoo, Do not disturb@gunwoo, 방해 금지

Desktop: Pending requests

Friend requests친구 요청

Incoming requests — 2받은 요청 — 2
H하
Haneul하늘
@haneul, Incoming request@haneul, 받은 요청
B바
Bada바다
@bada, Incoming request@bada, 받은 요청
Outgoing requests — 1보낸 요청 — 1
G강
Gangsan강산
@gangsan, Awaiting response@gangsan, 응답 대기 중

Mobile

Friends친구
All friends, 8전체 친구, 8
Pending대기 중
Incoming requests, 2받은 요청, 2
H하
Haneul하늘
@haneul
B바
Bada바다
@bada
Outgoing requests, 1보낸 요청, 1
Mobile

Mobile system

Mobile layout based on Discord/Slack patterns. Touch targets 44×44 or larger, automatic safe-area inset handling, optimized for one-handed operation with a bottom tab + bottom sheet combination.Discord/Slack 패턴 기반의 모바일 레이아웃. 터치 타겟 44×44 이상, safe-area inset 자동 처리, bottom tab + bottom sheet 조합으로 한 손 조작 최적화.

Layout patterns

The mobile primitives (qf-m-*) are documented individually — see the qufox app (chat module) group in the sidebar (topbar, tab bar, bottom sheet, list rows, composer) and the full chat mockup for assembled iOS/Android screens (same classes on both).qf-m-* 모바일 프리미티브는 개별 페이지로 문서화돼 있습니다 — 사이드바 qufox app (chat module) 그룹(topbar, tab bar, bottom sheet, list row, composer)과 조립된 iOS/Android 화면은 full chat mockup을 참고하세요(양 플랫폼 동일 클래스).

Mobile-only tokens

--m-topbar-h:   52px;     /* top nav height */
--m-tabbar-h:   56px;     /* bottom tab bar (excludes safe-area) */
--m-composer-h: 56px;     /* message input field */
--m-touch:      44px;     /* minimum hit target (Apple HIG) */
--m-gutter:     16px;     /* left/right padding */
--m-sheet-r:    20px;     /* bottom sheet top radius */

Core components핵심 컴포넌트

.qf-m-screen

Top-level shell. topbar + scrollable body + tabbar/composer structure.최상위 쉘. topbar + scrollable body + tabbar/composer 구조.

.qf-m-topbar

3-column (back, title, actions). Fixed 52px height.3-컬럼 (back, title, actions). 높이 52px 고정.

.qf-m-tabbar

Bottom nav with 4 tabs (Home, DMs, Activity, You). Automatic safe-area.바닥 네비 4탭 (Home, DMs, Activity, You). safe-area 자동.

.qf-m-composer

Chat input field. 3 elements: + / text / send. Rounded pill.채팅 입력창. + / 텍스트 / 전송 3요소. 라운드 pill.

.qf-m-sheet

Bottom sheet (action menu, emoji reactions). grab bar + items.Bottom sheet (액션 메뉴, 이모지 반응). grab bar + items.

.qf-m-fab

Floating action button. Primary actions such as new DM, new post.플로팅 액션 버튼. 새 DM, 새 글 등 primary action.

.qf-m-row

List row (DM, member, server). 64px minimum height, left avatar + 2-line text + aside.리스트 행 (DM, 멤버, 서버). 64px 최소 높이, 좌측 avatar + 2단 텍스트 + aside.

.qf-m-segment

Segmented control (filter switching like All/Mentions/Threads).Segmented control (All/Mentions/Threads 같은 필터 전환).

.qf-m-voice

Voice room grid + controls. speaking state outline.보이스 룸 그리드 + 컨트롤. speaking 상태 outline.

Rules규칙

  • Touch targets: Every interactive element is at least 44×44. When it needs to look smaller, secure the hit area with padding.터치 타겟: 모든 인터랙티브 요소는 최소 44×44. 작아 보여야 하는 경우 padding으로 hit area 확보.
  • Safe area: topbar uses env(safe-area-inset-top), tabbar/composer reflect the bottom inset. Already built into the components.Safe area: topbar는 env(safe-area-inset-top), tabbar/composer는 bottom inset 반영. 이미 컴포넌트에 내장.
  • Drawer pattern: Server/channel lists use a hamburger menu → left drawer. The member list is a right drawer (Discord style).Drawer 패턴: 서버/채널 리스트는 햄버거 메뉴 → 좌측 drawer. 멤버 리스트는 우측 drawer (Discord 방식).
  • Bottom sheet: Desktop context menus/modals convert to bottom sheets on mobile. Make it scrollable when there are 5 or more options.Bottom sheet: 데스크톱의 context menu/modal은 모바일에서 bottom sheet로 변환. 옵션 5개 이상이면 스크롤 가능하게.
  • Long-press = context menu: Long-press a message → bottom sheet + reaction emoji row.Long-press = context menu: 메시지 long-press → bottom sheet + 반응 이모지 row.
  • Swipe to reply: Swipe a message right → reply mode (native pattern).Swipe to reply: 메시지 우측 스와이프 → 답글 모드 (네이티브 패턴).
  • Keyboard dodge: The composer rises together with the keyboard. The body shrinks automatically.키보드 dodge: composer는 키보드 올라올 때 함께 올라감. body는 자동 축소.

React component mapping exampleReact 컴포넌트 매핑 예시

// Discord-style mobile chat screen
<div className="qf-m-screen">
  <header className="qf-m-topbar">
    <button className="qf-m-topbar__back">☰</button>
    <div className="qf-m-topbar__titleBlock">
      <div className="qf-m-topbar__title"># general</div>
      <div className="qf-m-topbar__subtitle">qufox team</div>
    </div>
    <button className="qf-m-topbar__action">👥</button>
  </header>

  <main className="qf-m-body">
    {messages.map(m => <MobileMessage key={m.id} {...m}/>)}
  </main>

  <footer className="qf-m-composer">
    <button className="qf-m-composer__plus">+</button>
    <textarea className="qf-m-composer__input" />
    <button className="qf-m-composer__send">➤</button>
  </footer>
</div>
v4: Task 050

Composer, Autocomplete

A Slack-grade rich composer with drop-up autocomplete. The format bar expands with qf-composer--rich or on focus-within, and @mentions, #channels, :emoji, and slash commands all share one skeleton.Slack 수준의 rich 컴포저와 드롭업 자동완성이에요. 포맷바는 qf-composer--rich 또는 focus-within 시 펼쳐지고, @멘션, #채널, :이모지, 슬래시 커맨드가 한 골격을 공유합니다.

Composer

A rich state with the format bar forced open, and an empty default state (send disabled).포맷바를 강제로 펼친 rich 상태와, 비어 있는 기본 상태(전송 비활성).
Enter Send, Shift+Enter New lineEnter 전송, Shift+Enter 줄바꿈 42 / 2000
.qf-composer, .qf-composer--rich

Autocomplete

A drop-up that appears above the composer. The demo lays out only the inner card inline, without a backdrop (position:static).컴포저 위로 뜨는 드롭업. 데모는 backdrop 없이 inner 카드만 인라인 배치(position:static).
Members
Design_Kim디자인_김 @designer_kim
Dev_Lee개발_이 @dev_lee
@mention: --mention@멘션: --mention
Channels
#
general일반 120 members멤버 120명
#
design-system디자인-시스템 24 members멤버 24명
#
deploy-alerts배포-알림 8 members멤버 8명
#channel: --channel#채널: --channel
Emoji
🎉 :tada:
🚀 :rocket:
🦊 :fox:
:emoji: --emoji:이모지: --emoji

Slash menu

A slash-command-only variant — leading slash icon + monospace command name + description hierarchy.슬래시 커맨드 전용 변형 — 좌측 슬래시 아이콘 + monospace 커맨드명 + 설명 위계.
Commands
/
/giphy[search term][검색어]
Sends a searched GIF to the channel검색한 GIF를 채널에 보냅니다
↵
/
/remind[who] [what] [when][누가] [무엇] [언제]
Sends a reminder at the specified time지정한 시각에 리마인더를 보냅니다
/
/shrug
Appends ¯\_(ツ)_/¯ to the end of your message¯\_(ツ)_/¯ 를 메시지 끝에 덧붙입니다
.qf-slash-menu
v4: Task 050

Command Palette, Emoji

A ⌘K quick switcher and emoji picker. In this demo we show only the inner card inline, without a fixed backdrop — in the actual app it floats above .qf-cmd-palette-backdrop.⌘K 빠른 전환기와 이모지 피커예요. 데모에서는 fixed backdrop 없이 inner 카드만 인라인으로 보여줍니다 — 실제 앱에서는 .qf-cmd-palette-backdrop 위에 떠 있어요.

Command palette

A large search input on top + section headers + result rows (icon, label, path/kbd). The selected row is highlighted with a left accent bar.상단 큰 검색 입력 + 섹션 헤더 + 결과 row(아이콘, 라벨, 경로/kbd). 선택 행은 좌측 accent bar로 강조.
Channels채널
general일반 qufox HQ
general-design일반-디자인 qufox HQ
Direct messages다이렉트 메시지
designer_kim Online온라인
Commands커맨드
Toggle theme테마 전환 ⌘⇧T
Open preferences환경설정 열기 ⌘,
.qf-cmd-palette: section / row / kbd

Emoji picker

Search + category tabs + 9-column grid + preview at the bottom. Fixed 350×420 card.검색 + 카테고리 탭 + 9열 그리드 + 하단 preview. 350×420 고정 카드.
Smileys, People스마일, 사람
😀 :grinning:
.qf-emoji-picker: tabs / grid / preview
v4: Task 050

Overlays, Banners

Status picker, hovercard, 4 banner types, shortcut sheet, role chips, search/upload overlays, and embed variants. The floating surfaces are rendered inline as cards only, without a backdrop.상태 피커, hovercard, 배너 4종, 단축키 시트, 역할 칩, 검색/업로드 오버레이, 임베드 변형이에요. 플로팅 면은 backdrop 없이 카드만 인라인으로 렌더했습니다.

Status picker, Hovercard

Status selection popover and user profile hovercard.상태 선택 팝오버와 유저 프로필 hovercard.
Online온라인
Away자리 비움
Do Not Disturb방해 금지You will not receive notifications알림을 받지 않습니다
Offline오프라인
Yuna Park박유나
@yuna
Online, Designing온라인, 디자인 중
Admin Design
The person building the qufox design system. Loves the color purple.qufox 디자인 시스템을 만드는 사람. 보라색을 좋아합니다.
.qf-status-picker, .qf-hovercard

Banner

info, warn, danger, accent — 4 variants. 4px left status-color bar + tint.info, warn, danger, accent 4변형. 좌측 4px 상태색 바 + 틴트.
A new version has been deployed. Refresh to apply it.새 버전이 배포되었습니다. 새로고침하면 적용됩니다.
Your connection is unstable. Message delivery may be delayed.연결이 불안정합니다. 메시지 전송이 지연될 수 있습니다.
Subscription expired — some features are now restricted.구독 만료 — 일부 기능이 제한되었습니다.
Try out the voice channel beta.음성 채널 베타에 참여해 보세요.

Keyboard shortcut sheet, Role chips

Shortcut sheet (two-column groups) and role chip variants.단축키 시트(2열 그룹)와 역할 칩 변형.
Navigation탐색
Quick switcher빠른 이동⌘+K
Search검색⌘+F
Mark as read읽음 처리Esc
Messages메시지
Edit last마지막 편집↑
Reply답장R
Emoji이모지⌘+E
Admin Moderator Active Bot
.qf-kbd-sheet, .qf-role-chip

Search overlay

Search bar + from:/in:/has: filter chips + result preview.검색바 + from:/in:/has: 필터 칩 + 결과 미리보기.
from:designer_kim in:general일반 has:link
designer_kim, # general, 2:34 PMdesigner_kim, # 일반, 오후 2:34
Finalized the logo size at 120×40. I'll send over the SVG.로고 크기 120×40으로 확정했어요. SVG 넘겨드릴게요.
Jump
dev_lee, # deploy-alerts, Yesterdaydev_lee, # 배포-알림, 어제
Finished deploying the new logo assets.새 로고 에셋 배포 완료했습니다.
Jump
.qf-search-overlay

Upload overlay

A dashed drag-and-drop overlay above the chat area (it is position:absolute, so it nests inside a position:relative box).채팅 영역 위 드래그앤드롭 점선 오버레이(position:absolute이므로 position:relative 박스 안에 안착).
Upload to # general# 일반에 업로드
Drag and drop your files here: 25MB max파일을 여기에 끌어다 놓으세요: 최대 25MB
.qf-upload-overlay

Embed variants

Image, video, bot/app message embeds.이미지, 비디오, 봇/앱 메시지 임베드.
.qf-embed--image
.qf-embed--video
qufox-bot APP
Deployment complete배포가 완료되었어요
main → NAS auto-deploy succeeded. /readyz 200 OK.main → NAS 자동 배포 성공. /readyz 200 OK.
.qf-embed--bot
v4: Task 050

Message actions, Density

Quick reactions on message hover, a reaction-add pill, code-block headers with copy, thread-follow avatar stacks, and a side-by-side comparison of the same message at cozy and compact densities.메시지 hover 빠른 반응, 반응 추가 pill, 코드블록 헤더/복사, 스레드 참여 아바타 스택, 그리고 같은 메시지를 cozy와 compact 밀도로 나란히 비교합니다.

Quick-react, Reaction add

Three quick-reaction slots plus a more button inside the hover action bar, with a dashed add pill at the end of the reaction row.hover 액션바 내부 빠른 반응 3슬롯 + 더보기, 그리고 반응 행 끝의 dashed 추가 pill.
dev_lee MOD Today 2:34 PM오늘 오후 2:34

Shipping the density toggle today. I'll wire up reactions right away too.밀도 토글 오늘 배포합니다. 반응도 바로 붙여볼게요.

.qf-msg-quickreact, .qf-reaction--add

Code block header, Thread follow-up

A header atop the code block (language + copy) and a thread-follow avatar stack with an accent count.코드블록 상단 헤더(lang + 복사)와 스레드 참여 아바타 스택 + accent 카운트.
typescript
const density = useDensity(); // 'cozy' | 'compact'
7 replies답글 7개 Last reply 2 hours ago마지막 답글 2시간 전
.qf-codeblock__header, .qf-thread-followup__avatars

Density — cozy vs compact

The same message group rendered side by side in the default container and a data-density="compact" container for comparison.같은 메시지 그룹을 기본 컨테이너와 data-density="compact" 컨테이너로 나란히 렌더해 비교.
Cozy (default)(기본)
designer_kim 10:24 AM오전 10:24

Cozy keeps the 40px avatar and generous spacing.cozy는 40px 아바타와 넉넉한 간격을 유지해요.

Consecutive messages align to the same width.연속 메시지도 같은 폭으로 정렬됩니다.

The reading flow carries smoothly through.읽기 흐름이 부드럽게 이어져요.

Default container기본 컨테이너
Compact
designer_kim 10:24 AM오전 10:24

Compact shrinks the avatar and tightens the gap between groups.compact는 아바타를 줄이고 그룹 간격을 좁혀요.

Consecutive messages are indented by the avatar width.연속 메시지는 아바타 폭만큼 인덴트됩니다.

Vertical density goes up while alignment stays the same.세로 밀도는 높이고 정렬은 그대로.

data-density="compact"
v4: Task 050

Mobile nav, IA

This is the mobile information-architecture upgrade. It shows, one screen at a time, the bottom tab bar with active pill, the OverlappingPanels left drawer, message-screen ergonomics, Home quick tiles/filters/profile, and the emoji drawer.모바일 정보구조 업그레이드예요. 하단 탭바 활성 pill, OverlappingPanels 좌 드로어, 메시지 화면 ergonomics, Home 퀵타일/필터/프로필, 그리고 이모지 드로어를 한 컷씩 보여줍니다.

Tab bar, Panels, Message ergonomics

(a) Tab bar with active pill + badges, (b) OverlappingPanels with the left drawer open, (c) unread divider + jump button + accessory bar.(a) 활성 pill + 배지 탭바, (b) 좌 드로어 열린 OverlappingPanels, (c) 읽지 않음 divider + jump 버튼 + accessory 바.
Home홈
Recent conversations최근 대화
designer_kim
Sent over the SVG, please take a look!SVG 넘겨드렸어요 확인 부탁!
2:34
# deploy-alerts# 배포-알림
Deployment completed배포가 완료되었어요
Yesterday어제
Text channels텍스트 채널
# general# 일반
# design# 디자인
# deploy# 배포
# design# 디자인
designer_kim2:14 PM오후 2:14
Putting the panel skeleton in place.패널 골격 들어갑니다.
# general# 일반
New messages새 메시지 7
designer_kim9:41 AM오전 9:41
Uploading a few photos사진 몇 장 올려요
+5

Home IA, You, Emoji drawer

(d) Home quick tiles + filter chips + You header, plus a single shot of the mobile emoji drawer.(d) Home 퀵타일 + 필터칩 + You 헤더, 그리고 모바일 이모지 드로어 한 컷.
Home홈
Members멤버
dev_lee
Active just now방금 전 활동
You나
Yuna Park박유나
@yuna
Online, Designing온라인, 디자인 중
Set a status message상태 메시지 설정
Settings설정
Notifications알림
Privacy, Security개인정보, 보안
Frequently used자주 쓰는