Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 2 additions & 21 deletions code/ui/blocks/src/components/ArgsTable/Empty.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { FC } from 'react';
import React, { useEffect, useState } from 'react';
import { styled } from '@storybook/theming';
import { Icon, Link } from '@storybook/components/experimental';
import { Link } from '@storybook/components/experimental';

interface EmptyProps {
inAddonPanel?: boolean;
Expand Down Expand Up @@ -53,16 +53,6 @@ const Divider = styled.div(({ theme }) => ({
backgroundColor: theme.appBorderColor,
}));

const VideoIcon = styled.div(({ theme }) => ({
width: 22,
height: 16,
borderRadius: theme.appBorderRadius,
border: `1px solid ${theme.color.secondary}`,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}));

export const Empty: FC<EmptyProps> = ({ inAddonPanel }) => {
const [isLoading, setIsLoading] = useState(true);

Expand Down Expand Up @@ -95,16 +85,7 @@ export const Empty: FC<EmptyProps> = ({ inAddonPanel }) => {
<Links>
{inAddonPanel && (
<>
<Link
href="https://youtu.be/0gOfS6K0x0E"
target="_blank"
icon={
<VideoIcon>
<Icon.Play size={8} />
</VideoIcon>
}
withArrow
>
<Link href="https://youtu.be/0gOfS6K0x0E" target="_blank" icon="Video" withArrow>
Watch 5m video
</Link>
<Divider />
Expand Down
1 change: 1 addition & 0 deletions code/ui/components/src/experimental.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ export { Input } from './new/Input/Input';
export { Select } from './new/Select/Select';
export { Link } from './new/Link/Link';
export { Icon } from './new/Icon/Icon';
export { IconButton } from './new/IconButton/IconButton';
34 changes: 17 additions & 17 deletions code/ui/components/src/new/IconButton/IconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const IconButton: {
IconButton.displayName = 'IconButton';

const StyledButton = styled.button<Omit<ButtonProps, 'icon'>>(
({ theme, variant = 'primary', size = 'medium', disabled = false, active = false }) => ({
({ theme, variant = 'solid', size = 'medium', disabled = false, active = false }) => ({
border: 0,
cursor: disabled ? 'not-allowed' : 'pointer',
display: 'inline-flex',
Expand Down Expand Up @@ -64,41 +64,41 @@ const StyledButton = styled.button<Omit<ButtonProps, 'icon'>>(
fontWeight: theme.typography.weight.bold,
lineHeight: '1',
background: `${(() => {
if (variant === 'primary') return theme.color.secondary;
if (variant === 'secondary') return theme.button.background;
if (variant === 'tertiary' && active) return theme.background.hoverable;
if (variant === 'solid') return theme.color.secondary;
if (variant === 'outline') return theme.button.background;
if (variant === 'ghost' && active) return theme.background.hoverable;
return 'transparent';
})()}`,
color: `${(() => {
if (variant === 'primary') return theme.color.lightest;
if (variant === 'secondary') return theme.input.color;
if (variant === 'tertiary' && active) return theme.color.secondary;
if (variant === 'tertiary') return theme.color.mediumdark;
if (variant === 'solid') return theme.color.lightest;
if (variant === 'outline') return theme.input.color;
if (variant === 'ghost' && active) return theme.color.secondary;
if (variant === 'ghost') return theme.color.mediumdark;
return theme.input.color;
})()}`,
boxShadow: variant === 'secondary' ? `${theme.button.border} 0 0 0 1px inset` : 'none',
boxShadow: variant === 'outline' ? `${theme.button.border} 0 0 0 1px inset` : 'none',
borderRadius: theme.input.borderRadius,

'&:hover': {
color: variant === 'tertiary' ? theme.color.secondary : null,
color: variant === 'ghost' ? theme.color.secondary : null,
background: `${(() => {
let bgColor = theme.color.secondary;
if (variant === 'primary') bgColor = theme.color.secondary;
if (variant === 'secondary') bgColor = theme.button.background;
if (variant === 'solid') bgColor = theme.color.secondary;
if (variant === 'outline') bgColor = theme.button.background;

if (variant === 'tertiary') return transparentize(0.86, theme.color.secondary);
if (variant === 'ghost') return transparentize(0.86, theme.color.secondary);
return theme.base === 'light' ? darken(0.02, bgColor) : lighten(0.03, bgColor);
})()}`,
},

'&:active': {
color: variant === 'tertiary' ? theme.color.secondary : null,
color: variant === 'ghost' ? theme.color.secondary : null,
background: `${(() => {
let bgColor = theme.color.secondary;
if (variant === 'primary') bgColor = theme.color.secondary;
if (variant === 'secondary') bgColor = theme.button.background;
if (variant === 'solid') bgColor = theme.color.secondary;
if (variant === 'outline') bgColor = theme.button.background;

if (variant === 'tertiary') return theme.background.hoverable;
if (variant === 'ghost') return theme.background.hoverable;
return theme.base === 'light' ? darken(0.02, bgColor) : lighten(0.03, bgColor);
})()}`,
},
Expand Down
73 changes: 41 additions & 32 deletions code/ui/components/src/new/Link/Link.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import type { Meta, StoryObj } from '@storybook/react';
import React from 'react';

import { Icon } from '@storybook/components/experimental';
import { Link } from './Link';

const meta: Meta<typeof Link> = {
Expand All @@ -26,24 +24,56 @@ export const Variants: Story = {
<Link href="https://storybook.js.org/" variant="secondary">
Secondary
</Link>
<Link href="https://storybook.js.org/" variant="tertiary">
Tertiary
</div>
),
};

export const Underline: Story = {
render: () => (
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
<Link href="https://storybook.js.org/" variant="primary" underline="hover">
Primary
</Link>
<Link href="https://storybook.js.org/" variant="primary" underline="always">
Secondary
</Link>
<Link href="https://storybook.js.org/" variant="secondary" underline="hover">
Secondary
</Link>
<Link href="https://storybook.js.org/" variant="secondary" underline="always">
Secondary
</Link>
</div>
),
};

export const WithIcon: Story = {
export const Weight: Story = {
render: () => (
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
<Link href="https://storybook.js.org/" variant="primary" icon={<Icon.FaceHappy />}>
<Link href="https://storybook.js.org/" variant="primary" weight="regular">
Primary
</Link>
<Link href="https://storybook.js.org/" variant="secondary" icon={<Icon.FaceHappy />}>
<Link href="https://storybook.js.org/" variant="primary" weight="bold">
Secondary
</Link>
<Link href="https://storybook.js.org/" variant="tertiary" icon={<Icon.FaceHappy />}>
Tertiary
<Link href="https://storybook.js.org/" variant="secondary" weight="regular">
Secondary
</Link>
<Link href="https://storybook.js.org/" variant="secondary" weight="bold">
Secondary
</Link>
</div>
),
};

export const WithIcon: Story = {
render: () => (
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
<Link href="https://storybook.js.org/" variant="primary" icon="FaceHappy">
Primary
</Link>
<Link href="https://storybook.js.org/" variant="secondary" icon="FaceHappy">
Secondary
</Link>
</div>
),
Expand All @@ -59,35 +89,14 @@ export const WithArrow: Story = {
<Link href="https://storybook.js.org/" variant="secondary" withArrow>
Secondary
</Link>
<Link href="https://storybook.js.org/" variant="tertiary" withArrow>
Tertiary
</Link>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
<Link
href="https://storybook.js.org/"
variant="primary"
icon={<Icon.FaceHappy />}
withArrow
>
<Link href="https://storybook.js.org/" variant="primary" icon="FaceHappy" withArrow>
Primary
</Link>
<Link
href="https://storybook.js.org/"
variant="secondary"
icon={<Icon.FaceHappy />}
withArrow
>
<Link href="https://storybook.js.org/" variant="secondary" icon="FaceHappy" withArrow>
Secondary
</Link>
<Link
href="https://storybook.js.org/"
variant="tertiary"
icon={<Icon.FaceHappy />}
withArrow
>
Tertiary
</Link>
</div>
</div>
),
Expand Down
73 changes: 36 additions & 37 deletions code/ui/components/src/new/Link/Link.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import type { MouseEvent, ReactNode } from 'react';
import type { MouseEvent } from 'react';
import React, { forwardRef } from 'react';
import { styled } from '@storybook/theming';
import { darken } from 'polished';
import type { Icons } from '@storybook/icons';
import { Icon } from '../Icon/Icon';
import type { PropsOf } from '../utils/types';

export interface LinkProps<T extends React.ElementType = React.ElementType> {
as?: T;
children: string;
variant?: 'primary' | 'secondary' | 'tertiary';
icon?: ReactNode;
variant?: 'primary' | 'secondary';
weight?: 'regular' | 'bold';
underline?: 'hover' | 'always';
icon?: Icons;
onClick?: (e: MouseEvent) => void;
withArrow?: boolean;
}
Expand All @@ -20,11 +22,12 @@ export const Link: {
): JSX.Element;
displayName?: string;
} = forwardRef(
({ as, children, icon, withArrow, ...props }: LinkProps, ref: React.Ref<HTMLAnchorElement>) => {
({ children, icon, withArrow, ...props }: LinkProps, ref: React.Ref<HTMLAnchorElement>) => {
const LocalIcon = Icon[icon];
return (
<StyledLink as={as} ref={ref} {...props}>
<StyledLink ref={ref} {...props}>
<StyledLeft>
{icon}
{icon && <LocalIcon />}
{children}
</StyledLeft>
{withArrow && <Icon.ChevronRight size={8} />}
Expand All @@ -35,39 +38,35 @@ export const Link: {

Link.displayName = 'Link';

const StyledLink = styled.a<Omit<LinkProps, 'children'>>(({ theme, variant = 'primary' }) => ({
display: 'inline-flex',
gap: 4,
alignItems: 'center',
transition: 'all 150ms ease-out',
textDecoration: 'none',
lineHeight: 1,
color: `${(() => {
if (variant === 'primary') return theme.color.secondary;
if (variant === 'secondary') return theme.textMutedColor;
if (variant === 'tertiary') return theme.color.dark;
return theme.color.secondary;
})()}`,

'&:hover, &:focus': {
cursor: 'pointer',
const StyledLink = styled.a<Omit<LinkProps, 'children'>>(
({ theme, variant = 'primary', underline = 'hover', weight = 'regular' }) => ({
display: 'inline-flex',
gap: 4,
alignItems: 'center',
transition: 'all 150ms ease-out',
textDecoration: 'none',
lineHeight: 1,
color: `${(() => {
if (variant === 'primary') return darken(0.07, theme.color.secondary);
if (variant === 'secondary') return theme.color.dark;
if (variant === 'tertiary') return theme.color.darkest;
return darken(0.07, theme.color.secondary);
if (variant === 'primary') return theme.color.secondary;
if (variant === 'secondary') return theme.color.defaultText;
return theme.color.secondary;
})()}`,
},

'&:active': {
color: `${(() => {
if (variant === 'primary') return darken(0.1, theme.color.secondary);
if (variant === 'secondary') return theme.color.darker;
if (variant === 'tertiary') return theme.textMutedColor;
return darken(0.1, theme.color.secondary);
fontWeight: `${(() => {
if (weight === 'regular') return theme.typography.weight.regular;
if (weight === 'bold') return theme.typography.weight.bold;
return theme.typography.weight.bold;
})()}`,
},
}));
textDecorationLine: `${underline === 'always' ? 'underline' : 'none'}`,
textDecorationStyle: 'solid',
textDecorationThickness: '1px',
textUnderlineOffset: '2px',

'&:hover, &:focus': {
cursor: 'pointer',
textDecorationLine: 'underline',
},
})
);

const StyledLeft = styled.span(({ theme }) => ({
display: 'inline-flex',
Expand Down
2 changes: 1 addition & 1 deletion code/ui/manager/src/globals/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export default {
'resetComponents',
'withReset',
],
'@storybook/components/experimental': ['Button', 'Icon', 'Input', 'Link', 'Select'],
'@storybook/components/experimental': ['Button', 'Icon', 'IconButton', 'Input', 'Link', 'Select'],
'@storybook/channels': [
'Channel',
'PostMessageTransport',
Expand Down