Skip to content

Commit

Permalink
Merge pull request #5 from travelmakers/LH-355/badge-tag
Browse files Browse the repository at this point in the history
LH-355/badge-tag
  • Loading branch information
baegofda authored Apr 3, 2023
2 parents 5e4986d + 24ac83d commit 3334578
Show file tree
Hide file tree
Showing 27 changed files with 1,009 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ export const AccordionItem = ({
{header}
<Icon
className={cx(classes.icon)}
type={"control"}
src={"IcAngleDown"}
width={ACCORDION_ICON_SIZE[type]}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import {
createStyles,
CSSObject,
TmTheme,
} from "@travelmakers-design-v2/styles";
import { DotBadgeSize, DotBadgeType, Props } from "./DotBadge";

const getFontSize = (
theme: TmTheme,
type: DotBadgeType,
size: DotBadgeSize<DotBadgeType>
) => {
if (type === "bullet") return;

switch (size) {
case "small":
return theme.typography.caption;
case "medium":
return theme.typography.body3;
case "large":
return theme.typography.body2;
default:
break;
}
};

const getBaseStyle = (theme: TmTheme, type: DotBadgeType): CSSObject => {
switch (type) {
case "text":
return {
display: "flex",
alignItems: "center",
justifyContent: "center",
fontWeight: 700,
borderRadius: "6px",
};
case "number":
return {
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
padding: `0 ${theme.spacing.spacing10}`,
borderRadius: theme.radius.radius100,
};
case "bullet":
return {
borderRadius: theme.radius.radius100,
};
default:
break;
}
};

const getStyle = (
theme: TmTheme,
type: DotBadgeType,
size: DotBadgeSize<DotBadgeType>
) => {
const sizeMap: Record<
DotBadgeType,
Record<DotBadgeSize<DotBadgeType>, CSSObject>
> = {
text: {
small: {
width: "16px",
height: "16px",
},
medium: {
width: "20px",
height: "20px",
},
large: {
width: "24px",
height: "24px",
},
xLarge: {},
},
number: {
small: {
height: "16px",
},
medium: {
height: "20px",
},
large: {
height: "24px",
},
xLarge: {},
},
bullet: {
small: {
width: "8px",
height: "8px",
},
medium: {
width: "16px",
height: "16px",
},
large: {
width: "20px",
height: "20px",
},
xLarge: {
width: "24px",
height: "24px",
},
},
};

return { ...sizeMap[type][size], ...getBaseStyle(theme, type) };
};

export default createStyles(
(theme, { type, size }: Pick<Props<DotBadgeType>, "type" | "size">) => {
const { colors } = theme;

return {
badge: {
color: colors.onError,
backgroundColor: colors.error,
...getStyle(theme, type, size),
...getFontSize(theme, type, size),
},
};
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import {
ClassNames,
PolymorphicComponentProps,
PolymorphicRef,
TmComponentProps,
} from "@travelmakers-design-v2/styles";
import { forwardRef, useEffect } from "react";
import { View } from "../../View";
import useStyles from "./DotBadge.style";

export type DotBadgeStylesNames = ClassNames<typeof useStyles>;

export type DotBadgeType = "text" | "number" | "bullet";
export type DotBadgeNormalSize = "small" | "medium" | "large";
export type DotBadgeBulletSize = DotBadgeNormalSize | "xLarge";
export type DotBadgeSize<T> = T extends "bullet"
? DotBadgeBulletSize
: DotBadgeNormalSize;

export interface Props<T extends DotBadgeType> {
type: T;
size: DotBadgeSize<T>;
label?: string | number;
}

export interface SharedDotBadgeProps
extends Props<DotBadgeType>,
TmComponentProps<DotBadgeStylesNames> {}

export type DotBadgeProps<C extends React.ElementType> =
PolymorphicComponentProps<C, SharedDotBadgeProps>;

type DotBadgeComponent = <C extends React.ElementType = "div">(
props: DotBadgeProps<C>
) => React.ReactElement;

export const DotBadge: DotBadgeComponent & {
displayName?: string;
} = forwardRef(
<C extends React.ElementType = "div">(
{ type, size, className, component, label, ...props }: DotBadgeProps<C>,
ref: PolymorphicRef<C>
) => {
useEffect(() => {
if (type !== "bullet" && size === "xLarge")
console.error(
'"xLarge" size는 type이 "bullet"의 경우에만 사용이 가능합니다.'
);
}, [type, size]);

const { classes, cx } = useStyles({ type, size });
const content = () => {
if (!label && type === "text") return "N";
if (!label && type === "number") return 0;

return label;
};

return (
<View<React.ElementType>
component={component || "div"}
ref={ref}
className={cx(classes.badge, className)}
{...props}
>
{content()}
</View>
);
}
);

DotBadge.displayName = "DotBadge";
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { DotBadge } from "./DotBadge";
export type { DotBadgeProps } from "./DotBadge";
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createStyles } from "@travelmakers-design-v2/styles";

export default createStyles((theme) => {
return {
root: {
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
color: theme.colors.primary3,
columnGap: "3px",
...theme.typography.body3,
},
vertical: {
width: "1px",
height: "10px",
backgroundColor: theme.colors.primary3,
},
};
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import {
ClassNames,
PolymorphicComponentProps,
PolymorphicRef,
TmComponentProps,
} from "@travelmakers-design-v2/styles";
import { forwardRef } from "react";
import { Icon } from "../..//Icon";
import { View } from "../../View";
import useStyles from "./GradeBadge.style";

export type GradeBadgeStylesNames = ClassNames<typeof useStyles>;

export type GradeBadgeType = "grade" | "minihotel" | "residence";

export interface Props {
type: GradeBadgeType;
grade: number;
hotelType?: string;
}
export interface SharedGradeBadgeProps
extends Props,
TmComponentProps<GradeBadgeStylesNames> {}

export type GradeBadgeProps<C extends React.ElementType> =
PolymorphicComponentProps<C, SharedGradeBadgeProps>;

type GradeBadgeComponent = <C extends React.ElementType = "div">(
props: GradeBadgeProps<C>
) => React.ReactElement;

export const GradeBadge: GradeBadgeComponent & {
displayName?: string;
} = forwardRef(
<C extends React.ElementType = "div">(
{ type, grade, hotelType, className, ...props }: GradeBadgeProps<C>,
ref: PolymorphicRef<C>
) => {
const { classes, cx } = useStyles();

const content = () => {
if (type === "grade") {
return (
<>
<Icon src={"IcStar"} width={16} height={16} />
{`${grade}성급`}
<div className={classes.vertical} />
{hotelType ?? "호텔"}
</>
);
}

if (type === "minihotel") {
return (
<>
<Icon src={"IcHotelTypeMini"} width={16} height={16} />
<div className={classes.vertical} />
{hotelType ?? "미니호텔"}
</>
);
}

if (type === "residence") {
return (
<>
<Icon src={"IcHotelTypeResidence"} width={16} height={16} />
<div className={classes.vertical} />
{hotelType ?? "레지던스"}
</>
);
}
};

return (
<View<React.ElementType>
component={"div"}
ref={ref}
className={cx(classes.root, className)}
{...props}
>
{content()}
</View>
);
}
);

GradeBadge.displayName = "GradeBadge";
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { GradeBadge } from "./GradeBadge";
export type { GradeBadgeProps } from "./GradeBadge";
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { TmTheme, createStyles } from "@travelmakers-design-v2/styles";
import { Props } from "./NewBadge";

const NEWBADGE_SIZE = {
small: "28px",
medium: "34px",
};

export default createStyles((theme: TmTheme, { type }: Props) => {
return {
root: {
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
height: NEWBADGE_SIZE[type],
padding: `0 ${theme.spacing.spacing30}`,
backgroundColor: theme.colors.secondary,
},
};
});
Loading

0 comments on commit 3334578

Please sign in to comment.