From 41ac7f1dcd64ff2bf2076560d3a7bab8469e511b Mon Sep 17 00:00:00 2001 From: Tiberiu Dumitru Date: Tue, 6 Feb 2024 15:06:24 +0200 Subject: [PATCH 1/4] OEL-2799: POC svg sprite css classes. --- builder/scripts/sprite.js | 42 +++++++------------ src/themes/default/src/scss/_svg_classes.scss | 24 +++++++++++ .../default/src/scss/oe-bcl-default.scss | 1 + 3 files changed, 41 insertions(+), 26 deletions(-) create mode 100644 src/themes/default/src/scss/_svg_classes.scss diff --git a/builder/scripts/sprite.js b/builder/scripts/sprite.js index a2fa4e038..c90556de0 100644 --- a/builder/scripts/sprite.js +++ b/builder/scripts/sprite.js @@ -1,28 +1,3 @@ -/** - * Generate svg sprites. - * - * @param {string} entry - array of paths to a folder or file. - * @param {string} dest - Output folder path - * @param {object} options - Object - * - * Example config object: { - * - * sprite: [ - * { - * entry: [ - * path.resolve(nodeModules, "bootstrap-icons/icons/"), - * path.resolve(__dirname, "src/icons/custom-icons") - * ], - * dest: path.resolve(outputFolder, "icons/"), - * options: { - * file: "bcl-default-icons.svg", - * list: myList, - * transformPlugins: (array of svgo plugins objects) - * }, - * }, - * ], - */ - const fs = require("fs"); const { globSync } = require("glob"); const mkdirp = require("mkdirp"); @@ -30,6 +5,15 @@ const path = require("path"); const defaultPlugins = require("../conf/svgoDefaultPlugins"); const SVGSpriter = require("svg-sprite"); +let svgMarkup; + +const addSvgMarkup = (filePath) => { + const fileContents = fs.readFileSync(filePath, { encoding: "utf-8" }); + svgMarkup = svgMarkup += ""; // Closing svg tag. + const updatedContents = fileContents.replace("", svgMarkup); + fs.writeFileSync(filePath, updatedContents); +}; + module.exports = (entry, dest, options) => { const iconList = Array.isArray(options.list) ? options.list.flat(1) @@ -64,7 +48,7 @@ module.exports = (entry, dest, options) => { }, }, }); - + let svgYPosition = 0; files.forEach((file) => { let filePath; if (Array.isArray(entry)) { @@ -75,6 +59,10 @@ module.exports = (entry, dest, options) => { } else { filePath = path.resolve(entry, file); } + const id = path.basename(file, path.extname(file)); // Extracting file name without extension as id + svgMarkup = + svgMarkup += ``; + svgYPosition = svgYPosition + 16; spriter.add( filePath, file, @@ -90,6 +78,8 @@ module.exports = (entry, dest, options) => { result[mode][resource].path, result[mode][resource].contents ); + const outputPath = result[mode][resource].path; + addSvgMarkup(outputPath); }); }); }); diff --git a/src/themes/default/src/scss/_svg_classes.scss b/src/themes/default/src/scss/_svg_classes.scss new file mode 100644 index 000000000..802523da4 --- /dev/null +++ b/src/themes/default/src/scss/_svg_classes.scss @@ -0,0 +1,24 @@ +.bcl-bg-icon-test { + mask-image: url("static/media/src/themes/default/icons/bcl-default-icons.svg#info-circle-fill-view"); + width: 1rem; + height: 1rem; + display: block; + background-color: red; +} + +.bcl-bg-icon-info-icon { + mask-position: 16px 0; +} + +.bcl-bg-icon { + width: 1rem; + height: 1rem; + display: block; + mask-image: var(--bcl-icon-path); +} + +@each $color, $value in $theme-colors { + .bcl-bg-icon-#{$color} { + background-color: $value; + } +} diff --git a/src/themes/default/src/scss/oe-bcl-default.scss b/src/themes/default/src/scss/oe-bcl-default.scss index 66afc8eb8..dc4ed8253 100644 --- a/src/themes/default/src/scss/oe-bcl-default.scss +++ b/src/themes/default/src/scss/oe-bcl-default.scss @@ -81,3 +81,4 @@ @import "@openeuropa/bcl-theme-default/src/scss/carousel"; @import "@openeuropa/bcl-theme-default/src/scss/gallery"; @import "@openeuropa/bcl-theme-default/src/scss/pagination"; +@import "@openeuropa/bcl-theme-default/src/scss/svg_classes"; From 13ed1e8395cc9b2896c3743efad3f1a7005efdc2 Mon Sep 17 00:00:00 2001 From: Tiberiu Dumitru Date: Tue, 28 May 2024 18:51:23 +0300 Subject: [PATCH 2/4] OEL-2799: Added icon classes. --- builder/scripts/sprite.js | 25 ++++++ .../bcl-icons-list/icons-list.story.js | 3 + .../bcl-icons-list/icons-manager.html.twig | 81 +++++++++++++++++++ .../src/js/icon-manager/icon-manager.js | 37 +++++++++ src/themes/default/src/js/index.esm.js | 2 + src/themes/default/src/js/index.umd.js | 2 + .../default/src/scss/_icon_manager.scss | 29 +++++++ src/themes/default/src/scss/_svg_classes.scss | 24 ------ .../default/src/scss/oe-bcl-default.scss | 2 +- 9 files changed, 180 insertions(+), 25 deletions(-) create mode 100644 src/compositions/bcl-icons-list/icons-manager.html.twig create mode 100644 src/themes/default/src/js/icon-manager/icon-manager.js create mode 100644 src/themes/default/src/scss/_icon_manager.scss delete mode 100644 src/themes/default/src/scss/_svg_classes.scss diff --git a/builder/scripts/sprite.js b/builder/scripts/sprite.js index c90556de0..0204ffe0f 100644 --- a/builder/scripts/sprite.js +++ b/builder/scripts/sprite.js @@ -1,3 +1,28 @@ +/** + * Generate svg sprites. + * + * @param {string} entry - array of paths to a folder or file. + * @param {string} dest - Output folder path + * @param {object} options - Object + * + * Example config object: { + * + * sprite: [ + * { + * entry: [ + * path.resolve(nodeModules, "bootstrap-icons/icons/"), + * path.resolve(__dirname, "src/icons/custom-icons") + * ], + * dest: path.resolve(outputFolder, "icons/"), + * options: { + * file: "bcl-default-icons.svg", + * list: myList, + * transformPlugins: (array of svgo plugins objects) + * }, + * }, + * ], + */ + const fs = require("fs"); const { globSync } = require("glob"); const mkdirp = require("mkdirp"); diff --git a/src/compositions/bcl-icons-list/icons-list.story.js b/src/compositions/bcl-icons-list/icons-list.story.js index 0e8e0232b..43bd6c000 100644 --- a/src/compositions/bcl-icons-list/icons-list.story.js +++ b/src/compositions/bcl-icons-list/icons-list.story.js @@ -1,4 +1,5 @@ import icons_list from "@openeuropa/bcl-icons-list/icons-list.html.twig"; +import icons_manager from "@openeuropa/bcl-icons-list/icons-manager.html.twig"; import icons from "@openeuropa/bcl-theme-default/src/icons/icons"; import customIcons from "@openeuropa/bcl-theme-default/src/icons/custom-icons"; import defaultSprite from "@openeuropa/bcl-theme-default/icons/bcl-default-icons.svg"; @@ -17,3 +18,5 @@ export default { export const Default = () => icons_list({ icons: iconsList, path: defaultSprite }); + +export const Attribute = () => icons_manager({ icons: iconsList }); diff --git a/src/compositions/bcl-icons-list/icons-manager.html.twig b/src/compositions/bcl-icons-list/icons-manager.html.twig new file mode 100644 index 000000000..e04585106 --- /dev/null +++ b/src/compositions/bcl-icons-list/icons-manager.html.twig @@ -0,0 +1,81 @@ +{% apply spaceless %} + +{# Parameters: + - icons: (icon[]) (default: []) + - path (string) (default: '') +#} + +{% set _icons = icons|default([]) %} +{% set _path = path|default('') %} + +{% if _icons is not empty and _icons is iterable %} +
+
+

Icon Colours

+
+ +

Default

+
+
+ +

Primary
icon-color-primary

+
+
+ +

Secondary
icon-color-secondary

+
+
+ +

Success
icon-color-success

+
+
+ +

Info
icon-color-info

+
+
+ +

Warning
icon-color-warning

+
+
+ +

Danger
icon-color-danger

+
+
+ +

Dark
icon-color-dark

+
+
+
+ +
+

Light
icon-color-light

+
+
+
+

Icon Sizes

+
+ +

Default

+
+
+ +

LG - icon-lg

+
+
+ +

XL - icon-xl

+
+
+
+

Icons List

+ {% for _icon in _icons %} +
+ +

{{ _icon }}

+
+ {% endfor %} +
+
+{% endif %} + +{% endapply %} diff --git a/src/themes/default/src/js/icon-manager/icon-manager.js b/src/themes/default/src/js/icon-manager/icon-manager.js new file mode 100644 index 000000000..6e9d9f500 --- /dev/null +++ b/src/themes/default/src/js/icon-manager/icon-manager.js @@ -0,0 +1,37 @@ +/** + * -------------------------------------------------------------------------- + * IconManager Class Documentation + * -------------------------------------------------------------------------- + * + * Overview: + * The `IconManager` class is a utility for dynamically setting the `mask-image` + * of HTML elements based on custom data attributes. It uses CSS custom properties + * and JavaScript to ensure the correct SVG icon is applied to elements with the class `.icon`. + * + */ + +import { defineJQueryPlugin } from '@openeuropa/bcl-bootstrap/js/src/util/index' + +class IconManager { + initializeIcons() { + this.iconPath = getComputedStyle(document.body).getPropertyValue('--icon-path').trim().replace(/['"]/g, ''); + document.querySelectorAll('.icon[data-icon]').forEach(icon => { + const iconId = icon.getAttribute('data-icon'); + this.setIconMask(icon, iconId); + }); + } + + setIconMask(icon, iconId) { + icon.style.maskImage = `url(${this.iconPath}#${iconId}-view)`; + icon.style.webkitMaskImage = `url(${this.iconPath}#${iconId}-view)`; + } +} + +document.addEventListener('DOMContentLoaded', () => { + const iconManager = new IconManager(); + iconManager.initializeIcons(); +}); + +defineJQueryPlugin(IconManager); + +export default IconManager; diff --git a/src/themes/default/src/js/index.esm.js b/src/themes/default/src/js/index.esm.js index 16e946ebc..4b9057fc4 100644 --- a/src/themes/default/src/js/index.esm.js +++ b/src/themes/default/src/js/index.esm.js @@ -19,6 +19,7 @@ import ScrollSpy from "@openeuropa/bcl-bootstrap/js/src/scrollspy-legacy"; import Tab from "@openeuropa/bcl-bootstrap/js/src/tab"; import Toast from "@openeuropa/bcl-bootstrap/js/src/toast"; import Tooltip from "@openeuropa/bcl-bootstrap/js/src/tooltip"; +import IconManager from "@openeuropa/bcl-theme-default/src/js/icon-manager/icon-manager"; export { Alert, @@ -35,4 +36,5 @@ export { Tab, Toast, Tooltip, + IconManager, }; diff --git a/src/themes/default/src/js/index.umd.js b/src/themes/default/src/js/index.umd.js index 8a3f1ec16..cdf884df3 100644 --- a/src/themes/default/src/js/index.umd.js +++ b/src/themes/default/src/js/index.umd.js @@ -19,6 +19,7 @@ import ScrollSpy from "@openeuropa/bcl-bootstrap/js/src/scrollspy-legacy"; import Tab from "@openeuropa/bcl-bootstrap/js/src/tab"; import Toast from "@openeuropa/bcl-bootstrap/js/src/toast"; import Tooltip from "@openeuropa/bcl-bootstrap/js/src/tooltip"; +import IconManager from "@openeuropa/bcl-theme-default/src/js/icon-manager/icon-manager"; export default { Alert, @@ -35,4 +36,5 @@ export default { Tab, Toast, Tooltip, + IconManager, }; diff --git a/src/themes/default/src/scss/_icon_manager.scss b/src/themes/default/src/scss/_icon_manager.scss new file mode 100644 index 000000000..e68d87050 --- /dev/null +++ b/src/themes/default/src/scss/_icon_manager.scss @@ -0,0 +1,29 @@ +body { + --icon-path: "static/media/src/themes/default/icons/bcl-default-icons.svg"; +} + +.icon { + width: 1rem; + height: 1rem; + display: block; + background-color: var(--bs-dark); + -webkit-mask-size: contain; + mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; +} + +@each $color, $value in $theme-colors { + .icon-color-#{$color} { + background-color: $value; + } +} + +.icon-lg { + width: 1.5rem; + height: 1.5rem; +} +.icon-xl { + width: 2rem; + height: 2rem; +} diff --git a/src/themes/default/src/scss/_svg_classes.scss b/src/themes/default/src/scss/_svg_classes.scss deleted file mode 100644 index 802523da4..000000000 --- a/src/themes/default/src/scss/_svg_classes.scss +++ /dev/null @@ -1,24 +0,0 @@ -.bcl-bg-icon-test { - mask-image: url("static/media/src/themes/default/icons/bcl-default-icons.svg#info-circle-fill-view"); - width: 1rem; - height: 1rem; - display: block; - background-color: red; -} - -.bcl-bg-icon-info-icon { - mask-position: 16px 0; -} - -.bcl-bg-icon { - width: 1rem; - height: 1rem; - display: block; - mask-image: var(--bcl-icon-path); -} - -@each $color, $value in $theme-colors { - .bcl-bg-icon-#{$color} { - background-color: $value; - } -} diff --git a/src/themes/default/src/scss/oe-bcl-default.scss b/src/themes/default/src/scss/oe-bcl-default.scss index dc4ed8253..a64be1efe 100644 --- a/src/themes/default/src/scss/oe-bcl-default.scss +++ b/src/themes/default/src/scss/oe-bcl-default.scss @@ -81,4 +81,4 @@ @import "@openeuropa/bcl-theme-default/src/scss/carousel"; @import "@openeuropa/bcl-theme-default/src/scss/gallery"; @import "@openeuropa/bcl-theme-default/src/scss/pagination"; -@import "@openeuropa/bcl-theme-default/src/scss/svg_classes"; +@import "@openeuropa/bcl-theme-default/src/scss/icon_manager"; From 86de5fb4d2a6dd52c6cf5abd7cb417ce55523ef5 Mon Sep 17 00:00:00 2001 From: Tiberiu Dumitru Date: Tue, 11 Jun 2024 19:05:14 +0300 Subject: [PATCH 3/4] OEL-2799: Fixed deploy demo. --- src/compositions/bcl-icons-list/icons-list.story.js | 6 +++++- src/themes/default/src/scss/_icon_manager.scss | 4 ---- tools/story-utils/index.js | 9 +++++++++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/compositions/bcl-icons-list/icons-list.story.js b/src/compositions/bcl-icons-list/icons-list.story.js index 43bd6c000..d5311b73a 100644 --- a/src/compositions/bcl-icons-list/icons-list.story.js +++ b/src/compositions/bcl-icons-list/icons-list.story.js @@ -3,6 +3,7 @@ import icons_manager from "@openeuropa/bcl-icons-list/icons-manager.html.twig"; import icons from "@openeuropa/bcl-theme-default/src/icons/icons"; import customIcons from "@openeuropa/bcl-theme-default/src/icons/custom-icons"; import defaultSprite from "@openeuropa/bcl-theme-default/icons/bcl-default-icons.svg"; +import { addIconPath } from "@openeuropa/bcl-story-utils"; let iconsList = icons.concat(customIcons); iconsList = iconsList.map((icon) => icon.substring(0, icon.length - 4)); @@ -19,4 +20,7 @@ export default { export const Default = () => icons_list({ icons: iconsList, path: defaultSprite }); -export const Attribute = () => icons_manager({ icons: iconsList }); +export const Attribute = () => + icons_manager({ icons: iconsList, path: defaultSprite }); + +Attribute.decorators = [addIconPath]; diff --git a/src/themes/default/src/scss/_icon_manager.scss b/src/themes/default/src/scss/_icon_manager.scss index e68d87050..baf5c0e6e 100644 --- a/src/themes/default/src/scss/_icon_manager.scss +++ b/src/themes/default/src/scss/_icon_manager.scss @@ -1,7 +1,3 @@ -body { - --icon-path: "static/media/src/themes/default/icons/bcl-default-icons.svg"; -} - .icon { width: 1rem; height: 1rem; diff --git a/tools/story-utils/index.js b/tools/story-utils/index.js index 6448f21d5..7e71703c7 100644 --- a/tools/story-utils/index.js +++ b/tools/story-utils/index.js @@ -342,6 +342,15 @@ export const initScrollspy = (story) => { ${demo}`; }; +export const addIconPath = (story) => { + const demo = story(); + return ` + + ${demo}`; +}; + export const initBadges = (story) => { const demo = story(); return ` From e7531fcdb0f299e6b68eb0e4dfbbec80680a6408 Mon Sep 17 00:00:00 2001 From: Tiberiu Dumitru Date: Tue, 11 Jun 2024 19:59:11 +0300 Subject: [PATCH 4/4] OEL-2799: Improved demo. --- .../bcl-icons-list/icons-manager.html.twig | 44 ++++++++++++++----- .../default/src/scss/_icon_manager.scss | 13 +----- .../default/src/scss/oe-bcl-default.scss | 2 +- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/compositions/bcl-icons-list/icons-manager.html.twig b/src/compositions/bcl-icons-list/icons-manager.html.twig index e04585106..8cf66c7cf 100644 --- a/src/compositions/bcl-icons-list/icons-manager.html.twig +++ b/src/compositions/bcl-icons-list/icons-manager.html.twig @@ -53,17 +53,41 @@

Icon Sizes

-
- -

Default

-
-
- -

LG - icon-lg

+
+
+ +

2XS - icon--2xs

+
+
+ +

XS - icon--xs

+
+
+ +

S - icon--s

+
+
+ +

M - icon--m

+
-
- -

XL - icon-xl

+
+
+ +

L - icon--l

+
+
+ +

XL - icon--xl

+
+
+ +

2XL - icon--2xl

+
+
+ +

Fluid - icon--fluid

+
diff --git a/src/themes/default/src/scss/_icon_manager.scss b/src/themes/default/src/scss/_icon_manager.scss index baf5c0e6e..d3a22fcca 100644 --- a/src/themes/default/src/scss/_icon_manager.scss +++ b/src/themes/default/src/scss/_icon_manager.scss @@ -1,6 +1,6 @@ .icon { - width: 1rem; - height: 1rem; + width: 1em; + height: 1em; display: block; background-color: var(--bs-dark); -webkit-mask-size: contain; @@ -14,12 +14,3 @@ background-color: $value; } } - -.icon-lg { - width: 1.5rem; - height: 1.5rem; -} -.icon-xl { - width: 2rem; - height: 2rem; -} diff --git a/src/themes/default/src/scss/oe-bcl-default.scss b/src/themes/default/src/scss/oe-bcl-default.scss index a64be1efe..09f92140c 100644 --- a/src/themes/default/src/scss/oe-bcl-default.scss +++ b/src/themes/default/src/scss/oe-bcl-default.scss @@ -67,6 +67,7 @@ @import "@openeuropa/bcl-theme-default/src/scss/header"; @import "@openeuropa/bcl-theme-default/src/scss/footer"; @import "@openeuropa/bcl-theme-default/src/scss/tabs"; +@import "@openeuropa/bcl-theme-default/src/scss/icon_manager"; @import "@openeuropa/bcl-theme-default/src/scss/icon"; @import "@openeuropa/bcl-theme-default/src/scss/search-form"; @import "@openeuropa/bcl-theme-default/src/scss/input"; @@ -81,4 +82,3 @@ @import "@openeuropa/bcl-theme-default/src/scss/carousel"; @import "@openeuropa/bcl-theme-default/src/scss/gallery"; @import "@openeuropa/bcl-theme-default/src/scss/pagination"; -@import "@openeuropa/bcl-theme-default/src/scss/icon_manager";