1
0
Fork
You've already forked stylx
0
CSS-in-JS library with near-zero runtime.
  • TypeScript 91.8%
  • JavaScript 8.2%
2023年10月02日 06:34:55 +07:00
.vscode initial commit 2023年09月15日 11:28:48 +07:00
src refactor: big rewrite 2023年09月25日 16:47:29 +07:00
.editorconfig initial commit 2023年09月15日 11:28:48 +07:00
.gitignore initial commit 2023年09月15日 11:28:48 +07:00
.prettierignore initial commit 2023年09月15日 11:28:48 +07:00
.prettierrc initial commit 2023年09月15日 11:28:48 +07:00
LICENSE initial commit 2023年09月15日 11:28:48 +07:00
package.json chore: babel/core types 2023年10月02日 06:34:55 +07:00
pnpm-lock.yaml chore: babel/core types 2023年10月02日 06:34:55 +07:00
README.md refactor: big rewrite 2023年09月25日 16:47:29 +07:00
test.js refactor: big rewrite 2023年09月25日 16:47:29 +07:00
tsconfig.json chore: fmt 2023年09月19日 11:10:20 +07:00

stylx

CSS-in-JS library with near-zero runtime.

Usage

import { createStyles } from '@intrnl/stylx';
const styles = createStyles({
	red: {
		color: 'red',
	},
	redEmboldened: {
		composes: ['$red'],
		fontWeight: 700,
	},
	underlinedOnHover: {
		'&:hover': {
			textDecoration: 'underline',
		},
	},
});
const App = () => {
	return (
		<div>
			<p className={styles.red}>This is red</p>
			<p className={styles.redEmboldened}>This is emboldened red</p>
		</div>
	);
};

Using the Babel plugin, this will generate...

const _red = 'm84tdn0 ',
	_redEmboldened = 'm84tdn1 m84tdn0 ',
	_underlinedOnHover = 'm84tdn2 ';
import * as _stylx from '@intrnl/stylx/runtime';
_stylx.inject(
	'm84tdn',
	'.m84tdn0{color:red;}.m84tdn1{font-weight:700;}.m84tdn2{&:hover{text-decoration:underline;}}',
);
const styles = {};
const App = () => {
	return (
		<div>
			<p className={_red}>This is red</p>
			<p className={_redEmboldened}>This is emboldened red</p>
		</div>
	);
};

By default, the styles object becomes empty to encourage writing code in a way that can be easily analyzed by the plugin. This can be disabled by setting loose: true in the plugin options.

Keyframes and CSS variables

Scoped keyframes and variables can be defined via createKeyframes and createVariables respectively.

const variables = createVariables({
	background: {},
});
const keyframes = createKeyframes({
	spin: {
		to: {
			transform: 'rotate(360deg)',
		},
	},
});
const styles = create({
	root: {
		background: `var(${variables.background})`,
		animation: `${keyframes.spin} 1s linear infinite`,
	},
	isHighlighted: {
		[variables.background]: 'yellow',
	},
});

Class name concatenation

stylx provides an optimized utility function for concatenation. Note that you can only reference variables that can be easily analyzed, as is the case with stylx' own styles.

const styles = createStyles({
	isBordered: {},
	root: {},
	isStandalone: {},
	isMultiple: {},
	item: {},
});
log(join(styles.root, !borderless && styles.isBordered));
log(join(styles.item, standalone ? styles.isStandalone : styles.isMultiple));
log(join('foo', 'bar'));

... where it would be generate...

log(_root + (!borderless ? _isBordered : ''));
log(_item + (standalone ? _isStandalone : _isMultiple));
log('foo' + ' ' + ('bar' + ' '));

Vite plugin

An optional Vite plugin can be used to emit the styles as actual CSS files, this removes the runtime aspect entirely, it's recommended that it's used during production builds only.

import { defineConfig } from 'vite';
import stylxVitePlugin from '@intrnl/stylx/vite';
export default defineConfig((ctx) => {
	const isProduction = ctx.mode === 'production';
	return {
		plugins: [
			// insert all other plugins...
			isProduction && stylxVitePlugin({ include: /\.tsx?$/ }),
		],
	};
});

You'd have to configure the plugin's mode to placeholder for this to work.