Commit 111d09e2 authored by tom's avatar tom

Text and Button recipies

parent 29aa85f3
...@@ -12,13 +12,22 @@ interface ButtonLoadingProps { ...@@ -12,13 +12,22 @@ interface ButtonLoadingProps {
loadingText?: React.ReactNode; loadingText?: React.ReactNode;
} }
export interface ButtonProps extends ChakraButtonProps, ButtonLoadingProps {} export interface ButtonProps extends ChakraButtonProps, ButtonLoadingProps {
active?: boolean;
selected?: boolean;
}
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
function Button(props, ref) { function Button(props, ref) {
const { loading, disabled, loadingText, children, ...rest } = props; const { loading, disabled, loadingText, children, active, selected, ...rest } = props;
return ( return (
<ChakraButton disabled={ loading || disabled } ref={ ref } { ...rest }> <ChakraButton
{ ...(active ? { 'data-active': true } : {}) }
{ ...(selected ? { 'data-selected': true } : {}) }
disabled={ loading || disabled }
ref={ ref }
{ ...rest }
>
{ loading && !loadingText ? ( { loading && !loadingText ? (
<> <>
<AbsoluteCenter display="inline-flex"> <AbsoluteCenter display="inline-flex">
......
// TODO @tom2drum convert this to rem
const breakpoints = { const breakpoints = {
// maybe we need them in future // maybe we need them in future
sm: '415px', sm: '415px',
// md: '768px', // md: '768px',
lg: '1000px', lg: '1000px',
......
import type { SemanticTokenDefinition } from '@chakra-ui/react/dist/types/styled-system/types'; import type { ThemingConfig } from '@chakra-ui/react';
const semanticTokens: SemanticTokenDefinition = { const semanticTokens: ThemingConfig['semanticTokens'] = {
// TODO @tom2drum remove *_hover in favor of conditional selectors
colors: { colors: {
// NEW TOKENS
buttons: {
outline: {
fg: {
DEFAULT: { value: { base: '{colors.blue.600}', _dark: '{colors.blue.300}' } },
},
hover: {
DEFAULT: { value: '{colors.blue.400}' },
},
},
anchor: {
fg: {
DEFAULT: { value: { base: '{colors.blackAlpha.800}', _dark: '{colors.whiteAlpha.800}' } },
selected: { value: { base: '{colors.blue.600}', _dark: '{colors.gray.50}' } },
},
border: {
DEFAULT: { value: { base: '{colors.gray.200}', _dark: '{colors.gray.600}' } },
selected: { value: { base: '{colors.blue.50}', _dark: '{colors.gray.600}' } },
},
hover: {
DEFAULT: { value: '{colors.blue.400}' },
},
},
},
// OLD TOKENS
divider: { divider: {
DEFAULT: { value: '{colors.blackAlpha.200}' }, DEFAULT: { value: '{colors.blackAlpha.200}' },
_dark: { value: '{colors.whiteAlpha.200}' }, _dark: { value: '{colors.whiteAlpha.200}' },
......
import type { ThemingConfig, TokenDefinition } from '@chakra-ui/react/dist/types/styled-system/types'; import type { ThemingConfig } from '@chakra-ui/react';
import type { ExcludeUndefined } from 'types/utils';
import config from 'configs/app'; import config from 'configs/app';
export const BODY_TYPEFACE = config.UI.fonts.body?.name ?? 'Inter'; export const BODY_TYPEFACE = config.UI.fonts.body?.name ?? 'Inter';
export const HEADING_TYPEFACE = config.UI.fonts.heading?.name ?? 'Poppins'; export const HEADING_TYPEFACE = config.UI.fonts.heading?.name ?? 'Poppins';
export const fonts: TokenDefinition['fonts'] = { export const fonts: ExcludeUndefined<ThemingConfig['tokens']>['fonts'] = {
heading: { value: `${ HEADING_TYPEFACE }, sans-serif` }, heading: { value: `${ HEADING_TYPEFACE }, sans-serif` },
body: { value: `${ BODY_TYPEFACE }, sans-serif` }, body: { value: `${ BODY_TYPEFACE }, sans-serif` },
}; };
export const textStyles: ThemingConfig['textStyles'] = { export const textStyles: ThemingConfig['textStyles'] = {
h2: { heading: {
fontSize: '32px', xl: {
fontWeight: '500', value: {
lineHeight: '40px', fontSize: '40px',
fontFamily: 'heading', lineHeight: '48px',
}, fontWeight: '500',
h3: { letterSpacing: '-1px',
fontSize: '24px', fontFamily: 'heading',
fontWeight: '500', },
lineHeight: '32px', },
fontFamily: 'heading', lg: {
value: {
fontSize: '32px',
lineHeight: '40px',
fontWeight: '500',
letterSpacing: '-0.5px',
fontFamily: 'heading',
},
},
md: {
value: {
fontSize: '24px',
lineHeight: '32px',
fontWeight: '500',
fontFamily: 'heading',
},
},
sm: {
value: {
fontSize: '18px',
lineHeight: '24px',
fontWeight: '500',
fontFamily: 'heading',
},
},
}, },
h4: { text: {
fontSize: 'md', md: {
fontWeight: '500', value: {
lineHeight: '24px', fontSize: '16px',
fontFamily: 'heading', lineHeight: '24px',
fontWeight: '400',
fontFamily: 'body',
},
},
sm: {
value: {
fontSize: '14px',
lineHeight: '20px',
fontWeight: '400',
fontFamily: 'body',
},
},
xs: {
value: {
fontSize: '12px',
lineHeight: '16px',
fontWeight: '400',
fontFamily: 'body',
},
},
}, },
}; };
import { defineRecipe } from '@chakra-ui/react';
export const recipe = defineRecipe({
base: {
display: 'flex',
borderRadius: 'base',
fontWeight: 600,
overflow: 'hidden',
_disabled: {
opacity: 0.2,
},
},
variants: {
visual: {
solid: {
bg: 'blue.600',
color: 'white',
_hover: {
bg: 'blue.400',
},
_active: { bg: 'blue.400' },
},
outline: {
borderWidth: '2px',
borderStyle: 'solid',
bg: 'transparent',
color: 'buttons.outline.fg',
borderColor: 'buttons.outline.fg',
_hover: {
bg: 'transparent',
color: 'buttons.outline.hover',
borderColor: 'buttons.outline.hover',
},
},
anchor: {
borderWidth: '2px',
borderStyle: 'solid',
bg: 'transparent',
color: 'buttons.anchor.fg',
borderColor: 'buttons.anchor.border',
_hover: {
bg: 'transparent',
color: 'buttons.anchor.hover',
borderColor: 'buttons.anchor.hover',
},
// When the dropdown is open, the button should be active
_active: {
bg: 'transparent',
color: 'buttons.anchor.hover',
borderColor: 'buttons.anchor.hover',
},
// We have a special state for this button variant that serves as a popover trigger.
// When any items (filters) are selected in the popover, the button should change its background and text color.
// The last CSS selector is for redefining styles for the TabList component.
_selected: {
bg: 'buttons.anchor.border.selected',
color: 'buttons.anchor.fg.selected',
borderColor: 'buttons.anchor.border.selected',
_hover: {
bg: 'buttons.anchor.border.selected',
color: 'buttons.anchor.fg.selected',
borderColor: 'buttons.anchor.border.selected',
},
},
},
},
size: {
xs: { px: 2, h: 6, fontSize: '12px' },
sm: { px: 3, h: 8, fontSize: '14px' },
md: { px: 4, h: 10, fontSize: '16px' },
lg: { px: 6, h: 12, fontSize: '20px' },
},
},
defaultVariants: {
size: 'md',
visual: 'solid',
},
});
export { recipe as button } from './button.recipe';
import { createSystem, defaultConfig, defineConfig } from '@chakra-ui/react'; import { createSystem, defaultConfig, defineConfig } from '@chakra-ui/react';
// TODO @tom2drum migrate this to the new recipe system
// import components from './components/index'; // import components from './components/index';
// import config from './config'; // import config from './config';
import * as borders from './foundations/borders'; import * as borders from './foundations/borders';
...@@ -11,11 +12,13 @@ import shadows from './foundations/shadows'; ...@@ -11,11 +12,13 @@ import shadows from './foundations/shadows';
import { fonts, textStyles } from './foundations/typography'; import { fonts, textStyles } from './foundations/typography';
import zIndex from './foundations/zIndex'; import zIndex from './foundations/zIndex';
import globalCss from './globalCss'; import globalCss from './globalCss';
import * as recipes from './recipes';
const customConfig = defineConfig({ const customConfig = defineConfig({
globalCss, globalCss,
theme: { theme: {
breakpoints, breakpoints,
recipes,
semanticTokens, semanticTokens,
textStyles, textStyles,
tokens: { tokens: {
......
...@@ -406,7 +406,6 @@ export default tseslint.config( ...@@ -406,7 +406,6 @@ export default tseslint.config(
'boolean': true, 'boolean': true,
string: true, string: true,
} ], } ],
'no-nested-ternary': 'error',
'no-multi-str': 'error', 'no-multi-str': 'error',
'no-spaced-func': 'error', 'no-spaced-func': 'error',
'no-with': 'error', 'no-with': 'error',
......
...@@ -38,6 +38,7 @@ declare module "nextjs-routes" { ...@@ -38,6 +38,7 @@ declare module "nextjs-routes" {
| DynamicRoute<"/block/countdown/[height]", { "height": string }> | DynamicRoute<"/block/countdown/[height]", { "height": string }>
| StaticRoute<"/block/countdown"> | StaticRoute<"/block/countdown">
| StaticRoute<"/blocks"> | StaticRoute<"/blocks">
| StaticRoute<"/chakra">
| StaticRoute<"/contract-verification"> | StaticRoute<"/contract-verification">
| StaticRoute<"/csv-export"> | StaticRoute<"/csv-export">
| StaticRoute<"/deposits"> | StaticRoute<"/deposits">
......
import type { NextPage } from 'next';
import React from 'react';
import PageNextJs from 'nextjs/PageNextJs';
import Chakra from 'ui/pages/Chakra';
const Page: NextPage = () => {
return (
<PageNextJs pathname="/chakra">
<Chakra/>
</PageNextJs>
);
};
export default Page;
export { login as getServerSideProps } from 'nextjs/getServerSideProps';
import { Heading, HStack } from '@chakra-ui/react';
import React from 'react';
import { Button } from 'chakra/components/button';
import PageTitle from 'ui/shared/Page/PageTitle';
const ChakraShowcases = () => {
return (
<>
<PageTitle title="Chakra UI Showcase"/>
<Heading textStyle="heading.md" mb={ 4 }>Buttons</Heading>
<HStack gap={ 4 }>
<Button>Solid</Button>
<Button visual="outline">Outline</Button>
<Button visual="anchor">Anchor</Button>
<Button visual="anchor" selected>Anchor selected</Button>
</HStack>
</>
);
};
export default React.memo(ChakraShowcases);
import { VStack, Textarea, Button, Alert, Code, Flex, Box } from '@chakra-ui/react'; import { VStack, Textarea, Alert, Code, Flex, Box } from '@chakra-ui/react';
import mixpanel from 'mixpanel-browser'; import mixpanel from 'mixpanel-browser';
import type { ChangeEvent } from 'react'; import type { ChangeEvent } from 'react';
import React from 'react'; import React from 'react';
import { Button } from 'chakra/components/button';
import { toaster } from 'chakra/components/toaster'; import { toaster } from 'chakra/components/toaster';
import config from 'configs/app'; import config from 'configs/app';
import * as cookies from 'lib/cookies'; import * as cookies from 'lib/cookies';
...@@ -10,7 +11,6 @@ import useFeatureValue from 'lib/growthbook/useFeatureValue'; ...@@ -10,7 +11,6 @@ import useFeatureValue from 'lib/growthbook/useFeatureValue';
import useGradualIncrement from 'lib/hooks/useGradualIncrement'; import useGradualIncrement from 'lib/hooks/useGradualIncrement';
import { useRollbar } from 'lib/rollbar'; import { useRollbar } from 'lib/rollbar';
import PageTitle from 'ui/shared/Page/PageTitle'; import PageTitle from 'ui/shared/Page/PageTitle';
const Login = () => { const Login = () => {
const rollbar = useRollbar(); const rollbar = useRollbar();
const [ num, setNum ] = useGradualIncrement(0); const [ num, setNum ] = useGradualIncrement(0);
......
...@@ -137,7 +137,7 @@ const PageTitle = ({ title, contentAfter, withTextAd, backLink, className, isLoa ...@@ -137,7 +137,7 @@ const PageTitle = ({ title, contentAfter, withTextAd, backLink, className, isLoa
<Heading <Heading
ref={ headingRef } ref={ headingRef }
as="h1" as="h1"
size="lg" textStyle="heading.lg"
whiteSpace="normal" whiteSpace="normal"
wordBreak="break-all" wordBreak="break-all"
style={{ style={{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment