본문으로 건너뛰기

PlButtonGroup

함께 묶이는 버튼 한 줄입니다. 이웃과 맞닿는 모서리를 각지게 깎고, variant size color density elevation disabled를 묶음 단위로 한 번만 지정합니다.

React
tsx
import { PlButton, PlButtonGroup } from 'plass-ui';

<PlButtonGroup variant="glass" color="secondary">
  <PlButton>Day</PlButton>
  <PlButton>Week</PlButton>
  <PlButton>Month</PlButton>
</PlButtonGroup>;
dart
import 'package:plass_ui/plass_ui.dart';

PlButtonGroup(
  variant: PlassVariant.glass,
  color: PlassColor.secondary,
  children: <Widget>[
    PlButton(onPressed: showDay, child: const Text('Day')),
    PlButton(onPressed: showWeek, child: const Text('Week')),
    PlButton(onPressed: showMonth, child: const Text('Month')),
  ],
);

Props

Prop타입기본값설명
variant공통'solid' | 'glass' | 'ghost'그룹 전체의 재질. 지정하지 않으면 각 버튼의 기본값(solid)을 씁니다
size공통'xs' | 'sm' | 'md' | 'lg' | 'xl'그룹 전체의 높이와 타입 스케일. 한 버튼만 크기가 다른 그룹을 막는 것이 이 컴포넌트의 절반입니다
color공통'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info'그룹 전체의 색 역할. 버튼이 스스로 정한 color가 우선합니다
density공통'default' | 'compact'그룹 전체의 가로 패딩
elevation공통0 | 1 | 2 | 3그룹 전체의 그림자 깊이
orientation공통'horizontal' | 'vertical''horizontal'버튼이 늘어서는 방향. vertical은 동등한 액션을 쌓은 메뉴입니다
disabledboolean그룹의 모든 버튼을 한 번에 비활성화합니다
fullWidthbooleanfalse컨테이너 너비만큼 늘리고 버튼끼리 너비를 똑같이 나눠 갖습니다
childrenReactNode버튼들. 진짜 PlButton으로 남습니다
Prop타입기본값설명
children * List<Widget>버튼들, 순서대로. 하나의 child가 아니라 목록인 건 그룹이 양 끝이 누구인지 알아야 모서리를 정할 수 있기 때문입니다
variant공통PlassVariant?그룹 전체의 재질. 지정하지 않으면 각 버튼의 기본값(solid)을 씁니다
size공통PlassSize?그룹 전체의 높이와 타입 스케일. 한 버튼만 크기가 다른 그룹을 막는 것이 이 컴포넌트의 절반입니다
color공통PlassColor?그룹 전체의 색 역할. 버튼이 스스로 정한 color가 우선합니다
density공통PlassDensity?그룹 전체의 가로 패딩
elevation공통int?그룹 전체의 그림자 깊이
orientation공통PlassOrientationPlassOrientation.horizontal버튼이 늘어서는 방향. vertical은 동등한 액션을 쌓은 메뉴입니다
disabledbool?그룹의 모든 버튼을 한 번에 비활성화합니다
fullWidthboolfalse컨테이너 너비만큼 늘리고 버튼끼리 너비를 똑같이 나눠 갖습니다

나머지 <div> 속성은 그대로 통과합니다. color는 위 표의 color와 이름이 겹쳐 제외했습니다.

children이 하나의 child가 아니라 목록인 것은 Flutter의 관례이기도 하지만, 그것만은 아닙니다. 그룹은 어느 멤버가 양 끝에 있는지 알아야 어느 모서리를 깎을지 정할 수 있고, 불투명한 subtree 하나만 받은 widget은 그걸 알 수 없습니다.

축들은 PlButtonPlIconButton에서도 nullable입니다. PlassVariant?, PlassSize?, int?. Dart에는 기본값과 실제로 넘어온 값을 구분할 방법이 없기 때문입니다. 거기서 null이 버튼은 말하지 않았다 는 뜻이고, 그래야 그룹이 대신 답할 수 있습니다.

다섯 개의 스타일 축에는 자기 기본값이 없습니다. 그룹이 지정하지 않은 축은 각 버튼이 자기 기본값으로 돌아가는 축이라, 아무 prop도 주지 않은 그룹은 모서리 말고는 아무것도 바꾸지 않습니다. 버튼이 직접 지정한 축은 그룹보다 우선합니다. secondary 액션 줄에 danger 버튼 하나가 섞이는 것은 실제로 있는 일입니다.

공유 축(variant size color density elevation)이 라이브러리 전체에서 무엇을 뜻하는지는 prop 규약에 있습니다.

PlButtonGroup과 PlSegmentedButton

버튼은 진짜 PlButton으로 남고, 그 무엇도 대체되지 않습니다. 그룹이 하는 일은 모서리 넷을 깎고 prop 여섯 개를 물려주는 것뿐입니다. 선택 상태를 관리하지 않고, value도 없으며, 어느 버튼도 고른 것 이 되지 않습니다.

여럿 중 하나를 고르는 컨트롤(뷰 전환, 모드 토글)은 PlSegmentedButton입니다. 그쪽이 roving focus와 radiogroup semantics까지 갖춘 진짜 그 컨트롤입니다.

Examples

variant

이음매를 처리해야 하는 것은 glass 하나뿐입니다. 테두리를 그리는 유일한 variant이기도 해서, glass 키 둘이 맞닿으면 hairline이 두 겹으로 겹쳐 페이지의 다른 모든 선보다 두 배로 무거워집니다. 그래서 뒤쪽을 1px 당겨 두 키가 선 하나를 나눠 쓰게 합니다.

solid는 그렇게 하면 안 됩니다. 겹칠 테두리가 없고, 겹치면 한 키의 그러데이션이 다음 키의 시작을 덮습니다.

React

size

한 번만 지정하니 버튼 하나만 크기가 어긋날 수 없습니다. 높이는 라이브러리의 컨트롤 사다리 그대로입니다.

React

orientation

vertical은 줄을 세로로 쌓고, 옆면 대신 위아래를 각지게 깎습니다. 동등한 액션을 쌓은 메뉴에 쓰고, 기본값이 horizontal인 것은 툴바가 그 모양이기 때문입니다.

React

fullWidth

그룹을 컨테이너 너비만큼 늘리고 버튼끼리 너비를 똑같이 나눠 갖게 합니다. 카드 아래 액션 세 개가 서로 다른 길이의 단어 셋이 아니라 똑같은 삼등분이 됩니다.

React

Accessibility

  • 그룹은 role="group"입니다. 줄 자체에 이름이 필요하면 aria-label을 주세요. 이것이 세 개 놓인 바는 이름 없는 그룹 세 개입니다.
  • role="toolbar"아니고 roving focus도 없습니다. 그 role은 키보드 동작에 대한 약속이고, 여기서는 버튼 하나하나가 각자의 focus 정거장입니다. 평범한 <button> semantics가 이미 말하고 있는 그대로입니다.
  • 모서리는 logical property로 깎으므로, RTL에서는 첫 버튼이 오른쪽에 오고 깎이는 면도 따라갑니다.
  • 버튼마다 stacking context가 생겨, border box 바깥에 그려지는 focus ring이 뒤에 오는 이웃에 덮이지 않습니다.
  • 그룹의 disabled는 안의 모든 버튼을 끕니다. 버튼이 직접 지정한 disabled는 그대로 우선합니다.

React 빌드와 다른 점

ReactFlutter이유
임의의 childrenchildren: List<Widget>어느 모서리를 깎을지 정하려면 그룹이 양 끝이 누구인지 알아야 합니다.
glass 키를 1px 당겨 hairline 둘을 겹칩니다이웃과 맞닿는 면을 아예 그리지 않습니다Flutter에는 음수 margin이 없고(EdgeInsets가 non-negative를 assert합니다), 대안은 Transform인데 이 라이브러리는 컨트롤에 transform을 걸지 않습니다. 둘 다 이음매마다 hairline 하나라는 같은 결과에 닿습니다.
축을 그냥 빼면 됩니다같은 파라미터가 nullable입니다Dart는 기본값과 넘어온 값을 구분하지 못하므로, 말하지 않았다 를 타입이 담을 수 있는 값으로 만들어야 합니다.
className, style, 네이티브 속성통과시킬 class 목록도 style 속성도 없습니다.

Released under the MIT License