From fffa535d112356bd2331964a8635ade9ca5d6a94 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Sun, 12 Jul 2020 09:56:58 +0200 Subject: [PATCH] Convert tabs to non sui styles (#3168) * Convert tabs to non sui styles * inactive hover * Adjust sequence display * Update --- packages/page-contracts/src/index.tsx | 10 +- packages/react-components/src/Tabs.tsx | 95 ------------------- packages/react-components/src/Tabs/Tab.tsx | 70 ++++++++++++++ packages/react-components/src/Tabs/index.tsx | 72 ++++++++++++++ packages/react-components/src/Tabs/types.ts | 14 +++ packages/react-components/src/styles/index.ts | 4 +- packages/react-components/src/styles/media.ts | 4 +- .../react-components/src/styles/semantic.ts | 25 ----- packages/react-components/src/styles/theme.ts | 4 - 9 files changed, 166 insertions(+), 132 deletions(-) delete mode 100644 packages/react-components/src/Tabs.tsx create mode 100644 packages/react-components/src/Tabs/Tab.tsx create mode 100644 packages/react-components/src/Tabs/index.tsx create mode 100644 packages/react-components/src/Tabs/types.ts diff --git a/packages/page-contracts/src/index.tsx b/packages/page-contracts/src/index.tsx index 881de74410..10a20d89d7 100644 --- a/packages/page-contracts/src/index.tsx +++ b/packages/page-contracts/src/index.tsx @@ -3,7 +3,7 @@ // of the Apache-2.0 license. See the LICENSE file for details. import { AppProps as Props } from '@polkadot/react-components/types'; -import { TabItem } from '@polkadot/react-components/Tabs'; +import { TabItem } from '@polkadot/react-components/Tabs/types'; import { ComponentProps } from './types'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; @@ -26,7 +26,6 @@ function ContractsApp ({ basePath, onStatusChange }: Props): React.ReactElement< const [constructorIndex, setConstructorIndex] = useState(0); const [isDeployOpen, toggleIsDeployOpen, setIsDeployOpen] = useToggle(); const [updated, setUpdated] = useState(0); - const [allCodes, setAllCodes] = useState(store.getAllCode()); const _triggerUpdate = useCallback( @@ -47,6 +46,11 @@ function ContractsApp ({ basePath, onStatusChange }: Props): React.ReactElement< [allCodes, toggleIsDeployOpen] ); + const _onCloseDeploy = useCallback( + () => setIsDeployOpen(false), + [setIsDeployOpen] + ); + const componentProps = useMemo( (): ComponentProps => ({ accounts: allAccounts, @@ -76,8 +80,6 @@ function ContractsApp ({ basePath, onStatusChange }: Props): React.ReactElement< const hidden: string[] = []; - const _onCloseDeploy = (): void => setIsDeployOpen(false); - return (
diff --git a/packages/react-components/src/Tabs.tsx b/packages/react-components/src/Tabs.tsx deleted file mode 100644 index 9d57743c6a..0000000000 --- a/packages/react-components/src/Tabs.tsx +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2017-2020 @polkadot/react-components authors & contributors -// This software may be modified and distributed under the terms -// of the Apache-2.0 license. See the LICENSE file for details. - -import React, { useEffect } from 'react'; -import { NavLink, useLocation } from 'react-router-dom'; -import styled from 'styled-components'; - -import { classes } from './util'; -import Icon from './Icon'; - -const MyIcon = styled(Icon)` - &&& { - width: 1rem; - margin: 0.7rem 0; - } -`; - -export interface TabItem { - alias?: string; - hasParams?: boolean; - isExact?: boolean; - isRoot?: boolean; - name: string; - text: React.ReactNode; -} - -interface Props { - className?: string; - basePath: string; - hidden?: (string | boolean | undefined)[]; - items: TabItem[]; - isSequence?: boolean; -} - -function renderItem ({ basePath, isSequence, items }: Props): (tabItem: TabItem, index: number) => React.ReactNode { - return function Tab ({ hasParams, isRoot, name, text, ...tab }: TabItem, index: number): React.ReactNode { - const to = isRoot - ? basePath - : `${basePath}/${name}`; - // only do exact matching when not the fallback (first position tab), - // params are problematic for dynamic hidden such as app-accounts - const isExact = tab.isExact || !hasParams || (!isSequence && index === 0); - - return ( - - - {text} - - {(isSequence && index < items.length - 1) && ( - - )} - - ); - }; -} - -function Tabs (props: Props): React.ReactElement { - const location = useLocation(); - const { className = '', basePath, hidden = [], items } = props; - - // redirect on invalid tabs - useEffect((): void => { - if (location.pathname !== basePath) { - // Has the form /staking/query/ - const [,, section] = location.pathname.split('/'); - const alias = items.find(({ alias }) => alias === section); - - if (alias) { - window.location.hash = alias.isRoot - ? basePath - : `${basePath}/${alias.name}`; - } else if (hidden.includes(section) || !items.some(({ isRoot, name }) => !isRoot && name === section)) { - window.location.hash = basePath; - } - } - }, [basePath, hidden, items, location]); - - return ( -
- {items - .filter(({ name }): boolean => !hidden.includes(name)) - .map(renderItem(props)) - } -
- ); -} - -export default React.memo(Tabs); diff --git a/packages/react-components/src/Tabs/Tab.tsx b/packages/react-components/src/Tabs/Tab.tsx new file mode 100644 index 0000000000..9613fb9e1a --- /dev/null +++ b/packages/react-components/src/Tabs/Tab.tsx @@ -0,0 +1,70 @@ +// Copyright 2017-2020 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { TabItem } from './types'; + +import React from 'react'; +import { NavLink } from 'react-router-dom'; +import styled from 'styled-components'; + +import Icon from '../Icon'; + +interface Props extends TabItem { + basePath: string; + className?: string; + index: number; + isSequence?: boolean; + num: number; +} + +function Tab ({ basePath, className = '', hasParams, index, isExact, isRoot, isSequence, name, num, text }: Props): React.ReactElement { + const to = isRoot + ? basePath + : `${basePath}/${name}`; + + // only do exact matching when not the fallback (first position tab), + // params are problematic for dynamic hidden such as app-accounts + const tabIsExact = isExact || !hasParams || (!isSequence && index === 0); + + return ( + + {text}{(isSequence && index < (num - 1)) && ( + + )} + + ); +} + +export default React.memo(styled(Tab)` + border-bottom: 2px solid transparent; + color: rgba(0, 0, 0, 0.87) !important; + padding: 0.75rem 1.5rem; + + &.tabLinkActive { + border-bottom-color: #e6e6e6; + color: rgba(0, 0, 0, 0.95); + font-weight: 700; + } + + &:hover { + color: inherit !important; + + &:not(.tabLinkActive) { + border-bottom-color: #e6e6e6; + } + } + + .tabIcon { + margin-left: 0.75rem; + } +`); diff --git a/packages/react-components/src/Tabs/index.tsx b/packages/react-components/src/Tabs/index.tsx new file mode 100644 index 0000000000..c53f4d8eb2 --- /dev/null +++ b/packages/react-components/src/Tabs/index.tsx @@ -0,0 +1,72 @@ +// Copyright 2017-2020 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { TabItem } from './types'; + +import React, { useEffect } from 'react'; +import { useLocation } from 'react-router-dom'; +import styled from 'styled-components'; + +import Tab from './Tab'; + +interface Props { + className?: string; + basePath: string; + hidden?: (string | boolean | undefined)[]; + items: TabItem[]; + isSequence?: boolean; +} + +function Tabs ({ basePath, className = '', hidden, isSequence, items }: Props): React.ReactElement { + const location = useLocation(); + + // redirect on invalid tabs + useEffect((): void => { + if (location.pathname !== basePath) { + // Has the form /staking/query/ + const [,, section] = location.pathname.split('/'); + const alias = items.find(({ alias }) => alias === section); + + if (alias) { + window.location.hash = alias.isRoot + ? basePath + : `${basePath}/${alias.name}`; + } else if (hidden && (hidden.includes(section) || !items.some(({ isRoot, name }) => !isRoot && name === section))) { + window.location.hash = basePath; + } + } + }, [basePath, hidden, items, location]); + + const filtered = hidden + ? items.filter(({ name }) => !hidden.includes(name)) + : items; + + return ( +
+ {filtered.map((tab, index) => ( + + ))} +
+ ); +} + +export default React.memo(styled(Tabs)` + border-bottom: 1px solid #e6e6e6; + margin: 0 -2em; + overflow-x: scroll; + padding: 2em 2em 0.75rem; + text-align: left; + + &::-webkit-scrollbar { + display: none; + width: 0px; + } +`); diff --git a/packages/react-components/src/Tabs/types.ts b/packages/react-components/src/Tabs/types.ts new file mode 100644 index 0000000000..63087b1ac5 --- /dev/null +++ b/packages/react-components/src/Tabs/types.ts @@ -0,0 +1,14 @@ +// Copyright 2017-2020 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import React from 'react'; + +export interface TabItem { + alias?: string; + hasParams?: boolean; + isExact?: boolean; + isRoot?: boolean; + name: string; + text: React.ReactNode; +} diff --git a/packages/react-components/src/styles/index.ts b/packages/react-components/src/styles/index.ts index 2442afee47..094ec82a54 100644 --- a/packages/react-components/src/styles/index.ts +++ b/packages/react-components/src/styles/index.ts @@ -58,8 +58,8 @@ export default createGlobalStyle` } .theme--default { - .ui.menu.tabular .item.active { - border-color: ${getHighlight} !important; + .ui--Tabs-Tab.tabLinkActive { + border-bottom-color: ${getHighlight}; } .ui.blue.progress > .bar { diff --git a/packages/react-components/src/styles/media.ts b/packages/react-components/src/styles/media.ts index cc7586f260..1d7b1383cc 100644 --- a/packages/react-components/src/styles/media.ts +++ b/packages/react-components/src/styles/media.ts @@ -189,8 +189,8 @@ export default css` /* tabs */ @media (max-width: 991px) { - .ui.menu.tabular { - padding-left: 5.2rem !important; + .ui--Tabs { + padding-left: 5.2rem; } } `; diff --git a/packages/react-components/src/styles/semantic.ts b/packages/react-components/src/styles/semantic.ts index 284c27a44e..eb25639400 100644 --- a/packages/react-components/src/styles/semantic.ts +++ b/packages/react-components/src/styles/semantic.ts @@ -177,31 +177,6 @@ export default css` justify-content: flex-start; } - .ui.menu.tabular { - border-color: #e6e6e6; - /* break out of the wrapping main padding */ - margin: -1em -2em 0; - overflow-x: scroll; - padding: 2em 2em 0 2em; - transition: padding-left 0.2s linear 0.4s; - - &::-webkit-scrollbar { - display: none; - width: 0px; - } - - .item { - border-bottom: 2px solid rgba(0, 0, 0, 0); - border: none; - top: -1px; - - &.active { - background: none;; - border-bottom: 2px solid #db2828; - } - } - } - /* remove the default white background, settings app has it as part of Tab */ .ui.segment { background: transparent; diff --git a/packages/react-components/src/styles/theme.ts b/packages/react-components/src/styles/theme.ts index 76234522d3..6db81495ff 100644 --- a/packages/react-components/src/styles/theme.ts +++ b/packages/react-components/src/styles/theme.ts @@ -61,10 +61,6 @@ export default css` border-bottom-color: ${colorBtnHighlight}; } - .ui.menu.tabular .item.active { - border-bottom-color: ${colorBtnHighlight}; - } - /* this is for dropdown buttons */ .ui.buttons .ui.button.selection.visible.dropdown { &:hover {