primer / react

An implementation of GitHub's Primer Design System using React
https://primer.style/guides/react
MIT License
3.13k stars 535 forks source link

TypeScript support #389

Closed emplums closed 5 years ago

emplums commented 5 years ago

After chatting with the Actions team a few months ago, I thought it might be useful to add TypeScript support to our components. @mxstbr pointed out this library that might be able to help us easily do that: https://github.com/atlassian/extract-react-types

emplums commented 5 years ago

Chatted with the Actions team about this, I think it would probably be best/safest to write TS bindings ourselves for each component. For now, I believe the only team using the components & TS is the Actions team, and they aren't using a ton of components yet, so this doesn't feel super high priority but might be a fun hack week project!

mxstbr commented 5 years ago

Got all the system properties typed correctly and typed Flex and Flex.Item:

// Inspired by the rebass types: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/rebass/index.d.ts
// Mostly taking the information from here and turning it into types: https://primer.style/components/docs/system-props

declare module "@primer/components" {
  type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
  import * as StyledSystem from "styled-system";
  import * as StyledComponents from "styled-components";
  import * as History from "history";

  export interface BaseProps extends React.Props<any> {
    as?: React.ReactType;
    css?:
      | StyledComponents.CSSObject
      | StyledComponents.FlattenSimpleInterpolation
      | string;
    // NOTE(@mxstbr): Necessary to make <Component as={Link} to="/bla" /> work
    // Not entirely sound but a good enough workaround
    to?: History.LocationDescriptor;
  }

  interface CommonProps
    extends BaseProps,
      StyledSystem.ColorProps,
      StyledSystem.SpaceProps {}

  interface LayoutProps
    extends BaseProps,
      StyledSystem.DisplayProps,
      StyledSystem.SizeProps,
      StyledSystem.WidthProps,
      StyledSystem.HeightProps,
      StyledSystem.MinWidthProps,
      StyledSystem.MinHeightProps,
      StyledSystem.MaxWidthProps,
      StyledSystem.MaxHeightProps,
      StyledSystem.OverflowProps,
      StyledSystem.VerticalAlignProps {}

  interface TypographyProps
    extends BaseProps,
      StyledSystem.FontFamilyProps,
      StyledSystem.FontSizeProps,
      StyledSystem.FontStyleProps,
      StyledSystem.FontWeightProps,
      StyledSystem.LineHeightProps,
      StyledSystem.TextAlignProps {}

  interface BorderProps
    extends BaseProps,
      StyledSystem.BordersProps,
      StyledSystem.BorderColorProps,
      StyledSystem.BoxShadowProps,
      StyledSystem.BorderRadiusProps {}

  interface PositionProps
    extends BaseProps,
      StyledSystem.PositionProps,
      StyledSystem.ZIndexProps,
      StyledSystem.TopProps,
      StyledSystem.RightProps,
      StyledSystem.BottomProps,
      StyledSystem.LeftProps {}

  interface FlexContainerProps
    extends BaseProps,
      StyledSystem.FlexBasisProps,
      StyledSystem.FlexDirectionProps,
      StyledSystem.FlexWrapProps,
      StyledSystem.AlignContentProps,
      StyledSystem.AlignItemsProps,
      StyledSystem.JustifyContentProps,
      StyledSystem.JustifyItemsProps {}

  interface FlexItemProps
    extends BaseProps,
      CommonProps,
      LayoutProps,
      StyledSystem.FlexProps,
      StyledSystem.JustifySelfProps,
      StyledSystem.AlignSelfProps,
      StyledSystem.OrderProps {}

  export interface FlexProps
    extends FlexContainerProps,
      Omit<React.HTMLProps<HTMLDivElement>, keyof FlexContainerProps> {}
  export const Flex: React.FunctionComponent<FlexProps> & {
    Item: React.FunctionComponent<FlexItemProps>;
  };
}

Not that much too it apart form repetition, typing the rest of the components should be simple enough 👍

shawnbot commented 5 years ago

In theory the prop type declarations should be easy to generate from the list of styled-system props that we use on each element. 🤔

emplums commented 5 years ago

Done! 🎉

jerrygreen commented 5 years ago

Btw thanks a lot 🎉 I was tracking this issue for a while. I've just tried this too on a pet project - it works perfectly!