From 1fc1add1737839d7da5fe05d0455922f0bb6d22b Mon Sep 17 00:00:00 2001 From: Evan Jacobs <570070+probablyup@users.noreply.github.com> Date: Thu, 25 May 2023 11:21:46 -0400 Subject: [PATCH] v6 docs (#919) * docs: add v6 migration guide * docs: remove references to withComponent() API * docs: update StyleSheetManager * docs: use tsx syntax in example code * docs: remove Flow section, update TS section * chore: link v6 migration doc --- .lintstagedrc.js | 2 +- pages/docs.json | 6 +- pages/docs/api.mdx | 2 - pages/docs/faqs.mdx | 8 +- pages/index.js | 2 +- sections/advanced/components-as-selectors.mdx | 4 +- sections/advanced/existing-css.mdx | 8 +- sections/advanced/security.mdx | 2 +- sections/advanced/server-side-rendering.mdx | 8 +- sections/advanced/style-objects.mdx | 6 +- .../advanced/tagged-template-literals.mdx | 12 +-- sections/advanced/theming.mdx | 6 +- sections/api/flow.mdx | 27 ------ sections/api/helpers/create-global-style.mdx | 16 ++-- sections/api/helpers/css.mdx | 15 ++- sections/api/helpers/is-styled-component.mdx | 2 +- sections/api/helpers/keyframes.mdx | 14 ++- sections/api/helpers/style-sheet-manager.mdx | 69 +++++++------- sections/api/helpers/theme-consumer.mdx | 2 +- sections/api/helpers/use-theme.mdx | 2 +- sections/api/helpers/with-theme.mdx | 2 +- sections/api/old/extend.mdx | 2 +- sections/api/old/inject-global.mdx | 2 +- sections/api/old/inner-ref.mdx | 2 +- sections/api/primary/css-prop.mdx | 4 +- sections/api/primary/styled-component.mdx | 18 ---- .../api/primary/tagged-template-literal.mdx | 6 +- sections/api/test-utils/enzyme-find.mdx | 2 +- sections/api/test-utils/find-all.mdx | 2 +- sections/api/test-utils/find.mdx | 2 +- sections/api/typescript.mdx | 34 ++----- sections/basics/adapting-based-on-props.mdx | 2 +- .../basics/attaching-additional-props.mdx | 18 ++-- sections/basics/coming-from-css.mdx | 8 +- sections/basics/extending-styles.mdx | 2 - sections/basics/installation.mdx | 2 +- sections/basics/passed-props.mdx | 6 +- sections/basics/react-native.mdx | 4 +- .../declare-components-in-render-method.mdx | 4 +- sections/faqs/html-attribute-warnings.mdx | 6 +- sections/faqs/migration-v4.mdx | 26 +++--- sections/faqs/migration-v6.mdx | 93 +++++++++++++++++++ sections/faqs/npm-link.mdx | 2 +- sections/faqs/override-inline-styles.mdx | 2 +- ...verride-styles-with-higher-specificity.mdx | 2 +- sections/faqs/reverse-selectors.mdx | 2 +- sections/faqs/when-to-use-attrs.mdx | 2 +- sections/homepage/getting-started.mdx | 10 +- sections/tooling/babel-macro.mdx | 4 +- sections/tooling/babel-plugin.mdx | 16 ++-- sections/tooling/jest.mdx | 6 +- sections/tooling/styled-theming.mdx | 22 ++--- sections/tooling/stylelint.mdx | 20 ++-- 53 files changed, 297 insertions(+), 251 deletions(-) delete mode 100644 sections/api/flow.mdx create mode 100644 sections/faqs/migration-v6.mdx diff --git a/.lintstagedrc.js b/.lintstagedrc.js index 313a9067d..763d5bc9c 100644 --- a/.lintstagedrc.js +++ b/.lintstagedrc.js @@ -1,3 +1,3 @@ module.exports = { - '**/*.{js,jsx,ts,tsx}': ['jest -c .jest.config.js --findRelatedTests', 'prettier --write'], + '**/*.{js,jsx,ts,tsx}': ['jest -c .jest.config.js --findRelatedTests --passWithNoTests', 'prettier --write'], }; diff --git a/pages/docs.json b/pages/docs.json index 37486a681..556bfe4c8 100644 --- a/pages/docs.json +++ b/pages/docs.json @@ -85,9 +85,6 @@ { "title": "Supported CSS" }, - { - "title": "Flow" - }, { "title": "TypeScript" }, @@ -127,6 +124,9 @@ "title": "FAQs", "pathname": "faqs", "sections": [ + { + "title": "What do I need to do to migrate to v6?" + }, { "title": "What do I need to do to migrate to v5?" }, diff --git a/pages/docs/api.mdx b/pages/docs/api.mdx index a9b90e7f7..1cdfd9f38 100644 --- a/pages/docs/api.mdx +++ b/pages/docs/api.mdx @@ -4,7 +4,6 @@ import NextPage from '../../components/NextPage' import Primary from '../../sections/api/primary/index.mdx' import Helpers from '../../sections/api/helpers/index.mdx' import SupportedCSS from '../../sections/api/supported-css.mdx' -import Flow from '../../sections/api/flow.mdx' import TypeScript from '../../sections/api/typescript.mdx' import OldAPIs from '../../sections/api/old/index.mdx' import TestUtilities from '../../sections/api/test-utils/index.mdx' @@ -19,7 +18,6 @@ export default ({ children }) => ( - diff --git a/pages/docs/faqs.mdx b/pages/docs/faqs.mdx index 24af24bad..ea17e1aaa 100644 --- a/pages/docs/faqs.mdx +++ b/pages/docs/faqs.mdx @@ -11,6 +11,7 @@ import HTMLAttributeWarnings from '../../sections/faqs/html-attribute-warnings.m import BrowserSupport from '../../sections/faqs/browser-support.mdx' import MigrationV4 from '../../sections/faqs/migration-v4.mdx' import MigrationV5 from '../../sections/faqs/migration-v5.mdx' +import MigrationV6 from '../../sections/faqs/migration-v6.mdx' import CRA from '../../sections/faqs/create-react-app.mdx' import NPMLink from '../../sections/faqs/npm-link.mdx' import FlickeringText from '../../sections/faqs/flickering-text.mdx' @@ -18,11 +19,12 @@ import DeclareComponentsInRenderMethod from '../../sections/faqs/declare-compone import MissingNativeImport from '../../sections/faqs/missing-native-import.mdx' export default ({ children }) => ( - -{children} - + + {children} + ) + diff --git a/pages/index.js b/pages/index.js index fb96293a9..93d7d66f6 100644 --- a/pages/index.js +++ b/pages/index.js @@ -30,7 +30,7 @@ const SupportingTagline = styled.h2` `; const headerCode = ` -const Button = styled.a\` +const Button = styled.a<{ $primary?: boolean; }>\` /* This renders the buttons above... Edit me! */ display: inline-block; border-radius: 3px; diff --git a/sections/advanced/components-as-selectors.mdx b/sections/advanced/components-as-selectors.mdx index 04641084f..7d2617114 100644 --- a/sections/advanced/components-as-selectors.mdx +++ b/sections/advanced/components-as-selectors.mdx @@ -63,7 +63,7 @@ This behaviour is only supported within the context of _Styled_ Components: attempting to mount `B` in the following example will fail because component `A` is an instance of React.Component not a Styled Component. -```jsx +```tsx class A extends React.Component { render() { return
@@ -82,7 +82,7 @@ styled component is attempting to call the component as an interpolation functio However, wrapping `A` in a styled() factory makes it eligible for interpolation -- just make sure the wrapped component passes along `className`. -```jsx +```tsx class A extends React.Component { render() { return
diff --git a/sections/advanced/existing-css.mdx b/sections/advanced/existing-css.mdx index 91b590ad5..5b3fadfc2 100644 --- a/sections/advanced/existing-css.mdx +++ b/sections/advanced/existing-css.mdx @@ -13,7 +13,7 @@ If you use the `styled(MyComponent)` notation and `MyComponent` does not render the passed-in `className` prop, then no styles will be applied. To avoid this issue, make sure your component attaches the passed-in className to a DOM node: -```jsx +```tsx class MyComponent extends React.Component { render() { // Attach the passed-in className to the DOM node @@ -25,7 +25,7 @@ class MyComponent extends React.Component { If you have pre-existing styles with a class, you can combine the global class with the passed-in one: -```jsx +```tsx class MyComponent extends React.Component { render() { // Attach the passed-in className to the DOM node @@ -40,7 +40,7 @@ If you apply a global class together with a styled component class, the result m what you're expecting. If a property is defined in both classes with the same specificity, the last one will win. -```jsx +```tsx // MyComponent.js const MyComponent = styled.div`background-color: green;`; @@ -84,7 +84,7 @@ body.my-body button { Since the rule contains a classname and two tag names, it has higher specificity than the single classname selector generated by this styled component: -```jsx +```tsx styled.button` padding: 16px; ` diff --git a/sections/advanced/security.mdx b/sections/advanced/security.mdx index b06f8db91..5124a73ab 100644 --- a/sections/advanced/security.mdx +++ b/sections/advanced/security.mdx @@ -7,7 +7,7 @@ browser that an attacker can place in your application. This example shows how bad user input can even lead to API endpoints being called on a user's behalf. -```jsx +```tsx // Oh no! The user has given us a bad URL! const userInput = '/api/withdraw-funds' diff --git a/sections/advanced/server-side-rendering.mdx b/sections/advanced/server-side-rendering.mdx index 4e691a32d..a049c1863 100644 --- a/sections/advanced/server-side-rendering.mdx +++ b/sections/advanced/server-side-rendering.mdx @@ -20,7 +20,7 @@ If possible, we definitely recommend using the babel plugin though because it is The basic API goes as follows: -```jsx +```tsx import { renderToString } from 'react-dom/server'; import { ServerStyleSheet } from 'styled-components'; @@ -40,7 +40,7 @@ The `collectStyles` method wraps your element in a provider. Optionally you can the `StyleSheetManager` provider directly, instead of this method. Just make sure not to use it on the client-side. -```jsx +```tsx import { renderToString } from 'react-dom/server'; import { ServerStyleSheet, StyleSheetManager } from 'styled-components'; @@ -98,7 +98,7 @@ _On the server:_ `ReactDOMServer.renderToNodeStream` emits a "readable" stream that styled-components wraps. As whole chunks of HTML are pushed onto the stream, if any corresponding styles are ready to be rendered, a style block is prepended to React's HTML and forwarded on to the client browser. -```js +```tsx import { renderToNodeStream } from 'react-dom/server'; import styled, { ServerStyleSheet } from 'styled-components'; @@ -124,7 +124,7 @@ stream.on('end', () => res.end('')); _On the client:_ -```js +```tsx import { hydrate } from 'react-dom'; hydrate(); diff --git a/sections/advanced/style-objects.mdx b/sections/advanced/style-objects.mdx index 6d60d6cf7..c8a2e97fd 100644 --- a/sections/advanced/style-objects.mdx +++ b/sections/advanced/style-objects.mdx @@ -4,7 +4,7 @@ styled-components optionally supports writing CSS as JavaScript objects instead ```react // Static object -const Box = styled.div({ +const Box = styled.div<{ $background?: string; }>({ background: '#BF4F74', height: '50px', width: '50px' @@ -12,7 +12,7 @@ const Box = styled.div({ // Adapting based on props const PropsBox = styled.div(props => ({ - background: props.background, + background: props.$background, height: '50px', width: '50px' })); @@ -20,7 +20,7 @@ const PropsBox = styled.div(props => ({ render(
- +
); ``` diff --git a/sections/advanced/tagged-template-literals.mdx b/sections/advanced/tagged-template-literals.mdx index b025b33da..a28aa60ba 100644 --- a/sections/advanced/tagged-template-literals.mdx +++ b/sections/advanced/tagged-template-literals.mdx @@ -5,7 +5,7 @@ which is how we're able to create styled components. If you pass no interpolations, the first argument your function receives is an array with a string in it. -```jsx +```tsx // These are equivalent: fn`some string here`; fn(['some string here']); @@ -14,7 +14,7 @@ fn(['some string here']); Once you pass interpolations, the array contains the passed string, split at the positions of the interpolations. The rest of the arguments will be the interpolations, in order. -```jsx +```tsx const aVar = 'good'; // These are equivalent: @@ -30,10 +30,10 @@ Speaking of which, during flattening, styled-components ignores interpolations t [short-circuit evaluation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND#Short-circuit_evaluation) to conditionally add CSS rules. -```jsx -const Title = styled.h1` - /* Text centering won't break if props.upsidedown is falsy */ - ${props => props.upsidedown && 'transform: rotate(180deg);'} +```tsx +const Title = styled.h1<{ $upsideDown?: boolean; }>` + /* Text centering won't break if props.$upsideDown is falsy */ + ${props => props.$upsideDown && 'transform: rotate(180deg);'} text-align: center; `; ``` diff --git a/sections/advanced/theming.mdx b/sections/advanced/theming.mdx index 267327f53..6cf182b3a 100644 --- a/sections/advanced/theming.mdx +++ b/sections/advanced/theming.mdx @@ -96,7 +96,7 @@ render( If you ever need to use the current theme outside styled components (e.g. inside big components), you can use the `withTheme` higher order component. -```jsx +```tsx import { withTheme } from 'styled-components' class MyComponent extends React.Component { @@ -113,7 +113,7 @@ export default withTheme(MyComponent) You can also use `useContext` to access the current theme outside of styled components when working with React Hooks. -```jsx +```tsx import { useContext } from 'react' import { ThemeContext } from 'styled-components' @@ -129,7 +129,7 @@ const MyComponent = () => { You can also use `useTheme` to access the current theme outside of styled components when working with React Hooks. -```jsx +```tsx import { useTheme } from 'styled-components' const MyComponent = () => { diff --git a/sections/api/flow.mdx b/sections/api/flow.mdx deleted file mode 100644 index 8eee10cf3..000000000 --- a/sections/api/flow.mdx +++ /dev/null @@ -1,27 +0,0 @@ -## Flow - -styled-components has first-class [Flow](https://flowtype.org) support to help -you find typing errors while using our public API. - -To use Flow with the public api of styled-components we recommend that you use the library definition in `flow-typed`. -To install it you can use the `flow-typed` cli or download it manually from the git repository and store it in -a `flow-typed/` folder in the same directory with your `flowconfig`. - -### Installing the definitions - -``` -npm i -g flow-typed # if you do not already have flow-typed -flow-typed install styled-components@ -``` - -> If you are on npm >= 5.2 you could simply use [npx](https://github.com/zkat/npx) - -### Ignore styled-components source - -You should add the following lines to your `.flowconfig`, if you run into Flow errors, coming from the styled-components -package in your `node_modules` directory. - -``` -[ignore] -.*/node_modules/styled-components/.* -``` diff --git a/sections/api/helpers/create-global-style.mdx b/sections/api/helpers/create-global-style.mdx index f4602baa0..304282ba3 100644 --- a/sections/api/helpers/create-global-style.mdx +++ b/sections/api/helpers/create-global-style.mdx @@ -16,31 +16,31 @@ A helper function to generate a special `StyledComponent` that handles global st Returns a `StyledComponent` that does not accept children. Place it at the top of your React tree and the global styles will be injected when the component is "rendered". -```jsx +```tsx import { createGlobalStyle } from 'styled-components' -const GlobalStyle = createGlobalStyle` +const GlobalStyle = createGlobalStyle<{ $whiteColor?: boolean; }>` body { - color: ${props => (props.whiteColor ? 'white' : 'black')}; + color: ${props => (props.$whiteColor ? 'white' : 'black')}; } ` // later in your app - + {/* example of other top-level stuff */} ``` Since the `GlobalStyle` component is a `StyledComponent`, that means it also has access to theming from the [`` component](/docs/api#themeprovider) if provided. -```jsx +```tsx import { createGlobalStyle, ThemeProvider } from 'styled-components' -const GlobalStyle = createGlobalStyle` +const GlobalStyle = createGlobalStyle<{ $whiteColor?: boolean; }>` body { - color: ${props => (props.whiteColor ? 'white' : 'black')}; + color: ${props => (props.$whiteColor ? 'white' : 'black')}; font-family: ${props => props.theme.fontFamily}; } ` @@ -50,7 +50,7 @@ const GlobalStyle = createGlobalStyle` {/* example of other top-level stuff */} - + ``` diff --git a/sections/api/helpers/css.mdx b/sections/api/helpers/css.mdx index 061b88170..70546c4b4 100644 --- a/sections/api/helpers/css.mdx +++ b/sections/api/helpers/css.mdx @@ -20,16 +20,21 @@ If you're interpolating a string you do not need to use this, only if you're int Returns an array of interpolations, which is a flattened data structure that you can pass as an interpolation itself. -```jsx +```tsx import styled, { css } from 'styled-components' -const complexMixin = css` - color: ${props => (props.whiteColor ? 'white' : 'black')}; +interface ComponentProps { + $complex?: boolean; + $whiteColor?: boolean; +} + +const complexMixin = css` + color: ${props => (props.$whiteColor ? 'white' : 'black')}; ` -const StyledComp = styled.div` +const StyledComp = styled.div` /* This is an example of a nested interpolation */ - ${props => (props.complex ? complexMixin : 'color: blue;')}; + ${props => (props.$complex ? complexMixin : 'color: blue;')}; ` ``` diff --git a/sections/api/helpers/is-styled-component.mdx b/sections/api/helpers/is-styled-component.mdx index 16223c809..fbdca428f 100644 --- a/sections/api/helpers/is-styled-component.mdx +++ b/sections/api/helpers/is-styled-component.mdx @@ -19,7 +19,7 @@ A utility to help identify styled components. Returns true if the passed function is a valid styled components-wrapped component class. It can be useful for determining if a component needs to be wrapped such that it can be used as a component selector: -```jsx +```tsx import React from 'react' import styled, { isStyledComponent } from 'styled-components' import MaybeStyledComponent from './somewhere-else' diff --git a/sections/api/helpers/keyframes.mdx b/sections/api/helpers/keyframes.mdx index 9fb86fb93..df9037c52 100644 --- a/sections/api/helpers/keyframes.mdx +++ b/sections/api/helpers/keyframes.mdx @@ -18,7 +18,7 @@ Returns a Keyframes model, to be used in your animation declarations. You can us > In styled-components v3 and below, the `keyframes` helper directly returned the animation name instead of an object with the `getName` method. -```jsx +```tsx import styled, { keyframes } from 'styled-components' const fadeIn = keyframes` @@ -37,9 +37,13 @@ const FadeInButton = styled.button` If you are composing your style rule as a partial, make sure to use the `css` helper. -```jsx +```tsx import styled, { css, keyframes } from 'styled-components' +interface AnimationProps { + $animationLength: number; +} + const pulse = keyframes` 0% { opacity: 0; @@ -50,11 +54,11 @@ const pulse = keyframes` ` const animation = props => - css` - ${pulse} ${props.animationLength} infinite alternate; + css` + ${pulse} ${props.$animationLength} infinite alternate; ` -const PulseButton = styled.button` +const PulseButton = styled.button` animation: ${animation}; ` ``` diff --git a/sections/api/helpers/style-sheet-manager.mdx b/sections/api/helpers/style-sheet-manager.mdx index f7c66578e..1327dccb4 100644 --- a/sections/api/helpers/style-sheet-manager.mdx +++ b/sections/api/helpers/style-sheet-manager.mdx @@ -15,34 +15,41 @@ A helper component for modifying how your styles are processed. For a given subt - - - disableVendorPrefixes (v5+) - - Opts the given subtree out of adding legacy CSS properties for rendered components. - - - - - sheet - - - Thar be dragons ahead. Create and provide your own StyleSheet if necessary for advanced SSR scenarios. - - - - - - stylisPlugins (v5+) - - - An array of plugins to be run by stylis during compilation. Check out{' '} - - what's available on npm - - . - - + + + disableVendorPrefixes (v5, removed in v6) + + Opts the given subtree out of adding legacy CSS properties for rendered components. + + + + + enableVendorPrefixes (v6+) + + Opts the given subtree into adding legacy CSS properties for rendered components. + + + + + sheet + + + Thar be dragons ahead. Create and provide your own StyleSheet if necessary for advanced SSR scenarios. + + + + + + stylisPlugins (v5+) + + + An array of plugins to be run by stylis during compilation. Check out{' '} + + what's available on npm + + . + + @@ -54,7 +61,7 @@ A helper component for modifying how your styles are processed. For a given subt -For example if your app runs only in modern browsers, you may want to disable vendor prefixing for your styles: +For example if your app is intended for legacy browsers, you may want to enable vendor prefixing for your styles: ```react // import styled, { StyleSheetManager } from 'styled-components' @@ -65,8 +72,8 @@ const Box = styled.div` ` render( - - If you inspect me, there are no vendor prefixes for the flexbox style. + + If you inspect me, there are vendor prefixes for the flexbox style. ) ``` diff --git a/sections/api/helpers/theme-consumer.mdx b/sections/api/helpers/theme-consumer.mdx index d5b994b93..b3b29edce 100644 --- a/sections/api/helpers/theme-consumer.mdx +++ b/sections/api/helpers/theme-consumer.mdx @@ -4,7 +4,7 @@ This is the ["consumer" component](https://reactjs.org/docs/context.html#consume It passes the current theme (based on a [`ThemeProvider`](/docs/api#themeprovider) higher in your component tree) as an argument to the child function. From this function, you may return further JSX or nothing. -```jsx +```tsx import { ThemeConsumer } from 'styled-components' export default class MyComponent extends React.Component { diff --git a/sections/api/helpers/use-theme.mdx b/sections/api/helpers/use-theme.mdx index 2d4a78b2f..df709277f 100644 --- a/sections/api/helpers/use-theme.mdx +++ b/sections/api/helpers/use-theme.mdx @@ -2,7 +2,7 @@ This is a custom hook to get the current theme from a `ThemeProvider`. -```jsx +```tsx import { useTheme } from 'styled-components' function MyComponent() { diff --git a/sections/api/helpers/with-theme.mdx b/sections/api/helpers/with-theme.mdx index 095ba7b23..37d6b9ec5 100644 --- a/sections/api/helpers/with-theme.mdx +++ b/sections/api/helpers/with-theme.mdx @@ -20,7 +20,7 @@ pass it to your component as a `theme` prop. Returns the passed component inside a wrapper (higher order component). The passed component will receive a `theme` prop with the current theme object. -```jsx +```tsx import { withTheme } from 'styled-components' class MyComponent extends React.Component { diff --git a/sections/api/old/extend.mdx b/sections/api/old/extend.mdx index afe350b51..f1d48f99d 100644 --- a/sections/api/old/extend.mdx +++ b/sections/api/old/extend.mdx @@ -16,7 +16,7 @@ This is a method that creates a new `StyledComponent` and extends its rules. -```jsx +```tsx import styled from 'styled-components' const Component = styled.div` diff --git a/sections/api/old/inject-global.mdx b/sections/api/old/inject-global.mdx index ce47aab1d..91d2fc470 100644 --- a/sections/api/old/inject-global.mdx +++ b/sections/api/old/inject-global.mdx @@ -17,7 +17,7 @@ the stylesheet directly. -```jsx +```tsx import { injectGlobal } from 'styled-components' injectGlobal` diff --git a/sections/api/old/inner-ref.mdx b/sections/api/old/inner-ref.mdx index b2f4ccfe1..51b8dbf5b 100644 --- a/sections/api/old/inner-ref.mdx +++ b/sections/api/old/inner-ref.mdx @@ -14,7 +14,7 @@ To get a ref to the actual, wrapped DOM node, pass the callback to the `innerRef This example uses `innerRef` to save a ref to the styled input and focuses it once the user hovers over it. -```jsx +```tsx const Input = styled.input` padding: 0.5em; margin: 0.5em; diff --git a/sections/api/primary/css-prop.mdx b/sections/api/primary/css-prop.mdx index a2c7ea29b..fce857821 100644 --- a/sections/api/primary/css-prop.mdx +++ b/sections/api/primary/css-prop.mdx @@ -4,7 +4,7 @@ Sometimes you don't want to create an extra component just to apply a bit of sty > To enable support for the `css` prop you have to use the [Babel plugin](/docs/tooling#babel-plugin). -```jsx +```tsx
- - - 1. component / tagname - - Either a valid react component or a tagname like `'div'`. - - - -Returns a new `StyledComponent` with the new tag / component being applied when it's used. - -> As of styled-components v4 the `withComponent` API is now a candidate for deprecation. In all likelihood, you probably want to use the new [`"as"` prop](#as-polymorphic-prop) to simply switch what element/component being rendered since the `withComponent` API is destructive toward styles if the lowest-wrapped component is a `StyledComponent`. - #### `"as"` polymorphic prop | v4 If you want to keep all the styling you've applied to a component but just switch out what's being ultimately rendered (be it a different HTML tag or a different custom component), you can use the `"as"` prop to do this at runtime. diff --git a/sections/api/primary/tagged-template-literal.mdx b/sections/api/primary/tagged-template-literal.mdx index d35a9db83..267f18451 100644 --- a/sections/api/primary/tagged-template-literal.mdx +++ b/sections/api/primary/tagged-template-literal.mdx @@ -38,18 +38,18 @@ Check the section on [Theming](/docs/advanced#theming) for more information on t const padding = '3em' -const Section = styled.section` +const Section = styled.section<{ $background?: string; }>` color: white; /* Pass variables as inputs */ padding: ${padding}; /* Adjust the background from the properties */ - background: ${props => props.background}; + background: ${props => props.$background}; ` render( -
+
✨ Magic
) diff --git a/sections/api/test-utils/enzyme-find.mdx b/sections/api/test-utils/enzyme-find.mdx index 723707958..b0eb1934f 100644 --- a/sections/api/test-utils/enzyme-find.mdx +++ b/sections/api/test-utils/enzyme-find.mdx @@ -2,7 +2,7 @@ A convenience method for finding instances of a particular styled component within an enzyme wrapper. -```jsx +```tsx import { mount } from 'enzyme' import styled from 'styled-components' import { enzymeFind } from 'styled-components/test-utils' diff --git a/sections/api/test-utils/find-all.mdx b/sections/api/test-utils/find-all.mdx index b30bfed2a..ca4c48453 100644 --- a/sections/api/test-utils/find-all.mdx +++ b/sections/api/test-utils/find-all.mdx @@ -2,7 +2,7 @@ A convenience method to find all instances of a styled component's rendered DOM node within a given DOM root. -```js +```tsx import styled from 'styled-components' import { findAll } from 'styled-components/test-utils' diff --git a/sections/api/test-utils/find.mdx b/sections/api/test-utils/find.mdx index beccba3c4..fb5428881 100644 --- a/sections/api/test-utils/find.mdx +++ b/sections/api/test-utils/find.mdx @@ -2,7 +2,7 @@ A convenience method to find a single instance of a styled component's rendered DOM node within a given DOM root. -```js +```tsx import styled from 'styled-components' import { find } from 'styled-components/test-utils' diff --git a/sections/api/typescript.mdx b/sections/api/typescript.mdx index 6f7d851ca..921b10e0d 100644 --- a/sections/api/typescript.mdx +++ b/sections/api/typescript.mdx @@ -1,24 +1,8 @@ -## TypeScript +## TypeScript | v6 -styled-components has community-organized [TypeScript definitions](https://www.npmjs.com/package/@types/styled-components) on [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) which powers the editing experience in IDEs and can provide types for TypeScript projects. To install them, run: +styled-components provides TypeScript definitions which empowers the editing experience in IDEs and increases type safety for TypeScript projects. -```sh -# Web -npm install --save-dev @types/styled-components - -# React Native -npm install --save-dev @types/styled-components @types/styled-components-react-native -``` - -React Native only: If your `tsconfig` assigns `types` then you will need to add "styled-components-react-native" there. For example: - -```json -"types": ["jest", "styled-components-react-native"], -``` - -> Now that Babel 7 is out and the [TypeScript preset](https://babeljs.io/docs/en/babel-preset-typescript) is available, it's now possible to use the [styled-components babel plugin](/docs/tooling#babel-plugin) in conjunction with TypeScript. - -Before you can effectively start to use TypeScript you will have to do a little bit of configuration. +> For older versions of styled-components, there are community definitions available via the `@types/styled-components` NPM package. ### Create a declarations file @@ -86,7 +70,7 @@ export { myTheme }; That's it! We're able to use styled-components just by using any original import. -```jsx +```tsx import styled, { createGlobalStyle, css } from 'styled-components'; // theme is now fully typed @@ -116,11 +100,11 @@ import styled from 'styled-components'; import Header from './Header'; interface TitleProps { - readonly isActive: boolean; + readonly $isActive: boolean; } const Title = styled.h1` - color: ${(props) => (props.isActive ? props.theme.colors.main : props.theme.colors.secondary)}; + color: ${(props) => (props.$isActive ? props.theme.colors.main : props.theme.colors.secondary)}; `; ``` @@ -161,7 +145,7 @@ const NewHeader3 = styled(({ customColor, ...rest }: { customColor: string } & H `; ``` -Or using [shouldForwardProp](https://styled-components.com/docs/api#shouldforwardprop): +Or using [shouldForwardProp](/docs/api#shouldforwardprop): ```tsx import styled from 'styled-components'; @@ -179,7 +163,7 @@ const NewHeader4 = styled(Header).withConfig({ When defining a component you will need to mark `className` as optional in your Props interface: -```jsx +```tsx interface LogoProps { /* This prop is optional, since TypeScript won't know that it's passed by the wrapper */ className?: string; @@ -204,7 +188,7 @@ To use function components and have typechecking for the props you'll need to de the component alongside with its type. This is not special to styled-components, this is just how React works: -```jsx +```tsx interface BoxProps { theme?: ThemeInterface; borders?: boolean; diff --git a/sections/basics/adapting-based-on-props.mdx b/sections/basics/adapting-based-on-props.mdx index 2ebc0cf03..26e525c26 100644 --- a/sections/basics/adapting-based-on-props.mdx +++ b/sections/basics/adapting-based-on-props.mdx @@ -7,7 +7,7 @@ You can pass a function ("interpolations") to a styled component's template lite This button component has a primary state that changes its color. When setting the $primary prop to true, we are swapping out its background and text color. ```react -const Button = styled.button` +const Button = styled.button<{ $primary?: boolean; }>` /* Adapt the colors based on primary prop */ background: ${props => props.$primary ? "#BF4F74" : "white"}; color: ${props => props.$primary ? "white" : "#BF4F74"}; diff --git a/sections/basics/attaching-additional-props.mdx b/sections/basics/attaching-additional-props.mdx index a569f3189..796b38ca2 100644 --- a/sections/basics/attaching-additional-props.mdx +++ b/sections/basics/attaching-additional-props.mdx @@ -12,23 +12,23 @@ const Input = styled.input.attrs(props => ({ type: "text", // or we can define dynamic ones - size: props.size || "1em", -}))` + $size: props.$size || "1em", +}))<{ $size?: string; }>` color: #BF4F74; font-size: 1em; border: 2px solid #BF4F74; border-radius: 3px; /* here we use the dynamically computed prop */ - margin: ${props => props.size}; - padding: ${props => props.size}; + margin: ${props => props.$size}; + padding: ${props => props.$size}; `; render(

- +
); ``` @@ -44,11 +44,11 @@ This allows each wrapper to **override** nested uses of `.attrs`, similarly to h ```react const Input = styled.input.attrs(props => ({ type: "text", - size: props.size || "1em", -}))` + $size: props.$size || "1em", +})<{ $size?: string; }>` border: 2px solid #BF4F74; - margin: ${props => props.size}; - padding: ${props => props.size}; + margin: ${props => props.$size}; + padding: ${props => props.$size}; `; // Input's attrs will be applied first, and then this attrs obj diff --git a/sections/basics/coming-from-css.mdx b/sections/basics/coming-from-css.mdx index 04ea3a9fe..644b96ea2 100644 --- a/sections/basics/coming-from-css.mdx +++ b/sections/basics/coming-from-css.mdx @@ -4,7 +4,7 @@ If you're familiar with importing CSS into your components (e.g. like CSSModules) you'll be used to doing something like this: -```jsx +```tsx import React from 'react'; import styles from './styles.css'; @@ -32,7 +32,7 @@ export default class Counter extends React.Component { Because a Styled Component is the _combination_ of the element and the rules that style it, we'd write `Counter` like this: -```jsx +```tsx import React from 'react'; import styled from 'styled-components'; @@ -72,7 +72,7 @@ It is important to define your styled components outside of the render method, o Write your styled components the recommended way: -```jsx +```tsx const StyledWrapper = styled.div` /* ... */ `; @@ -84,7 +84,7 @@ const Wrapper = ({ message }) => { Instead of: -```jsx +```tsx const Wrapper = ({ message }) => { // WARNING: THIS IS VERY VERY BAD AND SLOW, DO NOT DO THIS!!! const StyledWrapper = styled.div` diff --git a/sections/basics/extending-styles.mdx b/sections/basics/extending-styles.mdx index b021ccfcd..f1382cace 100644 --- a/sections/basics/extending-styles.mdx +++ b/sections/basics/extending-styles.mdx @@ -84,5 +84,3 @@ render(
); ``` - -> If you are still on an older version than v4, you can use the [`.withComponent`](/docs/api#withcomponent) or [`.extend`](/docs/api#deprecated-extend) API's to achieve the same result as with the [`"as" prop`](/docs/api#as-polymorphic-prop), but note that this is discouraged as with v4 [`.extend` was removed](/releases#breaking-changes) and `.withComponent` was marked as a candidate for future deprecation. diff --git a/sections/basics/installation.mdx b/sections/basics/installation.mdx index 83ef24ba6..455fe3ad4 100644 --- a/sections/basics/installation.mdx +++ b/sections/basics/installation.mdx @@ -35,7 +35,7 @@ If you're not using a module bundler or package manager we also have a global (" Once you've added `styled-components` you will have access to the global `window.styled` variable. -```js +```tsx const Component = window.styled.div` color: red; ` diff --git a/sections/basics/passed-props.mdx b/sections/basics/passed-props.mdx index 54f124039..09e734b07 100644 --- a/sections/basics/passed-props.mdx +++ b/sections/basics/passed-props.mdx @@ -7,10 +7,10 @@ DOM node that is mounted, as with React elements. ```react // Create an Input component that'll render an tag with some styles -const Input = styled.input` +const Input = styled.input<{ $inputColor?: string; }>` padding: 0.5em; margin: 0.5em; - color: ${props => props.inputColor || "#BF4F74"}; + color: ${props => props.$inputColor || "#BF4F74"}; background: papayawhip; border: none; border-radius: 3px; @@ -20,7 +20,7 @@ const Input = styled.input` render(
- +
); ``` diff --git a/sections/basics/react-native.mdx b/sections/basics/react-native.mdx index 254760232..5c4784a58 100644 --- a/sections/basics/react-native.mdx +++ b/sections/basics/react-native.mdx @@ -3,7 +3,7 @@ styled-components can be used with React Native in the same way and with the same import. Try this example with [Snack by Expo](https://snack.expo.io/@danielmschmidt/styled-components). -```jsx +```tsx import React from 'react' import styled from 'styled-components/native' @@ -37,7 +37,7 @@ be an array, and shorthands (e.g. for `margin`) thanks to Imagine how you'd write the property in React Native, guess how you'd transfer it to CSS, and you're probably right: -```jsx +```tsx const RotatedBox = styled.View` transform: rotate(90deg); text-shadow-offset: 10px 5px; diff --git a/sections/faqs/declare-components-in-render-method.mdx b/sections/faqs/declare-components-in-render-method.mdx index c1b7da45a..cea12e25c 100644 --- a/sections/faqs/declare-components-in-render-method.mdx +++ b/sections/faqs/declare-components-in-render-method.mdx @@ -5,7 +5,7 @@ This means that React will have to discard and re-calculate that part of the DOM 🚫 -```jsx +```tsx const Header = () => { const Title = styled.h1` font-size: 10px; @@ -21,7 +21,7 @@ const Header = () => { ✅ -```jsx +```tsx const Title = styled.h1` font-size: 10px; ` diff --git a/sections/faqs/html-attribute-warnings.mdx b/sections/faqs/html-attribute-warnings.mdx index 6e40a7c4e..4fe9890ab 100644 --- a/sections/faqs/html-attribute-warnings.mdx +++ b/sections/faqs/html-attribute-warnings.mdx @@ -13,7 +13,7 @@ To learn more about how props are passed, see [this section](/docs/basics#passed For example: -```jsx +```tsx const Link = props => ( {props.text} @@ -41,7 +41,7 @@ To fix this, you can use transient props or destructure props: You can use [transient props](https://styled-components.com/docs/api#transient-props) to fix this: -```jsx +```tsx const Link = ({ className, text, ...props }) => ( {text} @@ -59,7 +59,7 @@ const StyledComp = styled(Link)` If you use a version < 5.1 or if you can't use transient props, you can use argument destructuring to pull out those known styling props: -```jsx +```tsx const Link = ({ className, red, text, ...props }) => ( {text} diff --git a/sections/faqs/migration-v4.mdx b/sections/faqs/migration-v4.mdx index eb6901d39..564dad427 100644 --- a/sections/faqs/migration-v4.mdx +++ b/sections/faqs/migration-v4.mdx @@ -4,13 +4,13 @@ This is a pretty big release with lots of changes both under the hood and at the 1. Upgrade to the latest styled-components: -``` +```sh npm install styled-components@^4.0.0 ``` 2. Make sure your application is using `react` >= 16.3; internally we are using the new `React.forwardRef` API and new context APIs if you wish to try and polyfill for older React version support -``` +```sh npm install react@^16.3 react-dom@^16.3 ``` @@ -22,7 +22,7 @@ A [codemod is available](https://github.com/styled-components/styled-components- 🚫 -```js +```tsx import styled from 'styled-components' const Component = styled.div` @@ -37,7 +37,7 @@ const ExtendedComponent = Component.extend` ✅ -```js +```tsx import styled from 'styled-components' const Component = styled.div` @@ -58,7 +58,7 @@ A [codemod is available](https://github.com/styled-components/styled-components- 🚫 -```js +```tsx import { injectGlobal } from 'styled-components' injectGlobal` @@ -70,7 +70,7 @@ injectGlobal` ✅ -```jsx +```tsx import { createGlobalStyle } from "styled-components" const GlobalStyle = createGlobalStyle` @@ -93,7 +93,7 @@ See the documentation for [`createGlobalStyle`](/docs/api#createglobalstyle) to 🚫 -```jsx +```tsx const Component = styled.div` background: blue; color: red; @@ -105,7 +105,7 @@ const Component = styled.div` ✅ -```jsx +```tsx const Component = styled.div` background: blue; color: red; @@ -119,7 +119,7 @@ const Component = styled.div` 🚫 -```js +```tsx import styled, { keyframes } from 'styled-components' const animation = keyframes` @@ -143,7 +143,7 @@ const Component = styled.div` ✅ -```js +```tsx import styled, { css, keyframes } from 'styled-components' const animation = keyframes` @@ -169,7 +169,7 @@ const Component = styled.div` 🚫 -```js +```tsx import styled from 'styled-components' const Input = styled.input.attrs({ @@ -182,7 +182,7 @@ const Input = styled.input.attrs({ ✅ -```js +```tsx import styled from 'styled-components' const Input = styled.input.attrs(props => ({ @@ -195,7 +195,7 @@ const Input = styled.input.attrs(props => ({ 8. If you're using TypeScript, the typings are now located in DefinitelyTyped: -``` +```sh npm install @types/styled-components ``` diff --git a/sections/faqs/migration-v6.mdx b/sections/faqs/migration-v6.mdx new file mode 100644 index 000000000..12c15679a --- /dev/null +++ b/sections/faqs/migration-v6.mdx @@ -0,0 +1,93 @@ +## What do I need to do to migrate to v6? + +First, let's start by updating the necessary packages to their latest versions. + +If you're using NPM: + +```sh +npm install styled-components@^6.0.0 stylis@^4.0.0 +npm uninstall @types/styled-components +``` + +If you're using Yarn: + +```sh +yarn add styled-components@^6.0.0 stylis@^4.0.0 +yarn remove @types/styled-components +``` + +As styled-components now provides its own types, there's no longer a need for community ones. + +### TypeScript + +Good news for TypeScript enthusiasts – styled-components is now natively written in TypeScript! Even if you haven't used TypeScript before, it's recommended for improving the reliability of your project as it can alert you when you're using an unknown prop or if a prop has a different value than expected. + +However, if you don't use TypeScript in your project, don't worry! IDEs like VS Code will still pick up the types and provide hints as you write your code. + +### `shouldForwardProp` is no longer provided by default + +If haven't migrated your styling to use [transient props (`$prefix`)](/docs/faqs#transient-props-since-51), you might notice React warnings about styling props getting through to the DOM in v6. To restore the v5 behavior, use `StyleSheetManager`: + +```tsx +import isPropValid from '@emotion/is-prop-valid'; +import { StyleSheetManager } from 'styled-components'; + +function MyApp() { + return ( + + {/* other providers or your application's JSX */} + + ) +} +``` + +### Vendor prefixes are omitted by default + +As the web and browsers have matured significantly by 2023, vendor prefixing is often unnecessary. Therefore, for the v6 release, we've decided to omit automatic prefixing by default to reduce the amount of CSS delivered to a page. If you prefer the v5 behavior, you can restore it via `StyleSheetManager`: + +```tsx +import { StyleSheetManager } from 'styled-components'; + +function MyApp() { + return ( + + {/* other providers or your application's JSX */} + + ) +} +``` + +To accommodate this change, the original `disableVendorPrefixes` prop was inverted to `enableVendorPrefixes`; if you have `disableVendorPrefixes` set, you can now remove it as it's the new default. + +### Update stylis plugins + +With styled-components v6 utilizing the newer stylis v4, make sure to update any `stylisPlugins` you're providing to StyleSheetManager. + +styled-components v6 uses the newer stylis v4; if you are providing `stylisPlugins` to `StyleSheetManager`, ensure the plugins are up-to-date. For instance, [`stylis-plugin-rtl`](https://www.npmjs.com/package/stylis-plugin-rtl) released a new version to support the updated stylis. + +### Transient `$as` and `$forwardedAs` props have been dropped + +To reduce confusion around application order, we've dropped the transient `$as` and `$forwardedAs` props. Please use the regular `as` and `forwardedAs` props instead. + +### Dropped legacy `withComponent()` API + +This change has been a long time coming. The `withComponent` API is no longer supported, so please use the `as` prop instead. You can specify `as` at definition time via `attrs` or at runtime: + +```tsx +import styled from 'styled-components'; + +const Button = styled.button` + background: blue; + color: white; +`; + +const ButtonLink = styled(Button).attrs({ as: 'a' })``; + +// These are equivalent, but `ButtonLink` allows for attaching further styling if desired. +