From 7e3a6d9c423bc7455684ea9926920fd133310ddc Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 16 Dec 2025 13:56:36 +0000 Subject: [PATCH] Switch to rendering svg icons rather than masking them (#31550) * Switch to rendering svg icons rather than masking them in SpacePanel Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix badly rendered icon in JoinRuleDropdown Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix badly rendered icon in RoomPreviewCard Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix badly rendered icon in Space menus Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix badly rendered icon in ThreadPanel Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update snapshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update screenshot Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Remove unused icon underfill Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update screenshot Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add test Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add missing snapshot Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../tac-hovered-linux.png | Bin 4812 -> 4837 bytes .../threads.spec.ts/thread-panel-linux.png | Bin 17400 -> 17600 bytes res/css/_components.pcss | 2 +- res/css/structures/_SpacePanel.pcss | 155 ++++------- res/css/structures/_SpacePillButton.pcss | 48 ++++ res/css/structures/_SpaceRoomView.pcss | 59 ----- res/css/views/right_panel/_ThreadPanel.pcss | 27 +- res/css/views/rooms/_EventTile.pcss | 5 - res/css/views/rooms/_RoomPreviewCard.pcss | 39 +-- res/css/views/spaces/_SpaceCreateMenu.pcss | 12 - res/css/views/spaces/_SpacePublicShare.pcss | 21 -- src/components/structures/SpacePillButton.tsx | 27 ++ src/components/structures/SpaceRoomView.tsx | 30 ++- src/components/structures/ThreadPanel.tsx | 4 +- .../views/elements/JoinRuleDropdown.tsx | 2 +- .../views/rooms/RoomPreviewCard.tsx | 6 +- .../views/spaces/SpaceCreateMenu.tsx | 25 +- src/components/views/spaces/SpacePanel.tsx | 25 +- .../views/spaces/SpacePublicShare.tsx | 26 +- .../views/spaces/SpaceTreeLevel.tsx | 13 +- .../__snapshots__/ThreadPanel-test.tsx.snap | 33 +++ .../views/spaces/SpaceTreeLevel-test.tsx | 30 ++- .../__snapshots__/SpacePanel-test.tsx.snap | 127 ++++++++- .../SpaceTreeLevel-test.tsx.snap | 248 ++++++++++++++++++ 24 files changed, 645 insertions(+), 319 deletions(-) create mode 100644 res/css/structures/_SpacePillButton.pcss delete mode 100644 res/css/views/spaces/_SpacePublicShare.pcss create mode 100644 src/components/structures/SpacePillButton.tsx diff --git a/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-hovered-linux.png b/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-hovered-linux.png index 5884f6f56f5eb7c88f05f37afdaa9d983bc5cbca..40f1243619526070d07347ce7227684f7050769c 100644 GIT binary patch delta 4089 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 delta 4064 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 S$P8lu0000J61b24}1PRuSy9IZL#yde8 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 V5d5=B<<5hnAgd|^l`{VRKLGmyQBD8= literal 17400 zcmeIaRa9J2)aOY^2oQn=_Yf=u_uvE#?(Xh|7cL3z!5xCTJ4Hbf+?}Fu*TS7DVECq| zr&q7(m+9^`YaYIbz3y7);of`B-TUl)e*3>}q>7RZ<~!1NNJvPSvfm}ukdR)9A|WA9 zq9MPG*ov(4A|c@*$x43H@XCg*pc^E6Yz~~~32d?BapCdp2Q9xz|0G#xBF^+B+2-&k zBW3yyJ)q-2YjGD~`PeA2NKEA$zvLSYfW>cqKk3`&(RG$R z_A=3jE{JwC*M!g|`$fi@+xv;0`?cpM8KfX_a%3cTaWGQT|B7*1fHUnOJXQ9P=hDZ# zn`DaDsPBo{osq03#jxxr#gNYg&;E!LoBZP1GO*4NIUu_)1f9VD^u z2#(p!l=HuSxIP)TSQi6MLFuR@kscDlKZw^JTBhmbYb53R#!PH|G}&jP)Ixix{dolL zty)XAyV-aX6oAd~M)(LE@Yt~`zZ~X&*L(y)M;fC9p!v+h^-ojVV*lZAz4D598F+x* znR!-u1Rizb!4wvBP1%}K3qA$-U*#_XPc}sPj~+9!@8Ugob-`y(n^U_6(|g+}SybCI zsz>?Zzm@r6UCjU`UE?*cC-KnQcx{G8aj>32zO@Nb`BWV$M%Kt>Aow?@TbhrqoiRxQ zI5dbG*Xyc@?BDq^qM{;NJvWcrX3`K;SYrrEMLfo1^}sr%v79`$unUZC6brI^%k7Vj zp0DSC#cKCOrJw}d+7;WEH@utM%zRHpRsh$w{DQ58@X7C^{^(VL`rHq8orMn`d=80D zW2G2-YOX(!+s@8tMYbYVR9NQgqqBt313=e@MB?#{QwB%#gut1U-9V?6za@f9u+X?^ zN4MAS3I~|@B9k;M|DXlafOCsmReHvO?FNP*hG9Pl*n1~xxC27RYw?&>eG#va!17K zGTma@W5?E-T9i;KHl{C?j&sg2)rQha7!cvpQzIGbkT8X+>Pk_4gAT`mn$SzD##i>- znbprwO<>n@AJkOO=DQ5nEKLaIX>-SF?4$Wb>b#=-vho=EpCo-jPS%tQTwk9 zEt)F~bkgS{SvOm&(cGl#(O6J&F%+fO;{kz!YtEAC_Mz)e*{a#5_v*gU>MfL`^u}o+ z)2L*!Kal(6C_Uy~O?04SuZ6K{-$rtd{xs8qFFu_uS=VBorqc3HdgZ`G_3X@Ch^zT{ zlq)nVJCgKk&4!;!<2TS8cT z|9oL-$Erg-f1!!4r2ODr7Jxy&vvvJb*ox&L9trMYKUT_WT){P2qTO&sipVbCX_O5p zx;>dxpSd+zS}NqL9jYd_cEC)gFhhJQs(?@W-MI1YZ*ES$E&H|2oO{eX7;A@4sfofD zuFJ~Eq4Ys13~4lUlB1)m3RoUlIqf|Zm7b#EAsdGN2@~)HF2L;}^#>PT z!8Aq)^Sy%)U~zWDNx}K6r%>xCC8Au*)|JO1Wn8b{P5M>Yrmrx>$(>FvJ{hoTn^=x& zY7_w;1P*@6agX+l_=ha1%uNZ~N^Rdr9#1H5^IG4l)h;7Cr-vI7M~jw6lTH5y8j_ch zE#ynUD0g!}9~S1UXu5F8oR|65fc!Uy`2$Pf*KgnN`yu}jtGi1X9Ox@3+NO$I^Flp! zM}Ld;(d4rqhCTI^O+*HG$r<~YNq8VsJKO;Yk+WDqeIqrz zjY}P;o##X{sPKOUA8rV5ZsPVzmC=MLeW818!0KpfBU)}F#04TYtMyb?fs)(CWKXcB z!%r}X5@+Eq)iWpH`@1mFKy z=|NnNufSL<^+DxEk=bJ>ZFWnMb3<`V|EJ3f+L*Lbn%UW1l!jiu@%wuc;t%^Er1dIppO_zhxulNf*7dyBPZY(aPApTDFgiGJ5&7d30)^laey<`Cf1OE}g! z1(K2-;?<0|itjjoWt*_R6&Gx1We9vW59fk;qX|D@ej97H?`G_P*N=|O@eqBfkQP0j z8RG6org`&z_TcjypnZK6;vbc9y59uxNZimG{jsNu%h@?8^yK|D+PA#5Q^!X|%d+66 z*Qi+dB36<}pRXn*Caov8&fm8{&3k(Y@h1=eBWZvQ#(x6)^K!pk^URcZbsxM$u)L<`~A9%T;NB}Yuh)Gz>iL=vOU)_)zOrQ`PYH^Cvw|CG&%iKAyrA+1vq`@XUX_4zM0x8%b^ zI(Cnd0;#=S-`06qOJ`!Mk&X4(*T1!WvQ+#wpJHeRzGI_^a9IHtG?0x(fIbSb%S2m6-UXzeu*a$%k!t^!y9$Rcb?S`A2*s1H$`@zS!gfoqYVwGL>sDyTaYp>>fR0gJc?#z8G_tEX3)$dy!^vuZVI` zem;cGC{bv&n1mW^%luW(e3M_pL+I8us8?z7nudF>JtLf3d<{3%40$qib$*2M&c&sH zLHH^Ni-_?kitOG9_gmKo5o-DXE~54aW33A(As%)0>^95WDXz50a{IHnaC0YPlEC)R9;6L~nFl2zD6l`L@%?3|bWI#J8oE_+aMZ1%zz| zaSzk zaU$cAq-Gdr>Y5^JA&AX)ySTe+wIE1KWMMbLb(Ks)!! zeS2>&rS(CVgfCg+^Bwu_Xt7l}dTYs9XFq+iqEtZpzDB|yy3c=d10mSp&5NmJdam-y zLeM0yFiT-mpJPbfOdr8R*9D;{uYeL>C+D>KXbpdB>#to{$Z&~VEceA&d(YV2H9x3@ zoOa8aHL~f`TstEN2l{fK+v8ndWF%DXcBt}G_%Ai+&34gyxD@q=xr5%7bDkR9k)GwR z9x`}%H{6LXuw~MBNor9j-`F14(C~ILnihg(hO;G>{0lkwxIpghyGelo*Sp3>ju`2R zw_6i@hPJ6$Sy>;v)*r5cY!HjtY$>SQ z*_nVlRg)>>5C)S|f3|%B?jm=!N4s})yFe2VJ~gpv7~KyFq2ezYs=_73C(160X-Dpc zuzz^wn`B$!A5E(6p1A(o811NwY~=RhT2SPlQI{BD#&Ool({p;*BStwW!+e8`)^f(O zwGxAqNyGV~sv+5W7TR}p%fhI^5v(*jAqiv| zU393_JG67p$!aEc$sTq&slu=kqD8qLt!lJm8;ZXW-`-`SQa)Zo)7Mtfj`FR#s|_Yf zZSjz#HF>w53%>U9(LHhlT7c+A&2dVbF*v z$b5ln)2cm+i4%9Z>=#o5=f;<;?e}XpvVs6J7v1U-9l!>eKtmO6b6Z86aX~}sVpKbY zu#@~08_FC@wF^~EoIU7AlHuh3-Ej$U`eswsz!EOfb8aR_}9S{Sja#U z-X_;kM0sRJMC~ljD+yvtc`gnh4#^7QMq$*Q4A-C$ccwJCZzOTv%Dzpj#pvnBUl9ob zy@9~~(}N$cQJ<_Ktq!e_8bfok09(MFjjp3m$qNpDf|7+2j&TD(JKeUsdJ zKhczQ%KpVMOp56&iQK@(b&1s3q^3R?a7(@}sln3X^+T5xOp!>YH)5ryXjxE6)g1S? zds-vB-=9w0NVPkiks5!}bt5o4=o1`is zNaV*#{TNoY*|Z*ub!+8P7r5kYv9va08inig7t3xHElSyl)g-aef|4cAyPW&@0J}4j zllf=Ao)dpRI@i?N+waKOvQCg}WrA$Wf$7cZ%j2i}>)s)Kb)!xV@W}{^L&x85Kd?U< z7CchVB@cZlcuw*us0cOH8;&a~&Ni(wWELdWX`5FocQm(BtGW3YTkwT}qjAm!_TBAf zK*xelu3&hi3a9OBRJ)(PXHwX5wp>?bmaYChs ztGUAxk3Y_B7r%&-G11=Bm_l))YIbE*V@L#U;%0{~h>B$#+~YC%Us*u!p6l0wn$>Bj z*)yVa5b}f{=}uL%8VAPRV5ARuJhBMjZPseP>UDl6q- zbO5?E1IY4D*6jPZcXo_Ew1u}v0w$K`mj(m`;ro4m4suvH)?6HZY5Of^wl)M8{F5xQ z-xZlLqCQ|eH>Ndmm_u_M2nl(RZ9}eHpX36WujzwBiDehSfD%W+p3t7siOh^l!rP5u zyZ&A#l|##nLU@h8_<&K=+JkAL8Yt&n!-iNeoHg%O7Ml+ldnx#?$U?v4U1$T}!Ddn- z(k(keWG^=BxzT6L8iqC0(%oa7@)IC{CHCAL{<3_~h>T|F<=d)R#eMCm`IdBA55MGyf zpG(OM%TC0;2kPTIA`6n@A?>#t&FQNz;t20$Wx72W%l8dK9nRx2=2>?ojjfZq{11~z zJp^yxV+95RmqP~7#6*h&!7!zA+px+JO??{~Yb>|3w_I>JOS?1{IPPIq-Q>d8dqkl+H zo<~LfHsxl5hQ*^BH&~5ePlkEu?!q}~Va9va#?F?13tyE3r`3na+@%c( zp1#1P7E`ye$F0nYYr6|Q-QJG9$iHQcN$;?X>6F>9gt;dcBW#Adl_}ug`r@3%*(k0h zm+%1-iVDWUFc*)RUC35iwn~g&pw;plT+mw)^VPs4`7cp=GB2C=#u?ht`9fuKW&DZA zw+FF#K5y7)WPaHW6on;3NMvrw;IXC@zu^`(R9)SNU%Hao4&Fv~ik>&f z^;~>9V4;Lr_3v^uerfvM?rnfE{#I^KN<^{5O3V-evKW{WqVL_2c|{UDp3RVRKo)S< z?aNy{-nPEZ+qQFtO~4aeJr9PNP0)D13GxxH(KcF=dx$Z$23VYSInv-h3!9H%qo6Ki zRv*t--}g*!!1`I@-hK<5+)}njc<+b9-rDielUwkJZstrZJWf!YSa(rbpZyLrM3B7- z0{lTme`PbbMI-%5-hA5n!F?C$@%_t*N;CebnF65rppZ9C{yXo$1)RH;^F8m}XFL{3 z?Dne7sI?x;-(4W<+wu><#8(`oeMb=b|Q5LNI~Dzcbp>4XznSQp8k z4HBQREtS z0H6O^GdMA;tUVRjd)ST?e-NxK+XjuJ7JXTv>t6_BDRLontkmR>ZrV|$=d;44(3_|E)|Ea=B*6)1x7Z;wMtu`&zm0D ztuqR1L-uzfU9e8AAEDDz$ye0g-!3vk)r*x_jb6E}L6h_$Q|=Xu=7QQ|x%*ou=dhTv z{ny3E@0W#!_K}9#!J@e!el0$tfHdaY_h${0J4?*IH0w~PDw{Ip&Zft0hnR1#(u6cK zre`9N)|_pgoaVLq)pVUTINPs3lw~bfvwR+FmO7s*r|oVl3TbGz_Fac>#=AR;gB4jF zkKjErIML{%P?HQiJ7o7K{}DZ#e0q;a_EqsB)ta|(2Vh$CX7{Nh@VMw9mPsp68@lS# zP{DpPF#=44=9OBFv@l;MSI7CV72b4}dnKZ8PR5q*gq`GN1YbH0nrkDo31nL%WgKZXQw$Xf_;@{af6gdV0>?&nCrHIR1;79_vYud@OP|4 zYn{mZ&j6!Wvt$3PD+UJFMedl3fab2J6g?Cmh+V(d@uGvF?VJ>J2`^`@OZb?$9r2W+ z;$aBZPm#jVYX z{!%--_&l{#%Sye}`gV3Ca&T#LcP5&4{F4VDhm>h#lE3FU;PfTO#*a$*uw>IoyzXgn zGTe8EL|HpRg=fy0N4+niQ(QNz$#~~HU^ONf7^=S1QNkrk36gZMhbczTyzRG-OBuNg z3;58ujCxv!Q*m9R6-hVTgtYk;zs6tMDZ}1`ghEx!5_|9Kb`krWiEqMW?eRnuCy%Qt zQmWB0jOv=fTN0b9jXf+%4$HvbYQ=`JagTo8K37#7Eyv@@d)zKzm+i-=0Zg}8NkFeb z5U=@Gg(q+q*dp4l(PD2dPOWUl+CU-97sL?#^hF*dZge}-f~i}8zEQ~BB*CxD;^buc zD(LFc2faSKNkCwj;|M&Y1XNme+T&+2Al-$oM%Zn0>=_$}RGRPJfqX;!RM@Q)uSAgr zzRU~)4Hj$?^f;A>bl@5umJP2_E%#0;Z|8xvNBe)g^OAk4;*9vG5+nMn5Ql|-Dz4eu z1ciBMIsg}YN2#_Do!YhMw#l9p#2L(gfsX9{OGedh+}Y$e--Y78SGDR z8<=_iSV|)7Gn<_9gL-5DlYO$BXXCacFOOvJ$NkPylCWZ0N~cz8vtT^Zez9l__4HsB7AeEAx zUQ91p-(kDYXog2DUSVck`Vq2RGLSeLztICWcl{L^x#>P-#1jRZ?2xxEX$Pxl^w!3U zXxMWdkCoxbrX4Y}FqjqG{u*MU5q28?Q7+VWA8jyUIr7@kx4XZv?E7*PXwY)Lfe{D> z11M(Hl5^NvZ_iWCoVpDRyX77xpUnH374$`%k|T%-<8D`r?=AiI^mG(!0} z|9Nu#M{wc)9)=?8m!{RoNXtYaFnxd z7&NqYi%N_3@@l5imwe-}(XpJ{_bx`rYl9%>IcJMHntrxDuk0VXI7y!CbmDKv3Aba*i9&m(={_>JdMA z0=l!wKjbH+xW*;~KQ|2?&^Q7tD?Ud*T3njm7&4x0(KQ6k)!y5b)-ozBH^BEP+|=>u ztDrL$_H$|))0D23S*X@O@wN7qdfLN)DFq zt;7lv-{i~$1o`@B=bR*s4GCVBSFm^S)1Qgf6;RlsyB9QA(0R;X+`56y-y8d9m5`>Q zPc;luQ$xInDmR)D|Iyd$Sz2Jj=oX z%IL%Rd16Ge>&oJ{k`f6Gol}zsN~M)Ee$@lO2rSf7eU276Dh^4NB)8v*`X=RK=|&}9 z2}3hEF17Du(;I@}Y8IBcZbBK^MJ%X8cNy}Zs=s>xL^rdOmc{QKw<`F%%UO-7UuRb~h_19G~|-4zy1Xw(jaOVSF&3 zxv^N1j0LxwF*|2pS|zWKtfc&iE-0cmC~1i(`y&4ZVYQmAUjYOl->h_=t6e6UGVOsD z(KJf8JYlxvB=ugIG^LDebky{5%=+XuTDg>gb>ke{#ovhvhl9~wA`e<>72RkE81?Zk z!j$xHYAVa>**SR2GY^vNUtd@HK!w#_J#}sWoi5`kf^=j?N~>nI11)zATV0w2JMee- zz2yeZ&~q2%%OZt-KDx~hzpDr?x*Zn-73lP*jbohESq#Y6bJJeU?q0!00un*IA4&ez z-%uW>`)=E`yO&^;K5P%!G36b6n4^IBn+?>92~W?B8x&eRbK69SS@7HS7pQg=4-Z!1 z#~QBh73AdK9n|N_0AE<+wWW6ASHiAu({VF%tdY&F-6ucj|KeR-CNfo~c+QSAU-?>w z=G`zRr?Fl1`B~2OX@$8r=-R)a(oW%4Ng#?TH~hgB>f-gYG*-+v|GI~+*E7z&jR5pr zeC=aij3P>@Jwn1jTpL^nKiN*J7zK!VVJ z1f;UeU6gG0Udw-QQa<_!sV;WoHx!wwMsJ$2O9yom0Ym+sZ+a1LyCO4G1|3b;($h~S z6hW9C=0i^8h87Eu_H)2w6v^JI^?5j(jy_0J8+o-|mw)%=zZITcAq2mjKrV1IP3{P zf;kZil8fD$F`4ITOTT=Do{koXW1&Ys=B?l z)0Qad8c#o&Q^aN4!ldBAskz{C=2d2MH2+kzNtyfmZe|vq=Z2q;9PP>V zmMidjl;h4cXGNh$iWI1=%m_4(ara_qw&@F=Xt^TDH|Gt^1>aOk&Xr@p@Ni+{XaEZ! zn{~SjS>q{kag>SSu1q;jAUFU(P8j5cqzu5vy|5&!(>r)aG9D(3f;?d`V#IoY2XCU( zF$H=+vIARsr*52nF@>5nQ`tdG3kn^1QZCHGRS#541(qDFX1MbEVHN)Jbc4{s>5upK z#4pq=OPfb(nFZRs=Q@%u-6{=q1sNe4l4p@`q$W?g5>u|% zG3yu}<`(n~^=s8C1@o-_h`kQ1SeOgc0S);2_PTZAO~sphpJXy!-oC;-JqD<_R;@gi zhPFk?&OG8}!WE)F9YmfVeOS8Tml=PzzkkO9`6n+x%aU+Dx3lt1A@hN&4@EOO=vTt7 z=V+My>GSZ2bT}s$Z)am;CP!jh+kMys<{5|SX@fVXji0RAsBa}-y(lo1GN0>pGa2&# zlQ!1N&x!d&jsR+uKQA?0_eha`BIW((QC5G^bvotwQ`yDrs$n!iwHDRgJQcAqvlm)g zQsQ^N`WD!1xgW890K2%9{a&Z7@Gp}9j=uJ9W~D!~Rxq8d4#S^6hPI^EuwI?j9TSV3 zafr89f7<_{hk=fZGv1n9_ylI6?bB5-61f+m>_SdY9j0!m_FQA^K5)AxwCZ~+Q+0A~ zIxdo(W7jAwcltUK0$T3w3hvx{e*+ zW#?SLJoriZAORLyU4NnfU0)yhfp>J+5_jQAB4~)#-9sK>$`KNw{l0h!G_i^6aGt#* zNG+dXLRN;z=*H20O((_36@MAu^GLb55xFdqPmL(d%?fojJd1V2sReTBFDm7929sVl|ICwf>tgCO(10xdwsF+> z^{RJ4!^DBU&ZXJw5Jh=H^egrz7A?}G{aZn%oXw~&*Oz(N&wJX}P6`Z3BM_!SEoEb#<(sH(R#U zZtZ*rZ``66dZCw$k4KiCa{d>~kY>x+B2VTVg|&s}#7P6OE7#(?(cP;DCT(bQ(8D$r ztKr9gjBE?-=Wi4KA|JTXlrEZ=3S8;?%=^Z+cfAxO&|1x2ob22d!!D-)r&}pwkxNAM zv#<%QE^xptX%tPYyVRN;wJ@Iai{X5`@fRq`hn^XYJP|OW+9_OlVGwiSr0y6 z-_uXtMa3t4W-1k%hzL3oV@kjWUx5iS7Kd>W(B`$j6BX#1SsUA7SYXoZ1G}78@jC2Z z>&@eN9zn0=K7QIaqIcu0_eJYfnMgvzS5Rh!r+tQNC+#JW^)Cz6UVW-XH$lI$k~^m* zUWc0YKm+w=BSj;oXq{Uj4q^|W+TV@J?SsDj@LgRpT*dp_a&ytLh4Zod;=){;tbfPt zkq4FG!ZmyG9ej-;jQjy@{ZQ{-mc`L7j#LKO@?lceP7*Pn%(yJ#^6$ZZ_M9l0 zB_SeTe%ng^lwV*~H`kG72=k_mM^dRBxE{9Gm(AmVjmE-OS{-ROyR9AW^VgB|8=F@; zcmj0hXhyc%5+|mfS%iX9!GDt-cw%HMhDU$O=8}C zq(-Xt@$3C=VXN?eQPFQNBGp3|a7$0MY~I04#_KCC;Tp(GGCJTgnrO#G+Rvqg9P!TQ z$17QLMF>tFlc2u9;=+m3+y3gir#%Y(-pSmIJ@d&mHKhH$t9#79lYFng3cbeehP^MX zdjAs5jt{dh9bihnXGSxXEuvULy>)U8B;ntC?K}%Eu4UnL95|?X`AKVNACV^UeCF+G zw;#Q4VFQjKMG$6kh1A}$&5P^DS?$aEz&G+l^vm9vxfQ}}@(cm)1wD=OkQ3uO*mf++ z;gYcs(ij78SUg6w$kcMIEfXH0*8)FE)v!&MFV-^=jMgQizF8l`Ag#sVOTAmix%FLJ zou;q6px|0dhgyq$Da^oAc?dHe=~4NOHK%0nTL%lF^s9g7B?w4YBs=fSWk@17t{@7l zpNDBsQk!qmZS8(@5)PBNM(T|rx^lzdX%((!V zVK2ZKYH{@yJK@A>u{jJKBW)Dx%!LY!5Mwz=P6*vA(oR!oDjQ>&>0@M5e4@3hnCe7I33D(L$6dwjwmyK_0b2PeL`VLPQAEz`3`k%a^N}TY^SqErpac;w$>Z#>& zN=U^Q@8i<7grU4r%8|v}lI;bC(-MvH2qF99%F|rp4!?noWq!*1m(z zeUqS(drac5e*(wLc)B}z4|oDs&6md+toYKQL-XXu0>E58xR@Ev;RBWSo8{I1Mhu;R z-$q#p6>_P+tof~>_)d{J%p`aZrDCg*+vdmbyT=%S$K_uQCga0Ho#vp% zFQ*0o*}MKn#v`JbggQ~^F5xE+%Wo-}6g6DmO=c@61oR^uWkSJE6|H4kk*7Z5xi+(~ zv{J8yMIQyjwm(_PJ6bEC{)*j5hu2nKkmKi*5Cf2&uZdInOiZ~Fq339izuasLM@xZ{ z5z(LeP`N8I~mG)t)BV|)dXI^+PRqO z#q+|Nro#f*apbtuS}rigAmF(rucO9@h17@XO>Ss-`u3cya)PHlej*WVm2NvQFy;HF z`d`Fzwrk|G7e4&B-ula4=?OMvy*~$zOg4RqG6uF*9-`dO9A*1MW1kKSxAE9~BW@5n zdtm465YMwXP-I(ltjRIZ=_k-ai!Y5b+7RTk@h-7$yk0|znT5H(dtCd!vVa%>Yg2Uy zLv5vck_ZBc`3m>-a{ya7pG_~V_6@c-tDt@&S8;3s>Q=1(4X#~g$mEA3qK_NXce5i4O;<^$5lzsl4gjejo% z(sihWFiz`SItf5Y>LHxXSKz4+xw#B~_9CGKQK4I1`Y!C+PjQVA7IXDkYafp73lg=p z%B7SDb+k)VySs2&5@^{K^s>%ue*&yEs~r?|&VB;1TO(w~uv)*?yDYsrJ}KVCtIs>t zj?d-kzZsWZz*VaulYr7NEwxg#l|8C$^9;%6BJP35T9p-Fn1I^f3e*i-}Fa8keW6*7w zE_z=|3N?31#Y#wD?eC@4xBfR&4Qp9j@>aq~3-fN_8zuH0y@wEO9H#R>olsI!;m7FW zJ;nzKdZLiBZSB;2a1C49Re1Ree5eLrJQ}`ywCI6z@H3IwnD{o$u!hq=;RxXCbo98XYNFm zvS7GM=_zDkEs~J}o_BDHk9wt68&9T5(;+N2>4M$}Zfm9^0exi-E zjlW1|{MN6NAWx|e6M2EF35BZ0_MXUCPLnSUNE9|QriR{Tn%~+gwbVI6Dv0a651Q55 zpzP^Eud|=~wlosXed?1`hdl3ZG?$-k`)~8CuJ%>cwcds?Q}O)~E1eHnBSQeYOc58y zL%Ag*az;!ei#ak#SJPDeMq#E{){lA~rGRTt>kEVH-?bP=+ul)`6=WkTYqZZeHwgv$J_6rv^XJt zP1L35qzyYYSA7+6N89_@$5RB6@xJTut!OMDs|{~#M`qLPW{>9s z*E33`b%%$yKR1xUEkJMTv6V@_f=Qkm_IaY2hmY%%i!{XOqQ9i$L)e(NNObCbQcMdQG7DyB*VKvY zF0I3Ny8P%Kzp)N4-WQZH#bB$M`idzn{Of8!q`p#bK>Yzxigj<)=W5KFe)! z%rh#f9%25_*g=}VgY&))b<^_*RmHTcMjwpv)DuO1=jY=W6>YkR_s>1Nal^5om7ly9 z@8U_>7$c1G@@ZFGh024j^j5K@d>|v-_{F6b@^sNQl%vtFPClV3p^;I zXNialrt_sy$y;=%T?m*R9uj>ZKjf19t*^|_T(FxhZl9!ZTIvGzHvb|v^$0kw(c;qyx6Oj&^*zh~d(Q2h zBTNWcW^kv6vl*`je`HeDOfq7EYfji_l)hd~UTg~JRIlfDAA77N%CIe$F@{>UT&!#gMWWBBOFP^r z!JsR+)zIHZ$tYGPh#-yK!yBqNKaJD~lgH#^NHBKbjP^Px#Fgk3ra&V5ABkQm^yB(^ zEwVyGsso@QrmgXtz<#$v!nQ{B$_o3hxCu-Mn4q2^ggcE;BRrfH^Zgek#i+EQs7~wn zj;-bV7Xp75>=8%JCe=Z#NvRMauh8o6n5n;JoZMkNH*%8j?(CKhJ5{=x8azLzz#X+X z+RVgt+7Vm0GFAL}Vn|&eO!;iqNL+Cn7nawkrKLha3-)}gp#IH@#8`msPfy}w{s(yp zab-uPi7psJJ?NgRzZuiuD&RM8dN-54{#Rj}4udtZHxSsI^8Btm2Z-V-X|g}`k0q8u zQQ>6y?Oqi50Lo$Nu&A@aIK-PspP1-L*bxopk5KTW64u@0GeuL+bu+Lf+XU#Q`uid$ zj4YT4Pg@d2+Yn0+aoe@|<+pP?q}*Jae3@~p2!AVGw}t`di?81@R5}@|wgI-9XeUx2 zUJEL@{sAOJ3xVso9KD06dYC)`RBTUMB80@o7zfwG0V z1$KkoZ>xvyPQFOrda<@f;{aID1?kdkPQ0~%TXdEaT~{BZ9W2fIA)mSZ%z|34YOeo# zK%Lf2@ZSMyLGA4(c=l;V98=S7QUNKi_6k~087V1`pZvx#H$H*wIcMlq@dSNcVLiaJ z23WL*CMm7po%EBsB=C#BzuczKxwr6=*GMqS)E#2 z7xLR;aLkiP$~@<%lUd2ps21ss_VKUEDxpLiFvE{@@Fo){ha0x;dBcREU_rXxwEjz5 z?v`TjP1TbQ$TM>#=jjDhUx-~*PUtmP^RM0SxwzyRL;nEVcn)~%iQEc^{;C`h2k7eA zJz1i_dwdzqM>=lJF&4eqHZr{)1YeY?aj8trzV1pTC7Ky`vW_Rq+%s6eI&d{qHPb&a zsqX_Cfu8sV$#gsOoQvnY&yyMSB|VYXpIqNNQ=<$WNPWuVkhrH%EdDIoAk2H+gs7p8 zH$1=D)-EdAPPTQjZt^X{(n2$k{u9OB=)c_!rt+{Sl#5#3T9k?NYA&;e~T zG7)1`wbA1>mfuh73pv77?V5V3J2!3YZoF5n*NMGV%^bu#Zcv=`12O>jP|u{IF<*>B z%!}S4s`8p@?Q&4t(@M~fw@(`NmCtp+_}iO^JuiQ@02bm8S8~LB{Qf<@AhKj~d(UTE z>Ke0Y_veroZEC@HA2UQpZ;StULL>6Yax_yNndnL>C+h>-L5TU`zNHiOq`$l3`pX@@ zGHAB=>l)yBrgJZ>6vTjY)}DHOHUuBw>6RnCYRbpI7M>=!3(FW;zZN%P(e|AB@ezI< z_p{UrV-^hXU-Z7YL$J$C)SE`<%^$NgT%c3^fYNyxjU+Gt@B%Gdd*786ITgMjM ziSiT-r_s8-W4A8PSlQZE9Z05=accj1vznsp_5ERDK_8fJXE#XIyEz`$7#S0*sMy>4 zdm+Ur-a6-9paA6W13t|BgOtJ!<$pCPO@}RcpFp9RbaX zj6`5r+5nl5^ZFm6Qqcjd?rl@FXXk0uAJ6j!;F1CJ7t9I1b3yaga2YcQF0wp#IZA3` zK;r;nqD5b|N_NIaJk{;`Jw9BQFu8Kgg!B7RtfaJ>>vA5n-y17YTyB0xo^*Su*0==E zM3&uk0~*1(fiyu^IB=XI44 .mx_SpaceButton > .mx_SpaceButton_toggleCollapse { padding: 0 10px; margin: 0 -10px; - transform: rotate(-90deg); } & > .mx_SpaceTreeLevel { @@ -166,109 +159,67 @@ Please see LICENSE files in the repository root for full details. } .mx_SpaceButton_toggleCollapse { - width: var(--gutterSize); - padding: 10px 0; - min-width: var(--gutterSize); height: 20px; - mask-position: center; - mask-size: 20px; - mask-repeat: no-repeat; - background-color: $tertiary-content; - mask-image: url("@vector-im/compound-design-tokens/icons/chevron-down.svg"); + width: var(--gutterSize); + flex-shrink: 0; + padding: 10px 0; + + svg { + width: 20px; + height: inherit; + display: inline-block; + color: $tertiary-content; + /* Re-align with parent */ + margin-left: -3px; + } } .mx_SpaceButton_icon { - width: var(--height-topLevel); - min-width: var(--height-topLevel); - height: var(--height-topLevel); + /* Calculate height excluding padding to allow svg to inherit */ + width: calc(var(--height-topLevel) - 14px); + height: calc(var(--height-topLevel) - 14px); + flex-shrink: 0; border-radius: 8px; - position: relative; - - &::before { - position: absolute; - content: ""; - width: var(--height-topLevel); - height: var(--height-topLevel); - top: 0; - left: 0; - mask-position: center; - mask-repeat: no-repeat; - mask-size: 18px; - } - } - - &.mx_SpaceButton_home, - &.mx_SpaceButton_favourites, - &.mx_SpaceButton_people, - &.mx_SpaceButton_orphans, - &.mx_SpaceButton_videoRooms { - .mx_SpaceButton_icon { - background-color: $panel-actions; - - &::before { - background-color: $secondary-content; - } - } - } - - &.mx_SpaceButton_withIcon .mx_SpaceButton_icon { + padding: 7px; background-color: $panel-actions; - } - &.mx_SpaceButton_home .mx_SpaceButton_icon::before { - mask-image: url("@vector-im/compound-design-tokens/icons/home-solid.svg"); - } - - &.mx_SpaceButton_favourites .mx_SpaceButton_icon::before { - mask-image: url("@vector-im/compound-design-tokens/icons/favourite-solid.svg"); - } - - &.mx_SpaceButton_people .mx_SpaceButton_icon::before { - mask-image: url("@vector-im/compound-design-tokens/icons/user-profile-solid.svg"); - } - - &.mx_SpaceButton_orphans .mx_SpaceButton_icon::before { - mask-image: url("@vector-im/compound-design-tokens/icons/room.svg"); - } - - &.mx_SpaceButton_videoRooms .mx_SpaceButton_icon::before { - mask-image: url("@vector-im/compound-design-tokens/icons/video-call-solid.svg"); + svg { + width: inherit; + height: inherit; + display: block; + color: $secondary-content; + } } &.mx_SpaceButton_new .mx_SpaceButton_icon { - &::before { - background-color: $primary-content; - mask-image: url("@vector-im/compound-design-tokens/icons/plus.svg"); + background-color: unset; + + svg { + color: $primary-content; transition: all 0.2s ease-in-out; /* TODO transition */ } } - &.mx_SpaceButton_newCancel .mx_SpaceButton_icon::before { + &.mx_SpaceButton_newCancel .mx_SpaceButton_icon svg { transform: rotate(45deg); } .mx_SpaceButton_menuButton { - width: 20px; - min-width: 20px; /* yay flex */ - height: 20px; + width: 16px; + height: 16px; + padding: var(--cpd-space-0-5x); + flex-shrink: 0; margin-top: auto; margin-bottom: auto; display: none; position: absolute; right: 4px; - &::before { - top: 3px; - left: 2px; - content: ""; - width: 16px; - height: 16px; - position: absolute; - mask-position: center; - mask-size: contain; - mask-repeat: no-repeat; - mask-image: url("@vector-im/compound-design-tokens/icons/overflow-horizontal.svg"); - background: $primary-content; + svg { + width: inherit; + height: inherit; + display: block; + color: $primary-content; } } } @@ -341,18 +292,6 @@ Please see LICENSE files in the repository root for full details. padding: 0 0 16px 0; scrollbar-gutter: stable; - & > .mx_SpaceButton { - height: var(--height-topLevel); - - &.mx_SpaceButton_active::before { - height: var(--height-topLevel); - } - } - - & > ul { - padding-left: 0; - } - &.mx_IndicatorScrollbar_topOverflow { mask-image: linear-gradient(to bottom, transparent, black 16px); } diff --git a/res/css/structures/_SpacePillButton.pcss b/res/css/structures/_SpacePillButton.pcss new file mode 100644 index 0000000000..eed2feb48a --- /dev/null +++ b/res/css/structures/_SpacePillButton.pcss @@ -0,0 +1,48 @@ +/* +Copyright 2025 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +.mx_SpacePillButton { + position: relative; + padding: 16px 32px 16px 72px; + width: 432px; + box-sizing: border-box; + border-radius: 8px; + border: 1px solid $input-border-color; + font-size: $font-17px; + font-weight: var(--cpd-font-weight-semibold); + margin: 20px 0; + + > div { + margin-top: 4px; + font-weight: normal; + font-size: $font-15px; + color: $secondary-content; + } + + svg { + position: absolute; + content: ""; + width: 28px; + height: 28px; + top: 50%; + transform: translateY(-50%); + left: 22px; + color: $tertiary-content; + } + + &:hover { + border-color: var(--cpd-color-bg-action-primary-rest); + + svg { + color: var(--cpd-color-icon-primary); + } + + > span { + color: $primary-content; + } + } +} diff --git a/res/css/structures/_SpaceRoomView.pcss b/res/css/structures/_SpaceRoomView.pcss index 7f00386b85..589e30b515 100644 --- a/res/css/structures/_SpaceRoomView.pcss +++ b/res/css/structures/_SpaceRoomView.pcss @@ -6,51 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com Please see LICENSE files in the repository root for full details. */ -@define-mixin SpacePillButton { - position: relative; - padding: 16px 32px 16px 72px; - width: 432px; - box-sizing: border-box; - border-radius: 8px; - border: 1px solid $input-border-color; - font-size: $font-17px; - font-weight: var(--cpd-font-weight-semibold); - margin: 20px 0; - - > div { - margin-top: 4px; - font-weight: normal; - font-size: $font-15px; - color: $secondary-content; - } - - &::before { - position: absolute; - content: ""; - width: 28px; - height: 28px; - top: 50%; - transform: translateY(-50%); - left: 22px; - mask-position: center; - mask-repeat: no-repeat; - mask-size: 28px; - background-color: $tertiary-content; - } - - &:hover { - border-color: var(--cpd-color-bg-action-primary-rest); - - &::before { - background-color: var(--cpd-color-icon-primary); - } - - > span { - color: $primary-content; - } - } -} - .mx_SpaceRoomView { --innerWidth: 428px; @@ -242,20 +197,6 @@ Please see LICENSE files in the repository root for full details. } } - .mx_SpaceRoomView_privateScope { - > .mx_AccessibleButton { - @mixin SpacePillButton; - } - - .mx_SpaceRoomView_privateScope_justMeButton::before { - mask-image: url("@vector-im/compound-design-tokens/icons/user-profile-solid.svg"); - } - - .mx_SpaceRoomView_privateScope_meAndMyTeammatesButton::before { - mask-image: url("@vector-im/compound-design-tokens/icons/group.svg"); - } - } - .mx_SpaceRoomView_inviteTeammates { .mx_SpaceRoomView_inviteTeammates_buttons { color: $secondary-content; diff --git a/res/css/views/right_panel/_ThreadPanel.pcss b/res/css/views/right_panel/_ThreadPanel.pcss index 2a282388eb..a5a6540dda 100644 --- a/res/css/views/right_panel/_ThreadPanel.pcss +++ b/res/css/views/right_panel/_ThreadPanel.pcss @@ -47,16 +47,12 @@ Please see LICENSE files in the repository root for full details. background: $quinary-content; } - &::before { + svg { margin-left: 2px; - content: ""; - width: 20px; height: 20px; - background: currentColor; - mask-image: url("@vector-im/compound-design-tokens/icons/chevron-down.svg"); - mask-size: 100%; - mask-repeat: no-repeat; - float: right; + width: 20px; + display: inline-block; + vertical-align: bottom; } } } @@ -181,25 +177,24 @@ Please see LICENSE files in the repository root for full details. } &[aria-checked="true"] { - :first-child { + span:first-child { margin-left: -20px; } - :first-child::before { - content: ""; + svg { width: 12px; height: 12px; margin-right: 8px; - mask-image: url("@vector-im/compound-design-tokens/icons/check.svg"); - mask-size: 100%; - mask-repeat: no-repeat; - background-color: $primary-content; + color: $primary-content; display: inline-block; vertical-align: middle; + position: absolute; + top: 14px; + left: 10px; } } - :last-child { + span:last-child { color: $secondary-content; } } diff --git a/res/css/views/rooms/_EventTile.pcss b/res/css/views/rooms/_EventTile.pcss index f04afccb13..8b9a8f46e1 100644 --- a/res/css/views/rooms/_EventTile.pcss +++ b/res/css/views/rooms/_EventTile.pcss @@ -833,7 +833,6 @@ $left-gutter: 64px; background-repeat: no-repeat; background-size: contain; - &::before, &::after { content: ""; display: block; @@ -844,10 +843,6 @@ $left-gutter: 64px; mask-size: contain; } - &::before { - mask-size: 80%; - } - &.mx_EventTile_e2eIcon_warning::after { mask-image: url("@vector-im/compound-design-tokens/icons/error-solid.svg"); background-color: $e2e-warning-color; /* red */ diff --git a/res/css/views/rooms/_RoomPreviewCard.pcss b/res/css/views/rooms/_RoomPreviewCard.pcss index 61afe0d92b..7ad0f20e79 100644 --- a/res/css/views/rooms/_RoomPreviewCard.pcss +++ b/res/css/views/rooms/_RoomPreviewCard.pcss @@ -22,20 +22,13 @@ Please see LICENSE files in the repository root for full details. line-height: $font-24px; color: $primary-content; margin-top: $spacing-24; - position: relative; - padding-left: calc(20px + $spacing-8); - &::before { - content: ""; - position: absolute; - height: $font-24px; - width: 20px; - left: 0; - mask-repeat: no-repeat; - mask-position: center; - mask-size: contain; - mask-image: url("@vector-im/compound-design-tokens/icons/info-solid.svg"); - background-color: $secondary-content; + svg { + height: 1em; + width: 1em; + margin-right: $spacing-8; + color: $secondary-content; + vertical-align: -2px; } } @@ -63,25 +56,19 @@ Please see LICENSE files in the repository root for full details. align-items: center; .mx_RoomPreviewCard_video { - width: 50px; - height: 50px; + width: 22px; + height: 22px; + padding: 14px; border-radius: calc((50px + 2 * 3px) / 2); background-color: $accent; border: 3px solid $system; - position: relative; left: calc(-50px / 4 - 3px); - &::before { - content: ""; - background-color: $button-primary-fg-color; - position: absolute; - width: 50px; - height: 50px; - mask-size: 22px; - mask-position: center; - mask-repeat: no-repeat; - mask-image: url("@vector-im/compound-design-tokens/icons/video-call-solid.svg"); + svg { + width: inherit; + height: inherit; + color: $button-primary-fg-color; } } diff --git a/res/css/views/spaces/_SpaceCreateMenu.pcss b/res/css/views/spaces/_SpaceCreateMenu.pcss index ca2a2c8fc1..8bc7f6e3ad 100644 --- a/res/css/views/spaces/_SpaceCreateMenu.pcss +++ b/res/css/views/spaces/_SpaceCreateMenu.pcss @@ -34,18 +34,6 @@ Please see LICENSE files in the repository root for full details. } } - .mx_SpaceCreateMenuType { - @mixin SpacePillButton; - } - - .mx_SpaceCreateMenuType_public::before { - mask-image: url("@vector-im/compound-design-tokens/icons/public.svg"); - } - - .mx_SpaceCreateMenuType_private::before { - mask-image: url("@vector-im/compound-design-tokens/icons/lock-solid.svg"); - } - .mx_SpaceCreateMenu_back { width: 28px; height: 28px; diff --git a/res/css/views/spaces/_SpacePublicShare.pcss b/res/css/views/spaces/_SpacePublicShare.pcss deleted file mode 100644 index b55c0e685c..0000000000 --- a/res/css/views/spaces/_SpacePublicShare.pcss +++ /dev/null @@ -1,21 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2021 The Matrix.org Foundation C.I.C. - -SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE files in the repository root for full details. -*/ - -.mx_SpacePublicShare { - .mx_AccessibleButton { - @mixin SpacePillButton; - - &.mx_SpacePublicShare_shareButton::before { - mask-image: url("@vector-im/compound-design-tokens/icons/link.svg"); - } - - &.mx_SpacePublicShare_inviteButton::before { - mask-image: url("$(res)/img/element-icons/room/invite.svg"); - } - } -} diff --git a/src/components/structures/SpacePillButton.tsx b/src/components/structures/SpacePillButton.tsx new file mode 100644 index 0000000000..0093e2911b --- /dev/null +++ b/src/components/structures/SpacePillButton.tsx @@ -0,0 +1,27 @@ +/* +Copyright 2025 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +import React, { type JSX } from "react"; + +import AccessibleButton from "../views/elements/AccessibleButton"; + +const SpacePillButton: React.FC<{ + title: string; + icon: JSX.Element; + description: string; + onClick(): void; +}> = ({ title, icon, description, onClick }) => { + return ( + + {icon} + {title} +
{description}
+
+ ); +}; + +export default SpacePillButton; diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index c1758a87c7..1df95439d4 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -10,7 +10,12 @@ import { EventType, RoomType, JoinRule, Preset, type Room, RoomEvent } from "mat import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import React, { type JSX, useCallback, useContext, useRef, useState } from "react"; -import { PlusIcon, RoomIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; +import { + GroupIcon, + PlusIcon, + RoomIcon, + UserProfileSolidIcon, +} from "@vector-im/compound-design-tokens/assets/web/icons"; import MatrixClientContext from "../../contexts/MatrixClientContext"; import createRoom, { type IOpts } from "../../createRoom"; @@ -68,6 +73,7 @@ import RightPanel from "./RightPanel"; import SpaceHierarchy, { showRoom } from "./SpaceHierarchy"; import { type RoomPermalinkCreator } from "../../utils/permalinks/Permalinks"; import { Icon as HashVideoIcon } from "../../../res/img/element-icons/roomlist/hash-video.svg"; +import SpacePillButton from "./SpacePillButton.tsx"; interface IProps { space: Room; @@ -455,24 +461,22 @@ const SpaceSetupPrivateScope: React.FC<{ })} - } + title={_t("create_space|personal_space")} + description={_t("create_space|personal_space_description")} onClick={() => { onFinished(false); }} - > - {_t("create_space|personal_space")} -
{_t("create_space|personal_space_description")}
-
- + } + title={_t("create_space|private_space")} + description={_t("create_space|private_space_description")} onClick={() => { onFinished(true); }} - > - {_t("create_space|private_space")} -
{_t("create_space|private_space_description")}
-
+ /> ); }; diff --git a/src/components/structures/ThreadPanel.tsx b/src/components/structures/ThreadPanel.tsx index 0657ab64c0..61386574ea 100644 --- a/src/components/structures/ThreadPanel.tsx +++ b/src/components/structures/ThreadPanel.tsx @@ -10,7 +10,7 @@ import React, { useContext, useEffect, useRef, useState } from "react"; import { type EventTimelineSet, type Room, Thread } from "matrix-js-sdk/src/matrix"; import { IconButton, Tooltip } from "@vector-im/compound-web"; import { logger } from "matrix-js-sdk/src/logger"; -import ThreadsIcon from "@vector-im/compound-design-tokens/assets/web/icons/threads"; +import { ThreadsIcon, CheckIcon, ChevronDownIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; import { Icon as MarkAllThreadsReadIcon } from "../../../res/img/element-icons/check-all.svg"; import BaseCard from "../views/right_panel/BaseCard"; @@ -57,6 +57,7 @@ export const ThreadPanelHeaderFilterOptionItem: React.FC< > = ({ label, description, onClick, isSelected }) => { return ( + {isSelected ? : null} {label} {description} @@ -145,6 +146,7 @@ export const ThreadPanelHeader: React.FC<{ }} > {`${_t("threads|show_thread_filter")} ${value?.label}`} + {contextMenu} diff --git a/src/components/views/elements/JoinRuleDropdown.tsx b/src/components/views/elements/JoinRuleDropdown.tsx index ac94112f2b..3ba27c1988 100644 --- a/src/components/views/elements/JoinRuleDropdown.tsx +++ b/src/components/views/elements/JoinRuleDropdown.tsx @@ -57,7 +57,7 @@ const JoinRuleDropdown: React.FC = ({ options.unshift( (
- + {labelKnock}
) as ReactElement & { key: string }, diff --git a/src/components/views/rooms/RoomPreviewCard.tsx b/src/components/views/rooms/RoomPreviewCard.tsx index 21f6e09a6d..5ddce5264b 100644 --- a/src/components/views/rooms/RoomPreviewCard.tsx +++ b/src/components/views/rooms/RoomPreviewCard.tsx @@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details. import React, { type JSX, type FC, useContext, useState } from "react"; import { type Room, JoinRule } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; +import { InfoSolidIcon, VideoCallSolidIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; import { _t } from "../../../languageHandler"; import defaultDispatcher from "../../../dispatcher/dispatcher"; @@ -152,7 +153,9 @@ const RoomPreviewCard: FC = ({ room, onJoinButtonClicked, onRejectButton avatarRow = ( <> -
+
+ +
); @@ -174,6 +177,7 @@ const RoomPreviewCard: FC = ({ room, onJoinButtonClicked, onRejectButton {room.getJoinRule() === "public" && } {cannotJoin ? (
+ {_t("room|join_failed_needs_invite", { roomName: room.name })}
) : null} diff --git a/src/components/views/spaces/SpaceCreateMenu.tsx b/src/components/views/spaces/SpaceCreateMenu.tsx index 6b881e33a8..bed090b164 100644 --- a/src/components/views/spaces/SpaceCreateMenu.tsx +++ b/src/components/views/spaces/SpaceCreateMenu.tsx @@ -18,7 +18,6 @@ import React, { type ReactNode, useEffect, } from "react"; -import classNames from "classnames"; import { RoomType, HistoryVisibility, @@ -28,6 +27,7 @@ import { type ICreateRoomOpts, } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; +import { LockSolidIcon, PublicIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; import { _t } from "../../../languageHandler"; import ContextMenu, { ChevronFace } from "../../structures/ContextMenu"; @@ -47,6 +47,7 @@ import { Filter } from "../dialogs/spotlight/Filter"; import { type OpenSpotlightPayload } from "../../../dispatcher/payloads/OpenSpotlightPayload.ts"; import { useSettingValue } from "../../../hooks/useSettings.ts"; import { UIFeature } from "../../../settings/UIFeature.ts"; +import SpacePillButton from "../../structures/SpacePillButton.tsx"; export const createSpace = async ( client: MatrixClient, @@ -86,20 +87,6 @@ export const createSpace = async ( }); }; -const SpaceCreateMenuType: React.FC<{ - title: string; - description: string; - className: string; - onClick(): void; -}> = ({ title, description, className, onClick }) => { - return ( - - {title} -
{description}
-
- ); -}; - const spaceNameValidator = withValidation({ rules: [ { @@ -285,16 +272,16 @@ const SpaceCreateMenu: React.FC<{

{_t("create_space|label")}

{_t("create_space|explainer")}

- } title={_t("common|public")} description={_t("create_space|public_description")} - className="mx_SpaceCreateMenuType_public" onClick={() => setVisibility(Visibility.Public)} /> - } title={_t("common|private")} description={_t("create_space|private_description")} - className="mx_SpaceCreateMenuType_private" onClick={() => setVisibility(Visibility.Private)} /> diff --git a/src/components/views/spaces/SpacePanel.tsx b/src/components/views/spaces/SpacePanel.tsx index 0b4b558482..fb2e4cc1df 100644 --- a/src/components/views/spaces/SpacePanel.tsx +++ b/src/components/views/spaces/SpacePanel.tsx @@ -22,6 +22,15 @@ import React, { import { DragDropContext, Draggable, Droppable, type DroppableProvidedProps } from "react-beautiful-dnd"; import classNames from "classnames"; import { type Room } from "matrix-js-sdk/src/matrix"; +import { + FavouriteSolidIcon, + HomeSolidIcon, + RoomIcon, + VideoCallSolidIcon, + UserProfileSolidIcon, + PlusIcon, + ChevronRightIcon, +} from "@vector-im/compound-design-tokens/assets/web/icons"; import { _t } from "../../../languageHandler"; import { useContextMenu } from "../../structures/ContextMenu"; @@ -114,6 +123,7 @@ export const HomeButtonContextMenu: React.FC { selected: boolean; isPanelCollapsed: boolean; + icon: JSX.Element; } type MetaSpaceButtonProps = Pick; @@ -152,7 +162,6 @@ const HomeButton: React.FC = ({ selected, isPanelCollapsed return ( = ({ selected, isPanelCollapsed ContextMenuComponent={HomeButtonContextMenu} contextMenuTooltip={_t("common|options")} size="32px" + icon={} /> ); }; @@ -168,12 +178,12 @@ const FavouritesButton: React.FC = ({ selected, isPanelCol return ( } /> ); }; @@ -182,12 +192,12 @@ const PeopleButton: React.FC = ({ selected, isPanelCollaps return ( } /> ); }; @@ -196,12 +206,12 @@ const OrphansButton: React.FC = ({ selected, isPanelCollap return ( } /> ); }; @@ -210,12 +220,12 @@ const VideoRoomsButton: React.FC = ({ selected, isPanelCol return ( } /> ); }; @@ -262,6 +272,7 @@ const CreateSpaceButton: React.FC} /> {contextMenu} @@ -449,7 +460,9 @@ const SpacePanel: React.FC = () => { className="mx_SpacePanel_Tooltip_KeyboardShortcut" /> } - /> + > + + {(provided, snapshot) => ( diff --git a/src/components/views/spaces/SpacePublicShare.tsx b/src/components/views/spaces/SpacePublicShare.tsx index c3a9fae562..4bb2bdb78d 100644 --- a/src/components/views/spaces/SpacePublicShare.tsx +++ b/src/components/views/spaces/SpacePublicShare.tsx @@ -9,15 +9,17 @@ Please see LICENSE files in the repository root for full details. import React, { useState } from "react"; import { type Room } from "matrix-js-sdk/src/matrix"; import { sleep } from "matrix-js-sdk/src/utils"; +import { LinkIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; import { _t } from "../../../languageHandler"; -import AccessibleButton from "../elements/AccessibleButton"; import { copyPlaintext } from "../../../utils/strings"; import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks"; import { showRoomInviteDialog } from "../../../RoomInvite"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { shouldShowComponent } from "../../../customisations/helpers/UIComponents"; import { UIComponent } from "../../../settings/UIFeature"; +import { Icon as InviteIcon } from "../../../../res/img/element-icons/room/invite.svg"; +import SpacePillButton from "../../structures/SpacePillButton.tsx"; interface IProps { space: Room; @@ -29,8 +31,10 @@ const SpacePublicShare: React.FC = ({ space, onFinished }) => { return (
- } + title={_t("space|invite_link")} + description={copiedText} onClick={async (): Promise => { const permalinkCreator = new RoomPermalinkCreator(space); permalinkCreator.load(); @@ -43,22 +47,18 @@ const SpacePublicShare: React.FC = ({ space, onFinished }) => { setCopiedText(_t("action|click_to_copy")); } }} - > - {_t("space|invite_link")} -
{copiedText}
-
+ /> {space.canInvite(MatrixClientPeg.safeGet().getSafeUserId()) && shouldShowComponent(UIComponent.InviteUsers) ? ( - } + title={_t("space|invite")} + description={_t("space|invite_description")} onClick={() => { if (onFinished) onFinished(); showRoomInviteDialog(space.roomId); }} - > - {_t("space|invite")} -
{_t("space|invite_description")}
-
+ /> ) : null}
); diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx index f2c41c367f..94ba7cff3e 100644 --- a/src/components/views/spaces/SpaceTreeLevel.tsx +++ b/src/components/views/spaces/SpaceTreeLevel.tsx @@ -20,6 +20,11 @@ import classNames from "classnames"; import { type Room, RoomEvent } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; import { type DraggableProvidedDragHandleProps } from "react-beautiful-dnd"; +import { + ChevronDownIcon, + ChevronRightIcon, + OverflowHorizontalIcon, +} from "@vector-im/compound-design-tokens/assets/web/icons"; import RoomAvatar from "../avatars/RoomAvatar"; import SpaceStore from "../../../stores/spaces/SpaceStore"; @@ -169,7 +174,9 @@ export const SpaceButton = ({ onClick={openMenu} title={contextMenuTooltip} isExpanded={menuDisplayed} - /> + > + + )} {contextMenu} @@ -349,7 +356,9 @@ export class SpaceItem extends React.PureComponent { onClick={this.toggleCollapse} tabIndex={-1} aria-label={collapsed ? _t("action|expand") : _t("action|collapse")} - /> + > + {collapsed ? : } + ) : null; // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/test/unit-tests/components/structures/__snapshots__/ThreadPanel-test.tsx.snap b/test/unit-tests/components/structures/__snapshots__/ThreadPanel-test.tsx.snap index f7487da90c..84ee81bdd5 100644 --- a/test/unit-tests/components/structures/__snapshots__/ThreadPanel-test.tsx.snap +++ b/test/unit-tests/components/structures/__snapshots__/ThreadPanel-test.tsx.snap @@ -34,6 +34,17 @@ exports[`ThreadPanel Header expect that All filter for ThreadPanelHeader properl tabindex="0" > Show: All threads + + +
@@ -73,6 +84,17 @@ exports[`ThreadPanel Header expect that My filter for ThreadPanelHeader properly tabindex="0" > Show: My threads + + + @@ -85,6 +107,17 @@ exports[`ThreadPanel Header expect that ThreadPanelHeader has the correct option role="menuitemradio" tabindex="0" > + + + All threads diff --git a/test/unit-tests/components/views/spaces/SpaceTreeLevel-test.tsx b/test/unit-tests/components/views/spaces/SpaceTreeLevel-test.tsx index c46b9681a9..2dd6ac5016 100644 --- a/test/unit-tests/components/views/spaces/SpaceTreeLevel-test.tsx +++ b/test/unit-tests/components/views/spaces/SpaceTreeLevel-test.tsx @@ -8,13 +8,14 @@ Please see LICENSE files in the repository root for full details. import React from "react"; import { fireEvent, getByTestId, render } from "jest-matrix-react"; +import { mocked } from "jest-mock"; import { mkRoom, stubClient } from "../../../../test-utils"; import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg"; import DMRoomMap from "../../../../../src/utils/DMRoomMap"; import defaultDispatcher from "../../../../../src/dispatcher/dispatcher"; import { Action } from "../../../../../src/dispatcher/actions"; -import { SpaceButton } from "../../../../../src/components/views/spaces/SpaceTreeLevel"; +import { SpaceItem, SpaceButton } from "../../../../../src/components/views/spaces/SpaceTreeLevel"; import { MetaSpace, type SpaceKey } from "../../../../../src/stores/spaces"; import SpaceStore from "../../../../../src/stores/spaces/SpaceStore"; import { StaticNotificationState } from "../../../../../src/stores/notifications/StaticNotificationState"; @@ -26,6 +27,8 @@ jest.mock("../../../../../src/stores/spaces/SpaceStore", () => { class MockSpaceStore extends EventEmitter { activeSpace: SpaceKey = "!space1"; setActiveSpace = jest.fn(); + getChildSpaces = jest.fn(); + getNotificationState = jest.fn(); } return { instance: new MockSpaceStore() }; @@ -127,3 +130,28 @@ describe("SpaceButton", () => { }); }); }); + +describe("SpaceItem", () => { + const cli = stubClient(); + const space = mkRoom(cli, "!1:example.org"); + space.name = "Root Space"; + const subspace = mkRoom(cli, "!2:example.org"); + subspace.name = "Subspace"; + + it("should render a space with subspaces", () => { + mocked(SpaceStore.instance.getChildSpaces).mockImplementation((spaceId) => + spaceId === space.roomId ? [subspace] : [], + ); + + const { asFragment, queryByText, getByLabelText } = render(); + + expect(queryByText("Root Space")).toBeVisible(); + expect(queryByText("Subspace")).toBeNull(); + expect(asFragment()).toMatchSnapshot(); + + fireEvent.click(getByLabelText("Expand")); + expect(queryByText("Root Space")).toBeVisible(); + expect(queryByText("Subspace")).toBeVisible(); + expect(asFragment()).toMatchSnapshot(); + }); +}); diff --git a/test/unit-tests/components/views/spaces/__snapshots__/SpacePanel-test.tsx.snap b/test/unit-tests/components/views/spaces/__snapshots__/SpacePanel-test.tsx.snap index c6fdc70948..a72f55978c 100644 --- a/test/unit-tests/components/views/spaces/__snapshots__/SpacePanel-test.tsx.snap +++ b/test/unit-tests/components/views/spaces/__snapshots__/SpacePanel-test.tsx.snap @@ -41,7 +41,19 @@ exports[` should show all activated MetaSpaces in the correct orde class="mx_AccessibleButton mx_SpacePanel_toggleCollapse" role="button" tabindex="0" - /> + > + + + +
    should show all activated MetaSpaces in the correct orde >
    @@ -73,7 +85,19 @@ exports[` should show all activated MetaSpaces in the correct orde >
    + > + + + +
    should show all activated MetaSpaces in the correct orde class="mx_AccessibleButton mx_SpaceButton_menuButton" role="button" tabindex="0" - /> + > + + + +
    @@ -94,7 +130,7 @@ exports[` should show all activated MetaSpaces in the correct orde >
    @@ -109,7 +145,19 @@ exports[` should show all activated MetaSpaces in the correct orde >
    + > + + + +
    @@ -122,7 +170,7 @@ exports[` should show all activated MetaSpaces in the correct orde >
    @@ -137,7 +185,22 @@ exports[` should show all activated MetaSpaces in the correct orde >
    + > + + + + +
    @@ -150,7 +213,7 @@ exports[` should show all activated MetaSpaces in the correct orde >
    @@ -165,7 +228,19 @@ exports[` should show all activated MetaSpaces in the correct orde >
    + > + + + +
    @@ -178,7 +253,7 @@ exports[` should show all activated MetaSpaces in the correct orde >
    @@ -193,7 +268,19 @@ exports[` should show all activated MetaSpaces in the correct orde >
    + > + + + +
    @@ -206,7 +293,7 @@ exports[` should show all activated MetaSpaces in the correct orde >
    should show all activated MetaSpaces in the correct orde >
    + > + + + +
    diff --git a/test/unit-tests/components/views/spaces/__snapshots__/SpaceTreeLevel-test.tsx.snap b/test/unit-tests/components/views/spaces/__snapshots__/SpaceTreeLevel-test.tsx.snap index e1f470f70a..64e735bb66 100644 --- a/test/unit-tests/components/views/spaces/__snapshots__/SpaceTreeLevel-test.tsx.snap +++ b/test/unit-tests/components/views/spaces/__snapshots__/SpaceTreeLevel-test.tsx.snap @@ -47,3 +47,251 @@ exports[`SpaceButton metaspace should render notificationState if one is provide `; + +exports[`SpaceItem should render a space with subspaces 1`] = ` + + + +`; + +exports[`SpaceItem should render a space with subspaces 2`] = ` + +
  • +
    +
    + + + +
    +
    +
    + + + +
    + + Root Space + + +
    +
    +
      +
    • +
      +
      +
      + + + +
      + + Subspace + + +
      +
      +
    • +
    +
  • +
    +`;