packages/core/src/docs/classes.md
@# Classes
Blueprint packages provide React components in JS files and associated styles in
a CSS file. Each package exports a Classes constants object in JavaScript that
contains keys of the form NAMED_CONSTANT for every CSS class used. This
separation allows us to change CSS classes between versions without breaking
downstream users (although in practice this happens very rarely).
Avoid referencing hardcoded Blueprint class names in your JS or CSS code.
// Don't do this! Avoid hardcoding Blueprint class names.
<button className="@ns-button @ns-large">Don't do this!</button>
The best practice is to add your own class to an element and then reference that class whenever needed.
<Button className="my-custom-class" text="customized button" />
.my-custom-class {
width: 4000px;
}
In cases where adding and styling a new class is impractical or undesirable, use
the Classes constants or $ns Sass/Less variable. The Classes constants can
be particularly useful when writing UI tests.
// use Classes constants for forward-compatible custom elements.
import { Classes } from "@blueprintjs/core";
<a className={Classes.MENU_ITEM}>custom menu item</a>;
// interpolate the $ns variable to generate forward-compatible class names.
// this approach is *not encouraged* as it increases maintenance cost.
@import "@blueprintjs/core/lib/scss/variables";
.#{$ns}-menu-item {
}
@## Modifiers
Blueprint components support a range of modifiers to adjust their
appearance. Some commonly used modifiers are intent, large, and minimal.
While modifiers are typically implemented as simple CSS classes, it is always
preferrable to use the corresponding prop on a React component.
// Prefer props over modifier classes.
<Button intent="primary" variant="minimal">Good stuff</Button>
// Don't do this!
<Button className={classNames(Classes.INTENT_PRIMARY, Classes.MINIMAL)}>Don't do this!</Button>
Another important note: Since modifiers typically correspond directly to CSS classes, they will often
cascade to children and cannot be disabled on descendants. If a <ButtonGroup>
is marked variant="outlined", then setting <Button variant="minimal"> on a child
will have no effect since Classes.OUTLINED cannot be removed or overriden
by a descendant.
@## Namespacing
All Blueprint CSS classes begin with a namespace prefix to isolate our styles
from other frameworks: .button is a very common name, but only Blueprint
defines .@ns-button.
This CSS namespace is versioned by major version of the library so two major versions of Blueprint can be used together on a single page.
@### Current namespace prefix
Blueprint v6 uses the bp6- prefix for all CSS classes. For example, Button components have the class .bp6-button, Cards have .bp6-card, etc. This prefix changes with each major version of Blueprint (e.g., v5 used bp5-, v6 uses bp6-).
When writing custom styles that target Blueprint components, you should reference the namespace using the $ns Sass variable rather than hardcoding the prefix:
@use "@blueprintjs/core/lib/scss/variables.scss" as bp;
.my-class .#{bp.$ns}-button {
// Custom styles for Blueprint buttons within .my-class
background-color: red;
}
@### Custom namespace
The CSS namespace can be changed at build time to produce a custom Blueprint build.
With this approach, you will import Blueprint's Sass sources from /lib/scss/ instead of the CSS files from the
/lib/css/ folders.
You must use Dart Sass and set up a few important bits of build configuration:
loadPaths must include the node_modules folder where @blueprintjs packages are installedsvg-icon() must be definedThe @blueprintjs/node-build-scripts package provides some utility functions to help with this. Here's a code example
for a custom Sass compiler that can import Blueprint .scss sources:
import { sassNodeModulesLoadPaths, sassSvgInlinerFactory } from "@blueprintjs/node-build-scripts";
import * as sass from "sass";
const result = await sass.compileAsync("path/to/input.scss", {
loadPaths: sassNodeModulesLoadPaths,
functions: {
/**
* Sass function to inline a UI icon svg and change its path color.
*
* Usage:
* svg-icon("16px/icon-name.svg", (path: (fill: $color)) )
*/
"svg-icon($path, $selectors: null)": sassSvgInlinerFactory("path/to/resources/icons", {
optimize: true,
encodingFormat: "uri",
}),
},
});
In addition to the JS API, you can specify this configuration with Webpack's sass-loader:
// webpack.config.mjs
import { sassNodeModulesLoadPaths, sassSvgInlinerFactory } from "@blueprintjs/node-build-scripts";
import * as sass from "sass";
const functions = {
/**
* Sass function to inline a UI icon svg and change its path color.
*
* Usage:
* svg-icon("16px/icon-name.svg", (path: (fill: $color)) )
*/
"svg-icon($path, $selectors: null)": sassSvgInlinerFactory("path/to/resources/icons", {
optimize: true,
encodingFormat: "uri",
}),
};
export default {
module: {
rules: [
{
test: /\.scss$/,
use: {
loader: require.resolve("sass-loader"),
options: {
sassOptions: {
loadPaths: sassNodeModulesLoadPaths,
functions,
},
},
},
},
],
},
};
Once you have this build configuration set up, you can proceed to customize Sass and JS variables:
$ns Sass variable in your app styles before importing blueprint.scss.BLUEPRINT_NAMESPACE variable to the same value; this will update the generated Classes constants. The easiest way to do is with webpack's DefinePlugin.plugins: [
new webpack.DefinePlugin({
BLUEPRINT_NAMESPACE: "my-custom-namespace",
}),
];
@## Linting
The @blueprintjs/eslint-config
NPM package provides advanced configuration for ESLint. The
@blueprintjs/eslint-plugin
NPM package includes a custom blueprint-html-components rule that will warn on usages of
JSX intrinsic elements (<h1>) that have a Blueprint alternative (<H1>). See
the package's README
for usage instructions.