Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/robinweser/brandeur

Convenience tool belt for css-hooks
https://github.com/robinweser/brandeur

css-hooks cssinjs inline-style styling

Last synced: 3 months ago
JSON representation

Convenience tool belt for css-hooks

Awesome Lists containing this project

README

        

# Brandeur

Brandeur is a convenience layer and tool belt on top of [css-hooks](https://css-hooks.com) for React.

npm version npm downloads Bundlephobia

## Benefits

- Similar API
- Theming
- RTL Conversion
- Vendor Prefixing
- Fallback Value Support
- Keyframes Support
- Extendable Plugin System
- Fela Plugin Compatibility
- TypeScript Support

## Installation

```sh
# npm
npm i --save brandeur
# yarn
yarn add brandeur
# pnpm
pnpm add brandeur
```

## The Gist

```javascript
import { createHooks } from 'brandeur'
import prefixer, { fallbacks } from 'brandeur-plugin-prefixer'

const theme = {
colors: { primary: 'red' },
}

const [staticCSS, css] = createHooks({
hooks: {
// either custom hooks or @css-hooks/recommended
},
plugins: [prefixer()] as const,
fallbacks: [
...fallbacks,
{ property: 'position', values: ['-webkit-sticky', 'sticky'] },
],
keyframes: {
fadeIn: {
from: { opacity: 0 },
to: { opacity: 1 },
},
},
theme,
})

// fades in, red color, vendor prefixed and browser-compatible position: sticky
const style = css(({ theme, keyframes }) => ({
animationName: keyframes.fadeIn,
color: theme.colors.primary,
position: 'sticky',
appearance: 'none',
}))
```

## Why

tbd.

## API

Currently Brandeur only exposes two functions:

- [createHooks](#createhooks)
- [fallbackValue](#fallbackValue)

### createHooks

The main API that wraps [createHooks](https://css-hooks.com/docs/react/api) from [css-hooks](https://css-hooks.com).

It returns the same structural array including both the static CSS and the `css` function. The difference is that the static CSS includes more than just the hooks and the `css` function also accepts functions.

#### Arguments

It accepts the following arguments as an object.

| Argument | Type | Description |
| --------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| plugins | _Array\_ | List of plugins that are used to process each style before transforming into a flat hooks style. See [Plugins](#plugins) for a list of all available plugins. |
| fallbacks | _Array\_ | List of fallbacks that are added and automatically replace within style objects. |
| keyframes | _Object_ | A map of animationName-keyframe pairs. |
| theme | _Object_ | A theme object that can be accessed from within style functions. |

##### Plugin

```ts
type Plugin = style => style
```

Plugins are simple functions that take a style object and return a new one, similar to Fela plugins.

> **Note**: See [Plugins](#plugins) for a list of all available plugins.

##### Fallback

```ts
type Fallback = {
property: string | Array
values: Array
match?: string
}
```

> **Tip**: The [fallbackValue](#fallbackvalue) API provides a convenient way to create those fallback objects.

#### Returns

It returns an array where the first item is a static CSS string and the second item is the `css` function to create styles. The `css` function accepts both style object as well as functions where the first argument is an object that only has a theme property.

#### Example

See [The Gist](#the-gist).

### fallbackValue

A tiny helper function to create fallbacks in a more convenient way.

#### Arguments

It accepts the following arguments as an object.

| Argument | Type | Description |
| -------- | -------------------------- | --------------------------------------------------------------------------------------------------------------- |
| property | _Array\ \| string_ | A property or list of properties for which the fallback value applies. |
| values | _Array\_ | A list of fallback values where the last one is the default. |
| match | _string?_ | An optional matcher string that's used to replace values in style objects. Defaults to the last `values` value. |

#### Returns

(_[Fallback](#fallback)_) An object with respective fallback properties.

#### Example

```js
import { fallbackValue } from 'brandeur'

const positionSticky = fallbackValue('position', ['-webkit-sticky', 'sticky'])
```

## Plugins

Brandeur becomes really powerful when utilising the rich plugin echosystem. That way, we can extend the styling engine to support our personal needs.

### Brandeur Plugins

| Name | Description |
| ------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| [brandeur-plugin-debug](https://github.com/robinweser/brandeur/tree/main/packages/brandeur-plugin-debug) | Uses [styles-debugger](https://github.com/kitze/styles-debugger) to visually debug styles. |
| [brandeur-plugin-enforce-longhand](https://github.com/robinweser/brandeur/tree/main/packages/brandeur-plugin-enforce-longhand) | Specific implementation of sort-property. Enforces longhand over shorthand properties for more deterministic results. |
| [brandeur-plugin-prefixer](https://github.com/robinweser/brandeur/tree/main/packages/brandeur-plugin-prefixer) | Adds vendor prefixes to style objects. |
| [brandeur-plugin-sort-property](https://github.com/robinweser/brandeur/tree/main/packages/brandeur-plugin-sort-property) | Sorts properties according to a priorty map. Helpful when trying to enforce certain properties over others. |
| [brandeur-plugin-responsive-value](https://github.com/robinweser/brandeur/tree/main/packages/brandeur-plugin-responsive-value) | Resolves responsive array values. |

### Fela Plugins

Thanks to similar architecture and API design, brandeur supports almost all [Fela plugins](https://fela.js.org/docs/latest/advanced/plugins) out of the box.

> **Tip**: In order to get proper types, make sure that you import `brandeur` in the same file where Fela plugins are imported as types for all Fela plugins are shipped with the core package.

| Name | Description | Compatibility |
| ------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| [fela-plugin-bidi](https://github.com/robinweser/fela/tree/master/packages/fela-plugin-bidi) | Enables direction-independent styles by converting them to either `rtl` or `ltr` on the fly. | Does not support context-specific `direction` via `theme`. |
| [fela-plugin-custom-property](https://github.com/robinweser/fela/tree/master/packages/fela-plugin-custom-property) | Resolves custom properties. | Full |
| [fela-plugin-expand-shorthand](https://github.com/robinweser/fela/tree/master/packages/fela-plugin-expand-shorthand) | Expands shorthand properties into their longhand forms. | Full |
| [fela-plugin-extend](https://github.com/robinweser/fela/tree/master/packages/fela-plugin-extend) | Adds a convenient syntax for (conditionally) extending styles. | Full |
| [fela-plugin-hover-media](https://github.com/robinweser/fela/tree/master/packages/fela-plugin-hover-media) | Wraps `:hover` styles in `@media (hover: hover)` queries. | Full |
| [fela-plugin-kebab-case](https://github.com/robinweser/fela/tree/master/packages/fela-plugin-kebab-case) | Converts properties written in kebab-case to camelCase. | Full |
| [fela-plugin-logger](https://github.com/robinweser/fela/tree/master/packages/fela-plugin-logger) | Logs processed style objects. | Full |
| [fela-plugin-multiple-selectors](https://github.com/robinweser/fela/tree/master/packages/fela-plugin-multiple-selectors) | Resolves multiple comma-separated selectors to individual object keys. | Full |
| [fela-plugin-responsive-value](https://github.com/robinweser/fela/tree/master/packages/fela-plugin-responsive-value) | Resolves array values to pre-defined media queries. Useful for component APIs. | Does not support the `props` argument to receive the `theme`. Use a static `theme` instead. |
| [fela-plugin-rtl](https://github.com/robinweser/fela/tree/master/packages/fela-plugin-rtl) | Converts styles to their right-to-left counterpart | Does not support context-specific `direction` via `theme`. |
| [fela-plugin-unit](https://github.com/robinweser/fela/tree/master/packages/fela-plugin-unit) | Automatically adds units to values if needed. | Full |
| [fela-plugin-validator](https://github.com/robinweser/fela/tree/master/packages/fela-plugin-validator) | Validates, logs & optionally deletes invalid properties for keyframes and rules. | Full |

#### Incompatible Plugins

| Plugin | Alternative |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| fela-plugin-prefixer | Use [brandeur-plugin-prefixer](https://github.com/robinweser/brandeur/tree/main/packages/brandeur-plugin-prefixer) instead. |
| fela-plugin-named-keys
fela-plugin-friendly-pseudo-class
fela-plugin-pseudo-prefixer
fela-plugin-fullscreen-prefixer
fela-plugin-placeholder-prefixer
| Use `hooks` directly to set those. |
| fela-plugin-embedded | No replacement yet due to missing font and keyframe primitives. |
| fela-plugin-theme-value | No replacement yet due to incompatible plugin APIs. |

## TypeScript

Brandeur comes with native TypeScript support, but requires some manual setup to get the correct types for all plugins.

### Style Object

By default, Brandeur automatically infers the type just like css-hooks does. It supports all `React.CSSProperties`. For convenience, we also export a `Style` type from brandeur.

In order to extend the type with plugins, we need to set them up correctly.

```tsx
import { createHooks } from 'brandeur'

import extend from 'fela-plugin-extend'
import responsiveValue, {
ResponsiveStyle,
} from 'brandeur-plugin-responsive-value'

const [staticCSS, css] = createHooks({
// ... config
plugins: [
// allow responsvie array values in extended styles
extend(),
responsiveValue([
'@media (min-width: 480px)',
'@media (min-width: 1024px)',
]),
prefixer(),
// use "as const" to get fixed types
] as const,
})
```

### Fela Plugins

Make sure to import `brandeur` in your configuration file to load all the plugin types for Fela plugins. Otherwise you'll get the native ones from Fela which have conflicting types.

```tsx
// load types
import 'brandeur'

import extend from 'fela-plugin-extend'
import hoverMedia from 'fela-plugin-hover-media'
```

## Keyframes

Brandeur provides a simple way to create and consume global keyframes. Check [the gist](#the-gist) for an example.

Sometimes however we want to have dynamic keyframes and/or not render all keyframes upfront. In such cases, we recommend using a separate package to deal with that.

I created [react-create-keyframe](https://github.com/robinweser/react-create-keyframe) for exactly those use cases. Feel free to check it out!

## Roadmap

- Theming Primitives
- Framework-Agnostic API

## License

Brandeur is licensed under the [MIT License](http://opensource.org/licenses/MIT).

Documentation is licensed under [Creative Commons License](http://creativecommons.org/licenses/by/4.0/).

Created with ♥ by [@robinweser](https://weser.io).