Install the dependencies with yarn
// install deps
yarn
// normal start, fast speed in develop component
yarn start
// start with docgen, that run when you write doc in component
yarn storybook:docgen├── index.ts // All item reexport from here, no logic involved.
├── InlineEditable.tsx // The main logic file.
├── __stories__
│ ├── InlineEditable.story.mdx // The component document page.
│ ├── InlineEditable.story.tsx // The component storybook.
│ └── __snapshots__
│ └── InlineEditable.story.tsx.snap // Auto generate snapshot.
├── __tests__
│ └── InlineEditable.test.tsx // Unit test for that component
├── styles
│ ├── InlineEditableStyle.tsx // Main custom style file
│ ├── index.ts // Re-export
│ └── textFieldStyle.tsx // Addition style
└── utils // All token and related method put in here.
├── InlineEditableUtils.ts
└── index.ts // Re-exporttype RcButtonColor = RcBaseColor<
'primary' | 'secondary' | 'negative' | 'positive' | 'action' | 'neutral'
>;
type RcButtonColorLoadingMode = 'prefix' | 'replace' | 'suffix';
type RcButtonVariant = 'text' | 'outlined' | 'contained' | 'plain';
type RcButtonRadius = keyof RcTheme['radius'];
type RcButtonProps = {
/** size of button, default is `large` */
size?: RcButtonSize;
/** variant of button, default is `contained` */
variant?: RcButtonVariant;
/** color of button */
color?: RcPaletteKeys | RcButtonColor;
/** is button loading */
loading?: boolean;
/** loading mode with button, default is `replace` */
loadingMode?: RcButtonColorLoadingMode;
/** Props send to `RcCircularProgress` when loading is `true` */
CircularProgressProps?: RcCircularProgressProps;
/** component for render root button, default is `button` */
component?: React.ElementType;
/** border radius for button */
radius?: RcButtonRadius;
/** should keep elevation when type is `container` */
keepElevation?: boolean;
/** @deprecated Icon, please use startIcon with `<RcIcon />` */
IconProps?: RcIconProps;
} & RcBaseProps<
ComponentProps<typeof MuiButton>,
| 'color'
| 'size'
| 'variant'
| 'title'
// * use disableFocusRipple, so omit that
| 'focusRipple'
>;
const _RcButton = forwardRef<any, RcButtonProps>(
(inProps: RcButtonProps, ref) => {
const props = useThemeProps({ props: inProps, name: 'RcButton' });
const {
children: childrenProp,
classes: classesProp,
startIcon: startIconProp,
endIcon: endIconProp,
// omit all your custom props
loading,
loadingMode,
IconProps,
size,
color,
CircularProgressProps,
variant,
radius,
keepElevation,
...rest
} = props;
...
const classes = useMemo(
() => combineClasses(RcButtonClasses, classesProp),
[classesProp],
);
return (
<MuiButton
ref={buttonRef}
startIcon={startIcon}
endIcon={endIcon}
classes={classes}
{...rest}
>
...
</MuiButton>
);
},
);
const RcButton = styled(_RcButton)`
${buttonStyle}
`;
RcButton.defaultProps = {
size: 'large',
color: 'primary',
variant: 'contained',
loadingMode: 'replace',
};
RcButton.displayName = 'RcButton';
export { RcButton };
export type {
RcButtonColor,
RcButtonColorLoadingMode,
RcButtonProps,
RcButtonSize,
RcButtonVariant,
};-
Import
import React, { FunctionComponent } from 'react';and not usingReact.xxx, other import should keep short and clear. -
The component
propsrelated type should be the top of file after allimportand naming for[Name]Props. -
Here is some
Basetype fromfoundation, you should use that to unified token, likesize,color, you need usingBaseSizeorBaseColorto pick that. -
Custom props you should add comment with and show the
default value. -
Join with Material Props with
&byBasePropsand Omit props you want omit in the second argument, and that should join after our addition props. -
Destructure props you need for logic inside
Componentnot on the function argument, and pass whole props intoStyled[Name], keep all props go into Styled. -
Custom class should using
utilsset classes likeRcButtonClasses, that implement will in the Token Utils section. -
All props we custom cover with need combine with out side pass in props, like
classes, user can add custom class name for this component, if we don't usingcombineClassesto combine those props, that will make outside props not working. -
When custom event should use
combinePropsto wrapper methods, that will combine two method together,combineProps({ onClick: onClickProp }, { onClick: handleClose });
-
final export with styled to contain this private component
_[Name]assign toFunctionComponent<[Name]Props>, that for us can using this component in otherstyledto styled that. -
Component need assign displayName for Storybook using show with correct name example
[Name].displayName = '[Name]'; -
At Main Component file, All export in main file should put in the bottom of file.(Other utils file can export directly)
1. Using styled from foundation.
```ts
import { styled, css, RcThemedStyled } from '../../../../foundation';
- Pick material props from
forwardcomponent and remove all props which should not pass to material.
// ButtonStyle.tsx
export const buttonStyle: RcThemedStyled<RcButtonProps, any> = (props) => {
const { variant, size, radius: radiusProp, keepElevation } = props;
const plainTextColor = plainButtonTextColor(props);
const iconSpace = spacing(RcButtonIconSpace[size!]);
const isPlain = variant === 'plain';
return css`
...some style
`;
};
// Button.tsx
const RcButton = styled(_RcButton)`
${buttonStyle}
`;- All method contain in
styledstyle template block will auto pass({ theme })after function return with function.- like above
palette2('primary', 'main'), it will return({ theme }: ThemeProps) => any, that will auto be pass with theme, don't pass manually likepalette2('primary', 'main')({theme}).
- like above
-
All token styled utils contain in
foundationfolder, we should using that from there.import { palette2, spacing, typography } from '../../../../foundation';
Custom class should get from
utils, don't use plain string like below.&.${ButtonClasses.contained} { ...; }
- If you want to pick method out of styled block, you need using
RcThemedStyledto declare method, like belowconst buttonHoverColor: RcThemedStyled<RcButtonProps, any> = ({ color, theme, }) => setOpacity(palette2('neutral.b02'), '08');
RcThemedStyledgeneric type first arg is the method argument type, and the second type is that return type, default with(themeOptions: RcThemeProps) => any, that will auto run with ({ theme }).
import { palette, Classes, PaletteType, UnitMap } from '../../../../foundation';
import { ButtonColor, ButtonProps, ButtonSize } from '../Button';
export const ButtonClasses = Classes<ButtonProps>(
['disabled', 'contained', 'text', 'outlined'],
'Button',
);
export const ButtonColors: UnitMap<ButtonColor, PaletteType> = {
primary: palette2('primary', 'main'),
secondary: palette2('secondary', 'main'),
negative: palette2('semantic', 'positive'),
positive: palette2('semantic', 'negative'),
action: palette2('common', 'white'),
};
export const ButtonSizes: UnitMap<ButtonSize> = {
medium: '36px',
large: '40px',
};- Classes related should use to contain, that will make all using class to unified
[alias]-[classType]like above disabled will be:Button-disabled, that will make us easy to debug and identify.Classes<[Name]Props>([...classTypes], 'alias')`
- Token relate should using
UnitMap<[Name][TokenName]>to unified size and check we has implement with, likesizeandcolor, and the second type will assign for every item type.
You can import svg icon components from icon/xxx.tsx like below,
import { ArrowDown } from '@ringcentral/juno-icon';ctrl + shift + pTyping task and choice Run Storybook, that will serve the application.
Press F5 to run Launch Chrome and you can debug with vscode.
Before you using attach debug, you should close all of chrome, and using terminal to open chrome.
ctrl + shift + pTyping task and choice Run app, to run app.
Press F5 to run Attach Browser and you can using vscode debug in the IDE now.
https://jkchao.github.io/typescript-book-chinese https://www.typescriptlang.org/docs/handbook/utility-types.html
yarn test- checkout branch from
main. - commit with message like
feat(Ticket-Number): [Update-scope] what change you made, likechore(RCUI-100): [Snapshot] update snapshot. - We test components change base on snapshot, run
yarn update-snapshotto update snapshot before you push.
