Skip to content

Commit

Permalink
feat(icons): implement ui icon set (#3969)
Browse files Browse the repository at this point in the history
Co-authored-by: Philipp Gfeller <[email protected]>
  • Loading branch information
oliverschuerch and gfellerph authored Dec 2, 2024
1 parent 554d60a commit 4c46ac8
Show file tree
Hide file tree
Showing 2,919 changed files with 20,691 additions and 1,929 deletions.
5 changes: 5 additions & 0 deletions .changeset/quick-mails-joke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@swisspost/design-system-components': minor
---

Refactored `post-icon` component to use the `<use>` tag to load and show icons under the hood. This enables responsive icons, enables better caching and improves render performance slightly. There is no further action required.
5 changes: 5 additions & 0 deletions .changeset/red-moose-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@swisspost/design-system-icons': minor
---

Added a new set of responsive UI icons. These new icons can be used with the `post-icon` component. These new icons will change their shape based on their size: small icons will render with less flourish and are optimised for a smaller pixel grid.
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@
"header:snapshots": "start-server-and-test docs:headless 9001 'pnpm --filter internet-header snapshots'",
"intranet-header": "pnpm intranet-header:start",
"intranet-header:start": "pnpm --filter design-system-intranet-header-workspace start",
"icons": "pnpm icons:start",
"icons:start": "pnpm --filter design-system-icons dev",
"icons": "pnpm icons:dev",
"icons:dev": "pnpm --filter design-system-icons dev",
"icons:start": "pnpm --filter design-system-icons start",
"icons:build": "pnpm --filter design-system-icons build",
"icons:test": "pnpm --filter design-system-icons test",
"icons:unit": "pnpm --filter design-system-icons test",
"icons:unit:watch": "pnpm --filter design-system-icons test:watch",
Expand Down
2 changes: 1 addition & 1 deletion packages/components/cypress/e2e/card-control.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ describe('Card-Control', () => {
.invoke('attr', 'icon', '1000')
.find('.card-control--icon slot[name="icon"] post-icon')
.should('exist')
.find('[style*="/1000.svg"]')
.find('use[href*="/1000.svg"]')
.should('exist');
cy.get('@card-control')
.invoke('removeAttr', 'icon')
Expand Down
38 changes: 30 additions & 8 deletions packages/components/src/components/post-icon/post-icon.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
@use 'sass:list';
@use 'sass:map';

$post-icon-sizes: (
'16': 16px,
'24': 24px,
'32': 32px,
'40': 40px,
'48': 48px,
'64': 64px,
);

$post-icon-animations: (
'cylon': icon-animation-cylon 0.75s ease-in-out infinite alternate,
'cylon-vertical': icon-animation-cylon-vertical 0.75s ease-in-out infinite alternate,
Expand All @@ -10,25 +20,37 @@ $post-icon-animations: (
);

:host {
container-name: post-icon;
container-type: inline-size;
display: inline-block;
width: 1em;
height: 1em;
vertical-align: -0.15em;
}

span {
svg {
display: block;
width: 100%;
height: 100%;
fill: currentColor;
forced-color-adjust: preserve-parent-color;
background-color: currentColor;
-webkit-mask-position: center center;
mask-position: center center;
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 100%;
mask-size: 100%;
}

@each $key, $value in $post-icon-sizes {
$keys: map.keys($post-icon-sizes);
$index: list.index($keys, $key);
$nextKey: if($index + 1 <= list.length($keys), list.nth($keys, $index + 1), null);
$nextValue: map.get($post-icon-sizes, $nextKey);

$min: if($index == 1, null, 'min-width: #{$value}');
$max: if($index == list.length($keys), null, 'max-width: #{$nextValue - 0.02}');
$connector: if($min and $max, ') and (', '');

@container post-icon (#{$min}#{$connector}#{$max}) {
svg {
--pis-#{$key}: block;
}
}
}

// flip
Expand Down
53 changes: 23 additions & 30 deletions packages/components/src/components/post-icon/post-icon.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Element, Host, h, Prop, State, Watch } from '@stencil/core';
import { Component, Element, Host, h, Prop, Watch } from '@stencil/core';
import { checkNonEmpty, checkType, checkEmptyOrType, checkEmptyOrOneOf } from '@/utils';
import { version } from '@root/package.json';

Expand All @@ -25,13 +25,8 @@ type Animation = (typeof ANIMATION_NAMES)[number];
shadow: true,
})
export class PostIcon {
private path: string;

@Element() host: HTMLPostIconElement;

@State() svgStyles: string;
@State() svgOutput: string;

/**
* The name of the animation.
*/
Expand Down Expand Up @@ -110,48 +105,46 @@ export class PostIcon {
checkEmptyOrType(newValue, 'number', 'The post-icon "scale" prop should be a number.');
}

componentDidLoad() {
this.validateBase();
this.validateName();
this.validateFlipH();
this.validateFlipV();
this.validateScale();
this.validateRotate();
this.validateAnimation();
}

componentWillRender() {
this.setPath();
}

private setPath() {
private getPath() {
// Construct icon path from different possible sources
const metaBase =
document.head
.querySelector('meta[name="design-system-settings"][data-post-icon-base]')
?.getAttribute('data-post-icon-base') ?? null;

const fileBase = `${this.base ?? metaBase ?? CDN_URL}/`.replace(/\/\/$/, '/');
const fileName = `${this.name}.svg`;
const fileName = `${this.name}.svg#i-${this.name}`;
const filePath = `${fileBase}${fileName}`;

this.path = new URL(filePath, window.location.origin).toString();
return new URL(filePath, window.location.origin).toString();
}

render() {
// create inline styles for some properties
const svgStyles = Object.entries({
'-webkit-mask-image': `url('${this.path}')`,
'mask-image': `url('${this.path}')`,
'transform':
private getStyles() {
return Object.entries({
transform:
(this.scale && !isNaN(Number(this.scale)) ? 'scale(' + this.scale + ')' : '') +
(this.rotate && !isNaN(Number(this.rotate)) ? ' rotate(' + this.rotate + 'deg)' : ''),
})
.filter(([_key, value]) => value !== null)
.reduce((styles, [key, value]) => Object.assign(styles, { [key]: value }), {});
}

componentDidLoad() {
this.validateBase();
this.validateName();
this.validateFlipH();
this.validateFlipV();
this.validateScale();
this.validateRotate();
this.validateAnimation();
}

render() {
return (
<Host data-version={version}>
<span style={svgStyles}></span>
<svg style={this.getStyles()}>
<use href={this.getPath()} />
</svg>
</Host>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ export const Color: Story = {

const sizeVariants = [
{ style: 'font-size: 1rem' },
{ class: 'h3' },
{ class: 'h1' },
{ class: 'h3 my-0' },
{ class: 'h1 my-0' },
{ class: 'fs-huge' },
{ style: 'font-size: 4rem' },
{ style: 'font-size: 6rem' },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<html>
<head>
<meta name="design-system-settings" data-post-icon-base="/assets/post-icons" />
<meta name="design-system-settings" data-post-icon-base="/path/to/all/icons/folder" />
</head>
</html>
4 changes: 3 additions & 1 deletion packages/icons/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ node_modules
.env

# Ignore generated files
icons
public/post-icons
public/report.json

icons-optimized
icons.json
no-svgs.json
6 changes: 6 additions & 0 deletions packages/icons/nodemon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"watch": ["src/**/*.ts", "src/icons/**/*.(svg|json)"],
"ext": "ts,svg,json",
"ignore": ["src/**/*.spec.ts"],
"exec": "ts-node ./src/build.ts"
}
6 changes: 5 additions & 1 deletion packages/icons/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
],
"private": false,
"scripts": {
"dev": "http-server ./public -o -a localhost -p 9330",
"dev": "pnpm build && http-server ./public -o -a localhost -p 9330",
"start": "nodemon",
"build": "ts-node src/build.ts",
"fetchSVGs": "ts-node src/index.ts",
"test": "jest",
"test:watch": "jest --watch",
Expand All @@ -43,6 +45,8 @@
"jest": "29.7.0",
"mock-fs": "5.2.0",
"node-fetch": "2.7.0",
"node-html-parser": "6.1.13",
"nodemon": "3.1.7",
"svgo": "3.3.2",
"ts-jest": "29.2.4",
"ts-node": "10.9.2",
Expand Down
Loading

0 comments on commit 4c46ac8

Please sign in to comment.