Button
누르는 동작을 담는다.
import { Button, IconButton, ButtonGroup, ButtonLink } from "@nui-kit/react";
// 서브패스로 좁힐 때
import { Button } from "@nui-kit/react/button";
import "@nui-kit/react/styles/button.css"; // 온디맨드일 때기본이 전체 너비다
Button 은 width: 100% 다. 모바일 폼을 전제로 한 기본값이라 아래 예제에서도 한 줄을 모두 차지한다. 너비를 제한하려면 바깥 컨테이너로 감싸거나 ButtonGroup 을 쓴다.
컨테이너로 너비를 제한한 예
색과 변형
색이 아니라 역할이 이름이다. 화면의 주 행동에는 primary, 그보다 덜 중요한 행동에는 secondary, 되돌릴 수 없는 삭제나 탈퇴에는 danger, 확인이 필요한 진행에는 warning 을 쓴다. 손을 올리면 한 단계, 누르면 두 단계 진해진다.
neutral | primary | secondary | danger | warning | |
|---|---|---|---|---|---|
solid | |||||
line | |||||
text |
<Button variant="line" color="danger">삭제</Button>variant × color 15조합
warning 만 글자가 어둡다. 노랑 배경에 흰 글자는 대비가 크게 미달한다.크기
large56pxmedium48pxsmall40px<Button size="large">라벨</Button>size: large | medium(기본) | small
모양
square기본round양끝이 반원<Button shape="round" color="primary">라벨</Button>shape: square(기본) | round
variant="text" 는 크기와 모양 옵션이 없다. 타입이 막는다 — size 와 shape 가 never 로 선언되어 있다.아이콘
icon prop 으로 라벨 앞에 넣는다.
icon + largeicon + mediumicon + small<Button icon={<DelIcon />}>삭제</Button>아이콘 크기는 버튼 크기를 따라간다
로딩
isLoading 이면 아이콘 자리에 스피너가 돌고 클릭·Enter·폼 제출이 막히며 aria-busy 가 붙는다. 라벨은 그대로 보이고 스크린리더에는 라벨 뒤에 loadingLabel(기본 "처리 중")이 붙는다. 색은 바뀌지 않고 포커스도 남는다 — disabled 가 아니다.
role="status" 영역에 놓여, 폼에서 Enter 로 제출해 포커스가 입력창에 있을 때도 로딩 시작이 읽힌다. 버튼 안 의 live 영역은 보조기술이 이름 변경으로 처리해 무시하기 때문이다.완료는 알리지 않는다. 버튼은 결과를 모른다 —
isLoading 이 내려간 것이 성공인지 실패인지 알 수 없다. 결과는 Toast 나 에러 메시지로 알린다.solid + isLoadingline + isLoadingtext + isLoadingicon + isLoading스피너가 아이콘 자리를 대신한다small + isLoading스피너도 16pxdisabled + isLoading색·커서는 disabled, 스피너는 남는다<Button isLoading>저장</Button>isLoading — 세 변형, 아이콘 유무
onClick 호출 0회
<Button isLoading={isSaving} onClick={save}>저장</Button>누르면 2초간 로딩 — 그동안 다시 눌러도 onClick 이 늘지 않는다
submit 호출 0회
<form onSubmit={submit}>
<Textfield … />
<Button type="submit" isLoading={isSaving}>제출</Button>
</form>type=submit — 로딩 중에는 입력창에서 Enter 를 눌러도 제출되지 않는다
비활성
solid + disabledline + disabledtext + disabled<Button disabled>라벨</Button>disabled — 세 변형 모두 대응한다
IconButton
아이콘만 담는 정사각 버튼이다. aria-label 을 반드시 준다. 없으면 스크린리더가 읽을 것이 없다. variant 는 solid 와 line 둘뿐이다.
large56pxmedium48pxsmall40pxdisabledisLoading아이콘 자리에 스피너. 정사각 그대로<IconButton aria-label="삭제"><DelIcon /></IconButton>크기 3 × 변형 2 + disabled + isLoading
ButtonGroup
기본은 균등 분할이다. shouldAutoWidth 를 주면 그 항목만 내용 폭이 된다.
균등 분할 — 기본
shouldAutoWidth — 왼쪽만 내용 폭
ButtonLink
생김새는 Button 과 같다. 누르는 대신 이동한다. next/link 를 쓰는 유일한 컴포넌트라 next 가 optional peer 다. 이 컴포넌트를 쓰지 않으면 설치할 필요가 없다.
커스터마이징
색은 컴포넌트별로 열지 않는다. 배경과 글자는 짝이라 배경만 바꾸면 대비가 깨지는데 화면에 드러나지 않는다. 버튼 하나의 색을 바꾸려면 className 을, 화면 전체를 바꾸려면 브랜드 프리셋을 쓴다.
치수는 크기 옵션마다 이름이 따로 있다. 하나로 두면 값을 넣는 순간 세 크기가 전부 같아진다.
large 만 높이를 바꾼다 — medium 은 그대로다
| 컴포넌트 | 변수 | 기본값 | 비고 |
|---|---|---|---|
| Button · IconButton · ButtonLink | --nui-button--border-width | var(--nui-border-width-1) | — |
| --nui-button--lg-height | var(--nui-size-field) | 크기 large | |
| --nui-button--lg-padding-x | var(--nui-space-6) | 크기 large | |
| --nui-button--md-height | var(--nui-size-control-xl) | 크기 medium (기본) | |
| --nui-button--md-padding-x | var(--nui-space-6) | 크기 medium (기본) | |
| --nui-button--min-width | 7.5rem | — | |
| --nui-button--radius | var(--nui-radius-1_5) | — | |
| --nui-button--round-radius | var(--nui-radius-full) | 크기 round | |
| --nui-button--sm-height | var(--nui-size-control-lg) | 크기 small | |
| --nui-button--sm-padding-x | var(--nui-space-4) | 크기 small |
API
Button
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
children * | ReactNode | — | — |
className | string | undefined | — | — |
color | "neutral" | "primary" | "secondary" | "danger" | "warning" | undefined | "neutral" | — |
icon | ReactNode | — | — |
isLoading | boolean | false | 요청 처리 중. 스피너를 보이고 클릭을 무시하며 `aria-busy` 를 붙인다 |
loadingLabel | string | "처리 중" | 로딩 중 스크린리더 안내. 소비자의 어휘·언어로 바꿀 수 있어야 한다 (a11y.md §9) |
shape | ButtonShape | undefined | "square" | — |
size | ButtonSize | undefined | "medium" | — |
variant | "solid" | "line" | "text" | undefined | "solid" | — |
ButtonProps 에서 자동 생성됨 (components/Button/Button.tsx). 표준 DOM 속성 285개는 그대로 전달되며 표에서 생략했다.
IconButton
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
children * | ReactNode | — | — |
aria-label | string | undefined | — | — |
aria-labelledby | string | undefined | — | — |
className | string | undefined | — | — |
color | "neutral" | "primary" | "secondary" | "danger" | "warning" | undefined | "neutral" | — |
isLoading | boolean | false | 요청 처리 중. 스피너를 보이고 클릭을 무시하며 `aria-busy` 를 붙인다 |
loadingLabel | string | "처리 중" | 로딩 중 스크린리더 안내. 소비자의 어휘·언어로 바꿀 수 있어야 한다 (a11y.md §9) |
shape | ButtonShape | undefined | — | — |
size | ButtonSize | undefined | "medium" | — |
variant | IconButtonVariant | "solid" | — |
IconButtonProps 에서 자동 생성됨 (components/Button/IconButton.tsx). 표준 DOM 속성 283개는 그대로 전달되며 표에서 생략했다.
ButtonGroup
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
children * | ReactNode | — | — |
className | string | — | — |
ButtonGroupProps 에서 자동 생성됨 (components/Button/ButtonGroup.tsx).
ButtonGroup.Item
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
children * | ReactNode | — | — |
className | string | — | — |
shouldAutoWidth | boolean | false | — |
ButtonGroupItemProps 에서 자동 생성됨 (components/Button/ButtonGroup.tsx).
ButtonLink
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
children * | ReactNode | — | — |
className | string | — | — |
color | "neutral" | "primary" | "secondary" | "danger" | "warning" | undefined | "neutral" | — |
icon | ReactNode | — | — |
shape | ButtonShape | undefined | — | — |
size | ButtonSize | undefined | "medium" | — |
variant | "solid" | "line" | "text" | undefined | "solid" | — |
ButtonLinkProps 에서 자동 생성됨 (components/Button/ButtonLink.tsx). 표준 DOM 속성 295개는 그대로 전달되며 표에서 생략했다.