Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add the ability to use our icons from within SCSS #4136

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
907248d
deps(components): install design-system-icons package and add copy ta…
oliverschuerch Dec 3, 2024
b98bec2
fix(icons): remove fill and stroke attributes from svg elements
oliverschuerch Dec 3, 2024
6ea4619
feat(icons): update output of icons to make them available in css
oliverschuerch Dec 3, 2024
26eee7a
feat(styles): add post-icon mixin to use our icons in styles package.
oliverschuerch Dec 3, 2024
183ec7b
chore: update pnpm-lock
oliverschuerch Dec 3, 2024
2b18dbc
feat(documentation): update icon docs page to show how to use the pos…
oliverschuerch Dec 3, 2024
727823c
chore: changeset
oliverschuerch Dec 3, 2024
6747db2
revert(components): revert component package, they will be added with…
oliverschuerch Dec 4, 2024
e59d976
chore(components): update lock file
oliverschuerch Dec 4, 2024
815b525
fix(icons): rename closex-soliid source icons
oliverschuerch Dec 4, 2024
0d08add
Merge branch 'main' into fix/post-icon-setup
oliverschuerch Dec 4, 2024
e8b6fc8
Merge branch 'main' into fix/post-icon-setup
oliverschuerch Dec 12, 2024
8cede70
chore(components): update autogenerated readme.md and components.d.ts…
oliverschuerch Dec 17, 2024
e16f29b
refactor(icons): ui-icon template to use media queries
oliverschuerch Dec 17, 2024
56c77b9
chore(styles): update icons mixin and make it more backward compatible
oliverschuerch Dec 17, 2024
ff4ce88
chore(styles): udpate post-icon mixin and use some more mask-image pr…
oliverschuerch Dec 17, 2024
651449b
feat(icons): improve icons v2 template
oliverschuerch Dec 17, 2024
0287ac5
chore(components): roll back post-icon component to use mask-image wi…
oliverschuerch Dec 17, 2024
285864f
Update packages/documentation/src/stories/foundations/icons/icon.docs…
oliverschuerch Dec 17, 2024
8f7ac21
Update packages/documentation/src/stories/foundations/icons/icon.docs…
oliverschuerch Dec 17, 2024
2133903
Merge branch 'main' into fix/post-icon-setup
oliverschuerch Dec 18, 2024
be23a95
feat(documentation): upate icon documentation page
oliverschuerch Dec 18, 2024
aac356f
chore(style): add stylelint-disable-next-line property-no-vendor-pref…
oliverschuerch Dec 18, 2024
2c7ce5d
test(components): fix e2e test of card-control component
oliverschuerch Dec 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/lovely-mails-clap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@swisspost/design-system-documentation': minor
'@swisspost/design-system-styles': minor
'@swisspost/design-system-icons': minor
---

Updated the output structure of our UI-Icons.
Added a `post-icon` mixin, to use any of our icons from within SCSS.
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Canvas, Controls, Meta } from '@storybook/blocks';
import { Canvas, Controls, Meta, Source } from '@storybook/blocks';
import * as IconStories from './icon.stories';
import { PostTabHeader, PostTabPanel, PostTabs } from '@swisspost/design-system-components-react';
import SampleMixin from './mixin.sample.scss?raw';
import { Search } from './search/search-icons.blocks';
import './icon.styles.scss';

<Meta of={IconStories} />

Expand All @@ -14,19 +16,12 @@ import { Search } from './search/search-icons.blocks';
</div>

<div className="lead">
The official Swiss Post Icon Library for the web with over 800 high-quality scalable vector
graphics.
The official Swiss Post Icon Library with 900+ high-quality svg icons and the official Swiss Post UI Icons Library, exclusivley designed and provided for the web with 160+ icons and size-dependent level-of-detail.
</div>
oliverschuerch marked this conversation as resolved.
Show resolved Hide resolved

<PostTabs>
<PostTabHeader panel="usage">Usage</PostTabHeader>
<PostTabPanel name="usage">
Our <code>&lt;post-icon&gt;</code> component renders SVGs, so it scales quickly and easily and can
be styled with CSS.

<Canvas sourceState="shown" of={IconStories.Default} />
<Controls of={IconStories.Default} />

<PostTabs activePanel="search">
<PostTabHeader panel="installation">Installation</PostTabHeader>
<PostTabPanel name="installation">
## Installation

### Icon Component
Expand All @@ -38,8 +33,64 @@ import { Search } from './search/search-icons.blocks';

The SVG files for icons should be hosted within your project.
For guidelines on how to set this up, please refer to the [icon package documentation](/?path=/docs/40ed323b-9c1a-42ab-91ed-15f97f214608--docs#usage).
</PostTabPanel>

## Examples
<PostTabHeader panel="scss">Usage in CSS</PostTabHeader>
<PostTabPanel name="scss">
## Usage in CSS

To define one of our icons in your own CSS, you need the `@swisspost/design-system-styles` package and use our `post-icon` mixin. The icons can have a different level-of-detail, dependant on how big they are rendered on the page.

oliverschuerch marked this conversation as resolved.
Show resolved Hide resolved
Note: The used classes in the example below are only there for demonstration purposes.

<Canvas of={IconStories.ScssMixin} sourceState="shown"/>

### Mixin

<Source
language="scss"
dark
code={SampleMixin}
></Source>

<table className="table">
<thead>
<tr>
<td>Name</td>
<td>Description</td>
<td>Default</td>
</tr>
</thead>
<tbody>
<tr>
<td>`$name`</td>
<td>The name of the icon which should be used.<br/>Find the name of your desired icon in one of the tabs above.</td>
<td>-</td>
</tr>
<tr>
<td>`$base`</td>
<td>The base URL, where to load the icon from. Keep this undefined to get the icons loaded from unpkg.com (NOT recommended) or specifiy a path to your self-hosted icons.</td>
<td>`https://unpkg.com/`</td>
</tr>
<tr>
<td>`$color`</td>
<td>The color in which the icon should be implemented.<br/>You can change that also by just overriding the `color` property on the icon selector.</td>
<td>`currentColor`</td>
</tr>
</tbody>
</table>

</PostTabPanel>

<PostTabHeader panel="component">Usage as Web-Component</PostTabHeader>
<PostTabPanel name="component">
## Usage as Web-Component

Our <code>&lt;post-icon&gt;</code> component renders SVGs, so it scales quickly and easily and can
be styled with CSS.

<Canvas sourceState="shown" of={IconStories.Default} />
<Controls of={IconStories.Default} />

### Color

Expand Down Expand Up @@ -102,9 +153,6 @@ import { Search } from './search/search-icons.blocks';

<PostTabHeader panel="search">Find your Icon</PostTabHeader>
<PostTabPanel name="search">
The icons are designed to work with the Swiss Post Design System components. They are SVGs, so they scale and can be styled with CSS.<br/>
Use the grid below to browse all available icons.

<Search />
</PostTabPanel>
</PostTabs>
Original file line number Diff line number Diff line change
Expand Up @@ -254,3 +254,25 @@ export const Animate: Story = {
generateDecorators(story, context, 'd-flex flex-wrap text-center'),
],
};

export const ScssMixin: Story = {
render: () => {
return html`
<div class="my-accessibility-icon my-icon-1"></div>
<div class="my-accessibility-icon my-icon-2"></div>
<div class="my-accessibility-icon my-icon-3"></div>
<div class="my-accessibility-icon my-icon-4"></div>
<div class="my-accessibility-icon my-icon-5"></div>
<div class="my-accessibility-icon my-icon-6"></div>
<hr />
<div class="my-handvictory-icon" style="color: currentColor"></div>
<div class="my-handvictory-icon" style="width: 32px; height: 32px;"></div>
<div class="my-handvictory-icon" style="width: 64px; height: 64px; color: #f60;"></div>
<div class="my-handvictory-icon" style="width: 48px; height: 48px;"></div>
<div
class="my-handvictory-icon"
style="width: 32px; height: 32px; color: hsl(230, 90%, 40%); transform: rotate(15deg)"
></div>
`;
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@use '@swisspost/design-system-styles/core' as post;

.my-accessibility-icon {
@include post.post-icon($name: 'accessibility', $base: '/post-icons');
}

.my-handvictory-icon {
@include post.post-icon($name: 'handvictory', $base: '/post-icons', $color: #666666);
}

.my-icon-1 {
width: 16px;
height: 16px;
}

.my-icon-2 {
width: 24px;
height: 24px;
}

.my-icon-3 {
width: 32px;
height: 32px;
}

.my-icon-4 {
width: 40px;
height: 40px;
}

.my-icon-5 {
width: 48px;
height: 48px;
}

.my-icon-6 {
width: 64px;
height: 64px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@use '@swisspost/design-system-styles/core' as post;

.my-icon {
@include post.post-icon(
$name: 'accessibility',
// optional
$base: '/optional/path/to/your/self-hosted/svgs',
// optional
$color: '#fc0'
);
}
32 changes: 32 additions & 0 deletions packages/icons/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,35 @@ export const ICON_V1_TEMPLATE = `<svg xmlns="http://www.w3.org/2000/svg">
{uses}
</svg>`;

const ICON_V2_CONTAINER_STYLES = ICON_V2_SIZES.map((size, i) => {
const nextSize = ICON_V2_SIZES[i + 1];
const min = i !== 0 && `(min-width: ${size}px)`;
const max = i < ICON_V2_SIZES.length - 1 && `(max-width: ${nextSize - 1}px)`;

return `@container pi ${[min, max].filter(Boolean).join(' and ')} {
g {
--pis-${size}: block;
}
}`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a fallback for browsers that don't support container queries?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary anymore, because I switched to use media queries. They are working great, and are supported since almost a decade. Please have a look at the tested browsers at the top of this PR.

});

const ICON_V2_TEMPLATE_STYLES = `<style>
svg {
container-name: pi;
container-type: inline-size;
display: block;
width: 100%;
height: 100%;
}

${ICON_V2_CONTAINER_STYLES.join('\n')}
</style>`;

export const ICON_V2_TEMPLATE = `<svg xmlns="http://www.w3.org/2000/svg">
${ICON_V2_TEMPLATE_STYLES.split('\n')
.map(line => line.trim())
.map(line => (line.startsWith('@') ? line : line.replace(/(\s|\t|\n)/g, '')))
.join('')}
<defs>
<symbol id="{id}">
<defs>
Expand All @@ -29,4 +57,8 @@ export const ICON_V2_TEMPLATE = `<svg xmlns="http://www.w3.org/2000/svg">
{uses}
</symbol>
</defs>

<g>
<use href="#{id}"/>
</g>
</svg>`;
2 changes: 1 addition & 1 deletion packages/icons/src/utilities/buildSVGs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ function createFiles(groupedFilePaths: Record<string, File[]>) {

function createSvg(id: string, template: string, symbols: string[], uses: string[]): string {
const file = template
.replace('{id}', `${ID_PREFIX}-${id}`)
.replaceAll('{id}', `${ID_PREFIX}-${id}`)
.replace('{symbols}', symbols.join(''))
.replace('{uses}', uses.join(''));

Expand Down
2 changes: 1 addition & 1 deletion packages/icons/svgo.config.ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default {
name: 'removeAttrs',
params: {
elemSeparator: '::',
attrs: ['style', 'data-.*', 'svg::(width|height|xml:space)'],
attrs: ['style', 'fill', 'stroke', 'data-.*', 'svg::(width|height|xml:space)'],
},
},
],
Expand Down
14 changes: 14 additions & 0 deletions packages/styles/src/mixins/_icons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@
forced-color-adjust: preserve-parent-color;
}

@mixin post-icon(
$base: 'https://unpkg.com/@swisspost/design-system-icons/public/post-icons',
$name: '',
$color: currentColor
) {
display: inline-block;
width: 1em;
height: 1em;
vertical-align: -0.15em;
background-color: currentColor;
color: $color;
mask-image: url('#{$base}/#{$name}.svg');
}

@mixin remove-icon() {
mask-image: none;
}
Loading