기업용 소프트웨어 · 새 리소스

HPE Grommet 디자인 시스템.

Grommet의 레이아웃 기본 요소, 제어형 폼 필드, 숫자 미터를 사용해 수용 인원 예약 인터페이스를 구성하세요. 테마 스케일을 의도적으로 활용하고, 기본 Grommet 테마와 별도로 설치하는 HPE 테마를 구분하세요.

OpenDesign 가이드9개 챕터참조 항목 38개독자적 적용 가이드
01

HPE Grommet 디자인 시스템 인터페이스 미리보기

제안된 할당량을 조정하고 유효성을 검사한 로컬 계획을 준비합니다.

용량 예약 계획 도구전체 예시 열기
기본 Grommet 치수와 색상을 독립적으로 해석한 HTML/CSS 구현이며, Arial 글꼴을 명시적으로 선택했습니다. 별도의 HPE 테마가 아닙니다. · 구현 레퍼런스
02

HPE Grommet 디자인 시스템 디자인 참조

baseSpacing=24 및 scale=6으로 생성한 Grommet v2 기본 테마입니다. 이 값은 grommet-theme-hpe 값이 아닙니다. 기본 스타터에서는 Arial과 예시의 브랜드 및 포커스 색상을 애플리케이션 테마 선택 항목으로 명시적으로 설정합니다.

기본 가장자리 크기 스케일

출처
이름 / 규칙값 / 구성용도
global.edgeSize.hair1px작은 화면 반응형 재정의를 적용하지 않은 기본 크기.
global.edgeSize.xxsmall3px작은 화면 반응형 재정의를 적용하지 않은 기본 크기.
global.edgeSize.xsmall6px작은 화면 반응형 재정의를 적용하지 않은 기본 크기.
global.edgeSize.small12px작은 화면 반응형 재정의를 적용하지 않은 기본 크기.
global.edgeSize.medium24px작은 화면 반응형 재정의를 적용하지 않은 기본 크기.
global.edgeSize.large48px작은 화면 반응형 재정의를 적용하지 않은 기본 크기.
global.edgeSize.xlarge96px작은 화면 반응형 재정의를 적용하지 않은 기본 크기.

작은 화면 반응형 재정의

출처
이름 / 규칙값 / 구성용도
global.breakpoints.small.value768기본 테마의 작은 화면 중단점 경계.
small.edgeSize.xxsmall2px작은 화면용 세밀한 간격.
small.edgeSize.xsmall3px작은 화면용 xsmall 간격.
small.edgeSize.small6px반응형 작은 패딩.
small.edgeSize.medium12px반응형 중간 패딩.
small.edgeSize.large24px반응형 큰 여백.
global.breakpoints.medium.value1536다음 기본 중단점 경계.

기본 색상과 컨트롤

출처
이름 / 규칙값 / 구성용도
global.colors.brand#7D4CDB HPE 그린이 아닌 기본 Grommet 브랜드 색상.
global.colors.focus#6FFFB0 기본 포커스 강조 색상.
global.colors.text.light#444444 밝은 테마 본문 텍스트.
global.colors.text.dark#f8f8f8 어두운 테마 본문 텍스트.
global.colors.background-front.light#FFFFFF 전면 밝은 표면.
global.colors.background-front.dark#444444 전면 어두운 표면.
global.control.border.radius4px기본 컨트롤 모서리.
global.control.border.width1px기본 컨트롤 테두리.

폼 및 필드 계약

출처
이름 / 규칙값 / 구성용도
Form.valueObject keyed by field name제어 예약 객체 하나를 사용합니다.
Form.onChange(value) => {}DOM 이벤트가 아닌 업데이트된 객체를 받습니다.
Form.onSubmit({ value, touched }) => {}유효성이 인정된 현재 폼 값을 읽습니다.
Form.validateblur | submit | change유효성 검사 실행 시점을 선택합니다.
Form.errorsObject keyed like value원격 또는 애플리케이션 오류를 필드에 연결합니다.

Select 및 범위 통합

출처
이름 / 규칙값 / 구성용도
Select.optionsString array or object array값 형식을 단순하게 유지하기 위해 예시에서는 문자열을 사용합니다.
Select.onChange({ value, option }) => {}Select에서는 event.target.value를 읽지 마세요.
Select.valueKey{ key, reduce } for object optionsreduce는 전체 객체가 아닌 키가 지정된 값을 반환합니다.
Select.labelKeyProperty name or function객체 옵션에 표시할 라벨입니다.
Select.onSearchFunction; enables search input필요한 경우 애플리케이션 필터링을 제공합니다.

미터 구조

출처
이름 / 규칙값 / 구성용도
valuenumber표시할 수량입니다. values가 지정되면 무시됩니다.
maxnumber or numeric string사용 가능한 전체 용량입니다. 백분율로 오해하지 마세요.
typebar | circle | pie | semicircle사용률 개요에는 circle을 사용합니다.
colorColor identifier값이 하나만 있어도 유효합니다.
a11yTitlestring측정 대상과 분모를 설명합니다.
sizeNamed size or CSS dimension사용 가능한 너비 안에 링을 배치합니다.
03

HPE Grommet 디자인 시스템 완벽 가이드

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

DESIGN-hpe-grommet.md

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

가이드 다운로드

HPE Grommet 디자인 시스템: Grommet 기본 테마와 HPE 테마

보라색을 HPE 토큰으로 표시하지 마세요

Grommet은 HPE와 관련된 React 프레임워크이며 자체 기본 테마를 제공합니다. 별도의 grommet-theme-hpe 패키지는 HPE 디자인 스타일을 적용하는 애플리케이션을 위해 hpe를 내보냅니다. 이 참조에서는 기본 프레임워크와 명시적으로 설정한 예시를 안내합니다. 보라색 브랜드 색상과 민트색 포커스 색상은 기본 테마에서 가져온 것이며, 현재 HPE 브랜드 팔레트를 나타내지 않습니다.

이 OpenDesign 가이드에서

지원 사양 읽기

작고 명시적인 애플리케이션 테마

설정에서는 애플리케이션 글꼴로 Arial을 지정하고 문서에 나온 기본 브랜드 및 포커스 색상을 다시 사용합니다. 그 외 모든 컴포넌트 규칙은 Grommet을 상속합니다. 실제 HPE 제품에서는 승인된 hpe 테마를 전달할 수 있습니다. 이 경우 테마 재정의로 기본값이 달라질 수 있으므로 결과에 반영된 간격과 타이포그래피를 확인하세요.

지원 사양 읽기

HPE Grommet 디자인 시스템: 중단점에 따라 테마 스케일이 달라질 수 있습니다

이름이 지정된 값은 반응형 설계의 결정 사항입니다

기본 생성기는 24픽셀에서 시작합니다. 기본 중간 가장자리 간격은 24px이지만, 작은 화면 중단점에서는 중간 간격이 12px로 바뀝니다. 따라서 반응형 패딩을 사용하는 Box는 JSX에 중간 크기가 지정되어 있어도 작아질 수 있습니다. 스케일과 중단점 재정의를 함께 확인하고, 중간 크기가 항상 24픽셀이라고 단정하지 마세요.

지원 사양 읽기

실제 레이아웃에는 Box를 사용하세요

계획 도구에서는 페이지에 세로 방향 Box를, 폼과 용량 요약에는 화면에 따라 행 또는 열로 바뀌는 Box를 사용합니다. 자식 폼은 확장할 수 있고 요약 영역은 적절한 최소 너비를 유지합니다. 작은 화면에서는 문서 순서에 맞춰 차트가 컨트롤 뒤에 배치됩니다.

지원 사양 읽기

HPE Grommet 디자인 시스템: 읽기 쉬운 기준을 의도적으로 지정하기

글꼴 크기와 줄 높이는 별도의 테마 값입니다

기본 생성기는 간격 입력값을 바탕으로 18픽셀 글꼴과 24픽셀 줄 높이를 도출합니다. 독점 브랜드 글꼴을 다운로드했다고 오해하지 않도록 예시에서는 해당 조합과 Arial을 명시적으로 사용합니다. 제목에는 Grommet Heading을, 본문에는 Text를 사용해 컴포넌트 내부 구현을 CSS에서 다시 작성하지 않고 테마가 각 역할에 맞는 값을 적용하도록 합니다.

지원 사양 읽기

HPE Grommet 디자인 시스템: 단일 제어 예약 객체

이름으로 필드를 폼에 연결합니다

Form이 폼의 통합 계약을 관리합니다. 제어 패턴에서는 value와 onChange를 호출자가 담당합니다. 각 FormField와 자식 입력 요소의 name은 해당 값의 키를 지정합니다. 예약 객체에는 name과 pool이 들어 있습니다. 용량 슬라이더는 제출 전에 실시간 다이어그램을 갱신하므로 별도의 숫자로 관리합니다.

지원 사양 읽기

예약 이름을 검증합니다

지원 사양 읽기

HPE Grommet 디자인 시스템 Select만의 이벤트 형식

문자열을 사용하면 간단한 경우를 예측하기 쉽습니다

예제 풀의 옵션은 Production과 Development입니다. 따라서 제어되는 값은 문자열입니다. 객체 옵션으로 전환한다면 labelKey를 설정하고, reduce와 함께 valueKey를 선택적으로 설정한 다음 저장된 값이 해당 설정과 일치하도록 유지하세요. Select의 onChange는 네이티브 range input 이벤트와 달리 value/option 객체를 전달합니다.

지원 사양 읽기

검색과 옵션 로딩은 애플리케이션에서 처리해야 합니다

onSearch를 전달하면 Select에 검색 필드를 표시할 수 있습니다. 이 prop을 전달한다고 해서 모든 옵션이 자동으로 필터링되는 것은 아닙니다. 검색을 닫거나 지웠을 때 원래 옵션을 복원할 수 있도록 필터링되지 않은 원본 목록을 별도로 유지하세요. 두 풀을 사용하는 이 예제에서는 의도적으로 검색 기능을 생략했습니다.

지원 사양 읽기

HPE Grommet 디자인 시스템에서 미터에는 단위와 분모가 필요합니다

설명 없는 백분율이 아니라 용량을 나타내세요

Meter에는 사용 예정량과 max=100이 전달됩니다. 이 예시용 플래너에서는 예제 풀의 기존 사용량이 35단위이며, 예약 제안량은 5~60단위입니다. 예제의 분모가 100이어서 백분율과 수치가 우연히 일치합니다. 데이터 계약이 다른 총량에서도 유지되도록 코드에는 max를 명시적으로 전달합니다.

지원 사양 읽기

차트와 텍스트를 동일한 값으로 동기화하세요

원형 표시, 사용 예정량 레이블, 잔여 단위는 모두 동일한 숫자 슬라이더 값에서 계산됩니다. 네이티브 RangeInput은 DOM 이벤트를 내보내므로 산술 연산 전에 event.target.value를 Number로 변환하세요. 그렇지 않으면 문자열에 35를 더했을 때 화면상 그럴듯하지만 잘못된 합계가 나올 수 있습니다.

지원 사양 읽기

HPE Grommet 디자인 시스템에서 문서 스크롤과 좁은 화면 레이아웃 구성

이 페이지에는 full="min"을 선택하세요

Grommet의 full=true는 자체 뷰포트와 내부 스크롤을 제어하는 애플리케이션을 위한 설정입니다. 이 플래너에는 문서가 길어질 수 있도록 full="min"을 사용합니다. 그러면 휴대전화에서 고정 높이 셸 아래에 양식과 유효성 검사 메시지가 갇히는 일을 방지할 수 있습니다.

지원 사양 읽기

Grommet 내부에서 ResponsiveContext를 읽으세요

하위 컴포넌트가 현재 컨텍스트를 읽어 좁은 화면에서는 column, 그 외에는 row를 선택합니다. 컨텍스트가 선택한 테마를 반영하도록 하위 컴포넌트를 provider로 감싸야 합니다. 사용 가능한 너비가 좁을 때 기본 레이아웃도 자연스럽게 세로 방향으로 배치됩니다.

  • 필드 레이블을 입력란 위에 배치하세요.
  • 소스 순서에서 컨트롤 뒤에 용량 요약을 배치하세요.
  • 유효성 검사 텍스트가 가려지지 않도록 동작 행에서 줄바꿈을 허용하세요.

지원 사양 읽기

HPE Grommet 디자인 시스템에서 레이블, 오류 및 측정값 연결

모든 숫자 표시의 의미를 명확히 하세요

range 컨트롤에는 항상 표시되는 레이블과 단위가 있습니다. 원형 표시는 사용 예정량과 총용량을 담은 a11yTitle을 받습니다. 인접한 텍스트에도 같은 숫자를 표시해 색이 있는 호에만 정보가 의존하지 않도록 합니다. 오류 문구에는 예약 관련 문제가 명시되며 해당 필드 옆에 표시됩니다.

지원 사양 읽기

로컬 작업의 결과를 명확히 하세요

  1. 이름을 비워 둔 채 제출해 필수 필드 오류를 확인하세요.
  2. 이름을 입력하고 풀을 선택한 다음 할당량을 조정하세요.
  3. 계획을 준비하고 로컬 스냅샷에 선택한 풀과 숫자 단위가 포함되는지 확인하세요.

지원 사양 읽기

HPE Grommet 디자인 시스템에서 완전한 Grommet 구성 마운트

프레임워크와 스타일링 peer 의존 항목 설치

클라이언트 프로젝트에 grommet, styled-components, React runtime을 설치하세요. Grommet을 마운트한 다음 ResponsiveContext를 사용하는 하위 컴포넌트, 제어되는 Form, FormField/TextInput/Select, RangeInput, Meter를 마운트합니다. 기본 레이블 스타일 버튼 동작을 명확히 유지하려면 children 대신 Button label을 사용하세요.

지원 사양 읽기

HPE Grommet 디자인 시스템 컴포넌트 예제

완전한 독립형 인터랙티브 예제

전체 문서를 index.html로 저장한 다음 브라우저에서 여세요. 기본 Grommet의 치수와 색상을 HTML/CSS로 독립적으로 해석하고 Arial 글꼴을 명시적으로 선택했습니다. 별도 HPE 테마는 사용하지 않습니다.

html
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Capacity reservation — Grommet study</title><style>*{box-sizing:border-box}body{margin:0;background:white;color:#444;font:18px/24px Arial,sans-serif}header{padding:24px 36px;border-bottom:1px solid #ddd;display:flex;gap:12px;align-items:center}.mark{width:22px;height:22px;border:4px solid #7d4cdb;border-radius:50%}main{max-width:1050px;margin:auto;padding:36px}h1{font-size:36px;line-height:42px;margin:12px 0 24px;color:#222}h2{font-size:24px;line-height:30px;margin:0 0 12px}.intro{max-width:650px;margin-bottom:36px}.layout{display:grid;grid-template-columns:minmax(0,1fr) 310px;gap:48px}label{display:block;font-weight:600;margin-bottom:12px}input,select,button{font:inherit;max-width:100%}input[type=text],select{width:100%;border:1px solid #888;border-radius:4px;background:transparent;padding:12px;color:#444}input:focus-visible,select:focus-visible,button:focus-visible{outline:3px solid #6fffb0;outline-offset:3px}.field{margin-bottom:24px}input[type=range]{width:100%;accent-color:#7d4cdb}.limits{display:flex;justify-content:space-between;font-size:14px;color:#666;margin-top:6px}button{border:2px solid #7d4cdb;border-radius:24px;background:#7d4cdb;color:white;padding:10px 24px;font-weight:600;cursor:pointer}button:hover{background:#6839c0}aside{background:#f2f2f2;padding:24px;border-radius:12px;align-self:start;text-align:center}.ring{width:192px;height:192px;border-radius:50%;background:conic-gradient(#7d4cdb var(--used),#dadada 0);margin:24px auto;display:grid;place-items:center;position:relative}.ring:before{content:'';position:absolute;inset:12px;background:#f2f2f2;border-radius:50%}.ring span{position:relative;font-size:36px;font-weight:bold}.ring small{display:block;font-size:14px;font-weight:400;line-height:20px}.legend{text-align:left;border-top:1px solid #ddd;padding-top:12px;font-size:14px}.legend div{display:flex;justify-content:space-between;margin:8px 0}.error{font-size:14px;color:#b30000;margin-top:6px}#result{background:#f2f2f2;border-left:4px solid #7d4cdb;padding:24px;margin-top:36px}footer{font-size:12px;line-height:18px;color:#666;border-top:1px solid #ddd;padding:24px 36px}@media(max-width:700px){main{padding:24px}.layout{grid-template-columns:1fr;gap:24px}h1{font-size:30px;line-height:36px}header,footer{padding:24px}.intro{margin-bottom:24px}}</style><header><span class="mark" aria-hidden="true"></span><strong>Capacity planner</strong></header><main><h1>Plan a reservation</h1><p class="intro">Explore a proposed allocation before preparing a local plan. This model contains 100 capacity units.</p><div class="layout"><form id="form" novalidate><div class="field"><label for="name">Reservation name</label><input id="name" type="text" required aria-describedby="error"><div class="error" id="error" hidden></div></div><div class="field"><label for="pool">Capacity pool</label><select id="pool"><option>Production</option><option>Development</option></select></div><div class="field"><label for="units">Requested allocation: <output id="requested">20</output> units</label><input id="units" type="range" min="5" max="60" step="5" value="20"><div class="limits"><span>5 units</span><span>60 units</span></div></div><button type="submit">Prepare plan</button><p style="font-size:14px;color:#666">No infrastructure will be provisioned.</p></form><aside><h2>Projected usage</h2><div class="ring" id="ring" style="--used:55%" role="img" aria-label="55 of 100 units projected usage"><span><output id="used">55</output><small>of 100 units</small></span></div><div class="legend"><div><span>Already used</span><strong>35</strong></div><div><span>Proposed reservation</span><strong id="proposed">20</strong></div><div><span>Remaining</span><strong id="remaining">45</strong></div></div></aside></div><section id="result" hidden><h2>Prepared local plan</h2><p id="snapshot" role="status"></p><p style="font-size:14px">This snapshot changes only when you prepare the plan again.</p></section></main><footer>Independent base Grommet HTML/CSS interpretation. Base purple/mint palette and spacing; Arial is an application font choice. This is not the separate HPE branded theme.</footer><script>
const $=id=>document.getElementById(id);$('units').oninput=()=>{const units=Number($('units').value),used=35+units;$('requested').textContent=$('proposed').textContent=units;$('used').textContent=used;$('remaining').textContent=100-used;$('ring').style.setProperty('--used',used+'%');$('ring').setAttribute('aria-label',used+' of 100 units projected usage')};$('form').onsubmit=e=>{e.preventDefault();const name=$('name').value.trim();if(name.length<3){$('error').textContent='Use at least three characters for the reservation name.';$('error').hidden=false;$('name').setAttribute('aria-invalid','true');$('name').focus();return}$('error').hidden=true;$('name').removeAttribute('aria-invalid');$('snapshot').textContent=name+' · '+$('pool').value+' · '+$('units').value+' units. Prepared in this local demonstration.';$('result').hidden=false};
</script></html>

코드 참조

  • 용량 계산에는 화면에 표시된 예제 풀을 사용합니다. 독립 실행형 레이아웃은 HTML이며, 네이티브 예제에서는 별도 HPE 테마가 아닌 기본 Grommet을 선택합니다.

전체 네이티브 구현 엔트리

셋업의 전체 구현을 집중적인 API 설명과 함께 여기에 모았습니다. 셋업에 문서화된 패키지 및 빌드 전제 조건을 따르세요.

jsx
// npm install react react-dom grommet styled-components
import React, { useContext, useState } from 'react';
import { createRoot } from 'react-dom/client';
import { Grommet, Box, Heading, Text, Form, FormField, TextInput,
 Select, RangeInput, Meter, Button, ResponsiveContext } from 'grommet';
const theme={global:{font:{family:'Arial, sans-serif',size:'18px',height:'24px'},colors:{brand:'#7D4CDB',focus:'#6FFFB0'}}};
function Planner(){
 const size=useContext(ResponsiveContext);
 const [value,setValue]=useState({name:'',pool:'Production'});
 const [units,setUnits]=useState(20),[plan,setPlan]=useState(null);
 const used=35+units;
 return <Box pad="medium" gap="medium" width={{max:'large'}} margin="auto">
 <Heading level={1} margin="none">Plan a reservation</Heading>
 <Text>Local capacity model. No infrastructure is provisioned.</Text>
 <Box direction={size==='small'?'column':'row'} gap="large">
 <Box flex><Form value={value} onChange={setValue} validate="submit" onSubmit={({value:accepted})=>setPlan({...accepted,units})}>
 <FormField name="name" htmlFor="reservation-name" label="Reservation name" required validate={name=>String(name || '').trim().length<3?'Use at least three characters':undefined}>
 <TextInput name="name" id="reservation-name"/></FormField>
 <FormField name="pool" htmlFor="pool" label="Capacity pool"><Select name="pool" id="pool" options={['Production','Development']}/></FormField>
 <Box gap="small" margin={{vertical:'medium'}}><label htmlFor="units">Requested allocation: {units} units</label>
 <RangeInput id="units" min={5} max={60} step={5} value={units} onChange={event=>setUnits(Number(event.target.value))}/></Box>
 <Button type="submit" primary label="Prepare plan"/>
 </Form></Box>
 <Box align="center" gap="small" pad="medium" background="light-2" round="small">
 <Meter type="circle" value={used} max={100} size="small" thickness="small" color="brand" a11yTitle={`${used} of 100 units projected usage`}/>
 <Text weight="bold">{used} / 100 units used</Text><Text>{100-used} units remaining</Text>
 </Box></Box>
 {plan&&<Box background="light-2" pad="medium" role="status"><Text>Local plan: {plan.name} · {plan.pool} · {plan.units} units</Text></Box>}
 </Box>
}
createRoot(document.getElementById('root')).render(<Grommet theme={theme} themeMode="light" full="min"><Planner/></Grommet>);

코드 참조

  • 루트 요소가 있는 프로젝트용 클라이언트 main.jsx입니다. 기본 Grommet에 애플리케이션 글꼴과 브랜드 재정의를 명시적으로 선언합니다. HPE 테마를 암묵적으로 적용하지 않습니다. 공식 문서에서 API을 확인했으며, 여기서는 네이티브 컴파일을 검증하지 않았습니다.

HPE 브랜드 테마로 명시적으로 전환

의도한 디자인 대상이 HPE 테마일 때만 별도 패키지를 사용하고, 설치된 릴리스의 값과 다시 대조하세요.

jsx
// npm install grommet-theme-hpe
import { Grommet } from 'grommet';
import { hpe } from 'grommet-theme-hpe';
// Wrap the Planner from the full setup example:
<Grommet theme={hpe} themeMode="light" full="min"><Planner /></Grommet>

코드 참조

  • 위 참조 표는 기본 테마를 설명하며, 이 선택적 재정의는 포함하지 않습니다.

객체형 Select 값

레이블을 표시하면서 풀 ID를 저장하세요.

jsx
<Select options={[{id:'prod',label:'Production'},{id:'dev',label:'Development'}]}
 labelKey="label" valueKey={{key:'id',reduce:true}}
 value={poolId} onChange={({value})=>setPoolId(value)} />

코드 참조

  • 호출하는 컴포넌트에서 useState로 poolId/setPoolId를 선언하세요.
  • reduce를 사용하면 저장되는 값은 객체가 아니라 ID입니다.
04

HPE Grommet 디자인 시스템 AI 에이전트 설정

구현 시작점

루트 요소가 있는 프로젝트용 클라이언트 main.jsx입니다. 기본 Grommet에 애플리케이션 글꼴과 브랜드 재정의를 명시적으로 선언합니다. HPE 테마를 암묵적으로 적용하지 않습니다. 공식 문서에서 API을 확인했으며, 여기서는 네이티브 컴파일을 검증하지 않았습니다.

jsx
// npm install react react-dom grommet styled-components
import React, { useContext, useState } from 'react';
import { createRoot } from 'react-dom/client';
import { Grommet, Box, Heading, Text, Form, FormField, TextInput,
 Select, RangeInput, Meter, Button, ResponsiveContext } from 'grommet';
const theme={global:{font:{family:'Arial, sans-serif',size:'18px',height:'24px'},colors:{brand:'#7D4CDB',focus:'#6FFFB0'}}};
function Planner(){
 const size=useContext(ResponsiveContext);
 const [value,setValue]=useState({name:'',pool:'Production'});
 const [units,setUnits]=useState(20),[plan,setPlan]=useState(null);
 const used=35+units;
 return <Box pad="medium" gap="medium" width={{max:'large'}} margin="auto">
 <Heading level={1} margin="none">Plan a reservation</Heading>
 <Text>Local capacity model. No infrastructure is provisioned.</Text>
 <Box direction={size==='small'?'column':'row'} gap="large">
 <Box flex><Form value={value} onChange={setValue} validate="submit" onSubmit={({value:accepted})=>setPlan({...accepted,units})}>
 <FormField name="name" htmlFor="reservation-name" label="Reservation name" required validate={name=>String(name || '').trim().length<3?'Use at least three characters':undefined}>
 <TextInput name="name" id="reservation-name"/></FormField>
 <FormField name="pool" htmlFor="pool" label="Capacity pool"><Select name="pool" id="pool" options={['Production','Development']}/></FormField>
 <Box gap="small" margin={{vertical:'medium'}}><label htmlFor="units">Requested allocation: {units} units</label>
 <RangeInput id="units" min={5} max={60} step={5} value={units} onChange={event=>setUnits(Number(event.target.value))}/></Box>
 <Button type="submit" primary label="Prepare plan"/>
 </Form></Box>
 <Box align="center" gap="small" pad="medium" background="light-2" round="small">
 <Meter type="circle" value={used} max={100} size="small" thickness="small" color="brand" a11yTitle={`${used} of 100 units projected usage`}/>
 <Text weight="bold">{used} / 100 units used</Text><Text>{100-used} units remaining</Text>
 </Box></Box>
 {plan&&<Box background="light-2" pad="medium" role="status"><Text>Local plan: {plan.name} · {plan.pool} · {plan.units} units</Text></Box>}
 </Box>
}
createRoot(document.getElementById('root')).render(<Grommet theme={theme} themeMode="light" full="min"><Planner/></Grommet>);

프로젝트를 위한 프롬프트

에이전트 프롬프트
제공된 기본 Grommet 예약 플래너를 제어되는 Form, 이름이 지정된 FormField, Select, RangeInput, max를 명시한 Meter로 구현하세요. 기본 테마 값은 grommet-theme-hpe와 구분하세요. 슬라이더 값을 숫자로 변환하고, 단위를 표시하며, 이름을 검증하고, 로컬 계획 스냅샷만 생성하세요.
05

HPE Grommet 디자인 시스템 소스 및 범위

기본 Grommet을 독립적으로 구현하기 위한 참조입니다. HPE 브랜드 테마 적용은 별도로 설명합니다. 용량 수치는 가상의 로컬 데이터이며, 인프라 지표나 프로비저닝을 나타내지 않습니다.