-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
92 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
packages/merge-sx/README.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
# merge-sx | ||
|
||
[![Coverage Status](https://coveralls.io/repos/github/RobinTail/merge-sx/badge.svg?branch=master)](https://coveralls.io/github/RobinTail/merge-sx?branch=master) | ||
![NPM Downloads](https://img.shields.io/npm/dw/merge-sx) | ||
![NPM License](https://img.shields.io/npm/l/merge-sx) | ||
|
||
Combines multiple [`SxProps`](https://mui.com/system/getting-started/the-sx-prop) | ||
for [Material UI](https://mui.com/) components. | ||
|
||
## Installation | ||
|
||
```shell | ||
npm install merge-sx | ||
# or | ||
yarn add merge-sx | ||
``` | ||
|
||
## Usage | ||
|
||
The utility provides a very simple and semantically clean interface, that supports conditional and optional inclusions. | ||
|
||
```ts | ||
import { mergeSx } from "merge-sx"; | ||
|
||
// Merge your SxProps | ||
mergeSx(sx1, sx2 /*, ... */); | ||
// Merge optionally | ||
mergeSx(internalSx, props?.sx); // supports undefined | ||
// Merge conditionally | ||
mergeSx(commonSx, isMobile && mobileSx); // supports false | ||
``` | ||
|
||
## Why might you need it | ||
|
||
<abbr title="Material UI">MUI</abbr> 5 has introduced a new way of styling React components using a Theme-aware | ||
`sx` property. It can be necessary to create your own styled components while still allowing for additional styling | ||
by the consumer. In this case your component will have its own `sx` property, most likely optional. This makes it | ||
necessary somehow to combine your own styles with the styles coming from the consumer of your component. One approach | ||
might be using a styling wrapper, an alternative way to style your component with the | ||
[`styled()` utility](https://mui.com/system/styled/). Thus, you could apply the consumer's `sx` to the pre-styled | ||
component. However, this approach can be inconvenient for several reasons. | ||
|
||
I came to conclusion that merging several `sx` properties is better. However, the `SxProps` has rather complex data | ||
type. It can be an object with styling properties, can be function, can be `null`. It can be a challenge to perform | ||
a merge under strict typing of Typescript. | ||
|
||
## How it works | ||
|
||
Luckily, starting version [5.1.0](https://github.com/mui/material-ui/releases/tag/v5.1.0) of MUI `SxProps` | ||
[can](https://github.com/mui/material-ui/blob/v5.1.0/packages/mui-system/src/styleFunctionSx/styleFunctionSx.d.ts#L60) | ||
also be `array`. However, nested arrays are not allowed, so this utility does exactly the flat merge, also bringing | ||
support for conditional and optional inclusions, providing a very simple and semantically clean interface. | ||
|
||
## Performance | ||
|
||
The utility has been tested to support up to 65535 arguments. | ||
|
||
![Performance chart](https://raw.githubusercontent.com/RobinTail/merge-sx/refs/heads/master/performance.svg) | ||
|
||
## Examples | ||
|
||
### Conditional merging | ||
|
||
The utility supports `false`: | ||
|
||
```tsx | ||
<Button sx={mergeSx(commonSx, isMobile && mobileSx)}>Click me</Button> | ||
``` | ||
|
||
### Optional merging | ||
|
||
The utility supports `undefined`: | ||
|
||
```tsx | ||
interface MyButtonProps { | ||
sx?: SxProps<Theme>; // optional prop for consumer | ||
} | ||
|
||
const MyButton = ({ sx: consumerSx }: MyButtonProps) => ( | ||
<Button sx={mergeSx(internalSx, consumerSx)}>Click me</Button> | ||
); | ||
``` | ||
|
||
### Inline Theme supplying | ||
|
||
The utility is generic and accepts the type argument. | ||
|
||
```ts | ||
// theme is Theme | ||
mergeSx<Theme>(sx1, (theme) => ({ mb: theme.spacing(1) })); | ||
``` |