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-export
type 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
props
related type should be the top of file after allimport
and naming for[Name]Props
. -
Here is some
Base
type fromfoundation
, you should use that to unified token, likesize
,color
, you need usingBaseSize
orBaseColor
to pick that. -
Custom props you should add comment with and show the
default value
. -
Join with Material Props with
&
byBaseProps
and Omit props you want omit in the second argument, and that should join after our addition props. -
Destructure props you need for logic inside
Component
not on the function argument, and pass whole props intoStyled[Name]
, keep all props go into Styled. -
Custom class should using
utils
set 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 usingcombineClasses
to combine those props, that will make outside props not working. -
When custom event should use
combineProps
to 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 otherstyled
to 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
forward
component 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
styled
style 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
foundation
folder, 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
RcThemedStyled
to declare method, like belowconst buttonHoverColor: RcThemedStyled<RcButtonProps, any> = ({ color, theme, }) => setOpacity(palette2('neutral.b02'), '08');
RcThemedStyled
generic 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, likesize
andcolor
, 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 + p
Typing 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 + p
Typing 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-snapshot
to update snapshot before you push.