Layout

Box

Box 컴포넌트는 Lynx에서 가장 기초적인 레이아웃 표면을 구성하는 컴포넌트입니다.

Installation

npm install @seed-design/lynx-react @seed-design/lynx-css

Usage

import { Box, Text } from "@seed-design/lynx-react";

export function App() {
  return (
    <Box bg="bg.brandWeak" borderColor="stroke.brandWeak" borderWidth={1} borderRadius="r3" p="x4">
      <Text textStyle="t5Bold" color="fg.brand">
        Box
      </Text>
    </Box>
  );
}

Box는 Lynx 네이티브 <view>를 렌더링합니다. bg, p, borderRadius 같은 스타일 prop은 SEED 토큰을 직접 object style 값으로 변환해 적용합니다.

Lynx에서는 웹 Box처럼 CSS variable을 클래스에 주입하는 방식이 아니라, 지원 가능한 스타일 prop만 직접 계산해 <view style={...}>에 적용합니다.

Box는 편의를 위한 primitive입니다. 많은 항목을 반복 렌더링하는 화면에서는 primitive 컴포넌트와 object style 계산 비용이 누적될 수 있으므로, 앱 코드에서는 native <view>/<text>에 Tailwind utility className을 직접 사용하는 방식을 우선 고려하세요. 패키지 컴포넌트 내부에서는 native tag와 recipe className을 사용하고, inline style은 safe area처럼 런타임 값이 필요한 경우에만 제한적으로 사용합니다.

Props

Prop

Type

bindtouchstart?(() => void) | undefined
bindtouchend?(() => void) | undefined
bindtouchcancel?(() => void) | undefined
bg?(string & {}) | ScopedColorPalette | ScopedColorBg | ScopedColorBanner | undefined
background?(string & {}) | ScopedColorPalette | ScopedColorBg | ScopedColorBanner | undefined
color?(string & {}) | ScopedColorFg | ScopedColorPalette | undefined
borderColor?(string & {}) | ScopedColorPalette | ScopedColorStroke | undefined
borderWidth?0 | 1 | (string & {}) | undefined
borderTopWidth?0 | 1 | (string & {}) | undefined
borderRightWidth?0 | 1 | (string & {}) | undefined
borderBottomWidth?0 | 1 | (string & {}) | undefined
borderLeftWidth?0 | 1 | (string & {}) | undefined
borderRadius?0 | (string & {}) | "full" | "r0_5" | "r1" | "r1_5" | "r2" | "r2_5" | "r3" | "r3_5" | "r4" | "r5" | "r6" | undefined
borderTopLeftRadius?0 | (string & {}) | "full" | "r0_5" | "r1" | "r1_5" | "r2" | "r2_5" | "r3" | "r3_5" | "r4" | "r5" | "r6" | undefined
borderTopRightRadius?0 | (string & {}) | "r0_5" | "r1" | "r1_5" | "r2" | "r2_5" | "r3" | "r3_5" | "r4" | "r5" | "r6" | "full" | undefined
borderBottomRightRadius?0 | (string & {}) | "r0_5" | "r1" | "r1_5" | "r2" | "r2_5" | "r3" | "r3_5" | "r4" | "r5" | "r6" | "full" | undefined
borderBottomLeftRadius?0 | (string & {}) | "r0_5" | "r1" | "r1_5" | "r2" | "r2_5" | "r3" | "r3_5" | "r4" | "r5" | "r6" | "full" | undefined
width?(string & {}) | "full" | Dimension | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | undefined
minWidth?(string & {}) | "full" | Dimension | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | undefined
maxWidth?(string & {}) | "full" | Dimension | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | undefined
height?(string & {}) | "full" | Dimension | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | undefined
minHeight?(string & {}) | "full" | Dimension | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | undefined
maxHeight?(string & {}) | "full" | Dimension | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | undefined
top?0 | (string & {}) | undefined
left?0 | (string & {}) | undefined
right?0 | (string & {}) | undefined
bottom?0 | (string & {}) | undefined
padding?0 | (string & {}) | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | Dimension | undefined
p?0 | (string & {}) | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | Dimension | undefined
paddingX?0 | (string & {}) | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | Dimension | undefined
px?0 | (string & {}) | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | Dimension | undefined
paddingY?0 | (string & {}) | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | Dimension | undefined
py?0 | (string & {}) | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | Dimension | undefined
paddingTop?0 | (string & {}) | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | Dimension | "safeArea" | undefined
pt?0 | (string & {}) | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | Dimension | "safeArea" | undefined
paddingRight?0 | (string & {}) | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | Dimension | undefined
pr?0 | (string & {}) | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | Dimension | undefined
paddingBottom?0 | (string & {}) | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | Dimension | "safeArea" | undefined
pb?0 | (string & {}) | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | Dimension | "safeArea" | undefined
paddingLeft?0 | (string & {}) | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | Dimension | undefined
pl?0 | (string & {}) | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | Dimension | undefined
display?"none" | (string & {}) | "flex" | undefined
position?(string & {}) | "relative" | "absolute" | "fixed" | undefined
overflowX?(string & {}) | "hidden" | "visible" | undefined
overflowY?(string & {}) | "hidden" | "visible" | undefined
zIndex?Property.ZIndex | undefined
flexGrow?boolean | Property.FlexGrow | undefined
flexShrink?boolean | Property.FlexShrink | undefined
flexDirection?"row" | (string & {}) | "column" | "rowReverse" | "columnReverse" | undefined
flexWrap?boolean | "nowrap" | "wrap" | undefined
justifyContent?(string & {}) | "center" | "flexStart" | "flexEnd" | "spaceBetween" | "spaceAround" | undefined
justifySelf?Property.JustifySelf | undefined
alignItems?(string & {}) | "center" | "stretch" | "flexStart" | "flexEnd" | undefined
alignContent?(string & {}) | "center" | "stretch" | "flexStart" | "flexEnd" | undefined
alignSelf?(string & {}) | "center" | "stretch" | "flexStart" | "flexEnd" | undefined
gap?0 | (string & {}) | "spacingX.betweenChips" | "spacingX.globalGutter" | "spacingY.componentDefault" | "spacingY.navToTitle" | "spacingY.screenBottom" | "spacingY.betweenText" | Dimension | undefined
style?CSSProperties | undefined
children?React.ReactNode
className?string | undefined
bindtap?EventHandler<BaseTouchEvent<Target>> | undefined
main-thread:bindtap?EventHandler<BaseTouchEvent<Element>> | undefined

Style Props

현재 Box에서 여는 스타일 prop은 Lynx에서 안정적으로 검증한 범위로 제한합니다.

분류Props
색상bg, background, color, borderColor
테두리borderWidth, borderTopWidth, borderRightWidth, borderBottomWidth, borderLeftWidth, borderRadius와 corner radius props
크기width, minWidth, maxWidth, height, minHeight, maxHeight
패딩p, px, py, pt, pr, pb, pl과 longhand padding props
Flexdisplay, flexDirection, flexWrap, flexGrow, flexShrink, alignItems, justifyContent, gap
배치position, top, right, bottom, left, zIndex, overflowX, overflowY

명시적인 style prop은 마지막에 merge되므로, 필요한 경우 계산된 스타일을 덮어쓸 수 있습니다.

<Box p="x3" style={{ paddingLeft: "24px" }}>
  <Text>paddingLeft만 직접 override</Text>
</Box>

웹 버전과의 차이

Lynx Box는 React Box와 다음과 같은 차이가 있습니다.

  • as, asChild를 지원하지 않습니다. Lynx 컴파일러 제약 때문에 네이티브 <view>를 컴포넌트 파일 안에서 직접 렌더링합니다.
  • bgGradient, boxShadow, bleedX, bleedY, unstable_transform처럼 아직 Lynx에서 검증하지 않은 StyleProps는 열지 않습니다.
  • margin 계열 shorthand는 제공하지 않습니다. 레이아웃 간격은 VStack / HStackgap 또는 명시적인 style을 사용합니다.
  • 이벤트는 웹의 onClick 대신 Lynx의 bindtap 계열 prop을 사용합니다.

Last updated on

On this page