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

Docs: update JSX pragma guide with automatic runtime section #1718

Conversation

flo-sch
Copy link
Collaborator

@flo-sch flo-sch commented May 5, 2021

  • docs(pragma): add "automatic runtime" section to JSX pragma guide
    • add link to JSX pragma guide from "How it works" guide

Fixes #1335

- add link to JSX pragma guide from "How it works" guide
@vercel
Copy link

vercel bot commented May 5, 2021

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://vercel.com/systemui/theme-ui/4qzuzXah4UqVeaGT57bd9smhaJCD
✅ Preview: https://theme-ui-git-fork-flo-sch-docs-jsx-runtimeupdate-c-28cfdd.vercel.app

### Using TypeScript

If you use TypeScript to transpile your source code with `tsc` (or only
typecheck), or for instance to run tests with `ts-jest`
Copy link
Member

@hasparus hasparus May 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry mate, I was under impression we already merged this PR.

Could we write something like "If you use TypeScript to transpile your JSX"?
A lot of people are using TypeScript together with Babel, and they don't need to configure jsxImportSource globally twice (you only need it in Babel config if you're using Babel)

Copy link
Collaborator Author

@flo-sch flo-sch May 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You still need it for instance for eslint and other tools like ts-jest that do not use Babel, even if you use @babel/preset-typescript to build, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I assumed people would use babel-jest, but typescript-eslint will probably need it in the tsconfig when it's doing typechecking.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we still be more explicit here then? I don't mind 🤷

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's okay now. @lachlanjc could you take a look at this PR when you have a moment?

NOTE: this requires
[TypeScript >= 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html#react-17-jsx-factories)

NOTE: in order to typecheck `sx` using automatic runtime, you will also need to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this also the case when "jsxImportSource": "theme-ui" is configured in TypeScript config?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huuuh, I think this is above my TS understanding to be honest, but I can re-try in a project 😁

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was under impression that TS correctly found types from configured importSource, but I'll have to double-check.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like you're right actually, good catch :)
I will remove it

Copy link
Collaborator Author

@flo-sch flo-sch May 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hasparus just figured out why I thought this was still necessary:

If you apply sx to a non theme-ui component without manually providing sx types, then it does not typecheck even with jsxImportSource: "theme-ui" inside tsconfig.json (even though sx gets correctly compiled)

// StyledForm.tsx
import { Button, Flex, Input, Label } from 'theme-ui';

// Some interface not explicitly typing "sx"
export interface StyledFormProps {
  onChange(data: Record<string, unknown>): void;
}

const StyledForm: React.FC<StyledFormProps> = ({
  onChange,
  ...props
}) => (
  <form {...props}> // spreading props, including sx --> Emotion correctly compiles it to a className
    <Flex sx={{ flexFlow: 'column', p: 's' }}>
      <Label htmlFor="input.test">Test</Label>
      <Input
        id="input.test"
        type="text"
        onChange={
          (event) => onChange({
            test: event.target.value
          })
        }
      />
    </Flex>
  </form>
);

export default StyledForm;

TS error when forwarding sx

// App.tsx
const App = () => (
  <StyledForm
    onChange={console.log}
    sx={{
      // Type '{ /* ... */ sx: { ...; }; }' is not assignable to type 'IntrinsicAttributes & StyledFormProps & { children?: ReactNode; }'.
      //   Property 'sx' does not exist on type 'IntrinsicAttributes & StyledFormProps & { children?: ReactNode; }'.
      'px': 'm'
    }}
  />
);

This can be easily fixed by adding sx?: ThemeUIStyleObject to StyledFormProps in that case, just slightly sad that we get a TS error even though the className works fine IMHO, but I don't mind adding the types wherever it is needed

Could/Should the automatic sx typings be added to all JSX components instead of only theme-ui ones, or is that anti-pattern? 🤔

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @flo-sch 👋 @hasparus doesn't have access to his computer, and he asked me to write this 😄

Theme UI types add sx prop only to components which props already accept className, as sx transpiles to className.

The code responsible for this is at packages/core/src/jsx-namespace.ts#L3.

Here's a CodeSandbox, so you can try it out: https://codesandbox.io/s/frosty-https-wpp7f?file=/src/index.tsx

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @beerose, nice to meet you and thanks for relaying the answer 😁
(not sure if the sandbox link was the correct one though, seems more about GraphQL in there?)

That make sense in term of typings I guess, I did reproduce it (even without automatic runtime):
https://codesandbox.io/s/sx-props-typings-automatic-runtime-dte1v?file=/src/App.tsx

My only claim was that, since Emotion successfully compiles it anyway, it felt like a "false-negative" from TS to complain on missing sx types in that case (in that App.tsx, there is a TS complain on the first <Form sx={{ }} /> since it does not add types for className or sx)

But I guess this is another discussion here, not related to automatic runtime in itself

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey! I'm not sure how it happened but yes, the link was wrong 🤦‍♀️
Here's the valid one: https://codesandbox.io/s/affectionate-architecture-utrwm?file=/src/index.tsx
Sorry!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only claim was that, since Emotion successfully compiles it anyway, it felt like a "false-negative" from TS to complain on missing sx types in that case (in that App.tsx, there is a TS complain on the first <Form sx={{ }} /> since it does not add types for className or sx)

IMHO this isn't a false negative — sx is compiled to className which is not handled so we see almost the same error as if we passed a className, meaning "this component cannot be styled from the outside".

Co-authored-by: Piotr Monwid-Olechnowicz <hasparus@gmail.com>
@hasparus hasparus merged commit 51f7fd1 into system-ui:develop Jun 15, 2021
@hasparus
Copy link
Member

🚀 PR was released in v0.10.0 🚀

@hasparus hasparus added the released This issue/pull request has been released. label Jun 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
released This issue/pull request has been released.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Document using site-wide JSX pragma configuration
3 participants