Skip to content

Commit

Permalink
[v4] breaking: refactor icons build pipeline to use fantasticon (#4505)
Browse files Browse the repository at this point in the history
  • Loading branch information
adidahiya committed Sep 28, 2021
1 parent ce01f47 commit 6b6151d
Show file tree
Hide file tree
Showing 53 changed files with 1,198 additions and 1,311 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/_typography.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

@import "common/variables";
@import "common/mixins";
@import "~@blueprintjs/icons/src/icons";
@import "components/icon/icon";

/*
Headings
Expand Down
2 changes: 0 additions & 2 deletions packages/core/src/common/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,7 @@ export const TREE_NODE_SELECTED = `${TREE_NODE}-selected`;
export const TREE_ROOT = `${NS}-tree-root`;

export const ICON = `${NS}-icon`;
/** @deprecated use <Icon> components and iconName prop APIs instead */
export const ICON_STANDARD = `${ICON}-standard`;
/** @deprecated use <Icon> components and iconName prop APIs instead */
export const ICON_LARGE = `${ICON}-large`;

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/breadcrumbs/_breadcrumbs.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2016 Palantir Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0.

@import "~@blueprintjs/icons/src/icons";
@import "~@blueprintjs/icons/lib/scss/variables";
@import "../../common/variables";

/*
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/dialog/_dialog.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2015 Palantir Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0.

@import "~@blueprintjs/icons/src/icons";
@import "~@blueprintjs/icons/lib/scss/variables";
@import "../../common/mixins";
@import "../../common/react-transition";
@import "../../common/variables";
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/dialog/_multistep-dialog.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2020 Palantir Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0.

@import "~@blueprintjs/icons/src/icons";
@import "~@blueprintjs/icons/lib/scss/variables";
@import "../../common/mixins";
@import "../../common/react-transition";
@import "../../common/variables";
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/drawer/_drawer.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2018 Palantir Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0.

@import "~@blueprintjs/icons/src/icons";
@import "~@blueprintjs/icons/lib/scss/variables";
@import "../../common/mixins";
@import "../../common/react-transition";
@import "../../common/variables";
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/forms/_common.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2015 Palantir Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0.

@import "~@blueprintjs/icons/src/icons";
@import "~@blueprintjs/icons/lib/scss/variables";
@import "../../common/variables";
@import "../button/common";

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/html-select/_html-select.scss
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,6 @@ Styleguide select
&::after {
@extend %pt-select-arrow;
@include pt-icon();
content: $pt-icon-double-caret-vertical;
content: map-get($blueprint-icon-codepoints, "double-caret-vertical");
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
// Copyright 2015 Palantir Technologies, Inc. All rights reserved.
// Copyright 2021 Palantir Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0.

@import "generated/icon-variables";
@import "generated/icon-map";

$ns: "bp3" !default;

$icon-classes: (
".#{$ns}-icon",
".#{$ns}-icon-standard",
".#{$ns}-icon-large"
) !default;
@import "../../common/colors";

@mixin pt-icon-font-smoothing() {
-moz-osx-font-smoothing: grayscale;
Expand All @@ -21,9 +12,10 @@ $icon-classes: (
$font-size: $pt-icon-size-standard,
$font-family-size: strip-unit($font-size)
) {
font-family: "Icons#{$font-family-size}", sans-serif;
font-family: "blueprint-icons-#{$font-family-size}", sans-serif;
font-size: $font-size;
font-style: normal;
font-variant: normal;
font-weight: 400;
line-height: 1;
}
Expand Down
18 changes: 14 additions & 4 deletions packages/core/src/components/icon/_icon.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
// Copyright 2015 Palantir Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0.

@import "~@blueprintjs/icons/src/icons";
@import "~@blueprintjs/icons/lib/scss/variables";
@import "icon-mixins";

$icon-classes: (
".#{$ns}-icon",
".#{$ns}-icon-standard",
".#{$ns}-icon-large"
) !default;

// the icon class which will contain an SVG icon
.#{$ns}-icon {
Expand All @@ -24,6 +31,9 @@
> svg {
// prevent extra vertical whitespace
display: block;
// paths parsed by generate-icon-paths.js are mirrored vertically, so we need
// to flip them upright here
transform: scaleY(-1);

// inherit text color unless explicit fill is set
&:not([fill]) {
Expand Down Expand Up @@ -61,7 +71,7 @@ span.#{$ns}-icon-large {

// only apply icon font styles when <svg> image is not present
span.#{$ns}-icon:empty {
font-family: $icons20-family;
font-family: $blueprint-icons-20-font;
font-size: inherit;
font-style: normal;
font-weight: 400;
Expand All @@ -72,8 +82,8 @@ span.#{$ns}-icon:empty {
}
}

@each $name, $content in $icons {
@each $name, $codepoint in $blueprint-icon-codepoints {
.#{$ns}-icon-#{$name}::before {
content: $content;
content: $codepoint;
}
}
24 changes: 11 additions & 13 deletions packages/core/src/components/icon/icon.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,29 @@ it will be assumed that the icon is decorative if not labeled.
```tsx
import { Icon, IconSize } from "@blueprintjs/core";

// string literals are supported through IconName union type
// icon name string literals are type checked
<Icon icon="cross" />
<Icon icon="globe" size={20} />

// constants are provided for name and size
<Icon icon="graph" size={IconSize.LARGE} intent="primary" />

// can pass all valid HTML props
// you can also pass all valid HTML props
<Icon icon="add" onClick={this.handleAdd} onKeyDown={this.handleAddKeys} />
```

Custom sizes are supported. The following React component:

```tsx
<Icon icon="globe" iconSize={30} />
```

...renders this HTML markup:

```html
<Icon icon="globe" size={30} />
<!-- renders the following HTML markup: -->
<svg class="@ns-icon" data-icon="globe" width="30" height="30" viewBox="0 0 20 20">
<title>globe</title>
<path ... />
<path d="..."></path>
</svg>
```

Expand All @@ -63,14 +69,6 @@ import { Icon, IconSize } from "@blueprintjs/core";

@## CSS

<div class="@ns-callout @ns-intent-danger @ns-icon-warning-sign">
<h4 class="@ns-heading">Some icons are missing in the icon font in 3.x</h4>

Blueprint icons added after `@blueprintjs/icons@3.14.0` do not have icon font support.
Support for the icon font for these icons will be restored in Blueprint v4.0.

</div>

The CSS-only icons API uses the __icon fonts__ from the __@blueprintjs/icons__ package.

To use Blueprint UI icons via CSS, you must apply two classes to a `<span>` element:
Expand Down
10 changes: 5 additions & 5 deletions packages/core/src/components/icon/icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { polyfill } from "react-lifecycles-compat";
import { IconName, IconSvgPaths16, IconSvgPaths20 } from "@blueprintjs/icons";

import { AbstractPureComponent2, Classes, DISPLAYNAME_PREFIX, IntentProps, Props, MaybeElement } from "../../common";
import { iconNameToPathsRecordKey } from "./iconUtils";

export { IconName };

Expand Down Expand Up @@ -139,7 +140,6 @@ export class Icon extends AbstractPureComponent2<IconProps & Omit<React.HTMLAttr
// render path elements, or nothing if icon name is unknown.
const paths = this.renderSvgPaths(pixelGridSize, icon);

// eslint-disable-next-line deprecation/deprecation
const classes = classNames(Classes.ICON, Classes.iconClass(icon), Classes.intentClass(intent), className);
const viewBox = `0 0 ${pixelGridSize} ${pixelGridSize}`;

Expand All @@ -159,12 +159,12 @@ export class Icon extends AbstractPureComponent2<IconProps & Omit<React.HTMLAttr
}

/** Render `<path>` elements for the given icon name. Returns `null` if name is unknown. */
private renderSvgPaths(pathsSize: number, iconName: IconName): JSX.Element[] | null {
private renderSvgPaths(pathsSize: number, iconName: IconName): JSX.Element | null {
const svgPathsRecord = pathsSize === IconSize.STANDARD ? IconSvgPaths16 : IconSvgPaths20;
const pathStrings = svgPathsRecord[iconName];
if (pathStrings == null) {
const pathString = svgPathsRecord[iconNameToPathsRecordKey(iconName)];
if (pathString == null) {
return null;
}
return pathStrings.map((d, i) => <path key={i} d={d} fillRule="evenodd" />);
return <path d={pathString} fillRule="evenodd" />;
}
}
43 changes: 43 additions & 0 deletions packages/core/src/components/icon/iconUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2021 Palantir Technologies, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { IconName, IconSvgPaths16 } from "@blueprintjs/icons";

export function iconNameToPathsRecordKey(name: IconName): keyof typeof IconSvgPaths16 {
return kebabCaseToCamelCase(name);
}

/**
* Type safe string literal conversion of snake-case strings to camelCase strings.
* Note that this requires TypeScript 4.1+.
*
* Implementation and template literal mapped types borrowed from
* https://davidtimms.github.io/programming-languages/typescript/2020/11/20/exploring-template-literal-types-in-typescript-4.1.html
*/
function kebabCaseToCamelCase<S extends string>(snakeCaseString: S): KebabCaseToCamelCase<S> {
return snakeCaseString
.split("-")
.map((word, i) => (i === 0 ? word.toLowerCase() : word && word[0].toUpperCase() + word.slice(1).toLowerCase()))
.join("") as KebabCaseToCamelCase<S>;
}

type KebabCaseToCamelCase<S extends string> = S extends `${infer FirstWord}-${infer Rest}`
? `${Lowercase<FirstWord>}${KebabCaseToPascalCase<Rest>}`
: `${Lowercase<S>}`;

type KebabCaseToPascalCase<S extends string> = S extends `${infer FirstWord}-${infer Rest}`
? `${Capitalize<Lowercase<FirstWord>>}${KebabCaseToPascalCase<Rest>}`
: Capitalize<Lowercase<S>>;
2 changes: 1 addition & 1 deletion packages/core/src/components/menu/_menu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0.

@import "../../common/variables";
@import "~@blueprintjs/icons/src/icons";
@import "~@blueprintjs/icons/lib/scss/variables";
@import "../../common/mixins";

@import "./common";
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/menu/_submenu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0.

@import "../../common/variables";
@import "~@blueprintjs/icons/src/icons";
@import "~@blueprintjs/icons/lib/scss/variables";
@import "./common";

.#{$ns}-submenu {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/slider/_common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0.

@import "../../common/variables";
@import "~@blueprintjs/icons/src/icons";
@import "~@blueprintjs/icons/lib/scss/variables";
@import "../../common/mixins";
@import "../button/common";

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/tag/_common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ $tag-round-adjustment: 2px !default;
// CSS API support
&:empty::before {
@include pt-icon();
content: $pt-icon-small-cross;
content: map-get($blueprint-icon-codepoints, "small-cross");
}

.#{$ns}-large & {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/components/tree/_tree.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

@import "../../common/variables";
@import "../../common/mixins";
@import "~@blueprintjs/icons/src/icons";
@import "~@blueprintjs/icons/lib/scss/variables";

/*
Trees
Expand Down Expand Up @@ -106,7 +106,7 @@ $tree-icon-spacing: ($tree-row-height - $pt-icon-size-standard) / 2 !default;

// CSS API support
&.#{$ns}-icon-standard::before {
content: $pt-icon-chevron-right;
content: map-get($blueprint-icon-codepoints, "chevron-right");
}
}

Expand Down
37 changes: 26 additions & 11 deletions packages/core/src/docs/variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,35 @@ rare cases where custom styling is necessary and should be used sparingly:

@## Icon variables

Most icons should be displayed using the `span.@ns-icon-*` classes or via modifier classes on
components like `.@ns-button`. In rare cases, you may need direct access to the content
string that generates each icon in the icon font. Blueprint provides these variables with
straightforward names (see the [Icons section](#icons) for the full list of identifiers):
Most icons should be displayed using the `<Icon>` component from `@blueprintjs/icons` or the
`icon` and `iconName` prop APIs available on many Blueprint components. These APIs have the advantage
of rendering SVGs directly onto the page.

- `$pt-icon-style`
- `$pt-icon-align-left`
- `$pt-icon-align-center`
- ...
In some cases you may use the icon fonts instead with the CSS API targeting selectors of the kind
`span.@ns-icon-*` (be sure to include `.@ns-icon-standard` or `.@ns-icon-large` as well).

Variables are also provided for the two icon font families and their pixel sizes:
In rare cases, you may need direct access to the code points the icon font. Blueprint provides these
variables in Sass as a map and in TypeScript as an object (see the [Icons section](#icons) for the
full list of identifiers):

- `$icons16-family`
- `$icons20-family`
```css.scss
@import "~@blueprintjs/icons/lib/scss/variables";

.my-custom-icon {
content: map-get($blueprint-icon-codepoints, "tick");
}
```

```ts
import { IconCodepoints } from "@blueprintjs/icons";

document.querySelector(".my-custom-icon").style.content = IconCodepoints["tick"];
```

Sass variables are also provided for the two icon font families and their pixel sizes:

- `$blueprint-icons-16`
- `$blueprint-icons-20`
- `$pt-icon-size-standard`
- `$pt-icon-size-large`

Expand Down
1 change: 0 additions & 1 deletion packages/core/test/icon/iconTests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ describe("<Icon>", () => {
});

it("prefixed icon renders blank icon", () => {
// eslint-disable-next-line deprecation/deprecation
assert.lengthOf(shallow(<Icon icon={Classes.iconClass("airplane") as any} />).find("path"), 0);
});

Expand Down
2 changes: 1 addition & 1 deletion packages/datetime/src/_common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0.

@import "~@blueprintjs/core/src/common/variables";
@import "~@blueprintjs/icons/src/icons";
@import "~@blueprintjs/icons/lib/scss/variables";

$datepicker-padding: $pt-grid-size / 2 !default;

Expand Down
Loading

0 comments on commit 6b6151d

Please sign in to comment.