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, +});