Skip to content

Commit

Permalink
Add composeStyles function (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
markdalgleish committed Apr 22, 2021
1 parent ae9864c commit 156b491
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/small-guests-film.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vanilla-extract/css': minor
---

Add `composeStyles` function
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ document.write(`
- [globalFontFace](#globalfontface)
- [keyframes](#keyframes)
- [globalKeyframes](#globalkeyframes)
- [composeStyles](#composestyles)
- [Dynamic API](#dynamic-api)
- [createInlineTheme](#createinlinetheme)
- [setElementTheme](#setelementtheme)
Expand Down Expand Up @@ -580,6 +581,28 @@ export const animated = style({
});
```

### composeStyles

Combines mutliple styles into a single class string, while also deduplicating and removing unnecessary spaces.

```ts
import { style, composeStyles } from '@vanilla-extract/css';

const base = style({
padding: 12
});

export const blue = composeStyles(base, style({
background: 'blue'
}));

export const green = composeStyles(base, style({
background: 'green'
}));
```

> 💡 Styles can also be provided in shallow and deeply nested arrays. Think of it as a static version of [classnames.](https://github.com/JedWatson/classnames)
## Dynamic API

We also provide a lightweight standalone package to support dynamic runtime theming.
Expand Down
25 changes: 25 additions & 0 deletions packages/css/src/composeStyles.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { composeStyles } from './composeStyles';

describe('composeStyles', () => {
it.each([
{ args: ['1'], output: '1' },
{ args: ['1 1'], output: '1' },
{ args: ['1 2 3'], output: '1 2 3' },
{ args: ['1', '2', '3'], output: '1 2 3' },
{ args: [['1', '2'], '3'], output: '1 2 3' },
{ args: [['1', ['2', '3']], '4'], output: '1 2 3 4' },
{
args: [['1', ['2', ['3', '4']]], ['5', '6'], '7'],
output: '1 2 3 4 5 6 7',
},
{ args: ['1', '1', '1'], output: '1' },
{
args: ['1', ['1', '2'], ['1', '2', '3'], ['1', '2', '3', '4']],
output: '1 2 3 4',
},
{ args: ['1 2 3', '2 3 4', '1 5'], output: '1 2 3 4 5' },
{ args: [' 1 2 3 2 ', ' 2 3 4 2 ', ' 1 5 1 '], output: '1 2 3 4 5' },
])('composeStyles', ({ args, output }) => {
expect(composeStyles(...args)).toBe(output);
});
});
30 changes: 30 additions & 0 deletions packages/css/src/composeStyles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
type ClassNames = string | Array<ClassNames>;

function composeStylesIntoSet(
set: Set<string>,
...classNames: Array<ClassNames>
) {
for (const className of classNames) {
if (className.length === 0) {
continue;
}

if (typeof className === 'string') {
if (className.includes(' ')) {
composeStylesIntoSet(set, ...className.trim().split(' '));
} else {
set.add(className);
}
} else if (Array.isArray(className)) {
composeStylesIntoSet(set, ...className);
}
}
}

export function composeStyles(...classNames: Array<ClassNames>) {
const set: Set<string> = new Set();

composeStylesIntoSet(set, ...classNames);

return Array.from(set).join(' ');
}
1 change: 1 addition & 0 deletions packages/css/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './identifier';
export * from './theme';
export * from './style';
export * from './vars';
export { composeStyles } from './composeStyles';

0 comments on commit 156b491

Please sign in to comment.