Merge branch 'master' into test/Cypress-BDD-integration
This commit is contained in:
commit
82c426ded8
@ -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
|
||||
|
@ -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
|
||||
|
15
apps/explorer/src/app/lib/flags.ts
Normal file
15
apps/explorer/src/app/lib/flags.ts
Normal 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'] || ''),
|
||||
};
|
@ -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>
|
||||
))}
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -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>
|
||||
),
|
||||
];
|
||||
|
10
libs/ui-toolkit/src/components/button/Button.spec.tsx
Normal file
10
libs/ui-toolkit/src/components/button/Button.spec.tsx
Normal 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();
|
||||
});
|
||||
});
|
101
libs/ui-toolkit/src/components/button/Button.stories.tsx
Normal file
101
libs/ui-toolkit/src/components/button/Button.stories.tsx
Normal 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',
|
||||
};
|
161
libs/ui-toolkit/src/components/button/button.tsx
Normal file
161
libs/ui-toolkit/src/components/button/button.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
);
|
1
libs/ui-toolkit/src/components/button/index.ts
Normal file
1
libs/ui-toolkit/src/components/button/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './button';
|
@ -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;
|
||||
}
|
||||
}
|
@ -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>
|
||||
),
|
||||
};
|
||||
|
@ -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'
|
||||
);
|
||||
});
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
@ -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';
|
||||
|
||||
|
10
libs/ui-toolkit/src/components/icon/icon.spec.tsx
Normal file
10
libs/ui-toolkit/src/components/icon/icon.spec.tsx
Normal 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();
|
||||
});
|
||||
});
|
22
libs/ui-toolkit/src/components/icon/icon.stories.tsx
Normal file
22
libs/ui-toolkit/src/components/icon/icon.stories.tsx
Normal 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,
|
||||
};
|
32
libs/ui-toolkit/src/components/icon/icon.tsx
Normal file
32
libs/ui-toolkit/src/components/icon/icon.tsx
Normal 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>
|
||||
);
|
||||
};
|
1
libs/ui-toolkit/src/components/icon/index.ts
Normal file
1
libs/ui-toolkit/src/components/icon/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './icon';
|
1
libs/ui-toolkit/src/components/input-error/index.ts
Normal file
1
libs/ui-toolkit/src/components/input-error/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './input-error';
|
@ -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();
|
||||
});
|
||||
});
|
@ -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',
|
||||
};
|
41
libs/ui-toolkit/src/components/input-error/input-error.tsx
Normal file
41
libs/ui-toolkit/src/components/input-error/input-error.tsx
Normal 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>
|
||||
);
|
||||
};
|
1
libs/ui-toolkit/src/components/input/index.ts
Normal file
1
libs/ui-toolkit/src/components/input/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './input';
|
10
libs/ui-toolkit/src/components/input/input.spec.tsx
Normal file
10
libs/ui-toolkit/src/components/input/input.spec.tsx
Normal 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();
|
||||
});
|
||||
});
|
29
libs/ui-toolkit/src/components/input/input.stories.tsx
Normal file
29
libs/ui-toolkit/src/components/input/input.stories.tsx
Normal 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" />
|
||||
);
|
96
libs/ui-toolkit/src/components/input/input.tsx
Normal file
96
libs/ui-toolkit/src/components/input/input.tsx
Normal 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;
|
||||
}
|
||||
);
|
1
libs/ui-toolkit/src/components/select/index.ts
Normal file
1
libs/ui-toolkit/src/components/select/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './select';
|
10
libs/ui-toolkit/src/components/select/select.spec.tsx
Normal file
10
libs/ui-toolkit/src/components/select/select.spec.tsx
Normal 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();
|
||||
});
|
||||
});
|
26
libs/ui-toolkit/src/components/select/select.stories.tsx
Normal file
26
libs/ui-toolkit/src/components/select/select.stories.tsx
Normal 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,
|
||||
};
|
20
libs/ui-toolkit/src/components/select/select.tsx
Normal file
20
libs/ui-toolkit/src/components/select/select.tsx
Normal 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')}
|
||||
/>
|
||||
)
|
||||
);
|
1
libs/ui-toolkit/src/components/text-area/index.ts
Normal file
1
libs/ui-toolkit/src/components/text-area/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './text-area';
|
10
libs/ui-toolkit/src/components/text-area/text-area.spec.tsx
Normal file
10
libs/ui-toolkit/src/components/text-area/text-area.spec.tsx
Normal 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();
|
||||
});
|
||||
});
|
@ -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,
|
||||
};
|
14
libs/ui-toolkit/src/components/text-area/text-area.tsx
Normal file
14
libs/ui-toolkit/src/components/text-area/text-area.tsx
Normal 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)} />
|
||||
)
|
||||
);
|
@ -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';
|
||||
|
77
libs/ui-toolkit/src/primitives/colors.stories.mdx
Normal file
77
libs/ui-toolkit/src/primitives/colors.stories.mdx
Normal 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>
|
123
libs/ui-toolkit/src/primitives/typography.stories.mdx
Normal file
123
libs/ui-toolkit/src/primitives/typography.stories.mdx
Normal 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>
|
Binary file not shown.
@ -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);
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
fieldset {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
min-width: 0;
|
||||
}
|
@ -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);
|
@ -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;
|
||||
}
|
265
libs/ui-toolkit/src/utils/contrast.stories.tsx
Normal file
265
libs/ui-toolkit/src/utils/contrast.stories.tsx
Normal 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'],
|
||||
};
|
@ -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),
|
||||
],
|
||||
|
@ -22,5 +22,11 @@
|
||||
"**/*.stories.jsx",
|
||||
"**/*.stories.tsx"
|
||||
],
|
||||
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
|
||||
"include": [
|
||||
"**/*.js",
|
||||
"**/*.jsx",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
"src/primitives/typography.stories.mdx"
|
||||
]
|
||||
}
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user