[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