# Red Hat PatternFly 디자인 시스템

## Red Hat PatternFly 디자인 시스템 인터페이스 미리보기

서비스 갤러리를 검색하고, 개별 서비스나 표시된 서비스를 선택하고, 복제본 수를 확인한 다음 선택 항목을 검토하고 로컬 계획을 확정하세요.

## Red Hat PatternFly 디자인 시스템 디자인 참조

PatternFly React 6.6.1 및 @patternfly/react-tokens 6.6.1. 게시된 라이트 테마 토큰의 일부 해석 결과를 아래에 표시합니다. 기본 컴포넌트와 pf-v6-theme-dark가 다크 스타일을 적용하며, 서비스 예시 데이터와 레이아웃은 애플리케이션에서 정한 것입니다.

### 시맨틱 배경 및 텍스트 역할

| 이름 / 규칙 | 값 / 구성 | 용도 |
| --- | --- | --- |
| --pf-t--global--background--color--primary--default | rgb(255, 255, 255, 0.6000) | 활성 테마의 시맨틱 역할을 사용하세요. 브랜드 강조용 빨간색이 모든 기본 동작에 쓰이는 색상은 아닙니다. |
| --pf-t--global--background--color--secondary--default | rgb(199, 199, 199, 0.3000) | 활성 테마의 시맨틱 역할을 사용하세요. 브랜드 강조용 빨간색이 모든 기본 동작에 쓰이는 색상은 아닙니다. |
| --pf-t--global--text--color--regular | #151515 | 활성 테마의 시맨틱 역할을 사용하세요. 브랜드 강조용 빨간색이 모든 기본 동작에 쓰이는 색상은 아닙니다. |
| --pf-t--global--text--color--subtle | #383838 | 활성 테마의 시맨틱 역할을 사용하세요. 브랜드 강조용 빨간색이 모든 기본 동작에 쓰이는 색상은 아닙니다. |
| --pf-t--global--text--color--disabled | #a3a3a3 | 활성 테마의 시맨틱 역할을 사용하세요. 브랜드 강조용 빨간색이 모든 기본 동작에 쓰이는 색상은 아닙니다. |
| --pf-t--global--color--brand--default | #004d99 | 활성 테마의 시맨틱 역할을 사용하세요. 브랜드 강조용 빨간색이 모든 기본 동작에 쓰이는 색상은 아닙니다. |
| --pf-t--global--color--brand--hover | #003366 | 활성 테마의 시맨틱 역할을 사용하세요. 브랜드 강조용 빨간색이 모든 기본 동작에 쓰이는 색상은 아닙니다. |
| --pf-t--global--color--brand--accent--default | #ee0000 | 활성 테마의 시맨틱 역할을 사용하세요. 브랜드 강조용 빨간색이 모든 기본 동작에 쓰이는 색상은 아닙니다. |
| --pf-t--global--color--brand--subtle--default | #e0f0ff | 활성 테마의 시맨틱 역할을 사용하세요. 브랜드 강조용 빨간색이 모든 기본 동작에 쓰이는 색상은 아닙니다. |
### 상태 역할

| 이름 / 규칙 | 값 / 구성 | 용도 |
| --- | --- | --- |
| --pf-t--global--color--status--success--default | #204d00 | 상태의 의미를 텍스트 레이블로도 표시하세요. 여기 제시된 라이트 테마 값은 기본 Label이나 Alert 변형을 대체하지 않습니다. |
| --pf-t--global--color--status--warning--default | #73480b | 상태의 의미를 텍스트 레이블로도 표시하세요. 여기 제시된 라이트 테마 값은 기본 Label이나 Alert 변형을 대체하지 않습니다. |
| --pf-t--global--color--status--danger--default | #731f00 | 상태의 의미를 텍스트 레이블로도 표시하세요. 여기 제시된 라이트 테마 값은 기본 Label이나 Alert 변형을 대체하지 않습니다. |
| --pf-t--global--color--status--info--default | #3d2785 | 상태의 의미를 텍스트 레이블로도 표시하세요. 여기 제시된 라이트 테마 값은 기본 Label이나 Alert 변형을 대체하지 않습니다. |
| --pf-t--global--color--status--custom--default | #004d4d | 상태의 의미를 텍스트 레이블로도 표시하세요. 여기 제시된 라이트 테마 값은 기본 Label이나 Alert 변형을 대체하지 않습니다. |
| --pf-t--global--color--status--unread--default | #0066cc | 상태의 의미를 텍스트 레이블로도 표시하세요. 여기 제시된 라이트 테마 값은 기본 Label이나 Alert 변형을 대체하지 않습니다. |
### 본문 및 제목 글꼴

| 이름 / 규칙 | 값 / 구성 | 용도 |
| --- | --- | --- |
| --pf-t--global--font--size--body--default | 0.875rem | 글자 역할과 의미상 제목 수준을 의도적으로 선택하세요. 시각적 크기가 문서의 개요 구조를 결정하지는 않습니다. |
| --pf-t--global--font--size--body--lg | 1rem | 글자 역할과 의미상 제목 수준을 의도적으로 선택하세요. 시각적 크기가 문서의 개요 구조를 결정하지는 않습니다. |
| --pf-t--global--font--size--heading--h1 | 1.5rem | 글자 역할과 의미상 제목 수준을 의도적으로 선택하세요. 시각적 크기가 문서의 개요 구조를 결정하지는 않습니다. |
| --pf-t--global--font--size--heading--h2 | 1.25rem | 글자 역할과 의미상 제목 수준을 의도적으로 선택하세요. 시각적 크기가 문서의 개요 구조를 결정하지는 않습니다. |
| --pf-t--global--font--size--heading--h3 | 1.125rem | 글자 역할과 의미상 제목 수준을 의도적으로 선택하세요. 시각적 크기가 문서의 개요 구조를 결정하지는 않습니다. |
| --pf-t--global--font--size--heading--h4 | 1rem | 글자 역할과 의미상 제목 수준을 의도적으로 선택하세요. 시각적 크기가 문서의 개요 구조를 결정하지는 않습니다. |
| --pf-t--global--font--size--heading--h5 | 1rem | 글자 역할과 의미상 제목 수준을 의도적으로 선택하세요. 시각적 크기가 문서의 개요 구조를 결정하지는 않습니다. |
| --pf-t--global--font--size--heading--h6 | 1rem | 글자 역할과 의미상 제목 수준을 의도적으로 선택하세요. 시각적 크기가 문서의 개요 구조를 결정하지는 않습니다. |
### 간격 스케일

| 이름 / 규칙 | 값 / 구성 | 용도 |
| --- | --- | --- |
| --pf-t--global--spacer--xs | 0.25rem | 그룹과 컨트롤에는 지정된 간격 체계를 사용하세요. rem 값은 사용자 루트 글꼴 크기를 따릅니다. |
| --pf-t--global--spacer--sm | 0.5rem | 그룹과 컨트롤에는 지정된 간격 체계를 사용하세요. rem 값은 사용자 루트 글꼴 크기를 따릅니다. |
| --pf-t--global--spacer--md | 1rem | 그룹과 컨트롤에는 지정된 간격 체계를 사용하세요. rem 값은 사용자 루트 글꼴 크기를 따릅니다. |
| --pf-t--global--spacer--lg | 1.5rem | 그룹과 컨트롤에는 지정된 간격 체계를 사용하세요. rem 값은 사용자 루트 글꼴 크기를 따릅니다. |
| --pf-t--global--spacer--xl | 2rem | 그룹과 컨트롤에는 지정된 간격 체계를 사용하세요. rem 값은 사용자 루트 글꼴 크기를 따릅니다. |
| --pf-t--global--spacer--2xl | 3rem | 그룹과 컨트롤에는 지정된 간격 체계를 사용하세요. rem 값은 사용자 루트 글꼴 크기를 따릅니다. |
| --pf-t--global--spacer--3xl | 4rem | 그룹과 컨트롤에는 지정된 간격 체계를 사용하세요. rem 값은 사용자 루트 글꼴 크기를 따릅니다. |
| --pf-t--global--spacer--4xl | 5rem | 그룹과 컨트롤에는 지정된 간격 체계를 사용하세요. rem 값은 사용자 루트 글꼴 크기를 따릅니다. |
### 모양 및 포커스

| 이름 / 규칙 | 값 / 구성 | 용도 |
| --- | --- | --- |
| --pf-t--global--border--radius--tiny | 4px | 모든 표면에 알약 모양의 둥근 모서리를 적용하지 말고, 해당 컴포넌트에 맞는 형태를 사용하세요. |
| --pf-t--global--border--radius--small | 6px | 모든 표면에 알약 모양의 둥근 모서리를 적용하지 말고, 해당 컴포넌트에 맞는 형태를 사용하세요. |
| --pf-t--global--border--radius--medium | 16px | 모든 표면에 알약 모양의 둥근 모서리를 적용하지 말고, 해당 컴포넌트에 맞는 형태를 사용하세요. |
| --pf-t--global--border--radius--large | 24px | 모든 표면에 알약 모양의 둥근 모서리를 적용하지 말고, 해당 컴포넌트에 맞는 형태를 사용하세요. |
| --pf-t--global--border--radius--pill | 999px | 모든 표면에 알약 모양의 둥근 모서리를 적용하지 말고, 해당 컴포넌트에 맞는 형태를 사용하세요. |
| --pf-t--global--border--radius--control--form-element | 6px | 모든 표면에 알약 모양의 둥근 모서리를 적용하지 말고, 해당 컴포넌트에 맞는 형태를 사용하세요. |
| --pf-t--global--border--radius--action--default | 999px | 모든 표면에 알약 모양의 둥근 모서리를 적용하지 말고, 해당 컴포넌트에 맞는 형태를 사용하세요. |
## Red Hat PatternFly 디자인 시스템 전체 가이드

실제 인터페이스를 위해 이 시스템을 선택하고 적용하고 검토하는 실용 가이드.

완전한 안내와 구현 시작점, 소스 링크.

## Red Hat PatternFly 디자인 시스템 운영 레이아웃

### 운영 상황을 지속적으로 보여 주는 컬렉션

> 서비스 갤러리에서 운영자는 상태, 위치, 사용률을 비교하고, 별도의 범위 패널에서 선택한 항목을 확인할 수 있습니다. 선택 항목은 현재 검색 결과와 다릅니다. 필터링되어 보이지 않는 서비스도 사용자가 직접 제거하기 전까지 계속 선택된 상태입니다. 화면에 보이는 항목을 넘어 영향을 미치는 일괄 작업에서는 이 구분이 중요합니다.

### 기본 컴포넌트 계층 구조를 사용하세요

Gallery는 반응형 카드 열을 처리하고, Card는 서비스를 각각 구분하며, Label은 상태를 표시하고, Progress는 제목과 함께 예시 백분율을 보여 줍니다. 이 페이지는 임의의 색상 사각형으로 인프라 콘솔을 흉내 내지 않습니다. 전체 React 예제에서 데이터 모델, 컨트롤, 검토 상태를 구현합니다.

## Red Hat PatternFly 디자인 시스템의 의미 기반 색상 및 테마 역할

### 기본 브랜드 색상과 빨간색 강조 색상은 서로 다릅니다

PatternFly v6는 브랜드, 강조, 텍스트, 배경, 상태 역할을 각각 제공합니다. 선택한 라이트 테마 스냅샷에는 파란색 brand-default와 빨간색 brand-accent-default가 포함됩니다. 눈에 띄는 모든 동작에 Red Hat 빨간색을 사용하면 이러한 역할이 하나로 뒤섞입니다. 기본 Button 및 Label 컴포넌트는 각 변형에 적합한 시스템 역할을 사용합니다.

### 문서 요소에서 다크 테마를 적용하세요

예제에서는 문서 요소에 pf-v6-theme-dark를 전환 적용합니다. 애플리케이션의 표면과 텍스트는 --pf-t--global 의미 기반 변수를 사용하므로 테마에 따라 색상도 함께 적용됩니다. 사용자 정의 카드에 라이트 테마 색상을 고정해 두고 문서의 테마 클래스가 이를 수정해 주리라 기대하지 마세요.

## Red Hat PatternFly 디자인 시스템 글꼴 및 서비스 메타데이터

### 시각적 크기와 제목의 의미를 구분하세요

Title의 headingLevel h1은 페이지 제목을 설정하고, 크기는 시각적 강조 정도를 결정합니다. 이 패키지 스냅샷에서 body-default는 0.875rem입니다. 모든 값을 제목으로 만들지 않아도 카드 레이블, 상태, 수치 사용률을 읽기 쉽게 표시할 수 있습니다. 메타데이터 정의 목록에는 복제본 수와 서비스 ID를 명확히 표시합니다.

### 모호한 운영 레이블은 피하세요

컴포넌트와 바닥글에 예시 사용률임을 표시합니다. 설명 없는 진행률 표시줄은 배포 작업이나 로딩 동작으로 오해될 수 있습니다. 캡션은 백분율이 무엇을 나타내는지 설명하고, 상태 Label은 정상 용량 또는 검토 필요 용량을 별도로 전달합니다.

## Red Hat PatternFly 디자인 시스템 갤러리 및 일괄 선택

### 체크박스의 세 가지 상태를 사용하세요

보이는 항목 모두 선택 컨트롤은 보이는 서비스를 전부 선택했을 때 true, 하나도 선택하지 않았을 때 false, 일부만 선택했을 때 null입니다. PatternFly Checkbox는 null 값에 해당하는 부분 선택 상태를 지원합니다. 애플리케이션은 필터링된 컬렉션을 바탕으로 이 상태를 계산하며, 행별 선택 상태와 어긋날 수 있는 별도의 불리언 값을 사용하지 않습니다.

1. 서비스 하나를 선택하고 부분 선택 상태를 확인하세요.

2. 현재 보이는 서비스를 모두 선택하세요.

3. 이름 하나를 검색하고, 보이지 않는 선택 항목이 유지되는지 확인하세요.

4. 정확한 선택 항목과 복제본 수를 확인하세요.

5. 로컬 계획을 확인하고 결과를 읽으세요.

### 선택 집합을 단일 기준으로 사용하세요

각 서비스에는 고유한 ID가 있습니다. 개별 체크박스와 보이는 항목 모두 선택 컨트롤은 동일한 ID 집합을 업데이트합니다. 범위 패널은 해당 집합을 바탕으로 서비스 이름과 전체 복제본 수를 표시합니다. 검색은 항목이 보이는지 여부만 바꿉니다. 따라서 운영자가 여러 서비스를 선택한 뒤 갤러리의 검색 범위를 좁혀도 검토 요약은 일관되게 유지됩니다.

## Red Hat PatternFly 디자인 시스템 간격 및 반응형 카드

### 페이지 셸에 의미 기반 토큰을 사용하세요

예제의 배경, 일반 텍스트, 보조 메타데이터는 게시된 토큰 패키지의 의미 기반 CSS 속성을 사용합니다. 기본 간격 체계는 xs부터 4xl까지이며, 애플리케이션에서는 컬렉션과 범위 패널 사이에 24px를 사용합니다. 이 명시적인 레이아웃 값은 토큰 참조와 별개입니다.

### 콘텐츠를 줄이기 전에 갤러리가 재배치되도록 하세요

Gallery에는 최소 항목 너비 230px와 거터가 지정되어 있습니다. 애플리케이션의 850px 브레이크포인트에서는 범위 패널이 컬렉션 아래로 이동합니다. 500px에서는 페이지 패딩을 16px로 줄이고 검색창이 도구 모음 전체 너비를 차지합니다. 이는 예제의 레이아웃 결정이며, 모든 PatternFly 제품이 이 브레이크포인트를 사용한다는 의미는 아닙니다.

## Red Hat PatternFly 디자인 시스템 검토 및 선택 상태

### 선택 동작이 실제 작업을 실행하지 않도록 하세요

서비스를 체크하면 범위에 추가될 뿐입니다. ‘선택 항목 검토’를 누르면 안내 Alert와 확인 동작이 표시됩니다. ‘로컬 계획 확인’을 누르면 선택한 서비스와 복제본 수를 알리지만 유지보수 작업은 시작하지 않습니다. 선택 항목이 바뀌면 검토 상태가 닫히므로, 이전 선택 항목을 실수로 확정할 수 없습니다.

### 검색 결과 없음 처리와 선택 상태 복구를 분리하세요

일치하는 검색 결과가 없으면 인라인 안내 Alert와 ‘검색 지우기’가 표시됩니다. 이 기능은 검색어만 지우고 선택한 서비스는 그대로 유지합니다. 따라서 도구 모음의 선택 개수와 범위 패널에 표시되는 내용도 계속 일치합니다. 검색 결과가 없다는 이유로 선택 항목까지 초기화하면 사용자에게 알리지 않고 데이터를 삭제하는 동작이 됩니다.

## Red Hat PatternFly 디자인 시스템 접근성 컨트롤 및 상태

### 레이블을 연결하고 기본 컨트롤을 사용하세요

각 Checkbox에는 고유한 id와 화면에 표시되는 서비스 레이블이 있습니다. SearchInput에는 접근 가능한 이름이 지정되어 있고, Switch에는 모양 설정 이름이 지정되어 있으며, 선택 항목이 비어 있으면 ‘선택 항목 검토’가 비활성화됩니다. 기본 Progress는 값과 제목을 전달합니다. 카드 안에 숨겨져 마우스오버할 때만 나타나는 동작에 의존하지 않습니다.

### 상태를 텍스트로도 표시하세요

선택 개수는 정중한 라이브 영역을 사용하고, 서비스 상태는 Label 안에 표시하며, 마지막 Alert에는 발생한 상황을 설명합니다. 색상만으로 선택 범위나 상태를 나타내지 마세요. 키보드 테스트에는 일부 항목만 선택한 경우, 선택된 서비스가 필터링으로 사라진 경우, 전체 목록으로 돌아온 경우를 포함해야 합니다.

- 체크된 상태는 포함 여부를 나타내는 결정이지, 성공 상태가 아닙니다.

- 상태 Label은 서비스 상태를 설명하며, 선택 여부를 나타내지 않습니다.

- Progress는 작업 완료가 아니라 샘플 사용률을 나타냅니다.

## Red Hat PatternFly 디자인 시스템 React 통합

### 리셋 스타일과 컴포넌트 스타일을 한 번만 가져옵니다

예제는 진입점에서 @patternfly/react-core/dist/styles/base.css를 가져옵니다. 네이티브 React 컴포넌트는 패키지에서 컴포넌트 스타일을 제공합니다. 애플리케이션 CSS은 pf-example 범위로 한정되며 현재 --pf-t--global 네임스페이스를 참조합니다. 컴포넌트 내부 스타일을 덮어쓰지 않습니다.

### 실제 예약 기능은 서비스 계약이 마련된 경우에만 추가합니다

로컬 계획은 의도적으로 미리보기로만 제공됩니다. 프로덕션 구현에는 권한 부여, 유지 관리 시간대, 영향을 받는 종속 항목, 피드백 대기 상태 및 서버 측 검증이 필요합니다. 요청이 진행되는 동안 선택한 ID를 안정적으로 유지하고, 확인된 결과를 실제 서비스 응답과 일치시킵니다. 네이티브 표시 컴포넌트는 운영 백엔드를 제공하지 않습니다.

## Red Hat PatternFly 디자인 시스템 컴포넌트 예제

### main.jsx — 서비스 갤러리 및 일괄 검토

계산된 선택 범위와 로컬 확인 기능을 갖춘 완전한 네이티브 Gallery/Card/Checkbox/Progress 구성입니다.

```
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import {
  Alert,
  Button,
  Card,
  CardBody,
  CardTitle,
  Checkbox,
  Gallery,
  GalleryItem,
  Label,
  Progress,
  SearchInput,
  Switch,
  Title,
} from "@patternfly/react-core";
import "@patternfly/react-core/dist/styles/base.css";
import "./patternfly.css";
const services = [
  {
    id: "api",
    name: "Public API",
    region: "eu-west",
    replicas: 6,
    load: 62,
    status: "Healthy",
  },
  {
    id: "jobs",
    name: "Background jobs",
    region: "eu-west",
    replicas: 3,
    load: 81,
    status: "Review capacity",
  },
  {
    id: "search",
    name: "Search index",
    region: "us-east",
    replicas: 4,
    load: 44,
    status: "Healthy",
  },
  {
    id: "events",
    name: "Event stream",
    region: "us-east",
    replicas: 8,
    load: 72,
    status: "Healthy",
  },
];
function App() {
  const [query, setQuery] = useState(""),
    [selected, setSelected] = useState([]),
    [review, setReview] = useState(false),
    [notice, setNotice] = useState(""),
    [dark, setDark] = useState(false);
  const visible = services.filter((x) =>
    x.name.toLowerCase().includes(query.toLowerCase()),
  );
  const picked = services.filter((x) => selected.includes(x.id));
  const allVisible =
    visible.length > 0 && visible.every((x) => selected.includes(x.id));
  const someVisible = visible.some((x) => selected.includes(x.id));
  function choose(id, checked) {
    setSelected((v) =>
      checked ? [...new Set([...v, id])] : v.filter((x) => x !== id),
    );
    setReview(false);
  }
  function selectVisible(checked) {
    setSelected((v) =>
      checked
        ? [...new Set([...v, ...visible.map((x) => x.id)])]
        : v.filter((id) => !visible.some((x) => x.id === id)),
    );
    setReview(false);
  }
  return (
    <main className="pf-example">
      <header>
        <div>
          <span className="overline">PATTERNFLY · SERVICE OPERATIONS</span>
          <Title headingLevel="h1" size="2xl">
            Plan a maintenance review
          </Title>
          <p>
            Select services and inspect the combined scope before creating a
            local plan.
          </p>
        </div>
        <Switch
          id="dark-theme"
          label="Dark theme"
          isChecked={dark}
          onChange={(_, checked) => {
            setDark(checked);
            document.documentElement.classList.toggle(
              "pf-v6-theme-dark",
              checked,
            );
          }}
        />
      </header>
      <div className="service-toolbar">
        <SearchInput
          aria-label="Find a service"
          placeholder="Find a service"
          value={query}
          onChange={(_, value) => setQuery(value)}
          onClear={() => setQuery("")}
        />
        <Checkbox
          id="select-visible"
          label="Select visible"
          isChecked={allVisible ? true : someVisible ? null : false}
          isDisabled={!visible.length}
          onChange={(_, checked) => selectVisible(checked)}
        />
        <span aria-live="polite">{selected.length} selected</span>
        <Button isDisabled={!selected.length} onClick={() => setReview(true)}>
          Review selection
        </Button>
      </div>
      <div className="service-layout">
        <Gallery hasGutter minWidths={{ default: "230px" }}>
          {visible.map((s) => (
            <GalleryItem key={s.id}>
              <Card>
                <CardTitle>
                  <Checkbox
                    id={"select-" + s.id}
                    label={s.name}
                    isChecked={selected.includes(s.id)}
                    onChange={(_, checked) => choose(s.id, checked)}
                  />
                </CardTitle>
                <CardBody>
                  <div className="service-meta">
                    <Label color={s.status === "Healthy" ? "green" : "orange"}>
                      {s.status}
                    </Label>
                    <span>{s.region}</span>
                  </div>
                  <Progress
                    value={s.load}
                    title="Sample utilization"
                    measureLocation="outside"
                  />
                  <dl>
                    <dt>Replicas</dt>
                    <dd>{s.replicas}</dd>
                    <dt>Service ID</dt>
                    <dd>
                      <code>{s.id}</code>
                    </dd>
                  </dl>
                </CardBody>
              </Card>
            </GalleryItem>
          ))}
        </Gallery>
        <aside>
          <Card>
            <CardTitle>Maintenance scope</CardTitle>
            <CardBody>
              <p>
                {picked.length} services ·{" "}
                {picked.reduce((n, s) => n + s.replicas, 0)} replicas
              </p>
              {picked.length ? (
                <ul>
                  {picked.map((s) => (
                    <li key={s.id}>
                      {s.name}
                      <span>{s.region}</span>
                    </li>
                  ))}
                </ul>
              ) : (
                <p className="muted">Select a service to inspect its scope.</p>
              )}
              {review && (
                <div className="review">
                  <Alert
                    isInline
                    variant="info"
                    title="Review the selected services"
                  >
                    This is a fictional plan. No workload will be restarted.
                  </Alert>
                  <Button
                    onClick={() => {
                      setNotice(
                        `Local plan includes ${picked.length} services and ${picked.reduce((n, s) => n + s.replicas, 0)} replicas. No operation was scheduled.`,
                      );
                      setReview(false);
                    }}
                  >
                    Confirm local plan
                  </Button>
                </div>
              )}
            </CardBody>
          </Card>
        </aside>
      </div>
      {!visible.length && (
        <Alert isInline variant="info" title="No services match">
          <Button variant="link" onClick={() => setQuery("")}>
            Clear search
          </Button>
        </Alert>
      )}
      {notice && (
        <Alert isInline variant="success" title="Local plan recorded">
          {notice}
        </Alert>
      )}
      <footer>
        Native PatternFly 6.6.1 · service data and capacity figures are
        fictional, memory-only examples.
      </footer>
    </main>
  );
}
createRoot(document.getElementById("root")).render(<App />);
```

코드 참조

- src/main.jsx로 저장합니다. Checkbox onChange는 이벤트와 checked 값을 전달하며, 혼합 선택 상태에서는 isChecked가 null일 수 있습니다.

### patternfly.css — 반응형 운영 셸

사용자 지정 페이지 레이아웃은 의미 기반 v6 토큰을 사용하며 네이티브 컴포넌트 스타일을 그대로 유지합니다.

```
body {
  margin: 0;
}
.pf-example {
  padding: 24px;
  background: var(--pf-t--global--background--color--secondary--default);
  color: var(--pf-t--global--text--color--regular);
  font-family: var(--pf-t--global--font--family--body);
}
.pf-example header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  margin-bottom: 24px;
}
.overline {
  font-size: 11px;
  letter-spacing: 0.07em;
  color: var(--pf-t--global--text--color--subtle);
}
.pf-example header h1 {
  margin: 8px 0;
}
.service-toolbar {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: 24px;
}
.service-toolbar > .pf-v6-c-search-input {
  width: 280px;
}
.service-toolbar > span {
  margin-left: auto;
}
.service-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 280px;
  gap: 24px;
  align-items: start;
}
.service-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: 12px;
  margin-bottom: 24px;
}
.service-layout dl {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 24px;
  font-size: 12px;
}
.service-layout dd {
  margin: 0;
}
.service-layout ul {
  padding: 0;
  list-style: none;
  margin: 16px 0;
}
.service-layout li {
  padding: 12px 0;
  border-bottom: 1px solid var(--pf-t--global--border--color--default);
}
.service-layout li span {
  display: block;
  font-size: 12px;
  color: var(--pf-t--global--text--color--subtle);
}
.muted {
  color: var(--pf-t--global--text--color--subtle);
  margin-top: 16px;
}
.review > .pf-v6-c-button {
  margin-top: 16px;
}
.pf-example > .pf-v6-c-alert {
  margin-top: 24px;
}
.pf-example footer {
  font-size: 12px;
  color: var(--pf-t--global--text--color--subtle);
  margin-top: 24px;
}
@media (max-width: 850px) {
  .service-layout {
    grid-template-columns: 1fr;
  }
  .pf-example header {
    align-items: start;
  }
  .service-toolbar > span {
    margin-left: 0;
  }
}
@media (max-width: 500px) {
  .pf-example {
    padding: 16px;
  }
  .pf-example header {
    flex-direction: column;
  }
  .service-toolbar {
    gap: 16px;
  }
  .service-toolbar > .pf-v6-c-search-input {
    width: 100%;
  }
}
```

코드 참조

- src/patternfly.css로 저장합니다. 애플리케이션 중단점은 이 예제에 명시적으로 포함되어 있습니다.

## Red Hat PatternFly 디자인 시스템 에이전트 설정

### 구현 시작점

네이티브 React 18.3.1 / PatternFly 6.6.1 구성입니다. Vite를 사용하려면 지원되는 Node.js 버전이 필요합니다. 실제 서비스 데이터와 운영 API은 애플리케이션의 책임입니다.

```
npm create vite@latest patternfly-services -- --template react
cd patternfly-services
npm install
npm install react@18.3.1 react-dom@18.3.1 @patternfly/react-core@6.6.1
# Replace src/main.jsx and add src/patternfly.css using the complete examples.
npm run dev
```

### 프로젝트를 위한 프롬프트

```
네이티브 Gallery, Card, Checkbox, Progress, Label 및 Alert를 사용해 PatternFly 6.6.1 기반 운영 컬렉션을 구성합니다. 제공된 의미 기반 토큰과 전체 예제를 사용하세요. 필터링된 항목의 표시 여부와 선택된 ID를 분리하고, 일괄 선택의 부분 선택 상태를 계산하며, 정확한 영향 대상 목록을 검토하도록 합니다. 실제 API을 추가할 때는 대기·실패·성공 상태를 정확하게 표시하세요. 모바일 재배치와 키보드 접근성을 유지하세요.
```

## Red Hat PatternFly 디자인 시스템 출처 및 범위

OpenDesign에서 작성한 애플리케이션 가이드와 가상의 유지 관리 계획 예제로, 네이티브 PatternFly React 6.6.1을 실행합니다. 사용률, 지역 및 복제본 개수는 샘플 데이터입니다. 확인 작업은 로컬 상태만 업데이트하며 서비스가 재시작되거나 예약되지는 않습니다.

- PatternFly로 개발하기 네이티브 패키지 및 스타일시트 통합입니다.

- 게시된 토큰 모듈 버전이 지정된 토큰 이름과 확인된 라이트 테마 값입니다.

- 일괄 선택 패턴 선택 범위 및 컬렉션 동작입니다.

- PatternFly React 저장소 네이티브 컴포넌트 구현 및 라이선스입니다.

## Red Hat PatternFly 디자인 시스템 관련 리소스

### REI Cedar

네이티브 Vue 타일, 실제 토큰 값, 완전한 키보드 탐색, 반응형 제품 구성을 사용해 구체적인 Cedar 배송 방식 선택 화면을 구현하세요.

### Sainsbury's 디자인 시스템

Sainsbury’s의 공개 디자인 지침을 실제 상품 수령 시간대 선택 흐름에 적용해 보세요. 실제 색상과 크기 참고 자료, 접근성 높은 라디오 선택 항목, 변경 사항이 반영되는 요약, 그리고 로컬에서만 작동하는 명확한 피드백을 확인할 수 있습니다.

### Salesforce Lightning

밀도 높은 레코드 작업을 위한 Lightning 블루프린트 가이드입니다. 실제 간격과 타이포그래피, 의미 기반 색상, 편집 가능한 케이스 작업 공간, 필드 유효성 검사, 로컬 변경 사항을 반영하는 활동 기록을 제공합니다.


- [구현 레퍼런스](https://www.patternfly.org/patterns/bulk-selection/)
- [출처](https://cdn.jsdelivr.net/npm/@patternfly/react-tokens@6.6.1/dist/esm/)
- [코드 참조](https://www.patternfly.org/components/checkbox/)
- [코드 참조](https://www.patternfly.org/foundations-and-styles/design-tokens/develop/)
- [PatternFly로 개발하기 네이티브 패키지 및 스타일시트 통합입니다.](https://www.patternfly.org/get-started/develop/)
- [게시된 토큰 모듈 버전이 지정된 토큰 이름과 확인된 라이트 테마 값입니다.](https://cdn.jsdelivr.net/npm/@patternfly/react-tokens@6.6.1/dist/esm/)
- [일괄 선택 패턴 선택 범위 및 컬렉션 동작입니다.](https://www.patternfly.org/patterns/bulk-selection/)
- [PatternFly React 저장소 네이티브 컴포넌트 구현 및 라이선스입니다.](https://github.com/patternfly/patternfly-react)
