Skip to content

Commit

Permalink
Merge pull request #20898 from storybookjs/valentin/menu-design-upgrade
Browse files Browse the repository at this point in the history
Menu design upgrade
  • Loading branch information
valentinpalkovic authored Feb 7, 2023
2 parents 197cc17 + 882330a commit fdce812
Show file tree
Hide file tree
Showing 27 changed files with 417 additions and 213 deletions.
1 change: 0 additions & 1 deletion code/addons/a11y/src/components/VisionSimulator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ export const VisionSimulator = () => {
)}
<WithTooltip
placement="top"
trigger="click"
tooltip={({ onHide }) => {
const colorList = getColorList(filter, (i) => {
setFilter(i);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ export const BackgroundSelector: FC = memo(function BackgroundSelector() {
<Fragment>
<WithTooltip
placement="top"
trigger="click"
closeOnOutsideClick
tooltip={({ onHide }) => {
return (
Expand Down
1 change: 0 additions & 1 deletion code/addons/toolbars/src/components/ToolbarMenuList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ export const ToolbarMenuList: FC<ToolbarMenuListProps> = withKeyboardCycle(
return (
<WithTooltip
placement="top"
trigger="click"
tooltip={({ onHide }) => {
const links = items
// Special case handling for various "type" variants
Expand Down
39 changes: 7 additions & 32 deletions code/addons/toolbars/src/components/ToolbarMenuListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
import type { ReactNode } from 'react';
import React from 'react';
import type { TooltipLinkListLink } from '@storybook/components';
import { Icons } from '@storybook/components';
import type { ToolbarItem } from '../types';

interface ListItem {
id: string;
left?: ReactNode;
title?: ReactNode;
right?: ReactNode;
active?: boolean;
onClick?: () => void;
}

type ToolbarMenuListItemProps = {
export type ToolbarMenuListItemProps = {
currentValue: string;
onClick: () => void;
} & ToolbarItem;
Expand All @@ -28,34 +19,18 @@ export const ToolbarMenuListItem = ({
currentValue,
}: ToolbarMenuListItemProps) => {
const Icon = icon && <Icons style={{ opacity: 1 }} icon={icon} />;
const hasContent = left || right || title;

const Item: ListItem = {
const Item: TooltipLinkListLink = {
id: value || currentValue,
active: currentValue === value,
right,
title,
left,
onClick,
};

if (left) {
Item.left = left;
}

if (right) {
Item.right = right;
}

if (title) {
Item.title = title;
}

if (icon && !hideIcon) {
if (hasContent && !right) {
Item.right = Icon;
} else if (hasContent && !left) {
Item.left = Icon;
} else if (!hasContent) {
Item.right = Icon;
}
Item.left = Icon;
}

return Item;
Expand Down
1 change: 0 additions & 1 deletion code/addons/viewport/src/Tool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ export const ViewportTool: FC = memo(
<Fragment>
<WithTooltip
placement="top"
trigger="click"
tooltip={({ onHide }) => (
<TooltipLinkList links={toLinks(list, item, setState, state, onHide)} />
)}
Expand Down
1 change: 0 additions & 1 deletion code/ui/blocks/src/components/ArgsTable/ArgValue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ const ArgSummary: FC<ArgSummaryProps> = ({ value, initialExpandedArgs }) => {
return (
<WithTooltipPure
closeOnOutsideClick
trigger="click"
placement="bottom"
visible={isOpen}
onVisibleChange={(isVisible) => {
Expand Down
1 change: 0 additions & 1 deletion code/ui/blocks/src/controls/Color.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,6 @@ export const ColorControl: FC<ColorControlProps> = ({
return (
<Wrapper>
<PickerTooltip
trigger="click"
startOpen={startOpen}
closeOnOutsideClick
onVisibleChange={() => addPreset(color)}
Expand Down
4 changes: 3 additions & 1 deletion code/ui/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ export { Form } from './form/index';
export { WithTooltip, WithTooltipPure } from './tooltip/lazy-WithTooltip';
export { TooltipMessage } from './tooltip/TooltipMessage';
export { TooltipNote } from './tooltip/TooltipNote';
export { TooltipLinkList } from './tooltip/TooltipLinkList';
export { TooltipLinkList, type Link as TooltipLinkListLink } from './tooltip/TooltipLinkList';
export { default as ListItem } from './tooltip/ListItem';

// Toolbar and subcomponents
export { Tabs, TabsState, TabBar, TabWrapper } from './tabs/tabs';
Expand All @@ -68,6 +69,7 @@ export { AddonPanel } from './addon-panel/addon-panel';
// Graphics
export type { IconsProps } from './icon/icon';
export { Icons, Symbols } from './icon/icon';
export { icons } from './icon/icons';
export { StorybookLogo } from './brand/StorybookLogo';
export { StorybookIcon } from './brand/StorybookIcon';

Expand Down
1 change: 0 additions & 1 deletion code/ui/components/src/tabs/tabs.hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ export function useList(list: ChildrenList) {
<>
<WithTooltip
interactive
withArrows={false}
visible={isTooltipVisible}
onVisibleChange={setTooltipVisible}
placement="bottom"
Expand Down
23 changes: 19 additions & 4 deletions code/ui/components/src/tabs/tabs.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ import React, { Fragment } from 'react';
import { action } from '@storybook/addon-actions';
import { logger } from '@storybook/client-logger';
import type { Meta, StoryObj } from '@storybook/react';
import { within, fireEvent, waitFor, screen, getByText } from '@storybook/testing-library';
import {
within,
fireEvent,
waitFor,
screen,
getByText,
userEvent,
} from '@storybook/testing-library';
import { Tabs, TabsState, TabWrapper } from './tabs';

const colours = Array.from(new Array(15), (val, index) => index).map((i) =>
Expand Down Expand Up @@ -220,10 +227,18 @@ export const StatefulDynamicWithOpenTooltip = {
const addonsTab = await canvas.findByRole('tab', { name: /Addons/ });

await waitFor(async () => {
await fireEvent(addonsTab, new MouseEvent('mouseenter', { bubbles: true }));
const tooltip = await screen.getByTestId('tooltip');
await expect(tooltip).toBeInTheDocument();
const tooltip = await screen.queryByTestId('tooltip');

if (!tooltip) {
await userEvent.click(addonsTab);
}

if (!tooltip) {
throw new Error('Tooltip not found');
}
});

expect(screen.queryByTestId('tooltip')).toBeInTheDocument();
},
render: (args) => (
<TabsState initial="test1" {...args}>
Expand Down
111 changes: 59 additions & 52 deletions code/ui/components/src/tooltip/ListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import type { FC, ReactNode, ComponentProps } from 'react';
import type { FC, ReactNode, ComponentProps, ReactElement } from 'react';
import React from 'react';
import { styled } from '@storybook/theming';
import memoize from 'memoizerific';
import { transparentize } from 'polished';
import { Icons } from '../icon/icon';
import { icons } from '../icon/icons';

export interface TitleProps {
children?: ReactNode;
Expand Down Expand Up @@ -47,53 +49,39 @@ export interface RightProps {
active?: boolean;
}

const Right = styled.span<RightProps>(
{
'& svg': {
transition: 'all 200ms ease-out',
opacity: 0,
height: 12,
width: 12,
margin: '3px 0',
verticalAlign: 'top',
},
'& path': {
fill: 'inherit',
},
const Right = styled.span<RightProps>({
display: 'flex',
'& svg': {
height: 12,
width: 12,
margin: '3px 0',
verticalAlign: 'top',
},
({ active, theme }) =>
active
? {
'& svg': {
opacity: 1,
},
'& path': {
fill: theme.color.secondary,
},
}
: {}
);

const Center = styled.span({
flex: 1,
textAlign: 'left',
display: 'inline-flex',

'& > * + *': {
paddingLeft: 10,
'& path': {
fill: 'inherit',
},
});

const Center = styled.span<{ isIndented: boolean }>(
{
flex: 1,
textAlign: 'left',
display: 'flex',
flexDirection: 'column',
},
({ isIndented }) => (isIndented ? { marginLeft: 24 } : {})
);

export interface CenterTextProps {
active?: boolean;
disabled?: boolean;
}

const CenterText = styled.span<CenterTextProps>(
{
flex: 1,
textAlign: 'center',
},
({ theme }) => ({
fontSize: '11px',
lineHeight: '14px',
}),
({ active, theme }) =>
active
? {
Expand All @@ -112,17 +100,22 @@ export interface LeftProps {
active?: boolean;
}

const Left = styled.span<LeftProps>(({ active, theme }) =>
active
? {
'& svg': {
opacity: 1,
},
'& path': {
fill: theme.color.primary,
},
}
: {}
const Left = styled.span<LeftProps>(
({ active, theme }) =>
active
? {
'& svg': {
opacity: 1,
},
'& svg path': {
fill: theme.color.secondary,
},
}
: {},
() => ({
display: 'flex',
maxWidth: 14,
})
);

export interface ItemProps {
Expand All @@ -139,7 +132,7 @@ const Item = styled.a<ItemProps>(
justifyContent: 'space-between',

lineHeight: '18px',
padding: '7px 15px',
padding: '7px 10px',
display: 'flex',
alignItems: 'center',

Expand Down Expand Up @@ -188,14 +181,20 @@ export type LinkWrapperType = FC<any>;

export interface ListItemProps extends Omit<ComponentProps<typeof Item>, 'href' | 'title'> {
loading?: boolean;
/**
* @deprecated This property will be removed in SB 8.0
* Use `icon` property instead.
*/
left?: ReactNode;
title?: ReactNode;
center?: ReactNode;
right?: ReactNode;
icon?: keyof typeof icons | ReactElement;
active?: boolean;
disabled?: boolean;
href?: string;
LinkWrapper?: LinkWrapperType;
isIndented?: boolean;
}

const ListItem: FC<ListItemProps> = ({
Expand All @@ -204,8 +203,10 @@ const ListItem: FC<ListItemProps> = ({
title,
center,
right,
icon,
active,
disabled,
isIndented,
href,
onClick,
LinkWrapper,
Expand All @@ -214,11 +215,17 @@ const ListItem: FC<ListItemProps> = ({
const itemProps = getItemProps(onClick, href, LinkWrapper);
const commonProps = { active, disabled };

const isStorybookIcon = typeof icon === 'string' && icons[icon];

return (
<Item {...commonProps} {...rest} {...itemProps}>
{left && <Left {...commonProps}>{left}</Left>}
{icon ? (
<Left {...commonProps}>{isStorybookIcon ? <Icons icon={icon} /> : icon}</Left>
) : (
left && <Left {...commonProps}>{left}</Left>
)}
{title || center ? (
<Center>
<Center isIndented={!left && !icon && isIndented}>
{title && (
<Title {...commonProps} loading={loading}>
{title}
Expand Down
4 changes: 2 additions & 2 deletions code/ui/components/src/tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ const Wrapper = styled.div<WrapperProps>(
drop-shadow(0px 5px 5px rgba(0,0,0,0.05))
drop-shadow(0 1px 3px rgba(0,0,0,0.1))
`,
borderRadius: theme.appBorderRadius * 2,
borderRadius: theme.appBorderRadius,
fontSize: theme.typography.size.s1,
}
: {}
Expand All @@ -126,7 +126,7 @@ export interface TooltipProps {

export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
(
{ placement, hasChrome, children, arrowProps, tooltipRef, color, withArrows = true, ...props },
{ placement, hasChrome, children, arrowProps, tooltipRef, color, withArrows, ...props },
ref
) => {
return (
Expand Down
Loading

0 comments on commit fdce812

Please sign in to comment.