[TButtonTab] 공통 컴포넌트 - TButtonTab (탭바) 추가
This commit is contained in:
@@ -0,0 +1,66 @@
|
|||||||
|
import React, { useCallback } from "react";
|
||||||
|
|
||||||
|
import classNames from "classnames";
|
||||||
|
|
||||||
|
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
|
||||||
|
|
||||||
|
import css from "./TButtonTab.module.less";
|
||||||
|
import TButtonTabItem from "./TButtonTabItem";
|
||||||
|
|
||||||
|
const Container = SpotlightContainerDecorator(
|
||||||
|
{ enterTo: "last-focused" },
|
||||||
|
"div"
|
||||||
|
);
|
||||||
|
|
||||||
|
export const LIST_TYPE = {
|
||||||
|
large: "large",
|
||||||
|
medium: "medium",
|
||||||
|
small: "small",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const RIGHT_BUTTON_TYPE = {
|
||||||
|
sort: "sort",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function TButtonTab({
|
||||||
|
className,
|
||||||
|
selectedIndex,
|
||||||
|
onItemClick,
|
||||||
|
contents = [],
|
||||||
|
noMarquee = false,
|
||||||
|
listType = LIST_TYPE.medium,
|
||||||
|
spotlightId,
|
||||||
|
...rest
|
||||||
|
}) {
|
||||||
|
const onClick = useCallback(
|
||||||
|
(index) => (e) => {
|
||||||
|
if (onItemClick) {
|
||||||
|
onItemClick({ index, e });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[selectedIndex]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container
|
||||||
|
className={classNames(css.tabs, css[listType], className)}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{contents.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<TButtonTabItem
|
||||||
|
key={`buttonTabItem ${index}`}
|
||||||
|
selected={index === selectedIndex}
|
||||||
|
onClick={onClick(index)}
|
||||||
|
index={index}
|
||||||
|
selectedTabIndex={selectedIndex}
|
||||||
|
noMarquee={noMarquee}
|
||||||
|
listType={listType}
|
||||||
|
>
|
||||||
|
{item}
|
||||||
|
</TButtonTabItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
@import "../../style/CommonStyle.module.less";
|
||||||
|
@import "../../style/utils.module.less";
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
.size(@w: 1680px, @h: 67px);
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
.size(@w: 100%, @h: 1px);
|
||||||
|
background-color: @COLOR_DARK_RED;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
import React, { useCallback, useRef, useState } from "react";
|
||||||
|
|
||||||
|
import classNames from "classnames";
|
||||||
|
import compose from "ramda/src/compose";
|
||||||
|
|
||||||
|
import { Job } from "@enact/core/util";
|
||||||
|
import Marquee, { MarqueeController } from "@enact/sandstone/Marquee";
|
||||||
|
import Spottable from "@enact/spotlight/Spottable";
|
||||||
|
|
||||||
|
import * as Config from "../../utils/Config";
|
||||||
|
import { convertNewlinesToBr } from "../../utils/helperMethods";
|
||||||
|
import css from "./TButtonTabItem.module.less";
|
||||||
|
|
||||||
|
const SpottableComponent = Spottable("div");
|
||||||
|
|
||||||
|
const ItemBase = ({
|
||||||
|
panelInfo,
|
||||||
|
selected,
|
||||||
|
onClick,
|
||||||
|
index,
|
||||||
|
selectedTabIndex,
|
||||||
|
spotlightDisabled = false,
|
||||||
|
noMarquee,
|
||||||
|
children,
|
||||||
|
listType,
|
||||||
|
...rest
|
||||||
|
}) => {
|
||||||
|
const [pressed, setPressed] = useState(false);
|
||||||
|
const [blur, setBlur] = useState(true);
|
||||||
|
|
||||||
|
const _onClick = useCallback(
|
||||||
|
(e) => {
|
||||||
|
if (onClick) {
|
||||||
|
onClick(e);
|
||||||
|
setPressed(true);
|
||||||
|
clearPressedJob.current.start();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[onClick]
|
||||||
|
);
|
||||||
|
|
||||||
|
const clearPressedJob = useRef(
|
||||||
|
new Job((func) => {
|
||||||
|
setPressed(false);
|
||||||
|
setTimeout(func, Config.TBUTTON_PRESS_DELAY);
|
||||||
|
}, Config.TBUTTON_PRESS_DELAY)
|
||||||
|
);
|
||||||
|
|
||||||
|
const _onBlur = useCallback(() => {
|
||||||
|
setPressed(false);
|
||||||
|
clearPressedJob.current.stop();
|
||||||
|
setBlur(true);
|
||||||
|
}, [pressed]);
|
||||||
|
|
||||||
|
const _onFocus = useCallback(() => {
|
||||||
|
setBlur(false);
|
||||||
|
}, [blur]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SpottableComponent
|
||||||
|
{...rest}
|
||||||
|
className={classNames(
|
||||||
|
css.tItem,
|
||||||
|
selected && css.selected,
|
||||||
|
pressed && css.pressed,
|
||||||
|
css[listType]
|
||||||
|
)}
|
||||||
|
onClick={_onClick}
|
||||||
|
spotlightDisabled={spotlightDisabled}
|
||||||
|
spotlightId={`tab-${selectedTabIndex}`}
|
||||||
|
>
|
||||||
|
{noMarquee ? (
|
||||||
|
<div className={css.title}>{convertNewlinesToBr(children)}</div>
|
||||||
|
) : (
|
||||||
|
<Marquee
|
||||||
|
className={css.title}
|
||||||
|
alignment={"center"}
|
||||||
|
marqueeOn={!blur ? "focus" : undefined}
|
||||||
|
onFocus={_onFocus}
|
||||||
|
onBlur={_onBlur}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Marquee>
|
||||||
|
)}
|
||||||
|
</SpottableComponent>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ImageItemDecorator = compose(
|
||||||
|
MarqueeController({ mmarqueeOnFocus: true })
|
||||||
|
);
|
||||||
|
|
||||||
|
const TButtonTabItem = ImageItemDecorator(ItemBase);
|
||||||
|
|
||||||
|
export default TButtonTabItem;
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
@import "../../style/CommonStyle.module.less";
|
||||||
|
@import "../../style/utils.module.less";
|
||||||
|
|
||||||
|
@BORDER_WIDTH: 1px;
|
||||||
|
|
||||||
|
.tItem {
|
||||||
|
min-width: 100px;
|
||||||
|
max-width: 500px;
|
||||||
|
height: calc(100% - @BORDER_WIDTH);
|
||||||
|
background-color: @COLOR_WHITE;
|
||||||
|
border-top-right-radius: 12px;
|
||||||
|
border-top-left-radius: 12px;
|
||||||
|
border: 1px solid @COLOR_GRAY02;
|
||||||
|
border-bottom: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0 12px;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
.font(@fontFamily: @baseFontBold, @fontSize: 24px);
|
||||||
|
color: @COLOR_GRAY03;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
background-color: @COLOR_DARK_RED;
|
||||||
|
border-color: @COLOR_DARK_RED;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: @COLOR_WHITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-within {
|
||||||
|
background-color: @PRIMARY_COLOR_RED;
|
||||||
|
border-color: @PRIMARY_COLOR_RED;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: @COLOR_WHITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.medium {
|
||||||
|
min-width: 330px;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user