Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jamesknelson/use-sx
Composable styles for React
https://github.com/jamesknelson/use-sx
Last synced: about 1 month ago
JSON representation
Composable styles for React
- Host: GitHub
- URL: https://github.com/jamesknelson/use-sx
- Owner: jamesknelson
- Created: 2020-05-05T11:48:04.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2020-05-05T12:30:10.000Z (over 4 years ago)
- Last Synced: 2024-09-29T00:03:12.792Z (about 2 months ago)
- Language: TypeScript
- Size: 72.3 KB
- Stars: 8
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# use-sx
**CSS-in-JS, inside out and upside down.**
## What if?
What if instead of mapping selectors-to-properties-to-values...
```jsx
```
You mapped properties-to-selectors-to-values?
```jsx
```
If your css attributes could accept functions as values, you could even specify colors for all states in a single theme object...
```jsx
theme.buttons.borderColor
}}>
```---
And what if instead of tying your pseudo-selectors to individual elements:
```jsx
```
You could specified a control boundary, and nested elements would automatically place the `:hover` selector where it makes sense?
```jsx
{}}>
```
You could compose your styled components without a care for where they'll eventually be used...
```jsx
```
See this as a [live example](https://codesandbox.io/s/admiring-mahavira-dvw7v?file=/src/app.js).
How it works
------------**It's just a hook.**
This package gives you a `useSx()` hook that takes styles in the format of the `sx` prop above, and returns styles in the format expected by a `css` prop -- as supported by [Styled Components](http://styled-components.com/).
*Note: Currently, the `useSx` hook requires Styled Components, as it reads directly from the styled-components `theme` context. Support for emotion would make a great Pull Request! 😉*
## `useSx(options)`
### Basic usage
```js
export const Button = React.forwardRef(({ sx, ...rest }, ref) => {
const css = useSx({
// The `sx` option accepts an array of styles
sx: [
{
// Pass your default styles first
backgroundColor: 'transparent',
border: '1px solid black',
borderColor: {
focus: 'blue',
}
color: 'black'
},
// Then pass in styles from the component's `sx` prop
sx,
{
// Finally, pass in any override styles -- things you don't want to be
// customizable by the `sx` prop.
cursor: 'pointer',
},
],
})return
})// Then render your component like any other
ReactDOM.render(
Hello, world!
,
document.body
)
```### Mapped props
By passing a `maps` property to `useSx`, you can add custom style properties to your components. These custom properties can then be used with theme functions and selector objects -- just as with standard CSS properties.
For example, this `` component accepts three custom style props:
- `color`, which maps directly to the `borderTopColor` prop
- `direction`, which maps to varying rotate transforms
- `size`, which sets `borderWidth` and a corresponding negative margin```jsx
export const Caret = React.forwardRef(({ sx, ...rest }, ref) => {
const css = useSx({
sx: [
{
color: (theme = {}) => theme.foregroundColor || 'black',
direction: 'down',
width: 5,
},
sx,
{
borderColor: 'transparent',
borderStyle: 'solid',
height: 0,
width: 0,
},
],
maps: {
color: (value: string) => ({
borderTopColor: value,
}),
direction: (value: CaretDirection) => ({
transform: {
down: `rotate(0)`,
up: `rotate(180deg)`,
left: `rotate(-90deg)`,
right: `rotate(90deg)`,
}[value],
}),
width: (value: number) => ({
borderWidth: value,
marginBottom: -value,
}),
},
})return
})ReactDOM.render(
Hello, world!
,
document.body
)
```## `control(StyledComponent)`
This is a Higher Order Function which expects a Styled Component, returning an identical component that acts as a **control boundary** -- i.e. the component to which `:hover` pseudoselectors on nested elements will be applied.
## `mergeSx(sx)`
This function merges anything that can be passed into the `sx` option for `useSx` into a single object.
```jsx
const mergedSx = mergeSx([
null,
{
color: 'inherit',
},
{
color: 'black',
}
])console.log(mergedSx.color) // black
```This comes in handy when creating composite components that accept an `sx` prop, and pass individual style properties down to specific children.
For example, here's how you might use `mergeSx()` to extract the `color` style from a `` component's props, and pass it down to nested `` and `` elements:
```jsx
export const ButtonContent = React.forwardRef((props, ref) => {
const { caret, glyph, label, sx, ...rest } = propsconst css = useSx({ sx })
const color = mergeSx(sx).colorreturn (
{label}
{caret && (
<>
>
)}
)
})
```License
-------MIT licensed.