Skip to content

Commit

Permalink
feat!(metro-config): add unstable_styles to css modules (#23002)
Browse files Browse the repository at this point in the history
# Why

It's too confusing to have React Native styles be the default for CSS
modules. This PR makes CSS Modules in Expo work as expected by default.
We now export (and squat) `unstable_styles` which can be used to access
the CSS Modules as React Native Web style objects. This is a breaking
change but only released in the alpha.

# Test Plan

Updated tests.

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
This is required for changes to Expo modules.
-->

- [ ] Documentation is up to date to reflect these changes (eg:
https://docs.expo.dev and README.md).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).

---------

Co-authored-by: Expo Bot <34669131+expo-bot@users.noreply.github.com>
  • Loading branch information
EvanBacon and expo-bot committed Jun 21, 2023
1 parent 8df9096 commit e62df66
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 22 deletions.
26 changes: 20 additions & 6 deletions docs/pages/versions/unversioned/config/metro.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ import 'emoji-mart/css/emoji-mart.css';
CSS Modules are a way to scope CSS to a specific component. This is useful for avoiding naming collisions and for ensuring that styles are only applied to the intended component.

In Expo, CSS Modules are defined by creating a file with the `.module.css` extension. The file can be imported from any component. The exported value is an object with the class names as keys and the React Native style objects as values.
In Expo, CSS Modules are defined by creating a file with the `.module.css` extension. The file can be imported from any component. The exported value is an object with the class names as keys and the web-only scoped names as the values. The import `unstable_styles` can be used to access `react-native-web`-safe styles.

CSS Modules support platform extensions to allow you to define different styles for different platforms. For example, you can define a `module.ios.css` and `module.android.css` file to define styles for iOS and Android respectively. You'll need to import without the extension, for example:

Expand All @@ -129,20 +129,34 @@ Flipping the extension, e.g. `App.ios.module.css` will not work and result in a
> You cannot pass styles to the `className` prop of a React Native or React Native for web component. Instead, you must use the `style` prop.
```js App.js
import styles from './App.module.css';
import styles, { unstable_styles } from './App.module.css';

export default function Page() {
return <View style={styles.container}>Hello World</View>;
return (
<>
<Text
style={{
// This is how react-native-web class names are applied
$$css: true,
_: styles.text,
}}>
Hello World
</Text>
<Text style={unstable_styles.text}>Hello World</Text>
{/* Web-only usage: */}
<p className={styles.text}>Hello World</p>
</>
);
}
```

```css App.module.css
.container {
background-color: red;
.text {
color: red;
}
```

- On web, all CSS values are available. CSS is not processed or auto-prefixed like it is with the React Native Web `StyleSheet` API.
- On web, all CSS values are available. CSS is not processed or auto-prefixed like it is with the React Native Web `StyleSheet` API. You can use `postcss.config.js` to autoprefix your CSS.
- CSS Modules use [lightningcss](https://github.com/parcel-bundler/lightningcss) under the hood, check [the issues](https://github.com/parcel-bundler/lightningcss/issues) for unsupported features.

### PostCSS
Expand Down
2 changes: 2 additions & 0 deletions packages/@expo/metro-config/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### 🛠 Breaking changes

- CSS Modules now export web-compatible styles by default and `unstable_styles` for `react-native-web` style objects. ([#23002](https://github.com/expo/expo/pull/23002) by [@EvanBacon](https://github.com/EvanBacon))

### 🎉 New features

- Strip `app/+html` files from client bundles. ([#22881](https://github.com/expo/expo/pull/22881) by [@EvanBacon](https://github.com/EvanBacon))
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`CSS Modules web transforms for dev, minified 1`] = `
{
"input": "module.exports=Object.assign({"container":{"$$css":true,"_":"_R_BGG_container"}},{});
"input": "module.exports=Object.assign({"container":"_R_BGG_container"},{unstable_styles:{"container":{"$$css":true,"_":"_R_BGG_container"}}}{});
(() => {
if (typeof document === 'undefined') {
return
Expand Down Expand Up @@ -44,7 +44,7 @@ exports[`CSS Modules web transforms for dev, minified 1`] = `
exports[`CSS Modules web transforms for dev, not minified 1`] = `
{
"input": "module.exports=Object.assign({"container":{"$$css":true,"_":"_R_BGG_container"}},{});
"input": "module.exports=Object.assign({"container":"_R_BGG_container"},{unstable_styles:{"container":{"$$css":true,"_":"_R_BGG_container"}}}{});
(() => {
if (typeof document === 'undefined') {
return
Expand Down Expand Up @@ -90,9 +90,9 @@ exports[`CSS Modules web transforms for dev, not minified 1`] = `
}
`;
exports[`CSS Modules web transforms for prod, minified 1`] = `"module.exports=Object.assign({"container":{"$$css":true,"_":"_R_BGG_container"}},{});"`;
exports[`CSS Modules web transforms for prod, minified 1`] = `"module.exports=Object.assign({"container":"_R_BGG_container"},{unstable_styles:{"container":{"$$css":true,"_":"_R_BGG_container"}}}{});"`;
exports[`CSS Modules web transforms for prod, not minified 1`] = `"module.exports=Object.assign({"container":{"$$css":true,"_":"_R_BGG_container"}},{});"`;
exports[`CSS Modules web transforms for prod, not minified 1`] = `"module.exports=Object.assign({"container":"_R_BGG_container"},{unstable_styles:{"container":{"$$css":true,"_":"_R_BGG_container"}}}{});"`;
exports[`transforms a global CSS file in dev for web 1`] = `
{
Expand Down

0 comments on commit e62df66

Please sign in to comment.