Skip to content

Commit

Permalink
Merge pull request #30080 from storybookjs/floating-menu-button
Browse files Browse the repository at this point in the history
Core: Float context menu button on top of story titles in sidebar
  • Loading branch information
ghengeveld authored Dec 18, 2024
2 parents 4b23a1a + eed0b8b commit abe4c88
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 11 deletions.
19 changes: 15 additions & 4 deletions code/core/src/manager/components/sidebar/ContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -18,6 +19,16 @@ const empty = {
node: null,
};

const PositionedWithTooltip = styled(WithTooltip)({
position: 'absolute',
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);
Expand Down Expand Up @@ -63,7 +74,7 @@ export const useContextMenu = (context: API_HashEntry, links: Link[], api: API)
return {
onMouseEnter: handlers.onMouseEnter,
node: isRendered ? (
<WithTooltip
<PositionedWithTooltip
data-displayed={isOpen ? 'on' : 'off'}
closeOnOutsideClick
placement="bottom-end"
Expand All @@ -77,10 +88,10 @@ export const useContextMenu = (context: API_HashEntry, links: Link[], api: API)
}}
tooltip={<LiveContextMenu context={context} links={links} />}
>
<StatusButton type="button" status={'pending'}>
<FloatingStatusButton type="button" status={'pending'}>
<EllipsisIcon />
</StatusButton>
</WithTooltip>
</FloatingStatusButton>
</PositionedWithTooltip>
) : null,
};
}, [context, handlers, isOpen, isRendered, links]);
Expand Down
15 changes: 14 additions & 1 deletion code/core/src/manager/components/sidebar/StatusButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -43,6 +43,19 @@ export const StatusButton = styled(IconButton)<{

'&: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': {
Expand Down
24 changes: 18 additions & 6 deletions code/core/src/manager/components/sidebar/Tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)',
},
}));

Expand All @@ -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',
},

Expand All @@ -94,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"]': {
Expand All @@ -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 },
},
Expand Down

0 comments on commit abe4c88

Please sign in to comment.