From 9685776cad0beee9c50eace9009321a9a9303316 Mon Sep 17 00:00:00 2001
From: Xavier Carron <33637571+xav-car@users.noreply.github.com>
Date: Thu, 19 Sep 2024 11:26:32 +0200
Subject: [PATCH] feat(icon): add PixIcon Component
---
addon/components/pix-icon.hbs | 8 ++++
addon/components/pix-icon.js | 44 +++++++++++++++++++
addon/helpers/icons.js | 76 +++++++++++++++++++++++++++++++++
app/components/pix-icon.js | 1 +
app/stories/pix-icon.mdx | 20 +++++++++
app/stories/pix-icon.stories.js | 51 ++++++++++++++++++++++
6 files changed, 200 insertions(+)
create mode 100644 addon/components/pix-icon.hbs
create mode 100644 addon/components/pix-icon.js
create mode 100644 addon/helpers/icons.js
create mode 100644 app/components/pix-icon.js
create mode 100644 app/stories/pix-icon.mdx
create mode 100644 app/stories/pix-icon.stories.js
diff --git a/addon/components/pix-icon.hbs b/addon/components/pix-icon.hbs
new file mode 100644
index 000000000..e0295f280
--- /dev/null
+++ b/addon/components/pix-icon.hbs
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/addon/components/pix-icon.js b/addon/components/pix-icon.js
new file mode 100644
index 000000000..3917ab584
--- /dev/null
+++ b/addon/components/pix-icon.js
@@ -0,0 +1,44 @@
+import Component from '@glimmer/component';
+import { warn } from '@ember/debug';
+import { ICONS } from '@1024pix/pix-ui/helpers/icons';
+
+export default class PixIcon extends Component {
+ get alternativeText() {
+ return this.args.alternativeText || '';
+ }
+
+ get ariaHidden() {
+ warn(
+ 'PixIcon: @ariaHidden must be a boolean, default undefined',
+ [true, false, null, undefined].includes(this.args.ariaHidden),
+ {
+ id: 'pix-ui.icon.aria-hidden.not-boolean',
+ },
+ );
+ return this.args.ariaHidden ? 'true' : undefined;
+ }
+
+ get iconName() {
+ warn(
+ `PixIcon: @name must be one of these : ${Object.keys(ICONS).join(' | ')}`,
+ Object.keys(ICONS).includes(this.args.name),
+ {
+ id: 'pix-ui.icon.not-valid',
+ },
+ );
+
+ warn(
+ 'PixIcon: @plainIcon must be a boolean, default undefined',
+ [true, false, undefined, null].includes(this.args.plainIcon),
+ {
+ id: 'pix-ui.icon.plan-icon.not-boolean',
+ },
+ );
+
+ const icon = ICONS[this.args.name];
+
+ if (!icon) return null;
+
+ return this.args.plainIcon && Boolean(icon.plainIcon) ? icon.plainIcon : icon.default;
+ }
+}
diff --git a/addon/helpers/icons.js b/addon/helpers/icons.js
new file mode 100644
index 000000000..7545430ea
--- /dev/null
+++ b/addon/helpers/icons.js
@@ -0,0 +1,76 @@
+export const ICONS = {
+ add: { default: 'add' },
+ arrowBottom: { default: 'arrow_downward' },
+ arrowLeft: { default: 'arrow_back' },
+ arrowRight: { default: 'arrow_forward' },
+ arrowTop: { default: 'arrow_upward' },
+ assignment: { default: 'assignment', plainIcon: 'assignment_plainIcon' },
+ awards: { default: 'social_leaderboard', plainIcon: 'social_leaderboard_plainIcon' },
+ book: { default: 'menu_book', plainIcon: 'menu_book_plainIcon' },
+ bookmark: { default: 'bookmark', plainIcon: 'bookmark_plainIcon' },
+ buildings: { default: 'location_city' },
+ campaign: { default: 'campaign', plainIcon: 'campaign_plainIcon' },
+ cancel: { default: 'cancel', plainIcon: 'cancel_plainIcon' },
+ check: { default: 'check' },
+ checkCircle: { default: 'check_circle', plainIcon: 'check_circle_plainIcon' },
+ chevronBottom: { default: 'arrow_drop_down' },
+ chevronLeft: { default: 'chevron_left' },
+ chevronRight: { default: 'chevron_right' },
+ chevronTop: { default: 'arrow_drop_up' },
+ close: { default: 'close' },
+ conversionPath: { default: 'conversion_path' },
+ copy: { default: 'content_copy', plainIcon: 'content_copy_plainIcon' },
+ delete: { default: 'delete', plainIcon: 'delete_plainIcon' },
+ down: { default: 'keyboard_arrow_down' },
+ download: { default: 'download' },
+ edit: { default: 'edit_square', plainIcon: 'edit_square_plainIcon' },
+ error: { default: 'error', plainIcon: 'error_plainIcon' },
+ extension: { default: 'extension', plainIcon: 'extension_plainIcon' },
+ eye: { default: 'visibility', plainIcon: 'visibility_plainIcon' },
+ eyeOff: { default: 'visibility_off', plainIcon: 'visibility_off_plainIcon' },
+ favorite: { default: 'favorite', plainIcon: 'favorite_plainIcon' },
+ flag: { default: 'flag', plainIcon: 'flag_plainIcon' },
+ globe: { default: 'globe' },
+ help: { default: 'help', plainIcon: 'help_plainIcon' },
+ home: { default: 'home', plainIcon: 'home_plainIcon' },
+ image: { default: 'image', plainIcon: 'image_plainIcon' },
+ info: { default: 'info', plainIcon: 'info_plainIcon' },
+ infoUser: { default: 'contact_page', plainIcon: 'contact_page_plainIcon' },
+ inventory: { default: 'inventory_2', plainIcon: 'inventory_2_plainIcon' },
+ language: { default: 'language' },
+ link: { default: 'link' },
+ lock: { default: 'lock', plainIcon: 'lock_plainIcon' },
+ mapPin: { default: 'location_on', plainIcon: 'location_on_plainIcon' },
+ minus: { default: 'check_indeterminate_small' },
+ moreHoriz: { default: 'more_horiz' },
+ moreVert: { default: 'more_vert' },
+ newRealease: { default: 'new_releases', plainIcon: 'new_releases_plainIcon' },
+ openNew: { default: 'open_in_new' },
+ pauseCircle: { default: 'pause_circle', plainIcon: 'pause_circle_plainIcon' },
+ playCircle: { default: 'play_circle', plainIcon: 'play_circle_plainIcon' },
+ power: { default: 'power_settings_new' },
+ readMore: { default: 'read_more' },
+ refresh: { default: 'refresh' },
+ search: { default: 'search' },
+ seat: { default: 'airline_seat_recline_normal' },
+ session: { default: 'event_note', plainIcon: 'event_note_plainIcon' },
+ settings: { default: 'settings', plainIcon: 'settings_plainIcon' },
+ share: { default: 'share', plainIcon: 'share_plainIcon' },
+ shieldPerson: { default: 'shield_person', plainIcon: 'shield_person_plainIcon' },
+ signpost: { default: 'signpost', plainIcon: 'signpost_plainIcon' },
+ smartphone: { default: 'smartphone', plainIcon: 'smartphone_plainIcon' },
+ sort: { default: 'swap_vert' },
+ sortAz: { default: 'sort_by_alpha' },
+ star: { default: 'star', plainIcon: 'star_plainIcon' },
+ stopCircle: { default: 'stop_circle', plainIcon: 'stop_circle_plainIcon' },
+ tablet: { default: 'tablet_android', plainIcon: 'tablet_android_plainIcon' },
+ thumbUp: { default: 'thumb_up', plainIcon: 'thumb_up_plainIcon' },
+ tools: { default: 'construction' },
+ up: { default: 'keyboard_arrow_up' },
+ upload: { default: 'upload' },
+ userCircle: { default: 'account_circle', plainIcon: 'account_circle_plainIcon' },
+ users: { default: 'group', plainIcon: 'group_plainIcon' },
+ volumeOff: { default: 'volume_off', plainIcon: 'volume_off_plainIcon' },
+ volumeOn: { default: 'volume_up', plainIcon: 'volume_up_plainIcon' },
+ warning: { default: 'warning', plainIcon: 'warning_plainIcon' },
+};
diff --git a/app/components/pix-icon.js b/app/components/pix-icon.js
new file mode 100644
index 000000000..a2994c5a4
--- /dev/null
+++ b/app/components/pix-icon.js
@@ -0,0 +1 @@
+export { default } from '@1024pix/pix-ui/components/pix-icon';
diff --git a/app/stories/pix-icon.mdx b/app/stories/pix-icon.mdx
new file mode 100644
index 000000000..904233ba5
--- /dev/null
+++ b/app/stories/pix-icon.mdx
@@ -0,0 +1,20 @@
+import { Meta, Story, ArgTypes } from '@storybook/blocks';
+import * as ComponentStories from './pix-icon.stories';
+
+
+
+# Pix Icon
+
+> Permet d'utiliser les icônes disponible du Design System.
+
+
+
+## Usage
+
+```html
+
+```
+
+## Arguments
+
+
diff --git a/app/stories/pix-icon.stories.js b/app/stories/pix-icon.stories.js
new file mode 100644
index 000000000..535ef17cf
--- /dev/null
+++ b/app/stories/pix-icon.stories.js
@@ -0,0 +1,51 @@
+import { hbs } from 'ember-cli-htmlbars';
+import { ICONS } from '../../addon/helpers/icons.js';
+
+export default {
+ title: 'Others/Icon',
+ argTypes: {
+ name: {
+ name: 'name',
+ description: "Nom de l'icône à utiliser",
+ type: { name: 'string', required: true },
+ control: { type: 'select' },
+ options: Object.keys(ICONS),
+ },
+ plainIcon: {
+ name: 'plainIcon',
+ description: "Permet d'utiliser la version pleine de l'icône",
+ control: { type: 'boolean' },
+ type: { name: 'boolean', required: false },
+ table: {
+ type: { summary: 'boolean' },
+ defaultValue: { summary: false },
+ },
+ },
+ alternativeText: {
+ name: 'alternativeText',
+ description: "Permet d'ajouter un texte alternatif pour illustrer l'icône si besoin",
+ type: { name: 'string', required: false },
+ },
+ ariaHidden: {
+ name: 'ariaHidden',
+ description:
+ "Permet de ne pas vocaliser l'icône au lecteur d'écran dans le cas d'une icône purement décorative.",
+ control: { type: 'boolean' },
+ type: { name: 'boolean', required: false },
+ table: {
+ type: { summary: 'boolean' },
+ defaultValue: { summary: false },
+ },
+ },
+ },
+};
+
+export const icon = (args) => ({
+ template: hbs``,
+ context: args,
+});