diff --git a/src/apps/explorer/components/common/ExplorerTabs/ExplorerTab.tsx b/src/apps/explorer/components/common/ExplorerTabs/ExplorerTab.tsx new file mode 100644 index 000000000..1e1f1e1ae --- /dev/null +++ b/src/apps/explorer/components/common/ExplorerTabs/ExplorerTab.tsx @@ -0,0 +1,71 @@ +import React from 'react' +import styled from 'styled-components' + +import Tabs, { getTabTheme, Props as TabsProps, IndicatorTabSize } from 'components/common/Tabs/Tabs' +import { DARK_COLOURS } from 'theme' +import { MEDIA } from 'const' + +const StyledTabs = styled.div` + display: flex; + width: 100%; + padding: 0; + border: ${({ theme }): string => `1px solid ${theme.borderPrimary}`}; + border-radius: 4px; + + > div > div.tablist { + justify-content: flex-start; + border-bottom: ${({ theme }): string => `1px solid ${theme.borderPrimary}`}; + box-sizing: border-box; + } + + > div > div.tablist > button { + flex: 0 0 auto; + min-width: 96px; + padding: 12px 0.8rem; + line-height: 2; + height: auto; + font-family: var(--font-default); + } + + > div > div:last-of-type { + height: 100%; + } + + > div > div.tab-content { + padding: 20px 16px; + } + + .tab-extra-content { + width: 100%; + + @media ${MEDIA.mobile} { + display: none; /* for now we can hide the extra-content on mobiles */ + } + } +` +const tabCustomThemeConfig = getTabTheme({ + activeBg: 'var(--color-transparent)', + activeBgAlt: 'initial', + inactiveBg: 'var(--color-transparent)', + activeText: DARK_COLOURS.textPrimary1, + inactiveText: 'var(--color-text-secondary2)', + activeBorder: DARK_COLOURS.orange, + inactiveBorder: 'none', + fontSize: 'var(--font-size-large)', + fontWeight: 'var(--font-weight-bold)', + letterSpacing: 'initial', + borderRadius: false, + indicatorTabSize: IndicatorTabSize.big, +}) + +type ExplorerTabsProps = Omit + +const ExplorerTabs: React.FC = (props) => { + return ( + + + + ) +} + +export default ExplorerTabs diff --git a/src/apps/explorer/components/common/ExplorerTabs/ExplorerTabs.stories.tsx b/src/apps/explorer/components/common/ExplorerTabs/ExplorerTabs.stories.tsx new file mode 100644 index 000000000..116af53ff --- /dev/null +++ b/src/apps/explorer/components/common/ExplorerTabs/ExplorerTabs.stories.tsx @@ -0,0 +1,75 @@ +import React from 'react' +import styled from 'styled-components' + +// also exported from '@storybook/react' if you can deal with breaking changes in 6.1 +import { Meta, Story } from '@storybook/react/types-6-0' +import { GlobalStyles, ThemeToggler } from 'storybook/decorators' + +import StyledTabs from './ExplorerTab' +import { Props as TabsProps } from '../../../../../components/common/Tabs/Tabs' + +export default { + title: 'ExplorerApp/ExplorerTabs', + component: StyledTabs, + decorators: [GlobalStyles, ThemeToggler], +} as Meta + +const tabItems = [ + { + id: 1, + tab: 'Orders', + content: ( +
+

Orders Content

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. In libero mauris, dictum a orci ac, congue commodo + quam. Fusce ac accumsan diam. Nulla facilisi. Pellentesque ullamcorper ullamcorper metus, at viverra turpis + tristique vulputate. Ut dictum ac elit sit amet ultricies. Aliquam ultricies ante arcu, maximus malesuada leo + dignissim vitae. Nulla facilisi. Quisque sit amet arcu sed nulla hendrerit euismod. Donec gravida sollicitudin + libero, a auctor tortor convallis non. Nullam malesuada enim eu sollicitudin sodales. Nullam accumsan, nunc + sed ultrices elementum, lorem diam vulputate turpis, a ultrices tortor mauris id mauris. Pellentesque a + commodo libero, et convallis leo. Aenean facilisis arcu id magna scelerisque feugiat. Sed accumsan arcu vel + consequat lobortis. Proin gravida lacinia massa eu fringilla. Nulla venenatis sodales tempus. Nam convallis + justo vitae sollicitudin iaculis. Ut vehicula enim vel interdum varius. Aliquam erat volutpat. Pellentesque + sed tellus in dui pulvinar blandit et et elit. Quisque nec metus fringilla, laoreet orci id, scelerisque + velit. +

+
+ ), + }, + { + id: 2, + tab: 'Trades', + content: ( + <> +

Trades Content

+ + ), + }, +] + +const Wrapper = styled.div` + padding: 16px; + display: flex; + align-items: center; + justify-content: space-between; +` + +interface SProps { + text: string +} +const SimpleComponent: React.FC = (props) => { + return

{props.text}

+} + +const ExtraComponentNode: React.ReactNode = ( + + + + +) + +const Template: Story = (args) => + +export const DefaultTabs = Template.bind({}) +DefaultTabs.args = { tabItems, extra: ExtraComponentNode } diff --git a/src/components/common/Tabs/TabContent.tsx b/src/components/common/Tabs/TabContent.tsx index 36aaded4a..a7f9ab57e 100644 --- a/src/components/common/Tabs/TabContent.tsx +++ b/src/components/common/Tabs/TabContent.tsx @@ -12,7 +12,7 @@ const TabContent: React.FC = (props) => { if (!displayTab) return null - return
{displayTab.content}
+ return
{displayTab.content}
} export default TabContent diff --git a/src/components/common/Tabs/TabItem.tsx b/src/components/common/Tabs/TabItem.tsx index d3b159aa7..e79c09448 100644 --- a/src/components/common/Tabs/TabItem.tsx +++ b/src/components/common/Tabs/TabItem.tsx @@ -38,7 +38,7 @@ const TabItemWrapper = styled(TabItemBase)` letter-spacing: ${({ tabTheme }): string => tabTheme.letterSpacing}; border-bottom: ${({ isActive, tabTheme }): string => - `.1rem solid ${isActive ? tabTheme.activeBorder : tabTheme.inactiveBorder}`}; + `${tabTheme.indicatorTabSize}rem solid ${isActive ? tabTheme.activeBorder : tabTheme.inactiveBorder}`}; /* TODO: Provide alternative :focus styling because of using outline: 0; */ diff --git a/src/components/common/Tabs/Tabs.stories.tsx b/src/components/common/Tabs/Tabs.stories.tsx new file mode 100644 index 000000000..094ea3603 --- /dev/null +++ b/src/components/common/Tabs/Tabs.stories.tsx @@ -0,0 +1,68 @@ +import React from 'react' + +import { Meta, Story } from '@storybook/react/types-6-0' +import { GlobalStyles, ThemeToggler } from 'storybook/decorators' + +import Tabs, { getTabTheme, Props as TabsProps } from './Tabs' +import { DARK_COLOURS } from 'theme' + +export default { + title: 'Common/Tabs', + component: Tabs, + decorators: [GlobalStyles, ThemeToggler], +} as Meta + +const tabItems = [ + { + id: 1, + tab: 'Tab one', + content:

Tab One

, + }, + { + id: 2, + tab: 'Tab two', + content:

Tab Two

, + }, + { + id: 3, + tab: 'Tab three', + content:

Tab Three

, + }, +] + +const tabDefaultThemeConfig = getTabTheme() + +const Template: Story = (args) => + +export const DefaultTabs = Template.bind({}) +DefaultTabs.args = { tabItems, tabTheme: tabDefaultThemeConfig } + +const tabItemsWithoutChild = [ + { + id: 1, + tab: 'Orders', + content: null, + }, + { + id: 2, + tab: 'Trades', + content: null, + }, +] + +const tabCustomThemeConfig = getTabTheme({ + activeBg: 'var(--color-transparent)', + activeBgAlt: 'initial', + inactiveBg: 'var(--color-transparent)', + activeText: DARK_COLOURS.textPrimary1, + inactiveText: 'var(--color-text-secondary2)', + activeBorder: DARK_COLOURS.orange, + inactiveBorder: 'none', + fontSize: 'var(--font-size-large)', + fontWeight: 'var(--font-weight-bold)', + letterSpacing: 'initial', + borderRadius: false, +}) + +export const CustomizedThemeTabs = Template.bind({}) +CustomizedThemeTabs.args = { tabItems: tabItemsWithoutChild, tabTheme: tabCustomThemeConfig } diff --git a/src/components/common/Tabs/Tabs.tsx b/src/components/common/Tabs/Tabs.tsx index d1951686a..1dc3cec54 100644 --- a/src/components/common/Tabs/Tabs.tsx +++ b/src/components/common/Tabs/Tabs.tsx @@ -6,6 +6,11 @@ import TabItem from 'components/common/Tabs/TabItem' import TabContent from 'components/common/Tabs/TabContent' type TabId = number +export enum IndicatorTabSize { + small = 0.1, + big = 0.2, +} +export type TabBarExtraContent = React.ReactNode export interface TabItemInterface { readonly tab: React.ReactNode @@ -25,11 +30,13 @@ export interface TabTheme { readonly fontWeight: string readonly fontSize: string readonly borderRadius: boolean + readonly indicatorTabSize: IndicatorTabSize } -interface Props { +export interface Props { readonly tabItems: TabItemInterface[] readonly tabTheme: TabTheme readonly defaultTab?: TabId + readonly extra?: TabBarExtraContent } const Wrapper = styled.div` @@ -58,10 +65,21 @@ export const DEFAULT_TAB_THEME: TabTheme = { fontWeight: 'var(--font-weight-normal)', letterSpacing: 'initial', borderRadius: false, + indicatorTabSize: IndicatorTabSize.small, +} + +interface ExtraContentProps { + extra?: TabBarExtraContent +} + +const ExtraContent = ({ extra }: ExtraContentProps): JSX.Element | null => { + if (!extra) return null + + return
{extra}
} const Tabs: React.FC = (props) => { - const { tabTheme = DEFAULT_TAB_THEME, tabItems, defaultTab = 1 } = props + const { tabTheme = DEFAULT_TAB_THEME, tabItems, defaultTab = 1, extra: tabBarExtraContent } = props const [activeTab, setActiveTab] = useState(defaultTab) @@ -78,6 +96,7 @@ const Tabs: React.FC = (props) => { tabTheme={tabTheme} /> ))} +