Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
@cobalt-ui/plugin-css
Advanced tools
Generate CSS from your design tokens schema (requires @cobalt-ui/cli)
Generate CSS output for Cobalt from design tokens.
Automatically generates 🌈 P3 colors for more vibrant colors on displays that support it.
npm i -D @cobalt-ui/plugin-css
// tokens.config.mjs
import pluginCSS from '@cobalt-ui/plugin-css';
/** @type import('@cobalt-ui/core').Config */
export default {
plugins: [pluginCSS()],
};
Running npx co build
with the plugin set up will generate a tokens/tokens.css
file. Inspect that, and import where desired and use the CSS Custom Properties as desired (docs).
Here are all plugin options, along with their default values
// tokens.config.mjs
import pluginCSS from '@cobalt-ui/plugin-css';
/** @type import('@cobalt-ui/core').Config */
export default {
plugins: [
pluginCSS({
/** set the filename inside outDir */
filename: './tokens.css',
/** create selector wrappers around modes */
modeSelectors: {
// …
},
/** embed file tokens? */
embedFiles: false,
/** (optional) transform specific token values */
transform: () => null,
/** (optional) prefix variable names */
prefix: '--my-prefix',
}),
],
};
Say you have link
tokens in your tokens.json
:
{
"icon": {
"alert": {
"$type": "link",
"$value": "./icon/alert.svg"
}
}
}
By default, consuming those will print values as-is:
.icon-alert {
background-image: var(--icon-alert);
}
/* Becomes … */
.icon-alert {
background-image: url('./icon/alert.svg');
}
In some scenarios this is preferable, but in others, this may result in too many requests and may result in degraded performance. You can set embedFiles: true
to generate the following instead:
.icon-alert {
background-image: var(--icon-alert);
}
/* Becomes … */
.icon-alert {
background-image: url('image/svg+xml;utf8,<svg …></svg>');
}
To generate CSS for Modes, add a modeSelectors: {}
object to your config, and specify mode: [selector1, selector2, …]
.
For example, if your color.base
group has light
and dark
modes, and you want to alter the CSS variables based on a body attribute:
// tokens.config.mjs
import css from '@cobalt-ui/plugin-css';
/** @type import('@cobalt-ui/core').Config */
export default {
plugins: [
css({
modeSelectors: {
'color.base#light': ['body[data-color-mode="light"]'],
'color.base#dark': ['body[data-color-mode="dark"]', '@media (prefers-color-scheme:dark)'],
'transition#reduced': ['@media (prefers-reduced-motion)'],
},
}),
],
};
This will generate the following CSS:
/* default theme set by tokens.json (same as "light") */
:root {
--color-blue: #0969da;
--color-green: #2da44e;
--color-red: #cf222e;
/* … */
}
/* light theme colors */
body[data-color-mode='light'] {
--color-blue: #0969da;
--color-green: #2da44e;
--color-red: #cf222e;
/* … */
}
/* dark theme colors */
body[data-color-mode='dark'] {
--color-blue: #1f6feb;
--color-green: #2ea043;
--color-red: #da3633;
/* … */
}
But more than just classes can be used (that’s why it’s called modeSelectors
and not modeClasses
)! You could also generate CSS if your type.size
group had desktop
and mobile
sizes:
// tokens.config.mjs
import css from '@cobalt-ui/plugin-css';
/** @type import('@cobalt-ui/core').Config */
export default {
plugins: [
css({
modeSelectors: {
'type.size#desktop': ['@media (min-width: 600px)'],
},
}),
],
};
That will generate the following:
/* default size (in this case, mobile) */
:root {
--type-size: 16px;
}
/* desktop size */
@media (min-width: 600px) {
:root {
--type-size: 18px;
}
}
The #
character designates the mode. You must have a #
somewhere in the selector.
#light
: match any token that has a light
modecolor#light
: deeply match any token inside the color
group, that has a light
modecolor.base#light
: deeply match any token inside the color.base
group with a light
mode, but ignore any other tokens inside color
To learn about modes, read the documentation
Inside plugin options, you can specify an optional transform()
function.
/** @type import('@cobalt-ui/core').Config */
export default {
plugins: [
pluginCSS({
transform(token, mode) {
const oldFont = 'sans-serif';
const newFont = 'Custom Sans';
if (token.$type === 'font') {
return token.$value.map((value) => (value === oldFont ? newFont : value));
}
},
}),
],
};
Your transform will only take place if you return a truthy value, otherwise the default transformer will take place.
If you have your own custom token type, e.g. my-custom-type
, you’ll have to handle it within transform()
:
/** @type import('@cobalt-ui/core').Config */
export default {
plugins: [
pluginCSS({
transform(token, mode) {
switch (token.$type) {
case 'my-custom-type': {
return String(token.$value);
break;
}
}
},
}),
],
};
FAQs
Generate CSS from your design tokens schema (requires @cobalt-ui/cli)
The npm package @cobalt-ui/plugin-css receives a total of 6,630 weekly downloads. As such, @cobalt-ui/plugin-css popularity was classified as popular.
We found that @cobalt-ui/plugin-css demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.