Merge branch 'master' into test/Cypress-BDD-integration

This commit is contained in:
Joe 2022-03-08 10:28:41 +00:00
commit 82c426ded8
50 changed files with 4726 additions and 3736 deletions

View File

@ -1,6 +1,6 @@
module.exports = {
stories: [],
addons: ['@storybook/addon-essentials'],
addons: ['@storybook/addon-essentials', '@storybook/addon-a11y'],
// uncomment the property below if you want to apply some webpack config globally
// webpackFinal: async (config, { configType }) => {
// // Make whatever fine-grained changes you need that should apply to all storybook configs

View File

@ -20,6 +20,15 @@ NX_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
# App configuration variables
NX_CHAIN_EXPLORER_URL = "https://explorer.vega.trading/.netlify/functions/chain-explorer-api"
NX_TENDERMINT_URL = "https://mainnet-observer-proxy01.ops.vega.xyz"
NX_TENDERMINT_WEBSOCKET_URL = "wss://mainnet-observer-proxy01.ops.vega.xyz/websocket"
NX_VEGA_URL = "http://mainnet-observer.ops.vega.xyz:3008/query"
NX_TENDERMINT_URL = "https://lb.testnet.vega.xyz/tm"
NX_TENDERMINT_WEBSOCKET_URL = "wss://lb.testnet.vega.xyz/tm/websocket"
NX_VEGA_URL = "https://lb.testnet.vega.xyz/query"
# App flags
NX_EXPLORER_ASSETS = 1
NX_EXPLORER_GENESIS = 1
NX_EXPLORER_GOVERNANCE = 1
NX_EXPLORER_MARKETS = 1
NX_EXPLORER_NETWORK_PARAMETERS = 1
NX_EXPLORER_PARTIES = 1
NX_EXPLORER_VALIDATORS = 1

View File

@ -0,0 +1,15 @@
const { env } = process;
const truthy = ['1', 'true'];
export default {
assets: truthy.includes(env['NX_EXPLORER_ASSETS'] || ''),
genesis: truthy.includes(env['NX_EXPLORER_GENESIS'] || ''),
governance: truthy.includes(env['NX_EXPLORER_GOVERNANCE'] || ''),
markets: truthy.includes(env['NX_EXPLORER_MARKETS'] || ''),
networkParameters: truthy.includes(
env['NX_EXPLORER_NETWORK_PARAMETERS'] || ''
),
parties: truthy.includes(env['NX_EXPLORER_PARTIES'] || ''),
validators: truthy.includes(env['NX_EXPLORER_VALIDATORS'] || ''),
};

View File

@ -1,7 +1,24 @@
import { gql, useQuery } from '@apollo/client';
import React from 'react';
import { SyntaxHighlighter } from '../../components/syntax-highlighter';
import { ProposalsQuery } from './__generated__/ProposalsQuery';
import {
ProposalsQuery,
ProposalsQuery_proposals_terms_change,
} from './__generated__/ProposalsQuery';
export function getProposalName(change: ProposalsQuery_proposals_terms_change) {
if (change.__typename === 'NewAsset') {
return `New asset: ${change.symbol}`;
} else if (change.__typename === 'NewMarket') {
return `New market: ${change.instrument.name}`;
} else if (change.__typename === 'UpdateMarket') {
return `Update market: ${change.marketId}`;
} else if (change.__typename === 'UpdateNetworkParameter') {
return `Update network: ${change.networkParameter.key}`;
}
return 'Unknown proposal';
}
const PROPOSAL_QUERY = gql`
query ProposalsQuery {
@ -90,7 +107,7 @@ const Governance = () => {
{data.proposals.map((p) => (
<React.Fragment key={p.id}>
{/* TODO get proposal name generator from console */}
<h2>{p.id}</h2>
<h2>{getProposalName(p.terms.change)}</h2>
<SyntaxHighlighter data={p} />
</React.Fragment>
))}

View File

@ -15,7 +15,7 @@ import { Blocks } from './blocks/home';
import { Tx } from './txs/id';
import { Txs as TxHome } from './txs/home';
import { PendingTxs } from './pending';
import flags from '../lib/flags';
export const Routes = {
HOME: '/',
TX: 'txs',
@ -29,6 +29,85 @@ export const Routes = {
NETWORK_PARAMETERS: 'network-parameters',
};
const partiesRoutes = flags.parties
? [
{
path: Routes.PARTIES,
name: 'Parties',
element: <Party />,
children: [
{
index: true,
element: <Parties />,
},
{
path: ':party',
element: <PartySingle />,
},
],
},
]
: [];
const assetsRoutes = flags.assets
? [
{
path: Routes.ASSETS,
name: 'Assets',
element: <Assets />,
},
]
: [];
const genesisRoutes = flags.genesis
? [
{
path: Routes.GENESIS,
name: 'Genesis',
element: <Genesis />,
},
]
: [];
const governanceRoutes = flags.governance
? [
{
path: Routes.GOVERNANCE,
name: 'Governance',
element: <Governance />,
},
]
: [];
const marketsRoutes = flags.markets
? [
{
path: Routes.MARKETS,
name: 'Markets',
element: <Markets />,
},
]
: [];
const networkParametersRoutes = flags.networkParameters
? [
{
path: Routes.NETWORK_PARAMETERS,
name: 'NetworkParameters',
element: <NetworkParameters />,
},
]
: [];
const validators = flags.validators
? [
{
path: Routes.VALIDATORS,
name: 'Validators',
element: <Validators />,
},
]
: [];
const routerConfig = [
{
path: Routes.HOME,
@ -70,51 +149,13 @@ const routerConfig = [
},
],
},
{
path: Routes.PARTIES,
name: 'Parties',
element: <Party />,
children: [
{
index: true,
element: <Parties />,
},
{
path: ':party',
element: <PartySingle />,
},
],
},
{
path: Routes.ASSETS,
name: 'Assets',
element: <Assets />,
},
{
path: Routes.GENESIS,
name: 'Genesis',
element: <Genesis />,
},
{
path: Routes.GOVERNANCE,
name: 'Governance',
element: <Governance />,
},
{
path: Routes.MARKETS,
name: 'Markets',
element: <Markets />,
},
{
path: Routes.NETWORK_PARAMETERS,
name: 'NetworkParameters',
element: <NetworkParameters />,
},
{
path: Routes.VALIDATORS,
name: 'Validators',
element: <Validators />,
},
...partiesRoutes,
...assetsRoutes,
...genesisRoutes,
...governanceRoutes,
...marketsRoutes,
...networkParametersRoutes,
...validators,
];
export default routerConfig;

View File

@ -1,3 +1,5 @@
import * as Sentry from '@sentry/react';
import { BrowserTracing } from '@sentry/tracing';
import { StrictMode } from 'react';
import * as ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
@ -5,6 +7,18 @@ import './styles.css';
import App from './app/app';
const dsn = process.env['NX_SENTRY_DSN'];
/* istanbul ignore next */
if (dsn) {
Sentry.init({
dsn,
integrations: [new BrowserTracing()],
tracesSampleRate: 0.1,
environment: process.env['NODE_ENV'],
});
}
ReactDOM.render(
<StrictMode>
<BrowserRouter>

View File

@ -8,72 +8,47 @@ module.exports = {
colors: {
transparent: 'transparent',
current: 'currentColor',
black: '#000',
white: '#FFF',
neutral: {
// 250 - 23 = 227; (900-50) / 227 = 850 / 227 = 3.74449339207
50: '#fafafa', // FA = 250
100: '#ebebeb',
150: '#dcdcdc',
200: '#cdcdcd',
250: '#bebebe',
300: '#afafaf',
350: '#a1a1a1',
400: '#939393',
450: '#858585',
500: '#787878',
550: '#6a6a6a',
593: '#696969', // dark muted
600: '#5d5d5d',
650: '#515151',
700: '#444444',
753: '#3E3E3E', // dark -> 3F is muted
750: '#383838',
800: '#2d2d2d', // breakdown-background was 2C
850: '#222222',
900: '#171717', // 17 = 23
white: {
DEFAULT: '#FFF',
'02': 'rgba(255, 255, 255, 0.02)',
'05': 'rgba(255, 255, 255, 0.05)',
10: 'rgba(255, 255, 255, 0.10)',
25: 'rgba(255, 255, 255, 0.25)',
40: 'rgba(255, 255, 255, 0.40)',
60: 'rgba(255, 255, 255, 0.60)',
80: 'rgba(255, 255, 255, 0.80)',
95: 'rgba(255, 255, 255, 0.95)',
100: 'rgba(255, 255, 255, 1.00)',
},
black: {
DEFAULT: '#000',
'02': 'rgba(0, 0, 0, 0.02)',
'05': 'rgba(0, 0, 0, 0.05)',
10: 'rgba(0, 0, 0, 0.10)',
25: 'rgba(0, 0, 0, 0.25)',
40: 'rgba(0, 0, 0, 0.40)',
60: 'rgba(0, 0, 0, 0.60)',
80: 'rgba(0, 0, 0, 0.80)',
95: 'rgba(0, 0, 0, 0.95)',
100: 'rgba(0, 0, 0, 1)',
},
'light-gray-50': '#F5F8FA', //off-white - https://blueprintjs.com/docs/#core/colors
'gray-50': '#BFCCD6', // muted - https://blueprintjs.com/docs/#core/colors
coral: '#FF6057',
// below colors are not defined as atoms
vega: {
yellow: '#EDFF22',
pink: '#FF2D5E',
green: '#00F780',
},
'vega-yellow-dark': '#474B0A', // yellow 0.3 opacity on black
intent: {
danger: '#FF261A',
warning: '#FF7A1A',
prompt: '#EDFF22',
progress: '#FFF',
success: '#26FF8A',
help: '#494949',
background: {
danger: '#9E0025', // for white text
},
} /*,
data: {
red: {
white: {
50: '#FFFFFF',
220: '#FF6057', // overlay FFF 80%
390: '#FF6057', // overlay FFF 60%
560: '#FF6057', // overlay FFF 40%
730: '#FF6057', // overlay FFF 20%
900: '#FF6057',
},
green: {
50: '#30F68B',
220: '#89DC50',
475: '#F2BD09',
730: '#FF8501',
900: '#FF6057',
},
},
},*/,
},
'intent-background': {
danger: '#9E0025', // for white text
},
},
spacing: {
0: '0px',
@ -81,17 +56,37 @@ module.exports = {
4: '0.25rem',
8: '0.5rem',
12: '0.75rem',
16: '1rem',
20: '1.25rem',
24: '1.5rem',
28: '1.75rem',
32: '2rem',
44: '2.75rem',
},
backgroundColor: ({ theme }) => ({
transparent: 'transparent',
dark: theme('colors.dark'),
black: '#000',
white: theme('colors.white'),
danger: theme('colors.intent.background.danger'),
'neutral-200': theme('colors.neutral.200'),
}),
opacity: {
0: '0',
2: '0.02',
5: '0.05',
10: '0.1',
15: '0.15',
20: '0.2',
25: '0.25',
30: '0.3',
35: '0.35',
40: '0.4',
45: '0.45',
50: '0.5',
55: '0.55',
60: '0.6',
65: '0.65',
70: '0.7',
75: '0.75',
80: '0.8',
85: '0.85',
90: '0.9',
95: '0.95',
100: '1',
},
borderWidth: {
DEFAULT: '1px',
1: '1px',
@ -131,12 +126,12 @@ module.exports = {
],
},
fontSize: {
h1: ['72px', { lineHeight: '92px', letterSpacing: '-1%' }],
h2: ['48px', { lineHeight: '64px', letterSpacing: '-1%' }],
h3: ['32px', { lineHeight: '40px', letterSpacing: '-1%' }],
h1: ['72px', { lineHeight: '92px', letterSpacing: '-0.01em' }],
h2: ['48px', { lineHeight: '64px', letterSpacing: '-0.01em' }],
h3: ['32px', { lineHeight: '40px', letterSpacing: '-0.01em' }],
h4: ['24px', { lineHeight: '36px', letterSpacing: '-1%' }],
h5: ['18px', { lineHeight: '28px', letterSpacing: '-1%' }],
h4: ['24px', { lineHeight: '36px', letterSpacing: '-0.01em' }],
h5: ['18px', { lineHeight: '28px', letterSpacing: '-0.01em' }],
'body-large': ['16px', '24px'],
body: ['14px', '20px'],
@ -147,7 +142,9 @@ module.exports = {
extend: {
boxShadow: {
callout: '5px 5px 0 1px rgba(0, 0, 0, 0.05)',
callout: '5px 5px 0 1px rgba(255, 255, 255, 0.05)',
focus: '0px 0px 0px 1px #FFFFFF, 0px 0px 3px 2px #FFE600',
'focus-dark': '0px 0px 0px 1px #000000, 0px 0px 3px 2px #FFE600',
},
},
};

View File

@ -1,19 +1,29 @@
import '../src/styles.scss';
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
themes: {
/*themes: {
default: 'dark',
list: [
{ name: 'dark', class: ['dark', 'bg-black'], color: '#000' },
{ name: 'light', class: '', color: '#FFF' },
],
},
},*/
};
export const decorators = [
(Story) => (
<div className="dark bg-black">
<Story />
</div>
),
(Story, context) =>
context.parameters.themes === false ? (
<div className="text-body">
<Story />
</div>
) : (
<div className="text-body">
<div className="dark bg-black p-16">
<Story />
</div>
<div className="p-16">
<Story />
</div>
</div>
),
];

View File

@ -0,0 +1,10 @@
import { render } from '@testing-library/react';
import { Button } from './button';
describe('Button', () => {
it('should render successfully', () => {
const { baseElement } = render(<Button>Label</Button>);
expect(baseElement).toBeTruthy();
});
});

View File

@ -0,0 +1,101 @@
import { Story, Meta } from '@storybook/react';
import { Button } from './button';
export default {
component: Button,
title: 'Button',
} as Meta;
const Template: Story = (args) => (
<>
<div className="mb-8">
<Button {...args} />
</div>
{args['variant'] !== 'inline' && <Button {...args} disabled />}
</>
);
export const Primary = Template.bind({});
Primary.args = {
children: 'Primary',
};
export const Secondary = Template.bind({});
Secondary.args = {
children: 'Secondary',
variant: 'secondary',
};
export const Accent = Template.bind({});
Accent.args = {
children: 'Accent',
variant: 'accent',
};
export const Inline = Template.bind({});
Inline.args = {
children: 'Inline',
variant: 'inline',
};
export const NavAccent: Story = (args) => (
<>
<div className="mb-8">
<Button variant="accent" className="px-4">
Background
</Button>
</div>
<div className="mb-8">
<Button variant="accent" className="px-4" prependIconName="menu-open">
Background
</Button>
</div>
<div className="mb-8">
<Button variant="accent" className="px-4" appendIconName="menu-closed">
Background
</Button>
</div>
</>
);
export const NavInline: Story = (args) => (
<>
<div className="mb-8">
<Button variant="inline" className="uppercase">
Background
</Button>
</div>
<div className="mb-8">
<Button
variant="inline"
className="uppercase"
prependIconName="menu-open"
>
Background
</Button>
</div>
<div className="mb-8">
<Button
variant="inline"
className="uppercase"
appendIconName="menu-closed"
>
Background
</Button>
</div>
</>
);
export const IconPrepend = Template.bind({});
IconPrepend.args = {
children: 'Icon prepend',
prependIconName: 'search',
variant: 'accent',
};
export const IconAppend = Template.bind({});
IconAppend.args = {
children: 'Icon append',
appendIconName: 'search',
variant: 'accent',
};

View File

@ -0,0 +1,161 @@
import { AnchorHTMLAttributes, ButtonHTMLAttributes, forwardRef } from 'react';
import classNames from 'classnames';
import { Icon, IconName } from '../icon';
interface CommonProps {
children?: React.ReactNode;
variant?: 'primary' | 'secondary' | 'accent' | 'inline';
className?: string;
prependIconName?: IconName;
appendIconName?: IconName;
}
export interface ButtonProps
extends ButtonHTMLAttributes<HTMLButtonElement>,
CommonProps {}
export interface AnchorButtonProps
extends AnchorHTMLAttributes<HTMLAnchorElement>,
CommonProps {}
const getClassName = (
className: CommonProps['className'],
variant: CommonProps['variant']
) => {
const noPaddingLeftProvided = !(
className?.match(/(^| )p(l|x)-\d+( |$)/) || variant === 'inline'
);
const noPaddingRightProvided = !(
className?.match(/(^| )p(r|x)-\d+( |$)/) || variant === 'inline'
);
return classNames(
[
'inline-flex',
'items-center',
'justify-center',
'box-border',
'h-28',
'border',
'text-ui',
'no-underline',
'hover:underline',
'disabled:no-underline',
'transition-all',
],
{
'pl-28': noPaddingLeftProvided,
'pr-28': noPaddingRightProvided,
'hover:border-black dark:hover:border-white': variant !== 'inline',
'active:border-black dark:active:border-white': true,
'bg-black dark:bg-white': variant === 'primary',
'border-black-60 dark:border-white-60':
variant === 'primary' || variant === 'secondary',
'text-white dark:text-black': variant === 'primary',
'hover:bg-black-80 dark:hover:bg-white-80': variant === 'primary',
'active:bg-white dark:active:bg-black':
variant === 'primary' || variant === 'accent',
'active:text-black dark:active:text-white':
variant === 'primary' || variant === 'accent',
'bg-white dark:bg-black': variant === 'secondary',
'text-black dark:text-white': variant === 'secondary',
'hover:bg-black-25 dark:hover:bg-white-25': variant === 'secondary',
'hover:text-black dark:hover:text-white':
variant === 'secondary' || variant === 'accent',
'active:bg-black dark:active:bg-white': variant === 'secondary',
'active:text-white dark:active:text-black': variant === 'secondary',
uppercase: variant === 'accent',
'bg-vega-yellow dark:bg-vega-yellow': variant === 'accent',
'border-transparent dark:border-transparent':
variant === 'accent' || variant === 'inline',
'hover:bg-vega-yellow-dark dark:hover:bg-vega-yellow/30':
variant === 'accent',
'hover:text-white dark:hover:text-white': variant === 'accent',
'pl-4': variant === 'inline',
'pr-4': variant === 'inline',
'border-0': variant === 'inline',
underline: variant === 'inline',
'hover:no-underline': variant === 'inline',
'hover:border-transparent dark:hover:border-transparent':
variant === 'inline',
'active:border-transparent dark:active:border-transparent':
variant === 'inline',
'active:text-black dark:active:text-vega-yellow': variant === 'inline',
'text-black-95 dark:text-white-95': variant === 'inline',
'hover:text-black hover:dark:text-white': variant === 'inline',
'disabled:bg-black-10 dark:disabled:bg-white-10': variant !== 'inline',
'disabled:text-black-60 dark:disabled:text-white-60':
variant !== 'inline',
'disabled:border-black-25 dark:disabled:border-white-25':
variant !== 'inline',
},
className
);
};
const getContent = (
children: React.ReactNode,
prependIconName?: IconName,
appendIconName?: IconName
) => {
const iconName = prependIconName || appendIconName;
if (iconName === undefined) {
return children;
}
const iconClassName = classNames(['fill-current'], {
'mr-8': prependIconName,
'ml-8': appendIconName,
});
const icon = <Icon name={iconName} className={iconClassName} size={16} />;
return (
<>
{prependIconName && icon}
{children}
{appendIconName && icon}
</>
);
};
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
(
{
variant = 'primary',
children,
className,
prependIconName,
appendIconName,
...props
},
ref
) => {
return (
<button ref={ref} className={getClassName(className, variant)} {...props}>
{getContent(children, prependIconName, appendIconName)}
</button>
);
}
);
export const AnchorButton = forwardRef<HTMLAnchorElement, AnchorButtonProps>(
(
{
variant = 'primary',
children,
className,
prependIconName,
appendIconName,
...prosp
},
ref
) => {
return (
<a ref={ref} className={getClassName(className, variant)} {...prosp}>
{getContent(children, prependIconName, appendIconName)}
</a>
);
}
);

View File

@ -0,0 +1 @@
export * from './button';

View File

@ -1,58 +0,0 @@
@import '../../styles/colors';
.callout {
display: flex;
padding: 14px;
border: 1px solid $white;
box-shadow: 3px 3px 0px $white;
margin: 12px 0;
p {
margin: 0 0 10px 0;
&:last-child {
margin-bottom: 0;
}
}
// VARIATIONS
&--error {
box-shadow: 5px 5px 0px $vega-red3;
}
&--success {
box-shadow: 5px 5px 0px $vega-green3;
}
&--warn {
box-shadow: 5px 5px 0px $vega-orange3;
}
&--action {
box-shadow: 5px 5px 0px $vega-yellow3;
}
&__content {
width: 100%;
> :last-child {
margin-bottom: 0;
}
}
&__title,
h4,
h5,
h6 {
margin-bottom: 15px;
}
&__title {
margin-top: 0;
}
&__icon {
margin-right: 10px;
color: $white;
}
}

View File

@ -1,7 +1,8 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Callout } from '.';
import { Callout } from './callout';
import { Button } from '../button';
export default {
title: 'Callout',
@ -9,37 +10,61 @@ export default {
} as ComponentMeta<typeof Callout>;
const Template: ComponentStory<typeof Callout> = (args) => (
<Callout {...args}>Content</Callout>
<Callout {...args} />
);
export const Default = Template.bind({});
Default.args = {
children: 'Content',
};
export const Danger = Template.bind({});
Danger.args = {
intent: 'danger',
children: 'Content',
};
export const Warning = Template.bind({});
Warning.args = {
intent: 'warning',
children: 'Content',
};
export const Prompt = Template.bind({});
Prompt.args = {
intent: 'prompt',
children: 'Content',
};
export const Progress = Template.bind({});
Progress.args = {
intent: 'progress',
children: 'Content',
};
export const Success = Template.bind({});
Success.args = {
intent: 'success',
children: 'Content',
};
export const Help = Template.bind({});
Help.args = {
intent: 'help',
children: 'Content',
};
export const IconAndContent = Template.bind({});
IconAndContent.args = {
intent: 'help',
title: 'This is what this thing does',
iconName: 'endorsed',
children: (
<div className="flex flex-col">
<div>With a longer explaination</div>
<Button className="block mt-8" variant="secondary">
Action
</Button>
</div>
),
};

View File

@ -8,8 +8,10 @@ test('It renders content within callout', () => {
});
test('It renders title and icon', () => {
render(<Callout icon={<div data-testid="icon" />} title="title" />);
expect(screen.getByTestId('icon')).toBeInTheDocument();
render(<Callout iconName="endorsed" title="title" />);
expect(
screen.getByTestId('callout').querySelector('svg')
).toBeInTheDocument();
expect(screen.getByText('title')).toBeInTheDocument();
});
@ -33,7 +35,7 @@ intents.map((intent) =>
test(`Applies class for progress`, () => {
render(<Callout intent="progress" />);
expect(screen.getByTestId('callout')).toHaveClass(
'shadow-intent-black',
'dark:shadow-intent-progress'
'shadow-black',
'dark:shadow-white'
);
});

View File

@ -1,48 +1,55 @@
import React from 'react';
import classNames from 'classnames';
import { Icon, IconName } from '../icon';
export const Callout = ({
children,
title,
intent = 'help',
icon,
headingLevel,
}: {
export interface CalloutProps {
children?: React.ReactNode;
title?: React.ReactElement | string;
intent?: 'danger' | 'warning' | 'prompt' | 'progress' | 'success' | 'help';
icon?: React.ReactNode;
iconName?: IconName;
headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;
}) => {
}
export function Callout({
children,
title,
intent = 'help',
iconName,
headingLevel,
}: CalloutProps) {
const className = classNames(
'shadow-callout',
'border',
'border-black',
'dark:border-white',
'text-body-large',
'dark:text-white',
'p-8',
{
'shadow-intent-danger': intent === 'danger',
'shadow-intent-warning': intent === 'warning',
'shadow-intent-prompt': intent === 'prompt',
'shadow-intent-black dark:shadow-intent-progress': intent === 'progress',
'shadow-black dark:shadow-white': intent === 'progress',
'shadow-intent-success': intent === 'success',
'shadow-intent-help': intent === 'help',
flex: icon,
flex: !!iconName,
}
);
const TitleTag: keyof JSX.IntrinsicElements = headingLevel
? `h${headingLevel}`
: 'div';
const icon = iconName && (
<Icon name={iconName} className="fill-current ml-8 mr-16 mt-8" size={20} />
);
const body = (
<div className="body-large dark:text-white">
<>
{title && <TitleTag className="text-h5">{title}</TitleTag>}
{children}
</div>
</>
);
return (
<div data-testid="callout" className={className}>
{icon && <div className="">{icon}</div>}
{icon}
{icon ? <div className="grow">{body}</div> : body}
</div>
);
};
}

View File

@ -1,6 +1,5 @@
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import * as React from 'react';
import { EtherscanLink } from '.';
import { EthereumChainIds } from '../../utils/web3';

View File

@ -0,0 +1,10 @@
import { render } from '@testing-library/react';
import { Icon } from './icon';
describe('Icon', () => {
it('should render successfully', () => {
const { baseElement } = render(<Icon name="add" />);
expect(baseElement).toBeTruthy();
});
});

View File

@ -0,0 +1,22 @@
import { Story, Meta } from '@storybook/react';
import { Icon } from './icon';
export default {
component: Icon,
title: 'Input',
} as Meta;
const Template: Story = (args) => <Icon {...args} name="warning-sign" />;
export const Default = Template.bind({});
Default.args = {};
export const WithError = Template.bind({});
WithError.args = {
hasError: true,
};
export const Disabled = Template.bind({});
Disabled.args = {
disabled: true,
};

View File

@ -0,0 +1,32 @@
import { IconSvgPaths20, IconSvgPaths16, IconName } from '@blueprintjs/icons';
import classNames from 'classnames';
export type { IconName } from '@blueprintjs/icons';
interface IconProps {
hasError?: boolean;
disabled?: boolean;
name: IconName;
className?: string;
size?: 16 | 20 | 24 | 32 | 48 | 64;
}
export const Icon = ({ size = 16, name, className }: IconProps) => {
const effectiveClassName = classNames(
{
'w-20': size === 20,
'h-20': size === 20,
'w-16': size === 16,
'h-16': size === 16,
},
className
);
const viewbox = size <= 16 ? '0 0 16 16' : '0 0 20 20';
return (
<svg className={effectiveClassName} viewBox={viewbox}>
{(size <= 16 ? IconSvgPaths16 : IconSvgPaths20)[name].map((d, key) => (
<path fillRule="evenodd" clipRule="evenodd" d={d} key={key} />
))}
</svg>
);
};

View File

@ -0,0 +1 @@
export * from './icon';

View File

@ -0,0 +1 @@
export * from './input-error';

View File

@ -0,0 +1,10 @@
import { render } from '@testing-library/react';
import { InputError } from './input-error';
describe('InputError', () => {
it('should render successfully', () => {
const { baseElement } = render(<InputError />);
expect(baseElement).toBeTruthy();
});
});

View File

@ -0,0 +1,20 @@
import { Story, Meta } from '@storybook/react';
import { InputError } from './input-error';
export default {
component: InputError,
title: 'InputError',
} as Meta;
const Template: Story = (args) => <InputError {...args} />;
export const Danger = Template.bind({});
Danger.args = {
children: 'An error that might have happened',
};
export const Warning = Template.bind({});
Warning.args = {
intent: 'warning',
children: 'Something that might be an issue',
};

View File

@ -0,0 +1,41 @@
import classNames from 'classnames';
import { Icon } from '../icon';
interface InputErrorProps {
children?: React.ReactNode;
className?: string;
intent?: 'danger' | 'warning';
}
export const InputError = ({
intent = 'danger',
className,
children,
}: InputErrorProps) => {
const effectiveClassName = classNames(
[
'inline-flex',
'items-center',
'box-border',
'h-28',
'border-l-4',
'text-black-95 dark:text-white-95',
'text-ui',
],
{
'border-intent-danger': intent === 'danger',
'border-intent-warning': intent === 'warning',
},
className
);
const iconClassName = classNames(['mx-8'], {
'fill-intent-danger': intent === 'danger',
'fill-intent-warning': intent === 'warning',
});
return (
<div className={effectiveClassName}>
<Icon name="warning-sign" className={iconClassName} />
{children}
</div>
);
};

View File

@ -0,0 +1 @@
export * from './input';

View File

@ -0,0 +1,10 @@
import { render } from '@testing-library/react';
import { Input } from './input';
describe('Input', () => {
it('should render successfully', () => {
const { baseElement } = render(<Input />);
expect(baseElement).toBeTruthy();
});
});

View File

@ -0,0 +1,29 @@
import { Story, Meta } from '@storybook/react';
import { Input } from './input';
export default {
component: Input,
title: 'Input',
} as Meta;
const Template: Story = (args) => <Input {...args} value="I type words" />;
export const Default = Template.bind({});
Default.args = {};
export const WithError = Template.bind({});
WithError.args = {
hasError: true,
};
export const Disabled = Template.bind({});
Disabled.args = {
disabled: true,
};
export const IconPrepend: Story = () => (
<Input value="I type words" prependIconName="search" />
);
export const IconAppend: Story = () => (
<Input value="I type words and even more words" appendIconName="search" />
);

View File

@ -0,0 +1,96 @@
import { InputHTMLAttributes, forwardRef } from 'react';
import classNames from 'classnames';
import { Icon, IconName } from '../icon';
interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
hasError?: boolean;
disabled?: boolean;
className?: string;
prependIconName?: IconName;
appendIconName?: IconName;
}
export const inputClassNames = ({
hasError,
className,
}: {
hasError?: boolean;
className?: string;
}) => {
const noPaddingLeftProvided = !className?.match(/(^| )p(l|x)-\d+( |$)/);
const noPaddingRightProvided = !className?.match(/(^| )p(r|x)-\d+( |$)/);
return classNames(
[
'inline-flex',
'items-center',
'box-border',
'border',
'bg-clip-padding',
'border-black-60 dark:border-white-60',
'bg-black-25 dark:bg-white-25',
'text-black-60 dark:text-white-60',
'text-ui',
'focus-visible:shadow-focus dark:focus-visible:shadow-focus-dark',
'focus-visible:outline-0',
'disabled:bg-black-10 disabled:dark:bg-white-10',
],
{
'pl-8': noPaddingLeftProvided,
'pr-8': noPaddingRightProvided,
'border-vega-pink dark:border-vega-pink': hasError,
},
className
);
};
export const inputStyle = ({
style,
disabled,
}: {
style?: React.CSSProperties;
disabled?: boolean;
}) =>
disabled
? {
...style,
backgroundImage:
'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAAXNSR0IArs4c6QAAACNJREFUGFdjtLS0/M8ABcePH2eEsRlJl4BpBdHIuuFmEi0BABqjEQVjx/LTAAAAAElFTkSuQmCC)',
}
: style;
export const Input = forwardRef<HTMLInputElement, InputProps>(
({ prependIconName, appendIconName, className, ...props }, ref) => {
className = `${className} h-28`;
if (prependIconName) {
className += ' pl-28';
}
if (appendIconName) {
className += ' pr-28';
}
const input = (
<input
{...props}
ref={ref}
className={classNames(inputClassNames({ className, ...props }))}
/>
);
const iconName = prependIconName || appendIconName;
if (iconName !== undefined) {
const iconClassName = classNames(
['fill-black-60 dark:fill-white-60', 'absolute', 'z-10'],
{
'left-8': prependIconName,
'right-8': appendIconName,
}
);
const icon = <Icon name={iconName} className={iconClassName} size={16} />;
return (
<div className="inline-flex items-center relative">
{prependIconName && icon}
{input}
{appendIconName && icon}
</div>
);
}
return input;
}
);

View File

@ -0,0 +1 @@
export * from './select';

View File

@ -0,0 +1,10 @@
import { render } from '@testing-library/react';
import { Select } from './select';
describe('Select', () => {
it('should render successfully', () => {
const { baseElement } = render(<Select />);
expect(baseElement).toBeTruthy();
});
});

View File

@ -0,0 +1,26 @@
import { Story, Meta } from '@storybook/react';
import { Select } from './select';
export default {
component: Select,
title: 'Select',
} as Meta;
const Template: Story = (args) => (
<Select {...args}>
<option value="Only option">Only option</option>
</Select>
);
export const Default = Template.bind({});
Default.args = {};
export const WithError = Template.bind({});
WithError.args = {
hasError: true,
};
export const Disabled = Template.bind({});
Disabled.args = {
disabled: true,
};

View File

@ -0,0 +1,20 @@
import { SelectHTMLAttributes, forwardRef } from 'react';
import classNames from 'classnames';
import { inputClassNames } from '../input/input';
export interface SelectProps extends SelectHTMLAttributes<HTMLSelectElement> {
hasError?: boolean;
className?: string;
value?: string | number;
children?: React.ReactNode;
}
export const Select = forwardRef<HTMLSelectElement, SelectProps>(
(props, ref) => (
<select
ref={ref}
{...props}
className={classNames(inputClassNames(props), 'h-28')}
/>
)
);

View File

@ -0,0 +1 @@
export * from './text-area';

View File

@ -0,0 +1,10 @@
import { render } from '@testing-library/react';
import { TextArea } from './text-area';
describe('TextArea', () => {
it('should render successfully', () => {
const { baseElement } = render(<TextArea />);
expect(baseElement).toBeTruthy();
});
});

View File

@ -0,0 +1,26 @@
import { Story, Meta } from '@storybook/react';
import { TextArea } from './text-area';
export default {
component: TextArea,
title: 'TextArea',
} as Meta;
const Template: Story = (args) => (
<TextArea {...args} className="h-48">
I type words
</TextArea>
);
export const Default = Template.bind({});
Default.args = {};
export const WithError = Template.bind({});
WithError.args = {
hasError: true,
};
export const Disabled = Template.bind({});
Disabled.args = {
disabled: true,
};

View File

@ -0,0 +1,14 @@
import { TextareaHTMLAttributes, forwardRef } from 'react';
import { inputClassNames } from '../input/input';
export interface TextAreaProps
extends TextareaHTMLAttributes<HTMLTextAreaElement> {
hassError?: boolean;
className?: string;
}
export const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
(props, ref) => (
<textarea {...props} ref={ref} className={inputClassNames(props)} />
)
);

View File

@ -1,5 +1,11 @@
import * as EthereumUtils from './utils/web3';
export { Button } from './components/button';
export { Callout } from './components/callout';
export { EtherscanLink } from './components/etherscan-link';
export { EthereumUtils };
export { EtherscanLink } from './components/etherscan-link';
export { Icon } from './components/icon';
export { Input } from './components/input';
export { InputError } from './components/input-error';
export { Select } from './components/select';
export { TextArea } from './components/text-area';

View File

@ -0,0 +1,77 @@
import {
Meta,
ColorPalette,
ColorItem,
Typeset,
} from '@storybook/addon-docs/blocks';
import { theme } from '@vegaprotocol/tailwindcss-config';
<Meta title="Primitives/Colors" />
# Primitives
This project uses Tailwindcss so a lot of colour props are passed in as CSS classes that
Tailwind applies styling to i.e. `text-blue-500` to use the primary blue. You can find the
full colour palette [here](https://tailwindcss.com/docs/customizing-colors/#default-color-palette).
## Colours
### Shared
<ColorPalette>
<ColorItem
title="theme.color.white"
subtitle="White"
colors={theme.colors.white}
/>
<ColorItem
title="theme.color.black"
subtitle="Black"
colors={theme.colors.black}
/>
<ColorItem
title="theme.color.coral"
subtitle="Coral"
colors={[theme.colors.coral]}
/>
</ColorPalette>
### Vega
<ColorPalette>
<ColorItem
title="theme.color.vega"
subtitle="Vega colors"
colors={theme.colors.vega}
/>
</ColorPalette>
### Intent
<ColorPalette>
<ColorItem
title="theme.color.intent"
subtitle="Intent"
colors={theme.colors.intent}
/>
<ColorItem
title="theme.color.intent-background"
subtitle="Intent background"
colors={theme.colors['intent-background']}
/>
</ColorPalette>
### Background
<ColorPalette>
<ColorItem
title="theme.color.backgroundColor"
subtitle="Intent backgroundColor"
colors={{
black: theme.colors.black.DEFAULT,
white: theme.colors.white.DEFAULT,
danger: theme.colors['intent-background'].danger,
}}
/>
</ColorPalette>

View File

@ -0,0 +1,123 @@
import {
Meta,
ColorPalette,
ColorItem,
Typeset,
Canvas,
} from '@storybook/addon-docs/blocks';
import { theme } from '@vegaprotocol/tailwindcss-config';
<Meta title="Primitives/Typography" />
# Typography
## Headers
### H1
<span>
{theme.fontSize.h1[0]} / {theme.fontSize.h1[1].lineHeight}, letterSpacing:{' '}
{theme.fontSize.h1[1].letterSpacing}{' '}
</span>
<Canvas>
<div class="text-h1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit
</div>
</Canvas>
### H2
<span>
{theme.fontSize.h2[0]} / {theme.fontSize.h2[1].lineHeight}, letterSpacing:{' '}
{theme.fontSize.h2[1].letterSpacing}{' '}
</span>
<Canvas>
<div class="text-h2">
Lorem ipsum dolor sit amet, consectetur adipiscing elit
</div>
</Canvas>
### H3
<span>
{theme.fontSize.h3[0]} / {theme.fontSize.h3[1].lineHeight}, letterSpacing:{' '}
{theme.fontSize.h3[1].letterSpacing}{' '}
</span>
<Canvas>
<div class="text-h3">
Lorem ipsum dolor sit amet, consectetur adipiscing elit
</div>
</Canvas>
### H4
<span>
{theme.fontSize.h4[0]} / {theme.fontSize.h4[1].lineHeight}, letterSpacing:{' '}
{theme.fontSize.h4[1].letterSpacing}{' '}
</span>
<Canvas>
<div class="text-h4">
Lorem ipsum dolor sit amet, consectetur adipiscing elit
</div>
</Canvas>
### H5
<span>
{theme.fontSize.h5[0]} / {theme.fontSize.h5[1].lineHeight}, letterSpacing:{' '}
{theme.fontSize.h5[1].letterSpacing}{' '}
</span>
<Canvas>
<div class="text-h5">
Lorem ipsum dolor sit amet, consectetur adipiscing elit
</div>
</Canvas>
## Body
### Normal
<span>
{theme.fontSize.body[0]} / {theme.fontSize.body[1]}
</span>
<Canvas>
<div class="text-body">
Lorem ipsum dolor sit amet, consectetur adipiscing elit
</div>
</Canvas>
### Large
<span>
{theme.fontSize['body-large'][0]} / {theme.fontSize['body-large'][1]}
</span>
<Canvas>
<div class="text-body-large">
Lorem ipsum dolor sit amet, consectetur adipiscing elit
</div>
</Canvas>
## UI
### Normal
<span>
{theme.fontSize.body[0]} / {theme.fontSize.body[1]}
</span>
<Canvas>
<div class="text-ui">
Lorem ipsum dolor sit amet, consectetur adipiscing elit
</div>
</Canvas>
### Small
<span>
{theme.fontSize['ui-small'][0]} / {theme.fontSize['ui-small'][1]}
</span>
<Canvas>
<div class="text-ui-small">
Lorem ipsum dolor sit amet, consectetur adipiscing elit
</div>
</Canvas>

View File

@ -1,17 +0,0 @@
$font-main: 'Helvetica neue', 'Helvetica', arial, sans-serif;
$font-mono: 'Roboto Mono', monospace;
$font-pixelated: NeuePixelGrotesk, 'Helvetica neue', 'Helvetica', arial,
sans-serif;
.font-main {
font-family: $font-main;
}
.font-mono {
font-family: $font-mono;
}
@font-face {
font-family: NeuePixelGrotesk;
src: url(./NeuePixelGrotesk-Regular.woff);
}

View File

@ -1,6 +0,0 @@
fieldset {
border: 0;
padding: 0;
margin: 0;
min-width: 0;
}

View File

@ -1,99 +0,0 @@
/* === BLUEPRINT COLOR OVERRIDES === */
$black: #000;
$white: #fff;
$dark-gray1: #1f1f1f;
$dark-gray2: #2a2a2a;
$dark-gray3: #363636;
$dark-gray4: #3f3f3f;
$dark-gray5: #494949;
$gray1: #6e6e6e;
$gray2: #848484;
$gray3: #999;
$gray4: #b5b5b5;
$gray5: #cbcbcb;
$light-gray1: #d7d7d7;
$light-gray2: #e0e0e0;
$light-gray3: #e7e7e7;
$light-gray4: #f0f0f0;
$light-gray5: #f8f8f8;
/* === VEGA COLORS === */
/*
Note: We follow blueprints color naming scheme. https://blueprintjs.com/docs/#core/colors EG:
$color1 = Darkest
$color2
$color3 = Base color
$color4
$color5 = Lightest
*/
$vega-pink: #ff2d5e;
$vega-green: #00f780;
$vega-green3: #26ff8a;
$vega-red3: #ff261a;
$vega-blue3: #48aff0;
$vega-yellow3: #daff0d;
$vega-orange3: #d9822b;
$vega-yellow4: #edff22;
$vega-red1: darken($vega-red3, 38%);
$vega-green1: darken($vega-green3, 38%);
$vega-yellow1: darken($vega-yellow3, 38%);
$vega-orange1: darken($vega-orange3, 38%);
/* === TEXT COLORS === */
$text-color: #c7c7c7;
$text-color-inverse: #1a1821;
$text-color-deemphasise: #8a9ba8;
$text-color-emphasise: #f5f8fa;
$text-color-error: $vega-red3;
/* === BUY/SELL BUTTONS === */
$button-sell-hover: #893939;
$button-sell-active: #ff5e5e;
$button-buy-hover: #0a4023;
$button-buy-active: #00ffb2;
/* === MISC BLUEPRINT COLOR OVERRIDES === */
$pt-intent-danger: $vega-red3;
$input-background: #3f3f3f;
// App background
$pt-dark-app-background-color: $dark-gray2;
// Card
$dark-card-background-color: $dark-gray2;
// Menu
$dark-menu-background-color: $dark-gray2;
// Navbar
$dark-navbar-background-color: $black;
// Popover
$dark-popover-background-color: $dark-gray2;
//overlay-backdrop
.bp3-overlay-backdrop {
background-color: rgba(73, 73, 73, 0.7);
}
// Text helpers
.text-deemphasise {
color: $text-color-deemphasise;
}
.text-error {
color: $text-color-error;
}
// hover row
$row-hover-background-color: $dark-gray5;
// backdrop
$backdrop-black: rgba(0, 0, 0, 0.6);

View File

@ -1,136 +0,0 @@
@import './colors';
@import './fonts';
@import './reset';
html,
body,
#root {
background-color: $black;
color: $text-color;
font-family: $font-main;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
font-size: 14px;
@media (min-width: 960px) {
font-size: 16px;
}
}
// TYPOGRAPHY
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 500;
margin-top: 1em;
margin-bottom: 15px;
color: $white;
}
p {
word-break: break-word;
line-height: 1.4;
margin: 0 0 15px 0;
}
a,
.link {
text-decoration: underline;
color: $white;
&:hover {
color: $vega-yellow3;
}
}
.text-muted {
color: $text-color-deemphasise;
}
.text-pixelated {
font-family: $font-pixelated;
}
// BUTTONS
button {
color: $black;
background-color: $white;
border: 0;
border-radius: 4px;
padding: 12px 32px;
cursor: pointer;
&:hover {
background-color: $light-gray3;
}
&:disabled,
&.disabled {
opacity: 0.6;
cursor: not-allowed;
}
&.fill {
width: 100%;
}
&.button-secondary {
border: 1px solid $white;
border-radius: 0;
background: transparent;
color: white;
width: 100%;
&:hover {
background: $dark-gray4;
}
&:active {
background: $white;
color: $black;
}
}
&.button-link {
display: inline;
appearance: none;
padding: 0;
text-decoration: underline;
background-color: transparent;
color: $white;
outline: none;
&--dark {
color: $black;
}
&:hover {
color: $vega-yellow4 !important;
}
.invert & {
color: $black;
&:hover {
color: $black !important;
}
}
}
}
// FORM ELEMENTS
select,
input[type='text'],
input[type='password'] {
width: 100%;
padding: 12px;
border-radius: 4px;
background-color: #3f3f3f;
color: white;
border: 0;
}

View File

@ -0,0 +1,265 @@
import { Story, Meta } from '@storybook/react';
interface ContrastCheckerProps {
backgrounds: string[];
foregrounds: string[];
backgroundColor: string;
}
const ContrastChecker = ({
backgrounds,
foregrounds,
backgroundColor,
}: ContrastCheckerProps) => (
<div style={{ backgroundColor }}>
{backgrounds.map((backgroundColor) => (
<div key={backgroundColor} style={{ backgroundColor, margin: '16px' }}>
{foregrounds.map((color) => (
<div
id={`${backgroundColor}-${color}`}
style={{ color, padding: '8px' }}
key={color}
>
{color} on {backgroundColor}
</div>
))}
</div>
))}
</div>
);
export default {
component: ContrastChecker,
title: 'Primitives/Contrast',
parameters: { themes: false },
} as Meta;
const Template: Story = (args) => (
<ContrastChecker {...(args as ContrastCheckerProps)} />
);
export const GrayAlpha = Template.bind({});
GrayAlpha.args = {
backgroundColor: 'white',
backgrounds: [
'white',
' rgba(0,0,0,0.02)',
' rgba(0,0,0,0.05)',
' rgba(0,0,0,0.10)',
' rgba(0,0,0,0.15)',
' rgba(0,0,0,0.20)',
' rgba(0,0,0,0.25)',
' rgba(0,0,0,0.30)',
],
foregrounds: [
'black',
' rgba(0,0,0,0.98)',
' rgba(0,0,0,0.95)',
' rgba(0,0,0,0.90)',
' rgba(0,0,0,0.85)',
' rgba(0,0,0,0.80)',
' rgba(0,0,0,0.75)',
' rgba(0,0,0,0.70)',
' rgba(0,0,0,0.65)',
' rgba(0,0,0,0.60)',
' rgba(0,0,0,0.55)',
' rgba(0,0,0,0.50)',
],
};
export const GrayAlphaDark = Template.bind({});
GrayAlphaDark.args = {
backgroundColor: 'black',
backgrounds: [
'black',
' rgba(255,255,255,0.02)',
' rgba(255,255,255,0.05)',
' rgba(255,255,255,0.10)',
' rgba(255,255,255,0.15)',
' rgba(255,255,255,0.20)',
' rgba(255,255,255,0.25)',
' rgba(255,255,255,0.30)',
],
foregrounds: [
'white',
' rgba(255,255,255,0.98)',
' rgba(255,255,255,0.95)',
' rgba(255,255,255,0.90)',
' rgba(255,255,255,0.85)',
' rgba(255,255,255,0.80)',
' rgba(255,255,255,0.75)',
' rgba(255,255,255,0.70)',
' rgba(255,255,255,0.65)',
' rgba(255,255,255,0.60)',
' rgba(255,255,255,0.55)',
' rgba(255,255,255,0.50)',
],
};
export const VegaYellowBackground = Template.bind({});
VegaYellowBackground.args = {
backgroundColor: 'white',
backgrounds: [
'rgba(237, 255, 34)',
'rgba(237, 255, 34, 0.98)',
'rgba(237, 255, 34, 0.95)',
'rgba(237, 255, 34, 0.90)',
'rgba(237, 255, 34, 0.85)',
'rgba(237, 255, 34, 0.80)',
'rgba(237, 255, 34, 0.75)',
'rgba(237, 255, 34, 0.70)',
'rgba(237, 255, 34, 0.65)',
'rgba(237, 255, 34, 0.60)',
],
foregrounds: [
'black',
' rgba(0,0,0,0.98)',
' rgba(0,0,0,0.95)',
' rgba(0,0,0,0.90)',
' rgba(0,0,0,0.85)',
' rgba(0,0,0,0.80)',
' rgba(0,0,0,0.75)',
' rgba(0,0,0,0.70)',
' rgba(0,0,0,0.65)',
' rgba(0,0,0,0.60)',
' rgba(0,0,0,0.55)',
' rgba(0,0,0,0.50)',
],
};
export const VegaYellowBackgroundDark = Template.bind({});
VegaYellowBackgroundDark.args = {
backgroundColor: 'black',
backgrounds: [
'rgba(237, 255, 34)',
'rgba(237, 255, 34, 0.98)',
'rgba(237, 255, 34, 0.95)',
'rgba(237, 255, 34, 0.90)',
'rgba(237, 255, 34, 0.85)',
'rgba(237, 255, 34, 0.80)',
'rgba(237, 255, 34, 0.75)',
'rgba(237, 255, 34, 0.70)',
'rgba(237, 255, 34, 0.65)',
'rgba(237, 255, 34, 0.60)',
'rgba(237, 255, 34, 0.55)',
'rgba(237, 255, 34, 0.50)',
'rgba(237, 255, 34, 0.45)',
'rgba(237, 255, 34, 0.40)',
'rgba(237, 255, 34, 0.35)',
'rgba(237, 255, 34, 0.30)',
'rgba(237, 255, 34, 0.25)',
],
foregrounds: [
'black',
' rgba(0,0,0,0.98)',
' rgba(0,0,0,0.95)',
' rgba(0,0,0,0.90)',
' rgba(0,0,0,0.85)',
' rgba(0,0,0,0.80)',
' rgba(0,0,0,0.75)',
' rgba(0,0,0,0.70)',
' rgba(0,0,0,0.65)',
' rgba(0,0,0,0.60)',
' rgba(0,0,0,0.55)',
' rgba(0,0,0,0.50)',
],
};
export const VegaYellowBackgroundDarkWhiteText = Template.bind({});
VegaYellowBackgroundDarkWhiteText.args = {
backgroundColor: 'black',
backgrounds: [
'rgba(237, 255, 34)',
'rgba(237, 255, 34, 0.98)',
'rgba(237, 255, 34, 0.95)',
'rgba(237, 255, 34, 0.90)',
'rgba(237, 255, 34, 0.85)',
'rgba(237, 255, 34, 0.80)',
'rgba(237, 255, 34, 0.75)',
'rgba(237, 255, 34, 0.70)',
'rgba(237, 255, 34, 0.65)',
'rgba(237, 255, 34, 0.60)',
'rgba(237, 255, 34, 0.55)',
'rgba(237, 255, 34, 0.50)',
'rgba(237, 255, 34, 0.45)',
'rgba(237, 255, 34, 0.40)',
'rgba(237, 255, 34, 0.35)',
'rgba(237, 255, 34, 0.30)',
'rgba(237, 255, 34, 0.25)',
],
foregrounds: [
'white',
' rgba(255, 255, 255, 0.98)',
' rgba(255, 255, 255, 0.95)',
' rgba(255, 255, 255, 0.90)',
' rgba(255, 255, 255, 0.85)',
' rgba(255, 255, 255, 0.80)',
' rgba(255, 255, 255, 0.75)',
' rgba(255, 255, 255, 0.70)',
' rgba(255, 255, 255, 0.65)',
' rgba(255, 255, 255, 0.60)',
' rgba(255, 255, 255, 0.55)',
' rgba(255, 255, 255, 0.50)',
],
};
export const VegaYellowColor = Template.bind({});
VegaYellowColor.args = {
backgroundColor: 'black',
backgrounds: [
'white',
'rgba(255,255,255,0.98)',
' rgba(255,255,255,0.95)',
' rgba(255,255,255.90)',
' rgba(255,255,255,0.85)',
' rgba(255,255,255,0.80)',
' rgba(255,255,255,0.75)',
' rgba(255,255,255,0.70)',
' rgba(255,255,255,0.65)',
' rgba(255,255,255,0.60)',
' rgba(255,255,255,0.55)',
' rgba(255,255,255,0.50)',
' rgba(255,255,255,0.45)',
' rgba(255,255,255,0.40)',
' rgba(255,255,255,0.35)',
],
foregrounds: [
'#edff22',
'#ecff1c',
'#ebff13',
'#eaff05',
'#e1f500',
'#d4e700',
'#c7d800',
'#b9ca00',
'#acbb00',
'#9fad00',
'#929e00',
'#849000',
'#778200',
'#6f7900',
'#6a7300',
'#5c6500',
'#4f5600',
],
};
export const VegaYellowColorDark = Template.bind({});
VegaYellowColorDark.args = {
backgroundColor: 'white',
backgrounds: [
'black',
' rgba(0,0,0,0.98)',
' rgba(0,0,0,0.95)',
' rgba(0,0,0,0.90)',
' rgba(0,0,0,0.85)',
' rgba(0,0,0,0.80)',
' rgba(0,0,0,0.75)',
' rgba(0,0,0,0.70)',
' rgba(0,0,0,0.65)',
' rgba(0,0,0,0.60)',
' rgba(0,0,0,0.55)',
' rgba(0,0,0,0.50)',
],
foregrounds: ['#edff22'],
};

View File

@ -4,7 +4,7 @@ const theme = require('../tailwindcss-config/src/theme');
module.exports = {
content: [
join(__dirname, 'src/**/!(*.stories|*.spec).{ts,tsx,html}'),
join(__dirname, 'src/**/*.{ts,tsx,html,mdx}'),
join(__dirname, '.storybook/preview.js'),
...createGlobPatternsForDependencies(__dirname),
],

View File

@ -22,5 +22,11 @@
"**/*.stories.jsx",
"**/*.stories.tsx"
],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
"include": [
"**/*.js",
"**/*.jsx",
"**/*.ts",
"**/*.tsx",
"src/primitives/typography.stories.mdx"
]
}

View File

@ -14,8 +14,11 @@
"private": true,
"dependencies": {
"@apollo/client": "^3.5.8",
"@blueprintjs/icons": "^3.32.0",
"@nrwl/next": "13.8.1",
"@radix-ui/react-tabs": "^0.1.5",
"@sentry/react": "^6.18.1",
"@sentry/tracing": "^6.18.1",
"@types/uuid": "^8.3.4",
"apollo": "^2.33.9",
"autoprefixer": "^10.4.2",
@ -51,6 +54,7 @@
"@nrwl/tao": "13.8.1",
"@nrwl/web": "13.8.1",
"@nrwl/workspace": "13.8.1",
"@storybook/addon-a11y": "^6.4.19",
"@storybook/addon-essentials": "~6.4.12",
"@storybook/builder-webpack5": "~6.4.12",
"@storybook/manager-webpack5": "~6.4.12",

6571
yarn.lock

File diff suppressed because it is too large Load Diff