diff --git a/web/packages/teleterm/src/ui/DocumentCluster/DocumentCluster.tsx b/web/packages/teleterm/src/ui/DocumentCluster/DocumentCluster.tsx index f193b7c3f3041..b92823c0d5b75 100644 --- a/web/packages/teleterm/src/ui/DocumentCluster/DocumentCluster.tsx +++ b/web/packages/teleterm/src/ui/DocumentCluster/DocumentCluster.tsx @@ -82,7 +82,7 @@ export function Cluster() { } return ( - + ); diff --git a/web/packages/teleterm/src/ui/Documents/KeyboardShortcutsPanel.tsx b/web/packages/teleterm/src/ui/Documents/KeyboardShortcutsPanel.tsx index 2d635df24a19d..058ef1117f878 100644 --- a/web/packages/teleterm/src/ui/Documents/KeyboardShortcutsPanel.tsx +++ b/web/packages/teleterm/src/ui/Documents/KeyboardShortcutsPanel.tsx @@ -73,10 +73,17 @@ export function KeyboardShortcutsPanel() { function Entry(props: { title: string; accelerator: string }) { return ( <> - + {props.title} - + props.theme.colors.spotBackground[0]}; + `} + textAlign="left" + px="12px" + py="4px" + > {props.accelerator} @@ -84,9 +91,7 @@ function Entry(props: { title: string; accelerator: string }) { } const MonoText = styled(Text)` - font-family: ${props => props.theme.fonts.mono}; width: fit-content; - opacity: 0.7; border-radius: 4px; `; diff --git a/web/packages/teleterm/src/ui/TabHost/TabHost.tsx b/web/packages/teleterm/src/ui/TabHost/TabHost.tsx index fdc544e0a49d9..7a76a18c9e35d 100644 --- a/web/packages/teleterm/src/ui/TabHost/TabHost.tsx +++ b/web/packages/teleterm/src/ui/TabHost/TabHost.tsx @@ -106,7 +106,6 @@ export function TabHost({ ctx }: { ctx: IAppContext }) { onContextMenu={handleTabContextMenu} activeTab={activeDocument?.uri} onMoved={handleTabMoved} - disableNew={false} onNew={openClusterTab} newTabTooltip={getLabelWithAccelerator('New Tab', 'newTab')} closeTabTooltip={getLabelWithAccelerator('Close', 'closeTab')} diff --git a/web/packages/teleterm/src/ui/Tabs/TabItem.tsx b/web/packages/teleterm/src/ui/Tabs/TabItem.tsx index 5b0e6a6419b23..d69b9e59c59ea 100644 --- a/web/packages/teleterm/src/ui/Tabs/TabItem.tsx +++ b/web/packages/teleterm/src/ui/Tabs/TabItem.tsx @@ -16,7 +16,7 @@ limitations under the License. import React, { useRef } from 'react'; import styled from 'styled-components'; -import { Close as CloseIcon } from 'design/Icon'; +import * as Icons from 'design/Icon'; import { ButtonIcon, Text } from 'design'; import LinearProgress from 'teleterm/ui/components/LinearProgress'; @@ -27,6 +27,7 @@ type TabItemProps = { index?: number; name?: string; active?: boolean; + nextActive?: boolean; closeTabTooltip?: string; isLoading?: boolean; onClick?(): void; @@ -39,6 +40,7 @@ export function TabItem(props: TabItemProps) { const { name, active, + nextActive, onClick, onClose, index, @@ -62,71 +64,104 @@ export function TabItem(props: TabItemProps) { }; return ( - - - {name} - - {isLoading && active && } - {onClose && ( + + + {name} + + {isLoading && active && } + {onClose && ( + + + + )} + + {!active && !nextActive && } + {(!active || isDragging) && } + + ); +} + +type NewTabItemProps = { + tooltip: string; + onClick(): void; +}; + +export function NewTabItem(props: NewTabItemProps) { + return ( + + - + - )} - + + + ); } -const StyledTabItem = styled.div(({ theme, active, dragging, canDrag }) => { - const styles: any = { - display: 'flex', - flexBasis: '0', - flexGrow: '1', - opacity: '1', - color: theme.colors.text.slightlyMuted, - alignItems: 'center', - minWidth: '0', - height: '100%', - border: 'none', - borderRadius: '8px 8px 0 0', - '&:hover, &:focus': { - color: theme.colors.text.main, - transition: 'color .3s', - }, - position: 'relative', - }; - - if (active) { - styles['backgroundColor'] = theme.colors.levels.sunken; - styles['color'] = theme.colors.text.main; - styles['transition'] = 'none'; - } - - if (dragging) { - styles['opacity'] = 0; - } +const RelativeContainer = styled.div` + position: relative; + display: flex; + flex-basis: 0; + align-items: center; + height: 100%; +`; - if (canDrag) { - styles['cursor'] = 'pointer'; +const TabContent = styled.div` + display: flex; + z-index: 1; // covers shadow from the top + align-items: center; + min-width: 0; + width: 100%; + height: 100%; + border-radius: 8px 8px 0 0; + position: relative; + opacity: ${props => (props.dragging ? 0 : 1)}; + color: ${props => + props.active + ? props.theme.colors.text.main + : props.theme.colors.text.slightlyMuted}; + background: ${props => + props.active + ? props.theme.colors.levels.sunken + : props.theme.colors.levels.surface}; + box-shadow: ${props => + props.active ? 'inset 0px 2px 1.5px -1px rgba(0, 0, 0, 0.12)' : undefined}; + + &:hover, + &:focus { + color: ${props => props.theme.colors.text.main}; + transition: color 0.3s; } - - return styles; -}); +`; const Title = styled(Text)` display: block; @@ -142,3 +177,23 @@ const Title = styled(Text)` min-width: 0; width: 100%; `; + +const BottomShadow = styled.div` + box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1.5px rgba(0, 0, 0, 0.13), + 0 1px 4px rgba(0, 0, 0, 0.12); + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 1px; + background: inherit; +`; + +const Separator = styled.div` + height: 23px; + width: 1px; + position: absolute; + z-index: 1; + right: 0; + background: ${props => props.theme.colors.spotBackground[2]}; +`; diff --git a/web/packages/teleterm/src/ui/Tabs/Tabs.tsx b/web/packages/teleterm/src/ui/Tabs/Tabs.tsx index 7914f144ceb9e..5add8560ef5ce 100644 --- a/web/packages/teleterm/src/ui/Tabs/Tabs.tsx +++ b/web/packages/teleterm/src/ui/Tabs/Tabs.tsx @@ -14,15 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { Fragment } from 'react'; +import React from 'react'; import styled from 'styled-components'; import { typography } from 'design/system'; -import { Box, ButtonIcon } from 'design'; -import * as Icons from 'design/Icon'; +import { Box } from 'design'; import { Document } from 'teleterm/ui/services/workspacesService'; -import { TabItem } from './TabItem'; +import { TabItem, NewTabItem } from './TabItem'; export function Tabs(props: Props) { const { @@ -31,7 +30,6 @@ export function Tabs(props: Props) { onSelect, onClose, onNew, - disableNew, onMoved, onContextMenu, newTabTooltip, @@ -39,48 +37,34 @@ export function Tabs(props: Props) { ...styledProps } = props; - const $emptyTab = ( - <> - - - + const $items = items.length ? ( + items.map((item, index) => { + const active = item.uri === activeTab; + const nextActive = items[index + 1]?.uri === activeTab; + return ( + onSelect(item)} + onClose={() => onClose(item)} + onContextMenu={() => onContextMenu(item)} + onMoved={onMoved} + isLoading={getIsLoading(item)} + closeTabTooltip={closeTabTooltip} + /> + ); + }) + ) : ( + ); - const $items = items.length - ? items.map((item, index) => { - const active = item.uri === activeTab; - return ( - - onSelect(item)} - onClose={() => onClose(item)} - onContextMenu={() => onContextMenu(item)} - onMoved={onMoved} - isLoading={getIsLoading(item)} - closeTabTooltip={closeTabTooltip} - /> - - - ); - }) - : $emptyTab; - return ( {$items} - - - + ); } @@ -92,7 +76,6 @@ function getIsLoading(doc: Document): boolean { type Props = { items: Document[]; activeTab: string; - disableNew: boolean; newTabTooltip: string; closeTabTooltip: string; onNew: () => void; @@ -102,13 +85,6 @@ type Props = { [index: string]: any; }; -const Separator = styled.div` - height: 23px; - width: 1px; - margin: 0 1px; - background: ${props => props.theme.colors.spotBackground[2]}; -`; - const StyledTabs = styled(Box)` background-color: ${props => props.theme.colors.levels.surface}; min-height: 32px; @@ -116,10 +92,8 @@ const StyledTabs = styled(Box)` flex-wrap: nowrap; align-items: center; flex-shrink: 0; - overflow: hidden; + max-width: 100%; position: relative; z-index: 1; - box-shadow: 0px 1px 10px 0px rgba(0, 0, 0, 0.12), - 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 2px 4px -1px rgba(0, 0, 0, 0.2); ${typography} `; diff --git a/web/packages/teleterm/src/ui/TopBar/TopBar.tsx b/web/packages/teleterm/src/ui/TopBar/TopBar.tsx index ab435bce7e278..a85f504e792b3 100644 --- a/web/packages/teleterm/src/ui/TopBar/TopBar.tsx +++ b/web/packages/teleterm/src/ui/TopBar/TopBar.tsx @@ -49,7 +49,6 @@ const Grid = styled(Flex).attrs({ gap: 3, py: 2, px: 3 })` height: 56px; align-items: center; justify-content: space-between; - z-index: 2; // minimally higher z-index than the one defined in StyledTabs, so that its drop-shadow doesn't cover the TopBar `; const CentralContainer = styled(Flex).attrs({ gap: 3 })`