From 1583278a010700608f4bc430c11bc800533914e0 Mon Sep 17 00:00:00 2001 From: Mehak Jain <145124929+Mehak261124@users.noreply.github.com> Date: Mon, 5 Aug 2024 12:35:31 +0530 Subject: [PATCH] Add icon component to the toolkit (#123) * added new icon components * updated changes * added comments * did the suggested changes * updated files * updated changes * updated svg * updated color * updated snapshots --- packages/components/src/icon/icon.stories.ts | 43 +++++++++ packages/components/src/icon/icon.test.ts | 18 ++++ .../icon-change-icon-chromium-linux.png | Bin 0 -> 858 bytes .../icon-change-icon-firefox-linux.png | Bin 0 -> 1679 bytes .../icon-change-icon-webkit-linux.png | Bin 0 -> 1704 bytes .../icon-default-chromium-linux.png | Bin 0 -> 897 bytes .../icon-default-firefox-linux.png | Bin 0 -> 1617 bytes .../icon-default-webkit-linux.png | Bin 0 -> 1807 bytes packages/components/src/icon/index.ts | 85 ++++++++++++++++++ 9 files changed, 146 insertions(+) create mode 100644 packages/components/src/icon/icon.stories.ts create mode 100644 packages/components/src/icon/icon.test.ts create mode 100644 packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-chromium-linux.png create mode 100644 packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-firefox-linux.png create mode 100644 packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-webkit-linux.png create mode 100644 packages/components/src/icon/icon.test.ts-snapshots/icon-default-chromium-linux.png create mode 100644 packages/components/src/icon/icon.test.ts-snapshots/icon-default-firefox-linux.png create mode 100644 packages/components/src/icon/icon.test.ts-snapshots/icon-default-webkit-linux.png create mode 100644 packages/components/src/icon/index.ts diff --git a/packages/components/src/icon/icon.stories.ts b/packages/components/src/icon/icon.stories.ts new file mode 100644 index 0000000..e7e7eb9 --- /dev/null +++ b/packages/components/src/icon/icon.stories.ts @@ -0,0 +1,43 @@ +import type { StoryFn, Meta, StoryObj } from '@storybook/html'; +import { Icon } from './index'; + +// Register the icon with proper SVG formatting +Icon.register({ + name: 'search', + svgStr: ` + + + ` +}); + +export default { + title: 'Components/Icon', + argTypes: { + name: { control: 'select', options: ['search', 'default'] } + }, + parameters: { + actions: { disabled: true } + } +} as Meta; + +const Template: StoryFn = (args, context): string => { + if (args.delay !== undefined) { + setTimeout(() => { + Icon.register({ + name: 'search', + svgStr: ` + ` + }); + }, args.delay); + } + + return ``; +}; + +export const Default: StoryObj = { render: Template.bind({}) }; +Default.args = { name: 'search' }; +export const ChangeIcon: StoryObj = { render: Template.bind({}) }; +ChangeIcon.args = { + ...Default.args, + delay: 2000 // Two seconds delay +}; diff --git a/packages/components/src/icon/icon.test.ts b/packages/components/src/icon/icon.test.ts new file mode 100644 index 0000000..ff6c481 --- /dev/null +++ b/packages/components/src/icon/icon.test.ts @@ -0,0 +1,18 @@ +// Copyright (c) Jupyter Development Team. +// Distributed under the terms of the Modified BSD License. + +import { test, expect } from '@playwright/test'; + +test('Default', async ({ page }) => { + await page.goto('/iframe.html?id=components-icon--default'); + expect(await page.locator('jp-icon').screenshot()).toMatchSnapshot( + 'icon-default.png' + ); +}); +test('ChangeIcon', async ({ page }) => { + await page.goto('/iframe.html?id=components-icon--change-icon'); + await page.waitForTimeout(2000); + expect(await page.locator('jp-icon').screenshot()).toMatchSnapshot( + 'icon-change-icon.png' + ); +}); diff --git a/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-chromium-linux.png b/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-chromium-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..8ed077c40e6c9b8efd44e3ad6d2d6509738ae328 GIT binary patch literal 858 zcmeAS@N?(olHy`uVBq!ia0y~yV0i#!%W$v($rDQsFajyY;vjb?hIQv;UNSH+i+H*? zhE&XXd-trjOt}R6hxF?aA6Ol)zgfy1mipMUpw{|EvUt`3Z|7h3Cfl?4&l+wQ(Lbx2 ztL3?3)~!Fxk93c|Ej`%nZaAUo?uMlG^XABLZ9DpXSMZD{pDoYXe12+KKXYdMx|n@a zS%B6uOz4uHE_>$r=feO0t_uo&{P56xqDqxDNM^^0rCdACojX_Y<;Cq8^XBz+bOfyw z;pUD%`tV`ms?#7hJ6wCJFQp-tf9%z(Q-wdp1PzUig-@ThcZ-jYhbfpFePHV8rxDT7 z-47o=6#nk!=Jx36>G{bS85&!kf-F&ZeNN}WvSrJXQd2E|{r-KvW=Dh$&^WIUt*If? zn1Ko!)>v819K z+r9<&^!07iDXG~bq#w7&ZDYme)R`dp39dWezI~fgP+&0i!`!)ZcT|7>9I^=%VhY@! z!Yy+^EQTGk?wmPu{N#ZH4n96UNA_07Z&CU3@$vhl>}>6_^76+I9xPCWnq@xgY?{gJ zvoGGh&5eBV`ugs`_1B}Pv4hNroO{o|CEi`fB=$kYmX?YlM=M zrvh1v!+w9Qj}!oD*z{&c!|A8z>auf_lOM;k#!gb%xNqOQcWEHG4}3d97|UmUzBi+I zlNLzek83a}fih_Bx?=ypZ+H3CN)WF?URJ!|_wV27e0yteTNJ+C^V99|_w047Ai4K# z+ng4DP*7TQG2_U=gYp;e{c|*t>b-IMcDH$cUH5YT`L1ijtUo>oeGYQ)gW4(D)AN7E yiGXwlJrV%hqb6Mw<&;$Uwb9lM{ literal 0 HcmV?d00001 diff --git a/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-firefox-linux.png b/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-firefox-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..05bfb87cf99d915a7d8e14a9c12901363f24f2d6 GIT binary patch literal 1679 zcmeAS@N?(olHy`uVBq!ia0y~yV0i#!>vOOHNiVOhObiTcVV*9IAr*0N?-~XvIf}47 zP>Z)|IA*o;HS3)am8GX5_!hKkM$gJheDjFa=Qwi(qrQPuF{5QecCc#bnipJ`f*;fb zyRv-Vb^p5TUsIp!X6D=HHFq;GGO=(7C^$4A7>z1Sri?K{;jWyh;vkhhEGz|POjz`^ zFfr|D+2JLOViH)Lz=500=vDwFgt#~!2tCsBMY0%btOG+jKc>wB9vTV_-W{t=FfC_f zoMVgZ0jLUvg$)dPit8?6v7Dvg8^XVE0~-g@6OI1t1z)RdWn^Sps{Xp~*!4@e?XaRP zM&tk;`%n49N(Q~Q{Oi~MPDs7EA|_De;fD>nEt~hE#UsdHHKq-xH?1uwD>LJ}ANQJ< zt+}A4=8w=ZTL(2P0ro()k$-+e_rvJ@_xZE4vxD>NtE#x(mPK=kQL|Y_spq z%P&`&*Ho_+ciz$6-96#?_6b;0jld80gjd1^hBe*w)^ne}D%x6e%`2&@s*gexEyBgr9ruY6*B+fioIIg;vgryVt)i-!;k$v0$&-1< zk1x@yuST)57pq{ZnBcNt+upyQEl+Q{`1`(}pB1;HirgWA|4mZ%haVOwnu;o7YT3}m z^f)-6ysXTP-B9OI7rVio`}g%1O_9Qq=)*Y`lm70Xn2|q46{tQhYJu3{?GlH4ce50v>dr6349RJ+3GW!*EiOOC z`CwY@&9nWO5w63?7!!Hv7^cToENNg^H|g}cOpF}RxQXQ$W6ZSN*4eXXuY9~MYHffB zzwrIDzkY9$GU9_r3!KrIDkQ;PP#ARf*}v1vEe-eEoOhmg-*4{cHT&b29Xs2K;iLu! zNhV>&7)fTSW-M}3f#qLlRPJ6OjQlV~PoY73?wtnAzzr1=I1rk-^{W>~x(wI_^khj9 zGp1=Fo(>G*ORrwjhWi7?aCiwUX)m4R^}sYu6&RRP!=l$?I$FVdQ&MBb@0PMBEA^-pY literal 0 HcmV?d00001 diff --git a/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-webkit-linux.png b/packages/components/src/icon/icon.test.ts-snapshots/icon-change-icon-webkit-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..3298f099d93eaed676b3b7cecac9a223dd44b5f7 GIT binary patch literal 1704 zcmYjR2~-nT6pbj00>(-uA_TEYP*K8BK?PZ)a8N*q>>Bp%KqPE|u&+u{piqnKBoL5Q z;23SuEGDu@gp}<7mB1ktWD6MCN|1!5p);|4bI#10|L)v>=f3~{Bb2SB;(=oaAP|V+ z%^T+S5Xk!Gk1z$oN=WnnQMWuZlOddEx>0o95RYW6JpBJ$6pf>M~2X zFOOfmfVZMBulkP<}XjN8mNSLPE;07#G z);H|%$?UGcv|}R`pW3e9()F4=Qe+X@fBhX>y7$DyDu;mUTNEVE50i(aes5_J)Ru2MySTviwQh;l z4Go!UDk^t!yg-KVtcHe$Ok;Zd`j^#N+C2;=iPG5E7#tePOcV*;#IF~eQ3sHw37JR~ z8jbEFh^+nnr=MN6wz3)>9qnYXGBPp>PyUBGhcYzCNf2ROf`WJpCe`-!1qB7V3bL}Y zg=$cMO2ary2UT_2Abb+a$~_KkU&8i1@Gk1|!(cEnGBN=H0R?J@LFB| z@$1rrnL3w(n3xz@)#f`iS{={V7+06k(RsAxPzqY!xnA)2+a5$V@U;6y~{5x6D ztA}WkGzN>s>X%|Mn7g0TA`Qj|aU=#Ki7X4+<>QP>rA9AugIiuTH@Ccoqg#S`e14DL zg?DgSV4{aC8Z%Y6%wihF3qA|i77Aa~h|Owh;%{&5WM^le^FIjS-gd`Yrj8DTPYu;O zXliP*pP$Jz7S`!0w70glR@;GsT=AjjcU_2GnIikL+H~ET{k@L{TqqWcPECFG^5sjm zo-#n^b%#zdZK|vLy3D#*o+uFIyK+WGM*921rn~cDNRP&j1OS&ZNhg_({}$vB9UYCx zyF+POTVsZVY~M=WF%f`hL_5M@oh#W<0G&j}W6t*g4kEjPQ}aE)YFGLPao+5Lk{EpGI90EdKmIDz^V))hMzDfR7#kbwE88GdR{qetHa$IEo-~SI z`|BGfi5lQ44p`Xe|UHWSn|r2MiV&e7yoVr@gL`v3#gQ{Jt+Q?)w zrLO`J5)rY|4uxtGc6YHjT&wIUZaO>#q*3h3DV`iK_;xg3xG~GrB1}|g!H@_zDA<+O z7D**lS5M!EmRMU`-`BVjv-GhAJLZEn(bvas3D-2_h$hL#y1HR&^CrG%MSx7#uE_Q> zJ#K3}IyvOty)5ijwRIt5TbN63lJwj3EN9L8C_)v$L%edNjsU3!azaW^?)y4W6=p)w z5lB<$QLD}E&-<;S0t4qni^)gfZ~~D?q^Vd8{W~sYJq&OPYEtKonmfv2L_rvPArqV#sIk!W8$Zs9|W%`qt z)Q0PlQq}|cAvc}EU;qh8xhno}aPVT63^-79k!cD)z7u+arEZ+?dTB3P58QSd`m6Fo z3eFQdhDrP+M5=(=FMhaY5xE?gr#}_ literal 0 HcmV?d00001 diff --git a/packages/components/src/icon/icon.test.ts-snapshots/icon-default-chromium-linux.png b/packages/components/src/icon/icon.test.ts-snapshots/icon-default-chromium-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..662d255cce208c8c7a2741af26e8642cba3812a8 GIT binary patch literal 897 zcmeAS@N?(olHy`uVBq!ia0y~yV0i#!%W$v($rDQsFajyY;vjb?hIQv;UNSH+TYI`V zhE&XXdv||!Xu1sBhv!Rf%Cs)n$vNX8n_ix%bb*KPt7$GPC3VU^WIg+3zQyfTlDPNW zoVDBd1a)2th&vuk6TFjLFrk6nSL|eha>|Bauk}A!XD#0Q@bk@cmhZoRIK%(E)<1Cl z_x+qeix~ns`}$=;42CjeRv8c-vZ8o1yR);iq|`5)UN_~vd-q00M4WhhyubMWzrQvW zAFj8b;Q*=2U0v~;XU8IqqJMwNC8ecrm%RA)*51g{GP2SFB%M+IdSAorIX3ezUc9)c z?yuE!{r@v=-n_Y|;-k{z?r*inkJUGA`c$qL`|DwH3MfDtwq5+hdS{}t zd(qQV{*ke6vX+&fR-ZY4zW%}ikVO~#qUsJA*xAif z*;)1VIq&K1Dl=!#KHV$5U)9rZ&W}xxD!_{FMRDzLZnyKDbZ2*Y{^^Cg%ipVc^2z^O zvnT>2y}^2mNI~_tH=dJpbaZkozkGRlS;f=ee=U-%e*8Y4NngHx&9y9faG+7;QaVD(VH6)aeJ$#K7IOh&6+h!mM>R7-YQN+!OU5^z8Y=@X+H2j4itx(I|D^_79<)eD=W|Dv#t4Iz|737dDvJ z!-Xv%!y9^Yq7LMy1LJ#V-QVjarKL-CPS3F{HuLuOww}umGV@l{@o(N{-~RmkJjd?t znM;>~vbIL8i~X${8yjmqlNYSwp0#*Erw|{Az3p=xYs{snL!zz|pUf@W!UPmLuhOJI5Exl@408;irey;V`MVoZWUxk9W8?yI&7YhNg5{kLNX==p;Ca`&0OB%q= ivOOHNiVOhObiTc5}q!OAr*0N?>hQP1xg(F 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
`; + +/** + * Icon component + * + * Icon must first be registered: `Icon.register({ name, svgStr });` + * + * Then you can use it with `` . + * + * To style your icon, you should set `fill` and/or `stroke` attributes to `currentColor`. + * Then the icon will be colored with the active text color. + */ +@customElement({ + name: 'jp-icon', + template +}) +export class Icon extends FASTElement { + /** + * Name of the icon to display. + */ + @attr name: string; + + private static iconsMap = new Map(); + private static _defaultIcon = + ''; + + /** + * Register a new icon. + * + * @param options { name: Icon unique name, svgStr: Icon SVG as string } + */ + static register(options: { name: string; svgStr: string }): void { + if (Icon.iconsMap.has(options.name)) { + console.warn( + `Redefining previously loaded icon svgStr. name: ${ + options.name + }, svgStrOld: ${Icon.iconsMap.get(options.name)}, svgStr: ${ + options.svgStr + }` + ); + } + Icon.iconsMap.set(options.name, options.svgStr); + + // Rerender all existing icons with the same name + document + .querySelectorAll(`jp-icon[name="${options.name}"]`) + .forEach((node: HTMLElement) => { + node.setAttribute('name', ''); + node.setAttribute('name', options.name); + }); + } + + /** + * Set a new default icon. + * + * @param svgStr The SVG string to be used as the default icon. + */ + static setDefaultIcon(svgStr: string): void { + Icon._defaultIcon = svgStr; + } + + /** + * Default icon + * + * This icon will be displayed if the {@link name} does not match any known + * icon names. + */ + static defaultIcon(): string { + return Icon._defaultIcon; + } + + /** + * Get the icon SVG + */ + getSvg(): string { + return Icon.iconsMap.get(this.name) ?? Icon.defaultIcon(); + } +}