Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typing component props with Stitches #66

Open
kyh opened this issue Jul 26, 2021 · 2 comments
Open

Typing component props with Stitches #66

kyh opened this issue Jul 26, 2021 · 2 comments

Comments

@kyh
Copy link

kyh commented Jul 26, 2021

I've set up twin macros with stitches following the examples but my styled-components export any type.

I was wondering if there's a way to type it so that I can autocomplete the props in VSCode

Screen Shot 2021-07-26 at 12 35 22 AM


Here's my twin.d.ts

import "twin.macro";
import { css as cssImport } from "@stitches/react";
import styledImport from "@stitches/react";

// Support a css prop when used with twins styled.div({}) syntax
type CSSProp<T = AnyIfEmpty<DefaultTheme>> = string | CSSObject;

declare module "react" {
  // The css prop
  interface HTMLAttributes<T> extends DOMAttributes<T> {
    css?: CSSProp;
    tw?: string;
  }
  // The inline svg css prop
  interface SVGProps<T> extends SVGProps<SVGSVGElement> {
    css?: CSSProp;
    tw?: string;
  }
}

// Support twins styled.div({}) syntax
type StyledTags = {
  [Tag in keyof JSX.IntrinsicElements]: CreateStyledComponent<
    JSX.IntrinsicElements[Tag]
  >;
};

declare module "twin.macro" {
  // The styled and css imports
  const styled: typeof StyledTags | typeof styledImport;
  const css: typeof cssImport;
}
@kyh
Copy link
Author

kyh commented Jul 26, 2021

I have a workaround to the issue above by forwarding the ref in order to add props to the exported component:

interface Props {
  children?: ReactNode;
  size?: "xs" | "sm" | "md" | "lg" | "xl";
}

type Ref = ReactNode | HTMLElement | string;

const StyledButton = styled.button({
  ...
});

const Button = forwardRef<Ref, Props>(function Button({ ...rest }, ref) {
  return <StyledButton ref={ref} {...rest} />;
});

export default Button;

@matthewpi
Copy link

matthewpi commented Aug 22, 2021

twin.d.ts

import { css as cssImport } from '@stitches/react';
import type * as StyledComponent from '@stitches/react/types/styled-component';
import type * as Util from '@stitches/react/types/util';

import { config, CSS } from '../stitches.config';

import 'twin.macro';

type CSSProp<T = AnyIfEmpty<DefaultTheme>> = CSSObject | string;

type Stitches<Type = string> = <
	Composers extends (
		| string
		| React.ExoticComponent<any>
		| React.JSXElementConstructor<any>
		| Util.Function
		| { [name: string]: unknown }
	)[],
>(
	...composers: {
		[K in keyof Composers]: Composers[K] extends
			| string
			| React.ExoticComponent<any>
			| React.JSXElementConstructor<any>
			| Util.Function
			? Composers[K]
			: CSS & {
					variants?: {
						[Name in string]: {
							[Pair in number | string]: CSS;
						};
					};
					compoundVariants?: (('variants' extends keyof Composers[K]
						? {
								[Name in keyof Composers[K]['variants']]?:
									| Util.Widen<keyof Composers[K]['variants'][Name]>
									| Util.String;
						  } &
								Util.WideObject
						: Util.WideObject) & {
						css: CSS;
					})[];
					defaultVariants?: 'variants' extends keyof Composers[K]
						? {
								[Name in keyof Composers[K]['variants']]?:
									| Util.Widen<keyof Composers[K]['variants'][Name]>
									| Util.String;
						  }
						: Util.WideObject;
			  } & {
						[K2 in keyof Composers[K]]: K2 extends 'compoundVariants' | 'defaultVariants' | 'variants'
							? unknown
							: K2 extends keyof CSS
							? CSS[K2]
							: unknown;
					};
	}
) => StyledComponent.StyledComponent<Type, StyledComponent.StyledComponentProps<Composers>, typeof config.media, CSS>;

type StyledTags = {
	[Element in keyof JSX.IntrinsicElements]: Stitches<Element>;
};

declare module 'react' {
	interface HTMLAttributes<T> extends DOMAttributes<T> {
		css?: CSSProp;
		tw?: string;
	}

	interface SVGProps<T> extends SVGProps<T> {
		css?: CSSProp;
		tw?: string;
	}
}

declare module 'twin.macro' {
	const css: typeof cssImport;
	const styled: StyledTags;
}

stitches.config.ts

import { createStitches, CSS as StitchesCSS } from '@stitches/react';

const stitches = createStitches({});

export const { css, config, globalCss, keyframes, styled, theme, getCssText } = stitches;
export type CSS = StitchesCSS<typeof stitches>;

This is how I got this "working" in my project.

Few things to note, in the stitches config you need to make sure config and type CSS are exported.

This was tested with v1.0.0-canary.15 of @stitches/react, not v0.2.x.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants