PropertyPanel

Data Display

Figma Design 패널 스타일의 속성 편집 레이아웃.

Usage

선택한 객체의 여러 속성을 섹션·행으로 나눠 편집하는 사이드 패널 좌표·크기처럼 여러 칸의 숫자 입력을 한 행에 묶어야 하는 편집 UI

import

import

import { PropertyPanel } from '@mildang/design-system/unofficial/PropertyPanel';

PropertyPanel 하나만 가져오면 PropertyPanel.Root · PropertyPanel.Section · PropertyPanel.Item · PropertyPanel.EmptyHint · PropertyPanel.Row · PropertyPanel.Header 를 그 아래에서 쓸 수 있다.

예제를 복사해 쓸 때 필요한 준비

@mildang/icons 를 따로 설치한다. DS 패키지에 아이콘 컴포넌트가 포함되지 않는다.

@mildang/styled-system 은 이 저장소에서 Panda 가 생성하는 산출물이다. 저장소 안에서는 turbo run ship 이후 쓸 수 있고, 패키지 소비자는 자기 Panda 산출물이나 다른 레이아웃 수단으로 바꿔야 한다.

Anatomy

tsx

import { PropertyPanel } from '@mildang/design-system/unofficial/PropertyPanel';

export default function Example() {
  return (
    <PropertyPanel>
      <PropertyPanel.Header />
      <PropertyPanel.Section>
        <PropertyPanel.Row />
        <PropertyPanel.Item />
        <PropertyPanel.EmptyHint />
      </PropertyPanel.Section>
    </PropertyPanel>
  );
}

부품

필수 여부

반복

위치

PropertyPanel.Root

필수

PropertyPanel.Header

선택

PropertyPanel.Root 안 최상단에 둔다.

PropertyPanel.Section

필수

여러 개 가능

PropertyPanel.Root 안에 둔다.

PropertyPanel.Row

선택

여러 개 가능

PropertyPanel.Section 안에 둔다.

PropertyPanel.Item

선택

여러 개 가능

PropertyPanel.Section 안에 둔다.

PropertyPanel.EmptyHint

선택

PropertyPanel.Section 안, Item 대신 둔다.

  • Section 안에는 Item 또는 EmptyHint 중 상황에 맞는 쪽을 둔다 — 비어 있으면 EmptyHint, 편집 가능한 속성이 있으면 Item·Row다.

API Reference

PropertyPanel Props

Prop

Type

Default

children

ReactNode

지정 안 함

variant

"plain" | "card"

plain

PropertyPanel.Header

패널 제목·뒤로가기·trailing 액션을 담는 상단 헤더다.

Prop

Type

Default

title
필수

ReactNode

지정 안 함

caption

ReactNode

지정 안 함

onBack

{ label: string; onClick: () => void; }

지정 안 함

trailing

ReactNode

지정 안 함

PropertyPanel.Section

관련 속성을 묶는 구획이다. 제목을 주면 섹션 헤더가 함께 렌더된다.

Prop

Type

Default

actions

ReactNode

지정 안 함

children

ReactNode

지정 안 함

title

ReactNode

지정 안 함

PropertyPanel.Row

아이콘·제목·caption·meta 를 한 줄로 보여주는 목록형 행이다.

Prop

Type

Default

title
필수

ReactNode

지정 안 함

caption

ReactNode

지정 안 함

icon

ReactNode

지정 안 함

meta

ReactNode

지정 안 함

selected

boolean

지정 안 함

PropertyPanel.Item

라벨과 편집 필드(들)를 묶는 한 속성 단위다. children 으로 필드를 2~3칸 나란히 배치할 수 있다.

Prop

Type

Default

children

ReactNode

지정 안 함

label

ReactNode

지정 안 함

PropertyPanel.EmptyHint

Item 이 없는 빈 섹션에 보여주는 안내 문구다.

Prop

Type

Default

children

ReactNode

지정 안 함

예제

기본 사용

정렬·위치·회전 등 여러 Item을 Section으로 묶은 전체 패널 구성이다.

코드

import { useState } from 'react';
import { PropertyPanel } from '@mildang/design-system/unofficial/PropertyPanel';
import { SegmentedControl as SegmentedControl } from '@mildang/design-system/SegmentedControl';
import FormatAlignLeft from '@mildang/icons/react/editor/format-align-left';
import { VisuallyHidden } from '@mildang/styled-system/jsx';
import FormatAlignCenter from '@mildang/icons/react/editor/format-align-center';
import FormatAlignRight from '@mildang/icons/react/editor/format-align-right';
import FormatAlignTop from '@mildang/icons/react/editor/format-align-top';
import FormatAlignVertically from '@mildang/icons/react/editor/format-align-vertically';
import FormatAlignBottom from '@mildang/icons/react/editor/format-align-bottom';
import { Input } from '@mildang/design-system/Input';
import Refresh from '@mildang/icons/react/refresh';
import ImageHorizontalAlign from '@mildang/icons/react/editor/image_horizontal_align';
import ImageVerticalAlign from '@mildang/icons/react/editor/image_vertical_align';
import ImageLeftAlign from '@mildang/icons/react/editor/image_left_align';
import ImageMiddleAlign from '@mildang/icons/react/editor/image_middle_align';
import ImageRightAlign from '@mildang/icons/react/editor/image_right_align';
import { Select, createSelectCollection } from '@mildang/design-system/Select';
import { IconButton } from '@mildang/design-system/IconButton';
import Link from '@mildang/icons/react/link';
import Unlink from '@mildang/icons/react/unlink';
import { Slider } from '@mildang/design-system/unofficial/Slider';
import Eye from '@mildang/icons/react/eye';
import { Text } from '@mildang/design-system/Text';
import Filter from '@mildang/icons/react/filter';
import DragHandle from '@mildang/icons/react/drag-handle';
import Add from '@mildang/icons/react/add';
import { ColorField } from '@mildang/design-system/unofficial/ColorField';
import Remove from '@mildang/icons/react/remove';
import { css } from '@mildang/styled-system/css';

/** 우측 사이드바 폭(260px)으로 실제 사용 맥락을 재현하는 컨테이너 */
const sidebar = css({
  borderLeftWidth: '1px',
  borderLeftStyle: 'solid',
  borderLeftColor: 'neutral.border.low',
});

const basicSidebarSize = { width: 500, height: 1100 } as const;

const opacityRowStyle = css({
  display: 'grid',
  gridTemplateColumns: '96px minmax(0, 1fr) auto',
  alignItems: 'center',
  gap: '8',
});

const fillFieldStyle = css({ gridColumn: '1 / 3' });

const twoColumnActionRowStyle = css({
  display: 'grid',
  gridTemplateColumns: 'minmax(0, 1fr) minmax(0, 1fr) auto',
  alignItems: 'center',
  gap: '8',
});

const horizontalResizeCollection = createSelectCollection({
  items: [
    { value: 'fill', label: '채우기 (496)' },
    { value: 'hug', label: '내용 맞춤 (48)' },
    { value: 'fixed', label: '고정 (320)' },
  ],
});

const verticalResizeCollection = createSelectCollection({
  items: [
    { value: 'hug', label: '내용 맞춤 (48)' },
    { value: 'fill', label: '채우기 (180)' },
    { value: 'fixed', label: '고정 (180)' },
  ],
});

const blendModeCollection = createSelectCollection({
  items: [
    { value: 'pass-through', label: '통과' },
    { value: 'normal', label: '일반' },
    { value: 'multiply', label: '곱하기' },
  ],
});

const typographyStyleCollection = createSelectCollection({
  items: [
    { value: 'body', label: 'UI/본문' },
    { value: 'title', label: 'UI/제목' },
    { value: 'caption', label: 'UI/캡션' },
  ],
});

function BasicStory() {
  const [horizontalAlign, setHorizontalAlign] = useState('left');
  const [verticalAlign, setVerticalAlign] = useState('top');
  const [textAlign, setTextAlign] = useState('left');
  const [textVerticalAlign, setTextVerticalAlign] = useState('top');
  const [resizeMode, setResizeMode] = useState('auto');
  const [horizontalResize, setHorizontalResize] = useState(['fill']);
  const [verticalResize, setVerticalResize] = useState(['hug']);
  const [blendMode, setBlendMode] = useState(['pass-through']);
  const [typographyStyle, setTypographyStyle] = useState(['body']);
  const [x, setX] = useState('0');
  const [y, setY] = useState('20');
  const [rotation, setRotation] = useState('0');
  const [opacity, setOpacity] = useState(75);
  const [fill, setFill] = useState('neutral.text.low');

  return (
    <div className={sidebar} style={basicSidebarSize}>
      <PropertyPanel.Root aria-label="속성 패널">
        <PropertyPanel.Section aria-label="변형" pt="16">
          <PropertyPanel.Item label="정렬">
            <SegmentedControl
              size="sm"
              fullWidth
              value={horizontalAlign}
              onValueChange={setHorizontalAlign}
              aria-label="가로 정렬"
            >
              <SegmentedControl.Item value="left" startIcon={<FormatAlignLeft />}>
                <VisuallyHidden>왼쪽</VisuallyHidden>
              </SegmentedControl.Item>
              <SegmentedControl.Item value="center" startIcon={<FormatAlignCenter />}>
                <VisuallyHidden>가운데</VisuallyHidden>
              </SegmentedControl.Item>
              <SegmentedControl.Item value="right" startIcon={<FormatAlignRight />}>
                <VisuallyHidden>오른쪽</VisuallyHidden>
              </SegmentedControl.Item>
            </SegmentedControl>
            <SegmentedControl
              size="sm"
              fullWidth
              value={verticalAlign}
              onValueChange={setVerticalAlign}
              aria-label="세로 정렬"
            >
              <SegmentedControl.Item value="top" startIcon={<FormatAlignTop />}>
                <VisuallyHidden>위</VisuallyHidden>
              </SegmentedControl.Item>
              <SegmentedControl.Item value="middle" startIcon={<FormatAlignVertically />}>
                <VisuallyHidden>가운데</VisuallyHidden>
              </SegmentedControl.Item>
              <SegmentedControl.Item value="bottom" startIcon={<FormatAlignBottom />}>
                <VisuallyHidden>아래</VisuallyHidden>
              </SegmentedControl.Item>
            </SegmentedControl>
          </PropertyPanel.Item>

          <PropertyPanel.Item label="위치">
            <Input
              size="sm"
              fullWidth
              startAdornment="X"
              type="number"
              value={x}
              onChange={(e) => setX(e.target.value)}
              aria-label="X 좌표"
            />
            <Input
              size="sm"
              fullWidth
              startAdornment="Y"
              type="number"
              value={y}
              onChange={(e) => setY(e.target.value)}
              aria-label="Y 좌표"
            />
          </PropertyPanel.Item>

          <PropertyPanel.Item label="회전">
            <Input
              size="sm"
              fullWidth
              endAdornment="°"
              type="number"
              value={rotation}
              onChange={(e) => setRotation(e.target.value)}
              aria-label="회전"
            />
            <SegmentedControl size="sm" fullWidth disabled aria-label="뒤집기">
              <SegmentedControl.Item value="rotate" startIcon={<Refresh />}>
                <VisuallyHidden>90도 회전</VisuallyHidden>
              </SegmentedControl.Item>
              <SegmentedControl.Item value="horizontal" startIcon={<ImageHorizontalAlign />}>
                <VisuallyHidden>가로 뒤집기</VisuallyHidden>
              </SegmentedControl.Item>
              <SegmentedControl.Item value="vertical" startIcon={<ImageVerticalAlign />}>
                <VisuallyHidden>세로 뒤집기</VisuallyHidden>
              </SegmentedControl.Item>
            </SegmentedControl>
          </PropertyPanel.Item>
        </PropertyPanel.Section>

        <PropertyPanel.Section title="레이아웃">
          <PropertyPanel.Item label="크기 조절">
            <SegmentedControl
              size="sm"
              fullWidth
              value={resizeMode}
              onValueChange={setResizeMode}
              aria-label="크기 조절 방식"
            >
              <SegmentedControl.Item value="fixed" startIcon={<ImageLeftAlign />}>
                <VisuallyHidden>고정</VisuallyHidden>
              </SegmentedControl.Item>
              <SegmentedControl.Item value="auto" startIcon={<ImageMiddleAlign />}>
                <VisuallyHidden>자동</VisuallyHidden>
              </SegmentedControl.Item>
              <SegmentedControl.Item value="fill" startIcon={<ImageRightAlign />}>
                <VisuallyHidden>채우기</VisuallyHidden>
              </SegmentedControl.Item>
            </SegmentedControl>
          </PropertyPanel.Item>

          <PropertyPanel.Item label="크기 조절">
            <div className={twoColumnActionRowStyle}>
              <Select
                size="sm"
                fullWidth
                startAdornment="W"
                hideClearButton
                collection={horizontalResizeCollection}
                value={horizontalResize}
                onValueChange={(details) => setHorizontalResize(details.value)}
              >
                {horizontalResizeCollection.items.map((item) => (
                  <Select.Option key={item.value} item={item} />
                ))}
              </Select>
              <Select
                size="sm"
                fullWidth
                startAdornment="H"
                hideClearButton
                collection={verticalResizeCollection}
                value={verticalResize}
                onValueChange={(details) => setVerticalResize(details.value)}
              >
                {verticalResizeCollection.items.map((item) => (
                  <Select.Option key={item.value} item={item} />
                ))}
              </Select>
              <IconButton size="xs" variant="tertiary" aria-label="가로세로 비율 고정">
                <Link />
              </IconButton>
            </div>
          </PropertyPanel.Item>
        </PropertyPanel.Section>

        <PropertyPanel.Section
          title="모양"
          actions={
            <IconButton size="xs" variant="tertiary" aria-label="모양 속성 연결 해제">
              <Unlink />
            </IconButton>
          }
        >
          <PropertyPanel.Item label="불투명도">
            <div className={opacityRowStyle}>
              <Input
                size="sm"
                fullWidth
                endAdornment="%"
                type="number"
                min={0}
                max={100}
                value={String(opacity)}
                onChange={(event) => setOpacity(Math.min(100, Math.max(0, Number(event.target.value))))}
                aria-label="불투명도 숫자"
              />
              <Slider
                value={opacity}
                min={0}
                max={100}
                step={1}
                onValueChange={setOpacity}
                formatValue={(value) => `${value}%`}
                aria-label="불투명도"
                tooltip
              />
              <IconButton size="xs" variant="tertiary" aria-label="레이어 표시">
                <Eye />
              </IconButton>
            </div>
          </PropertyPanel.Item>

          <PropertyPanel.Item label="혼합 모드">
            <Select
              size="sm"
              fullWidth
              hideClearButton
              collection={blendModeCollection}
              value={blendMode}
              onValueChange={(details) => setBlendMode(details.value)}
            >
              {blendModeCollection.items.map((item) => (
                <Select.Option key={item.value} item={item} />
              ))}
            </Select>
          </PropertyPanel.Item>
        </PropertyPanel.Section>

        <PropertyPanel.Section
          title="타이포그래피"
          actions={
            <IconButton size="xs" variant="tertiary" aria-label="타이포그래피 초기화">
              <Refresh />
            </IconButton>
          }
        >
          <Select
            size="md"
            fullWidth
            hideClearButton
            aria-label="텍스트 스타일"
            startAdornment={
              <Text as="span" variant="title-2xl">
                Ag
              </Text>
            }
            collection={typographyStyleCollection}
            value={typographyStyle}
            onValueChange={(details) => setTypographyStyle(details.value)}
          >
            {typographyStyleCollection.items.map((item) => (
              <Select.Option key={item.value} item={item} />
            ))}
          </Select>

          <PropertyPanel.Item label="정렬">
            <div className={twoColumnActionRowStyle}>
              <SegmentedControl
                size="sm"
                fullWidth
                value={textAlign}
                onValueChange={setTextAlign}
                aria-label="텍스트 가로 정렬"
              >
                <SegmentedControl.Item value="left" startIcon={<FormatAlignLeft />}>
                  <VisuallyHidden>왼쪽</VisuallyHidden>
                </SegmentedControl.Item>
                <SegmentedControl.Item value="center" startIcon={<FormatAlignCenter />}>
                  <VisuallyHidden>가운데</VisuallyHidden>
                </SegmentedControl.Item>
                <SegmentedControl.Item value="right" startIcon={<FormatAlignRight />}>
                  <VisuallyHidden>오른쪽</VisuallyHidden>
                </SegmentedControl.Item>
              </SegmentedControl>
              <SegmentedControl
                size="sm"
                fullWidth
                value={textVerticalAlign}
                onValueChange={setTextVerticalAlign}
                aria-label="텍스트 세로 정렬"
              >
                <SegmentedControl.Item value="top" startIcon={<FormatAlignTop />}>
                  <VisuallyHidden>위</VisuallyHidden>
                </SegmentedControl.Item>
                <SegmentedControl.Item value="middle" startIcon={<FormatAlignVertically />}>
                  <VisuallyHidden>가운데</VisuallyHidden>
                </SegmentedControl.Item>
                <SegmentedControl.Item value="bottom" startIcon={<FormatAlignBottom />}>
                  <VisuallyHidden>아래</VisuallyHidden>
                </SegmentedControl.Item>
              </SegmentedControl>
              <IconButton size="xs" variant="tertiary" aria-label="타이포그래피 세부 설정">
                <Filter />
              </IconButton>
            </div>
          </PropertyPanel.Item>
        </PropertyPanel.Section>

        <PropertyPanel.Section
          title="채우기"
          actions={
            <>
              <IconButton size="xs" variant="tertiary" aria-label="채우기 순서 변경">
                <DragHandle />
              </IconButton>
              <IconButton size="xs" variant="tertiary" aria-label="채우기 추가">
                <Add />
              </IconButton>
            </>
          }
        >
          <PropertyPanel.Item>
            <div className={opacityRowStyle}>
              <div className={fillFieldStyle}>
                <ColorField
                  value={fill}
                  onChange={setFill}
                  label="비활성 요소 색상"
                  swatches={[
                    'neutral.text.low',
                    'neutral.text.base',
                    'brand.surface.base',
                    'positive.surface.base',
                  ]}
                />
              </div>
              <IconButton size="xs" variant="tertiary" aria-label="채우기 제거">
                <Remove />
              </IconButton>
            </div>
          </PropertyPanel.Item>
        </PropertyPanel.Section>

        <PropertyPanel.Section
          title="테두리"
          actions={
            <IconButton size="xs" variant="tertiary" aria-label="테두리 추가">
              <Add />
            </IconButton>
          }
        />

        <PropertyPanel.Section
          title="효과"
          actions={
            <IconButton size="xs" variant="tertiary" aria-label="효과 추가">
              <Add />
            </IconButton>
          }
        />

        <PropertyPanel.Section
          title="내보내기"
          actions={
            <IconButton size="xs" variant="tertiary" aria-label="내보내기 설정 추가">
              <Add />
            </IconButton>
          }
        />
      </PropertyPanel.Root>
    </div>
  );
}

const PropertyPanelBasicExample = () => <BasicStory />;

export default PropertyPanelBasicExample;

2칸 필드

x·y 좌표처럼 두 입력을 한 행에 나란히 배치하는 구성이다.

코드

import { useState } from 'react';
import { PropertyPanel } from '@mildang/design-system/unofficial/PropertyPanel';
import { Input } from '@mildang/design-system/Input';
import { css } from '@mildang/styled-system/css';

/** 우측 사이드바 폭(260px)으로 실제 사용 맥락을 재현하는 컨테이너 */
const sidebar = css({
  borderLeftWidth: '1px',
  borderLeftStyle: 'solid',
  borderLeftColor: 'neutral.border.low',
});

/** Panda 토큰 없는 데모 전용 사이즈는 inline style로 (스토리 스캐폴딩) */
const sidebarSize = { width: 260, height: 620 } as const;

function TwoColumnFieldsStory() {
  const [x, setX] = useState('120');
  const [y, setY] = useState('64');

  return (
    <div className={sidebar} style={sidebarSize}>
      <PropertyPanel.Root aria-label="2칸 좌표 입력">
        <PropertyPanel.Section title="위치">
          <PropertyPanel.Item label="좌표">
            <Input
              size="sm"
              fullWidth
              startAdornment="X"
              type="number"
              value={x}
              onChange={(e) => setX(e.target.value)}
              aria-label="X 좌표"
            />
            <Input
              size="sm"
              fullWidth
              startAdornment="Y"
              type="number"
              value={y}
              onChange={(e) => setY(e.target.value)}
              aria-label="Y 좌표"
            />
          </PropertyPanel.Item>
        </PropertyPanel.Section>
      </PropertyPanel.Root>
    </div>
  );
}

const PropertyPanelTwoColumnFieldsExample = () => <TwoColumnFieldsStory />;

export default PropertyPanelTwoColumnFieldsExample;

3칸 필드

x·y·z 3차원 좌표처럼 세 입력을 한 행에 배치하는 구성이다.

코드

import { PropertyPanel } from '@mildang/design-system/unofficial/PropertyPanel';
import { Input } from '@mildang/design-system/Input';
import { css } from '@mildang/styled-system/css';

/** 우측 사이드바 폭(260px)으로 실제 사용 맥락을 재현하는 컨테이너 */
const sidebar = css({
  borderLeftWidth: '1px',
  borderLeftStyle: 'solid',
  borderLeftColor: 'neutral.border.low',
});

/** Panda 토큰 없는 데모 전용 사이즈는 inline style로 (스토리 스캐폴딩) */
const sidebarSize = { width: 260, height: 620 } as const;

const PropertyPanelThreeColumnFieldsExample = () => (
    <div className={sidebar} style={sidebarSize}>
      <PropertyPanel.Root aria-label="3칸 좌표 입력">
        <PropertyPanel.Section title="위치">
          <PropertyPanel.Item label="3차원 좌표">
            <Input size="sm" fullWidth startAdornment="X" defaultValue="120" aria-label="X 좌표" />
            <Input size="sm" fullWidth startAdornment="Y" defaultValue="64" aria-label="Y 좌표" />
            <Input size="sm" fullWidth startAdornment="Z" defaultValue="0" aria-label="Z 좌표" />
          </PropertyPanel.Item>
        </PropertyPanel.Section>
      </PropertyPanel.Root>
    </div>
  );

export default PropertyPanelThreeColumnFieldsExample;

빈 섹션

Item 없이 EmptyHint만 보여주는 빈 섹션 상태다.

코드

import { PropertyPanel } from '@mildang/design-system/unofficial/PropertyPanel';
import { IconButton } from '@mildang/design-system/IconButton';
import Add from '@mildang/icons/react/add';
import { css } from '@mildang/styled-system/css';

/** 우측 사이드바 폭(260px)으로 실제 사용 맥락을 재현하는 컨테이너 */
const sidebar = css({
  borderLeftWidth: '1px',
  borderLeftStyle: 'solid',
  borderLeftColor: 'neutral.border.low',
});

/** Panda 토큰 없는 데모 전용 사이즈는 inline style로 (스토리 스캐폴딩) */
const sidebarSize = { width: 260, height: 620 } as const;

const PropertyPanelEmptySectionExample = () => (
    <div className={sidebar} style={sidebarSize}>
      <PropertyPanel.Root aria-label="빈 섹션">
        <PropertyPanel.Section
          title="채우기"
          actions={
            <IconButton size="xs" variant="tertiary" aria-label="채우기 추가">
              <Add />
            </IconButton>
          }
        >
          <PropertyPanel.EmptyHint>+ 버튼으로 채우기를 추가하세요</PropertyPanel.EmptyHint>
        </PropertyPanel.Section>
      </PropertyPanel.Root>
    </div>
  );

export default PropertyPanelEmptySectionExample;

비활성 필드

잠긴 좌표처럼 편집이 불가능한 필드를 보여주는 형태다.

코드

import { PropertyPanel } from '@mildang/design-system/unofficial/PropertyPanel';
import { Input } from '@mildang/design-system/Input';
import MoreHoriz from '@mildang/icons/react/more-horiz';
import { css } from '@mildang/styled-system/css';

/** 우측 사이드바 폭(260px)으로 실제 사용 맥락을 재현하는 컨테이너 */
const sidebar = css({
  borderLeftWidth: '1px',
  borderLeftStyle: 'solid',
  borderLeftColor: 'neutral.border.low',
});

/** Panda 토큰 없는 데모 전용 사이즈는 inline style로 (스토리 스캐폴딩) */
const sidebarSize = { width: 260, height: 620 } as const;

const PropertyPanelDisabledFieldExample = () => (
    <div className={sidebar} style={sidebarSize}>
      <PropertyPanel.Root aria-label="비활성 입력">
        <PropertyPanel.Section title="위치">
          <PropertyPanel.Item label="좌표 (잠김)">
            <Input size="sm" fullWidth startAdornment="X" defaultValue="120" disabled aria-label="X 좌표" />
            <Input size="sm" fullWidth startAdornment="Y" defaultValue="64" disabled aria-label="Y 좌표" />
          </PropertyPanel.Item>
          <PropertyPanel.Item label="더보기">
            <Input
              size="sm"
              fullWidth
              startAdornment="#"
              defaultValue="편집 불가"
              disabled
              endAdornment={<MoreHoriz />}
              aria-label="읽기 전용 값"
            />
          </PropertyPanel.Item>
        </PropertyPanel.Section>
      </PropertyPanel.Root>
    </div>
  );

export default PropertyPanelDisabledFieldExample;