Skip to content

Commit

Permalink
feat(FieldBox): FieldBox 컴포넌트에 TopAddon을 추가합니다. (#223)
Browse files Browse the repository at this point in the history
* feat: Add FieldBox/TopAddon

* cs

* fix: TopAddon 을 활용한 방식으로 문서 수정,
  • Loading branch information
Brokyeom authored Dec 2, 2024
1 parent b9761fa commit 17897dc
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changeset/violet-ducks-juggle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sopt-makers/ui': minor
---

Add FieldBox/TopAddon
57 changes: 50 additions & 7 deletions apps/docs/src/stories/FieldBox.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
FieldBoxProps,
FieldBoxLabelProps,
FieldBoxBottomAddonProps,
FieldBoxLabel,
TextField,
TextArea,
Radio,
Expand All @@ -22,7 +21,16 @@ type FieldBoxStoryProps = FieldBoxProps & FieldBoxLabelProps & FieldBoxBottomAdd
* #### 예시 코드
* ```tsx
* <FieldBox>
* topAddon={<FieldBox.Label label='안녕?' description='디스크립션' required />}
* topAddon={
* <FieldBox.TopAddon
* leftAddon={<FieldBox.Label label={args.label} description={args.description} required={args.required} />}
* rightAddon={
* <Button variant='outlined' size='sm' disabled>
* 미리보기
* </Button>
* }
* />
* }
* bottomAddon={
* <FieldBox.BottomAddon
* leftAddon={<div style={{ color: colors.white }}>레프트애드온</div>}
Expand Down Expand Up @@ -63,7 +71,14 @@ export const WithTextField: StoryObj<FieldBoxStoryProps> = {
return (
<FieldBox
topAddon={
<FieldBoxLabel label={args.label} description={args.description} required={args.required}></FieldBoxLabel>
<FieldBox.TopAddon
leftAddon={<FieldBox.Label label={args.label} description={args.description} required={args.required} />}
rightAddon={
<Button variant='outlined' size='sm' disabled>
미리보기
</Button>
}
/>
}
bottomAddon={
<FieldBox.BottomAddon
Expand All @@ -88,7 +103,14 @@ export const WithTextArea: StoryObj<FieldBoxStoryProps> = {
return (
<FieldBox
topAddon={
<FieldBoxLabel label={args.label} description={args.description} required={args.required}></FieldBoxLabel>
<FieldBox.TopAddon
leftAddon={<FieldBox.Label label={args.label} description={args.description} required={args.required} />}
rightAddon={
<Button variant='outlined' size='sm' disabled>
미리보기
</Button>
}
/>
}
bottomAddon={
<FieldBox.BottomAddon
Expand All @@ -114,7 +136,14 @@ export const WithRadio: StoryObj<FieldBoxStoryProps> = {
return (
<FieldBox
topAddon={
<FieldBoxLabel label={args.label} description={args.description} required={args.required}></FieldBoxLabel>
<FieldBox.TopAddon
leftAddon={<FieldBox.Label label={args.label} description={args.description} required={args.required} />}
rightAddon={
<Button variant='outlined' size='sm' disabled>
미리보기
</Button>
}
/>
}
bottomAddon={
<FieldBox.BottomAddon
Expand Down Expand Up @@ -146,7 +175,14 @@ export const WithCheckBox: StoryObj<FieldBoxStoryProps> = {
return (
<FieldBox
topAddon={
<FieldBoxLabel label={args.label} description={args.description} required={args.required}></FieldBoxLabel>
<FieldBox.TopAddon
leftAddon={<FieldBox.Label label={args.label} description={args.description} required={args.required} />}
rightAddon={
<Button variant='outlined' size='sm' disabled>
미리보기
</Button>
}
/>
}
bottomAddon={
<FieldBox.BottomAddon
Expand Down Expand Up @@ -180,7 +216,14 @@ export const WithChip: StoryObj<FieldBoxStoryProps> = {
return (
<FieldBox
topAddon={
<FieldBoxLabel label={args.label} description={args.description} required={args.required}></FieldBoxLabel>
<FieldBox.TopAddon
leftAddon={<FieldBox.Label label={args.label} description={args.description} required={args.required} />}
rightAddon={
<Button variant='outlined' size='sm' disabled>
미리보기
</Button>
}
/>
}
bottomAddon={
<FieldBox.BottomAddon
Expand Down
7 changes: 4 additions & 3 deletions packages/ui/FieldBox/FieldBox.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { forwardRef } from 'react';
import type { HTMLAttributes, ReactNode } from 'react';
import { BottomAddon, FieldBoxErrorMessage, FieldBoxLabel } from './components';
import { TopAddon, BottomAddon, FieldBoxErrorMessage, FieldBoxLabel } from './components';

export interface FieldBoxProps extends HTMLAttributes<HTMLDivElement> {
topAddon?: ReactNode;
Expand All @@ -13,8 +13,8 @@ const FieldBoxImpl = forwardRef<HTMLDivElement, FieldBoxProps>((props, forwarded
return (
<div ref={forwardedRef} {...restProps}>
{topAddon}
<div>{children}</div>
<div>{bottomAddon}</div>
{children}
{bottomAddon}
</div>
);
});
Expand All @@ -23,6 +23,7 @@ FieldBoxImpl.displayName = 'FieldBoxImpl';

export const FieldBox = Object.assign(FieldBoxImpl, {
Label: FieldBoxLabel,
TopAddon,
BottomAddon,
ErrorMessage: FieldBoxErrorMessage,
});
12 changes: 7 additions & 5 deletions packages/ui/FieldBox/components/Label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ export const FieldBoxLabel = forwardRef<HTMLDivElement, FieldBoxLabelProps>((pro
return (
<div aria-label={label} aria-required={required} ref={forwardedRef}>
<label className={TopAddonLabelStyle}>
<span>
{label}
{required ? <span className={requiredMarkStyle}>*</span> : null}
</span>
<p className={TopAddonDescriptionStyle}>{description}</p>
{label ? (
<span>
{label}
{required ? <span className={requiredMarkStyle}>*</span> : null}
</span>
) : null}
{description ? <p className={TopAddonDescriptionStyle}>{description}</p> : null}
</label>
</div>
);
Expand Down
21 changes: 21 additions & 0 deletions packages/ui/FieldBox/components/TopAddon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { HTMLAttributes, ReactNode } from 'react';
import { forwardRef } from 'react';
import { topAddonContainerStyle } from '../style.css';

export interface FieldBoxTopAddonProps extends HTMLAttributes<HTMLDivElement> {
leftAddon?: ReactNode;
rightAddon?: ReactNode;
}

export const TopAddon = forwardRef<HTMLDivElement, FieldBoxTopAddonProps>((props, forwardedRef) => {
const { leftAddon, rightAddon } = props;

return (
<div className={topAddonContainerStyle} ref={forwardedRef}>
{leftAddon}
{rightAddon}
</div>
);
});

TopAddon.displayName = 'TopAddon';
1 change: 1 addition & 0 deletions packages/ui/FieldBox/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './Label';
export * from './TopAddon';
export * from './BottomAddon';
export * from './ErrorMessage';
9 changes: 8 additions & 1 deletion packages/ui/FieldBox/style.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import theme from '../theme.css';
export const TopAddonLabelStyle = style({
...theme.fontsObject.LABEL_3_14_SB,
display: 'flex',
gap: '8px',
flexDirection: 'column',
textAlign: 'left',
color: theme.colors.white,
Expand All @@ -12,14 +13,20 @@ export const TopAddonLabelStyle = style({
export const TopAddonDescriptionStyle = style({
...theme.fontsObject.LABEL_4_12_SB,
color: theme.colors.gray300,
marginBottom: '8px',
});

export const requiredMarkStyle = style({
color: theme.colors.secondary,
marginLeft: '4px',
});

export const topAddonContainerStyle = style({
marginBottom: '8px',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
});

export const bottomAddonContainerStyle = style({
marginTop: '8px',
display: 'flex',
Expand Down
10 changes: 6 additions & 4 deletions packages/ui/Input/TextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => {
return (
<FieldBox
bottomAddon={
<FieldBox.BottomAddon
leftAddon={hasError() && errorMessage ? <FieldBox.ErrorMessage message={errorMessage} /> : null}
rightAddon={bottomAddon}
/>
(hasError() && errorMessage) || bottomAddon ? (
<FieldBox.BottomAddon
leftAddon={hasError() && errorMessage ? <FieldBox.ErrorMessage message={errorMessage} /> : null}
rightAddon={bottomAddon}
/>
) : null
}
className={className}
ref={ref}
Expand Down

0 comments on commit 17897dc

Please sign in to comment.