From c56e34a16c320b4d45f4ff369046d942c8b70b53 Mon Sep 17 00:00:00 2001 From: Gert Hengeveld Date: Mon, 16 Dec 2024 21:17:16 +0100 Subject: [PATCH 1/4] Float context menu button on top of story title and replace transparent backgrounds to make it look good --- .../components/sidebar/StatusButton.tsx | 20 ++++++++++++++++++- .../src/manager/components/sidebar/Tree.tsx | 20 +++++++++++++++---- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/code/core/src/manager/components/sidebar/StatusButton.tsx b/code/core/src/manager/components/sidebar/StatusButton.tsx index 9d1b49998df7..732838e043a7 100644 --- a/code/core/src/manager/components/sidebar/StatusButton.tsx +++ b/code/core/src/manager/components/sidebar/StatusButton.tsx @@ -3,7 +3,7 @@ import { styled } from '@storybook/core/theming'; import type { API_StatusValue } from '@storybook/types'; import type { Theme } from '@emotion/react'; -import { transparentize } from 'polished'; +import { darken, lighten, transparentize } from 'polished'; const withStatusColor = ({ theme, status }: { theme: Theme; status: API_StatusValue }) => { const defaultColor = @@ -34,15 +34,33 @@ export const StatusButton = styled(IconButton)<{ }>( withStatusColor, ({ theme, height, width }) => ({ + position: 'absolute', + right: 0, + top: 0, transition: 'none', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: width || 28, height: height || 28, + background: 'var(--tree-node-background-hover)', + boxShadow: '0 0 5px 5px var(--tree-node-background-hover)', '&:hover': { color: theme.color.secondary, + background: + theme.base === 'dark' + ? darken(0.3, theme.color.secondary) + : lighten(0.4, theme.color.secondary), + }, + + '[data-selected="true"] &': { + background: theme.color.secondary, + boxShadow: `0 0 5px 5px ${theme.color.secondary}`, + + '&:hover': { + background: lighten(0.1, theme.color.secondary), + }, }, '&:focus': { diff --git a/code/core/src/manager/components/sidebar/Tree.tsx b/code/core/src/manager/components/sidebar/Tree.tsx index d08ab8ffc4d7..62c9774dc991 100644 --- a/code/core/src/manager/components/sidebar/Tree.tsx +++ b/code/core/src/manager/components/sidebar/Tree.tsx @@ -24,9 +24,10 @@ import type { StoryEntry, } from '@storybook/core/manager-api'; -import { transparentize } from 'polished'; +import { darken, lighten } from 'polished'; import type { Link } from '../../../components/components/tooltip/TooltipLinkList'; +import { MEDIA_DESKTOP_BREAKPOINT } from '../../constants'; import { getGroupStatus, getHighestStatus, statusMapping } from '../../utils/status'; import { createId, @@ -66,7 +67,7 @@ const CollapseButton = styled.button(({ theme }) => ({ '&:hover, &:focus': { outline: 'none', - background: transparentize(0.93, theme.color.secondary), + background: 'var(--tree-node-background-hover)', }, })); @@ -79,9 +80,19 @@ export const LeafNodeStyleWrapper = styled.div(({ theme }) => ({ background: 'transparent', minHeight: 28, borderRadius: 4, + overflow: 'hidden', + '--tree-node-background-hover': theme.background.content, + + [MEDIA_DESKTOP_BREAKPOINT]: { + '--tree-node-background-hover': theme.background.app, + }, '&:hover, &:focus': { - background: transparentize(0.93, theme.color.secondary), + '--tree-node-background-hover': + theme.base === 'dark' + ? darken(0.35, theme.color.secondary) + : lighten(0.45, theme.color.secondary), + background: 'var(--tree-node-background-hover)', outline: 'none', }, @@ -107,7 +118,8 @@ export const LeafNodeStyleWrapper = styled.div(({ theme }) => ({ fontWeight: theme.typography.weight.bold, '&&:hover, &&:focus': { - background: theme.color.secondary, + '--tree-node-background-hover': theme.color.secondary, + background: 'var(--tree-node-background-hover)', }, svg: { color: theme.color.lightest }, }, From e77bd59a7c130d841b2aaabbef462d205db547f7 Mon Sep 17 00:00:00 2001 From: Gert Hengeveld Date: Tue, 17 Dec 2024 11:27:26 +0100 Subject: [PATCH 2/4] Fix tooltip positioning by absolutely positioning the WithTooltip wrapper rather than the button inside --- .../src/manager/components/sidebar/ContextMenu.tsx | 10 ++++++++-- .../manager/components/sidebar/StatusButton.tsx | 3 --- code/core/src/manager/components/sidebar/Tree.tsx | 14 ++++++++++---- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/code/core/src/manager/components/sidebar/ContextMenu.tsx b/code/core/src/manager/components/sidebar/ContextMenu.tsx index a2d98eab6a85..d2fa1d54310c 100644 --- a/code/core/src/manager/components/sidebar/ContextMenu.tsx +++ b/code/core/src/manager/components/sidebar/ContextMenu.tsx @@ -2,6 +2,7 @@ import type { ComponentProps, FC, SyntheticEvent } from 'react'; import React, { useMemo, useState } from 'react'; import { TooltipLinkList, WithTooltip } from '@storybook/core/components'; +import { styled } from '@storybook/core/theming'; import { type API_HashEntry, Addon_TypesEnum } from '@storybook/core/types'; import { EllipsisIcon } from '@storybook/icons'; @@ -18,6 +19,11 @@ const empty = { node: null, }; +const PositionedWithTooltip = styled(WithTooltip)({ + position: 'absolute', + right: 0, +}); + export const useContextMenu = (context: API_HashEntry, links: Link[], api: API) => { const [hoverCount, setHoverCount] = useState(0); const [isOpen, setIsOpen] = useState(false); @@ -63,7 +69,7 @@ export const useContextMenu = (context: API_HashEntry, links: Link[], api: API) return { onMouseEnter: handlers.onMouseEnter, node: isRendered ? ( - - + ) : null, }; }, [context, handlers, isOpen, isRendered, links]); diff --git a/code/core/src/manager/components/sidebar/StatusButton.tsx b/code/core/src/manager/components/sidebar/StatusButton.tsx index 732838e043a7..343440e1434b 100644 --- a/code/core/src/manager/components/sidebar/StatusButton.tsx +++ b/code/core/src/manager/components/sidebar/StatusButton.tsx @@ -34,9 +34,6 @@ export const StatusButton = styled(IconButton)<{ }>( withStatusColor, ({ theme, height, width }) => ({ - position: 'absolute', - right: 0, - top: 0, transition: 'none', display: 'inline-flex', alignItems: 'center', diff --git a/code/core/src/manager/components/sidebar/Tree.tsx b/code/core/src/manager/components/sidebar/Tree.tsx index 62c9774dc991..54a49207a90a 100644 --- a/code/core/src/manager/components/sidebar/Tree.tsx +++ b/code/core/src/manager/components/sidebar/Tree.tsx @@ -196,6 +196,12 @@ const StatusIconMap = { unknown: null, }; +const PositionedStatusButton = styled(StatusButton)({ + position: 'absolute', + right: 0, + top: 0, +}); + export const ContextMenu = { ListItem, }; @@ -334,7 +340,7 @@ const Node = React.memo(function Node({ )} {contextMenu.node} {icon ? ( - (function Node({ selectedItem={isSelected} > {icon} - + ) : null} ); @@ -436,11 +442,11 @@ const Node = React.memo(function Node({ {contextMenu.node} {['error', 'warn'].includes(itemStatus) && ( - + - + )} ); From 66faa7e0d62bf147502d51a7931947eaf691bc76 Mon Sep 17 00:00:00 2001 From: Gert Hengeveld Date: Tue, 17 Dec 2024 22:25:00 +0100 Subject: [PATCH 3/4] Don't absolutely position status icons --- .../src/manager/components/sidebar/ContextMenu.tsx | 9 +++++++-- .../manager/components/sidebar/StatusButton.tsx | 2 -- code/core/src/manager/components/sidebar/Tree.tsx | 14 ++++---------- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/code/core/src/manager/components/sidebar/ContextMenu.tsx b/code/core/src/manager/components/sidebar/ContextMenu.tsx index d2fa1d54310c..ac4aeb671d55 100644 --- a/code/core/src/manager/components/sidebar/ContextMenu.tsx +++ b/code/core/src/manager/components/sidebar/ContextMenu.tsx @@ -24,6 +24,11 @@ const PositionedWithTooltip = styled(WithTooltip)({ right: 0, }); +const FloatingStatusButton = styled(StatusButton)({ + background: 'var(--tree-node-background-hover)', + boxShadow: '0 0 5px 5px var(--tree-node-background-hover)', +}); + export const useContextMenu = (context: API_HashEntry, links: Link[], api: API) => { const [hoverCount, setHoverCount] = useState(0); const [isOpen, setIsOpen] = useState(false); @@ -83,9 +88,9 @@ export const useContextMenu = (context: API_HashEntry, links: Link[], api: API) }} tooltip={} > - + - + ) : null, }; diff --git a/code/core/src/manager/components/sidebar/StatusButton.tsx b/code/core/src/manager/components/sidebar/StatusButton.tsx index 343440e1434b..8002cc87ba33 100644 --- a/code/core/src/manager/components/sidebar/StatusButton.tsx +++ b/code/core/src/manager/components/sidebar/StatusButton.tsx @@ -40,8 +40,6 @@ export const StatusButton = styled(IconButton)<{ justifyContent: 'center', width: width || 28, height: height || 28, - background: 'var(--tree-node-background-hover)', - boxShadow: '0 0 5px 5px var(--tree-node-background-hover)', '&:hover': { color: theme.color.secondary, diff --git a/code/core/src/manager/components/sidebar/Tree.tsx b/code/core/src/manager/components/sidebar/Tree.tsx index 54a49207a90a..62c9774dc991 100644 --- a/code/core/src/manager/components/sidebar/Tree.tsx +++ b/code/core/src/manager/components/sidebar/Tree.tsx @@ -196,12 +196,6 @@ const StatusIconMap = { unknown: null, }; -const PositionedStatusButton = styled(StatusButton)({ - position: 'absolute', - right: 0, - top: 0, -}); - export const ContextMenu = { ListItem, }; @@ -340,7 +334,7 @@ const Node = React.memo(function Node({ )} {contextMenu.node} {icon ? ( - (function Node({ selectedItem={isSelected} > {icon} - + ) : null} ); @@ -442,11 +436,11 @@ const Node = React.memo(function Node({ {contextMenu.node} {['error', 'warn'].includes(itemStatus) && ( - + - + )} ); From eed0b8ba4d1692818f7a7fd1722bb9d2eb58bd3a Mon Sep 17 00:00:00 2001 From: Gert Hengeveld Date: Wed, 18 Dec 2024 10:54:36 +0100 Subject: [PATCH 4/4] Ensure status icon continues to claim space while hidden --- code/core/src/manager/components/sidebar/Tree.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/core/src/manager/components/sidebar/Tree.tsx b/code/core/src/manager/components/sidebar/Tree.tsx index 62c9774dc991..cbfc1e330be7 100644 --- a/code/core/src/manager/components/sidebar/Tree.tsx +++ b/code/core/src/manager/components/sidebar/Tree.tsx @@ -105,11 +105,11 @@ export const LeafNodeStyleWrapper = styled.div(({ theme }) => ({ }, '& [data-displayed="on"] + *': { - display: 'none', + visibility: 'hidden', }, '&:hover [data-displayed="off"] + *': { - display: 'none', + visibility: 'hidden', }, '&[data-selected="true"]': {