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;mUTNEV0Sv74aN_Nh3v+m
zef3ZG0x6_Xd7;3#l1``B*9Qdz%yj;&N^uL}?cD>E50i(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();
+ }
+}