Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ui-kit): 탭 컴포넌트 타입 깨지는 부분 수정 #38

Merged
merged 3 commits into from
Feb 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 23 additions & 21 deletions ui-kit/src/components/Tabs/TabNavList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,20 @@ export interface TabNavListProps {
children?: (node: React.ReactElement) => React.ReactElement;
}

function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
function TabNavList(
{ animated = true, ...props }: TabNavListProps,
ref: React.Ref<HTMLDivElement>
) {
const { tabs } = useContext(TabContext);
const { id, activeKey, animated, tabWidth, onTabClick } = props;
const { id, activeKey, tabWidth, onTabClick } = props;

const tabsWrapperRef = useRef<HTMLDivElement>();
const tabListRef = useRef<HTMLDivElement>();
const tabsWrapperRef = useRef<HTMLDivElement>(null);
const tabListRef = useRef<HTMLDivElement>(null);
const getTabRef = useRefs<HTMLDivElement>();

const [wrapperScrollWidth, setWrapperScrollWidth] = useState<number>(0);
const [wrapperContentWidth, setWrapperContentWidth] = useState<number>(0);
const [wrapperWidth, setWrapperWidth] = useState<number>(0);
const [, setWrapperContentWidth] = useState<number>(0);
const [, setWrapperWidth] = useState<number>(0);
const [barStyle, setBarStyle] = useState<React.CSSProperties>();
const [tabSizes, setTabSizes] = useState<TabSizeMap>(new Map());

Expand All @@ -38,18 +41,19 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
const lastOffset = tabSizes.get(tabs[0].key) ?? DEFAULT_SIZE;
const rightOffset = lastOffset.left + lastOffset.width;

for (let i = 0; i < tabs.length; i += 1) {
const { key } = tabs[i];
tabs.forEach(({ key }, i) => {
const prevTab = tabs[i - 1];

let data = tabSizes.get(key);

if (!data) {
data = tabSizes.get(tabs[i - 1]?.key) || DEFAULT_SIZE;
data = tabSizes.get(prevTab?.key) ?? DEFAULT_SIZE;
}

const entity = (map.get(key) || { ...data }) as TabOffset;
const entity = (map.get(key) ?? { ...data }) as TabOffset;
entity.right = rightOffset - entity.left - entity.width;
map.set(key, entity);
}
});

return map;
}, [tabs.map((tab) => tab.key).join('_'), tabSizes, wrapperScrollWidth]);
Expand All @@ -61,18 +65,18 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {

if (activeTabOffset) {
newBarStyle.left = activeTabOffset.left;
newBarStyle.width = tabWidth ? tabWidth : activeTabOffset.width;
newBarStyle.width = tabWidth ?? activeTabOffset.width;
}

setBarStyle(newBarStyle);
}, [activeTabOffset, tabWidth]);

useEffect(() => {
const offsetWidth = tabsWrapperRef.current?.offsetWidth || 0;
const offsetWidth = tabsWrapperRef.current?.offsetWidth ?? 0;

setWrapperWidth(offsetWidth);

const newWrapperScrollWidth = tabListRef.current?.offsetWidth || 0;
const newWrapperScrollWidth = tabListRef.current?.offsetWidth ?? 0;

setWrapperScrollWidth(newWrapperScrollWidth);

Expand All @@ -81,7 +85,7 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
setTabSizes(() => {
const newSizes: TabSizeMap = new Map();
tabs.forEach(({ key }) => {
const tabNode = getTabRef(key).current;
const tabNode = getTabRef(key)?.current;

if (tabNode) {
newSizes.set(key, {
Expand All @@ -97,8 +101,6 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
});
}, []);

function scrollToTab(key = activeKey) {}

const tabNodes: React.ReactElement[] = tabs.map((tab) => {
const { key } = tab;
return (
Expand All @@ -113,9 +115,9 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
onTabClick(key, e);
}}
onFocus={() => {
scrollToTab(key);

tabsWrapperRef.current.scrollToLeft = 0;
if (tabsWrapperRef?.current != null) {
tabsWrapperRef.current.scrollLeft = 0;
}
}}
/>
);
Expand All @@ -130,7 +132,7 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {

<div
className={classnames(`lubycon-tab__bar`, {
['lubycon-tab__bar__animated']: animated ? animated : true,
['lubycon-tab__bar__animated']: animated,
})}
style={barStyle}
/>
Expand Down
32 changes: 21 additions & 11 deletions ui-kit/src/components/Tabs/TabPane.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useMemo } from 'react';
import classnames from 'classnames';

export interface TabPaneProps {
Expand All @@ -9,25 +9,35 @@ export interface TabPaneProps {
disabled?: boolean;
}

export default function TabPane({ active, animated, children }: TabPaneProps) {
const mergedStyle: React.CSSProperties = {};
if (!active) {
if (animated) {
mergedStyle.visibility = 'hidden';
mergedStyle.height = 0;
mergedStyle.overflowY = 'hidden';
const animatedInvisibleStyle = {
visibility: 'hidden',
height: 0,
overflowY: 'hidden',
};
const notAnimatedInvisibleStyle = {
display: 'none',
};

export default function TabPane({ active = false, animated, children }: TabPaneProps) {
const style = useMemo(() => {
if (active) {
return {};
} else {
mergedStyle.display = 'none';
if (animated === true) {
return animatedInvisibleStyle;
} else {
return notAnimatedInvisibleStyle;
}
}
}
}, [active, animated]);

return (
<div
role="tabpanel"
tabIndex={active ? 0 : -1}
aria-hidden={!active}
className={classnames('lubycon-tab__pane', active && `lubycon-tab__pane__active`)}
style={{ ...mergedStyle }}
style={style}
>
{active && children}
</div>
Expand Down
9 changes: 4 additions & 5 deletions ui-kit/src/components/Tabs/Tabs.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import React from 'react';
import classnames from 'classnames';
import TabPane, { TabPaneProps } from './TabPane';
import TabPane from './TabPane';
import TabNavList from './TabNavList';
import { Tab } from './types';
import { useMergedState } from '../../hooks';
import { toArray } from '../../utils';
import TabContext from './TabContext';
import TabPanelList from './TabPanelList';

Expand All @@ -19,10 +18,10 @@ export interface TabsProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'o
}

function parseTabList(children: React.ReactNode): Tab[] {
return toArray(children)
.map((node: React.ReactElement<TabPaneProps>) => {
return React.Children.toArray(children)
.map((node) => {
if (React.isValidElement(node)) {
const key = node.key !== undefined ? String(node.key) : undefined;
const key = node.key !== undefined ? String(node.key).replace(/\.\$/, '') : undefined;
return {
key,
...node.props,
Expand Down
4 changes: 2 additions & 2 deletions ui-kit/src/hooks/useMergedState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default function useMergedState<T, R = T>(
postState?: (value: T) => T;
}
): [R, (value: T) => void] {
const { defaultValue, value, onChange, postState } = option || {};
const { defaultValue, value, onChange, postState } = option ?? {};
const [innerValue, setInnerValue] = React.useState<T>(() => {
if (value !== undefined) {
return value;
Expand Down Expand Up @@ -42,7 +42,7 @@ export default function useMergedState<T, R = T>(
}

if (value === undefined) {
setInnerValue(value);
setInnerValue(value as any);
}
}, [value]);

Expand Down
2 changes: 1 addition & 1 deletion ui-kit/src/hooks/useRefs.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useRef } from 'react';

// Key 기반으로 RefObject 저장하고 캐시로 성능 향상화
export default function useRefs<RefType>(): (key: React.Key) => React.RefObject<RefType> {
export default function useRefs<RefType>() {
const cacheRefs = useRef(new Map<React.Key, React.RefObject<RefType>>());

function getRef(key: React.Key) {
Expand Down
1 change: 0 additions & 1 deletion ui-kit/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export { generateID } from './generateID';
export { default as toArray } from './toArray';
26 changes: 0 additions & 26 deletions ui-kit/src/utils/toArray.ts

This file was deleted.