From 504083ee3b6f5d1b0f42d16dd83a321063ec970b Mon Sep 17 00:00:00 2001 From: McKayla Lankau Date: Tue, 3 Oct 2023 10:10:33 -0400 Subject: [PATCH] Remix nav items (#4249) * aqua10 and remixItemType * link has background * lock/eye buttons cover nav items with lozenge background; * attempt at isDescendantOfOutlet * show link target * path for outlet * add remixItemType to other ItemLabel instance * color variables for legibility * adjust test to confirm outlet row shows path * delete comments * adjust lock/eye background not to cover target parent outline * color inside outlet * drop target lines and target parent outline aqua when inside outlet * findAmongAncestorsOfPath * refactor to use findAmongAncestorsOfPath * no background for links, outlet says outlet: ~ * new link icons * Update editor/src/uuiui/styles/theme/light.ts Co-authored-by: RheeseyB <1044774+Rheeseyb@users.noreply.github.com> * update tests --------- Co-authored-by: Berci Kormendy Co-authored-by: RheeseyB <1044774+Rheeseyb@users.noreply.github.com> --- .../component/remix-link-aqua-18x18@2x.png | Bin 1239 -> 957 bytes .../component/remix-link-black-18x18@2x.png | Bin 1240 -> 1001 bytes .../component/remix-link-blue-18x18@2x.png | Bin 1300 -> 1026 bytes .../remix-link-darkgray-18x18@2x.png | Bin 1211 -> 980 bytes .../component/remix-link-gray-18x18@2x.png | Bin 1075 -> 864 bytes .../remix-link-lightaqua-18x18@2x.png | Bin 1187 -> 952 bytes .../remix-link-lightblue-18x18@2x.png | Bin 1167 -> 943 bytes .../remix-link-lightgray-18x18@2x.png | Bin 1181 -> 937 bytes .../remix-link-lightorange-18x18@2x.png | Bin 1212 -> 967 bytes .../remix-link-lightpurple-18x18@2x.png | Bin 1210 -> 959 bytes .../component/remix-link-orange-18x18@2x.png | Bin 1197 -> 961 bytes .../component/remix-link-purple-18x18@2x.png | Bin 1261 -> 998 bytes .../component/remix-link-red-18x18@2x.png | Bin 1124 -> 913 bytes .../component/remix-link-white-18x18@2x.png | Bin 900 -> 773 bytes .../remix/remix-navigator.spec.browser2.tsx | 4 +- .../remix/utopia-remix-root-component.tsx | 2 +- .../navigator/navigator-drag-layer.tsx | 1 + .../navigator/navigator-item/item-label.tsx | 59 +++++++++++++--- .../navigator-item-components.tsx | 28 ++++++-- .../navigator-item-dnd-container.tsx | 36 ++++++++++ .../navigator-item/navigator-item-wrapper.tsx | 3 + .../navigator-item/navigator-item.tsx | 65 +++++++++++++++--- editor/src/core/shared/element-path.ts | 14 ++++ editor/src/uuiui/styles/theme/dark.ts | 1 + editor/src/uuiui/styles/theme/light.ts | 2 +- 25 files changed, 187 insertions(+), 28 deletions(-) diff --git a/editor/resources/editor/icons/light/component/remix-link-aqua-18x18@2x.png b/editor/resources/editor/icons/light/component/remix-link-aqua-18x18@2x.png index 843d12856f74c42aa08531af8ed99ef8201571c7..a3e6386cf0f01679b0c6d93af4fff58b6f1127b9 100644 GIT binary patch delta 544 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 Hu0mjf2SShE diff --git a/editor/resources/editor/icons/light/component/remix-link-blue-18x18@2x.png b/editor/resources/editor/icons/light/component/remix-link-blue-18x18@2x.png index 466955f60c475d67f3208ead158347afce3a3fe9..651329f89aa380b291683837dab3da229ed30a5f 100644 GIT binary patch delta 613 zcmV-r0-F7l3W5l*sR4fiLrFwIRCodHRzYstFc93O=m13z$)PBGtNMcK2en_&JfZzT z^MRH|dXIk)`vp~B5cdbk57e8{Hlxx~hDyCbq901ZVrd48HZh)rP-^ICP32c082x{h03lbXPnHIYm{^?& z4bAV=y5xdGr5tSqL~|x~$;}}vJI$)a&A{Gic>Etfy%&&vy%28&i zJmTy*$7`@-Vb9m^C$n~?R5ZI?JBi5^tdO(=7Uh5YHe>{AvS(Xl#<5NvB;;Jx z4hW<##gXybcUd3vu2Cwgt=)7uSd&J00000NkvXXu0mjfnO`1O delta 889 zcmV-<1BU#92$Tx2sR4fjRY^oaRCodHS5Z#eKoFf-+fgMd)e@xQ4|4*-4d@N%34jv> z{@cWE4*;AX`bxRoNnIEs1oGw$Cg3CQ zBh(R>_L+z~BllPlHTZl&1ij%WFN6nRB~%Yb4bXVOmzJCtUgAg!gos3;C~Y83(eQKa z1fGEzLh@F*b}tPX4m+1>lz|(&kVz>wIZC_bRw3bY^kRPv*nO?slQ_f#o{1Sz=j3*v zh|DSHdeSdq{_C%{(i1MtrtIN#Mk~rQM21ierpn%D-He6EZfXsEuH0~(qN<`Ym(Z)S z2}-KwS$h(iayDxzqybcnDMC3=@wP?J`7f9vl!6x*>7ZbZ%h`6o^eHKE4%W8^x^^Xm zBpqBur*eOd8awMD1^3D1+PNq{`t?@!)i`s7m??V^c8$`@VpPD`l)lzisBnX|voBl3 z`~WnJ#|d%Y8q$$1V#R<4{wv=1Hw9od#xfEiFYj4S^m(K>5YbC?P(horl|F-RRpG@c}C>>smwE5>->auYjj#IVPO2d+PvZCBgTM8>5VOKw7yGqd) z(b-MpZr)$#(e^^p$PM@CyQS|{KA??bCubNqXk!s7+IEBViLaroPc?bf%3N7 P00000NkvXXu0mjf(yFXg diff --git a/editor/resources/editor/icons/light/component/remix-link-darkgray-18x18@2x.png b/editor/resources/editor/icons/light/component/remix-link-darkgray-18x18@2x.png index 057f2051ffd4c445b6b375872f1e1ae56f3a29cb..825f0aed043e616302c3803f61f755b79b8f6252 100644 GIT binary patch delta 566 zcmV-60?GZm3DgI$ssVo$NklDI034T^*WV|s(IRpPJTE4CD+kT^0@Rmq=}JloIm`{MWcIgDv&XlVQ` z40c2`8Vwt!ZWzYpcDwyVI~Wd!L5?MkL&$aAQ_Hf(XxhI57>0junr6G-?}svLDHCco zo2B)7{e~SWp&P;W3WdT4tPL{PG!7erlp{mRVhV_p*%Qw}K4qO1WHa)oQhHI-N%I`TVO=shnZn7054U zv)OCfno21f3kpDa zu_Qg!xvwn~E0Yi%RRp}tLxxZ+7CSLAj%=lt*&&pHl)cAWJF!!_FW7t zm&+D{rCtfpOBbfgazchsNH03NVgTvrLaY%T?YL$rO_=wRED3p#dAag(PvVR~;==d+ zC^;uCV7B|^$h@--AyY&AsM7Njl=O3m45bk5d!_)X-;bn-VSU&M>^a;mBAfR#DG?H+ zsK~KhT9PgZXlGQ(yk?sB?P>Xt-u-@8XErv-yidR*(2hW9smFU07*qoM6N<$ Ef=?9&&Hw-a delta 799 zcmV+)1K|AB2fGQdssVreNklZou4t5g@UHoFL=` zzzM>fAh1JxG;o6P4MHS@So#Q_9TLBJkCZbFm?Q){+3+OO?ryj1xw`6gq0|{?oQ9AJ z7};#rh(@Dn-uHSv>#gSlC6v$S@6l9VjDkVb#T!DWMtv0krD_TjPX zcDrqRtqZFFP%IWrA){yx_u?4X!^_he; zeBUw_4jXSRh$^2^C=|+Qs)!fHP6n}5g-3?ylT4M*px-*Q-nXEJ;S3BtNZ=9{33)s^ zVoa%H35kB(@>YK`#HJC9we+|k5%v7#j2lBzyN)1kGPsw^C9^Fp9vgy8O}zq7LU21@ z@P`KW7KoN;TaZ!DsZG>ju%S-C9wC0!VzGD>G8T=%D>lYVkhukstUO8*8;@YDh55!{ zFmTj~*b8dB_<@FC2z90 z6FLSY#==WP(*+g0;%*f_uqMPEj9+?fq3QtxO4)&^xdp?27O%d?$n~v)D4IMMPh~K8TcL-ZRqz`5S~dX`(5)#Tu>= z3VajWdGG3*S9}q^*VF_v3tDvr<2+)hMcg8KWmDk6i$4yn4fLNYg%c#WMQ$PY6hz5# d#u*nn{sAZldV+xs{F?v(002ovPDHLkV1oHHb*TUV diff --git a/editor/resources/editor/icons/light/component/remix-link-gray-18x18@2x.png b/editor/resources/editor/icons/light/component/remix-link-gray-18x18@2x.png index b33b905c24aff78d2760be8cb32f7a061c7ec8ea..564c05936473dfa59d01df0383ef830fba9c3371 100644 GIT binary patch delta 450 zcmV;z0X_b+2;c^=sR4fhp-DtRRCodHmf=mqKn#T)#DCa;FagXHIv!PHjL zLgKu0T*ej0UC+FrFs*1{2jrR|c;_b4V}A<7=2MEs@|R?l#m-tCd#Bj@2NJ+u*kTbaD}J!S)QX`N?Q zpEONf(Q$qplD0=e4@?c4Qh-#SA0181CD|oOa?>=;Okg^B-K&9r4P-#IpAxnz*fbQz s3#gU!6rb9BP=1ke0!KwfMV*Vj0bp*+;5wx9^Z)<=07*qoM6N<$g8%Q)i~s-t delta 663 zcmV;I0%-l<2D1pTsR4fibV)=(RCodHSIv3bFbsWaduUJf24yB_x&ga^GeOk}>`owQ zf}|5To}lprU+`t!W+D83Lk-VlRG}`pfLa&(B xXs#9cI<+zPpKA$ksgT_@mnAP*PB>wRTbJqW{p1fpkuCrL002ovPDHLkV1jQ`K^y=8 diff --git a/editor/resources/editor/icons/light/component/remix-link-lightaqua-18x18@2x.png b/editor/resources/editor/icons/light/component/remix-link-lightaqua-18x18@2x.png index e040d6f38735997cdda9f9e50124303390d077f5..869a249849d60f23a3d4ce8f2fba2108dba7c07e 100644 GIT binary patch delta 539 zcmV+$0_6Rp3AhKasR4fh`AI}URCodHmcdcNKoo}mMaLPvh&S~jR3IG?Dv%Pi1E@f( zKspdBAXZ@LKq@d^)FYlek@bI@1Op^wV{r74eZY0x5%>^8XCOwDo6 z_DQBV-ZtZaPpFO!R4Je(n3PS;e2tdVXz|sX9IH;=nl+RVVeYWO0`ji*&=JcCpNX;G z1R{jE$4$bBRrm~~HBd(?bfftLbo18SMF|mN#AXz~CtXNL(I6x@F$KMY!@M;MSx7c) zzw5E{s=H}($#{QCf<`ffC>3m!wS|%!@=qlu+$@+?7jo_*`qazY$I3!$8wR+sf|2~B zOnz$cIJ-7U(#~ZyTqFDMvtjnloVd%U+xm7}m1zB?I_Fj&{*&YNbk* dD*b1D0RR*A6y4y#9%}#q002ovPDHLkV1oK#`7i(g delta 775 zcmV+i1Ni*72crqFsR4fiTl%$wIzpZl*iD=tr!aT5f8pPr&{rZ@YJf2>1CAw$*%RkTRpWvaEV^e zHB5Bb*5W1Q3@ldz`En+?gQba&ulcOxs7Ln{u|vBuHKhW`EvZ2yM!+xR6IYN(b71HI z`E*2^5)%KIyrO?o?1&nXNr{mZvhseUXodYScA#Kgvf!rpeJC7kiFHVkZ~eAf(Qv*(tb)_F@cbfF(b{1 zTe?UpE~UKje$0Jb9RK9tn@YR%>zFHU>CuoQ<`jx=IO2albfX1m zZ&l`f=++DkOSQ_{lRYKi`*vqLsvtu5J~^545A;~f6WYa_`yEr3?HrmQNl&awrt41a zTnNc>;QaY4_hNDye1Qzw`}Q|NVh_ccDMu`Cd!N{s0PLDlrWf%TOcVm>rxx2c_<*shUm;vK0N%)cNte#`k^K-I&lOuw-wln@=C^ z9lSYRDlt+cp2EW_g*f{Xv1_iGlMh4vvy))V!K!~T{{n4VggGrgmVhPc*|;)23!#U= zGs3~;DuPgAfom&#tZtEmJFSqy0gM0}&VV)K$(E>g%BUK8vP( z%n>8NAq3uOPWdrQUC!7FA^s+snBkt5$(m7Mhz2^m#U>U<)hB<%pGAZakF<`VD3K{U?Q6S?Tuc$Xqq%K5Ge8}L%1MNZ2=G&;_K`&{Q5ySI zLNYy4BLy-tD*Q!o(p99MTWpa=sizCmf%Q^$!umAz^XFm;KeH`u8mZp^d!{p;2q}jF zy5w}gkJxa{R@8q}V@VWJLlSc;1=}LD;_yppVz|*((vz|Q=juhOOC~>78rtCS){2a* zPuVStq}FVTq@Ack+@R{;|3qe{Y%#JFc5GZ33F)hP=|VN~3fPN`rTdsY?9qRy_W9LnjUB~*}+DZD}rSbcu1iI|aC1;&hF zUkIhACLC{5EkZe|9V&97prs{J8JW6doCxK_GEK>@EgR*BjF#(Xs)vV%$A88*txe8Ex000UA07*qoM6N<$f)8u-0RR91 delta 755 zcmVGt;ay?X)%#Ryw{0tqP%`YD>u};8 z67RJ7_paw0#&m0wTh{Z#Mw^~5&D1n;ixb`=F|J@DgaSjS;wkJ(Nb-kyLYJ#+BZ-jM z7);y|MtNU&BC>z-lXM(gpOX&N+%*h1i}cMnZfrjoi!BHeqU`d5Z+?PR#BAreEodRx z9`Q)uel*wE18anIRdqagG82yI(`hlYZNv$?yl(rUGo*?*dg2wXsoV^EV%^kr^?^)u zL)lle?1bux0$m;BNVX&*DGFh)=T2(G2Ex)eV3BT7$z*@l2&IQ0M2QWlT?rT@ee-2R zRYb@kU2TLHLXl8IS1zO?4d(#-Ii+E|?bI%XkZy;=jb1Rx(NobHnYyL}L6ZjmrJ1=z ztcSfAd#+(0!ABOu{gFi8kYop0@&nRxg4vhtDx{bX6lt@634m~7Ofsxx@8>}Ggj;(d zruXXfka>S@$iBYzC2C3vY2}_3!WaKtps9}*e4(K_iAvMeGSrjra7=n|iV9Nqq({yS zSrXOEZ#cg9&Wv^@v?gNHyCM^ zdZ0@(Q3b3lf)@X lN$nK#_pyqS<$we7_ye?D5!R4X$eREF002ovPDHLkV1i>^a_s;B diff --git a/editor/resources/editor/icons/light/component/remix-link-lightgray-18x18@2x.png b/editor/resources/editor/icons/light/component/remix-link-lightgray-18x18@2x.png index 5d9e3331b2269fb358b08182136a3ccf27d791dd..f5b29ecd46e7844a658ada2b66c3103f9f25fb68 100644 GIT binary patch delta 524 zcmV+n0`vWy38@FLsR4fh>PbXFRCodHR$EfSFceLT|FQ$?3M>PBTUH=T&>hGM#1+5} zEGw|C!1~Pxx&zz+{`2r0xN&NykYtJ@A2~Cbo8)$KPwp#K%EQCM<9`vTBVsz8CJ=EL zhF9zL`V;fK+wJBKM;wRHY&L7IR;y=BlL~d#Xfy_`R%@;-P@8`c$VBkQ>t?fwuv}nF zf*^RuI)S|AKI9x;>)DVxQ#DW|Q(-ivo}Pm~hJ3=)F1a-nBFrhubJLklgd`_M zm`*yKPFB_x^9g^UO0|wTL@BM{IE1u8Olgo|$o7#bhY-3OdI-o(cB}|h7<{xOqx)0D z3)nPCD?%{%aNzcb$k3y)=ms{nj8(=`g~3}FGIEJgflSY~Q`?k%A~LrnBZNLwsU_IJ z7&4ZyOyBe#LUFHl$-VdX$d@t1SUJK-2ws@O@K5OyDCvJO`pkl*UCbGV3E#bxTY?LW zk1KNsgqWNpa4DVl7m5jtk%N%&&DsZJ4oRtUY>nzCp^A(+|3R=*$RBv!ko$fUi% z9`mW`T1~YGX;RYU;tF+6&(tO3L`Xw&s?UcK-uc4FTz^wNJUl#38Q&&mcGw~`E%pEa O002ovPDBK*LSTY6e)co~ delta 769 zcmV+c1OEJ}2b~G9sR4fi-bqA3RCodHSIKqaP!Mdk^C$z$5g0#~Gm`-mfpG-j2!IH{ z5r85XI|A#>^1u;{LeQOUszhr>f-l<`$-YqU=}CW6m-=_tZ;4!R!Fk9@##k&C)_T1z z^SM^5x$n)-l+b)WAMAF!&Oc+hoVVF*e%0&srF=D^2pJ!j2Qq&a+BVyTLg5zhOzZNJ z0kBPW=ouQXR;#y_O63~OCtMc1)Ja;K2_YB^Vg{t14?N-M{YJi$PzY?(kAt@L-kPGM z48%?gw=TTH*lD2Mg~y(iOjn6HN$XP!>gjaa$mjDT4P3${A;Z)qV@ggXME%%qw`~|` zYKAaVTo`qtaY26~=;xO+ZY-uY?tKLDn86M24A57m#~4%4qMp0~BcaJ;QikCd8aP^@ zT0)Xaq#^s%W)Syba42Wsh>(8OLdm!^QY;odsI3hGZS*yDDoF$$fhQfz8NzeEoQb2L z2APqPdBk2v^}-{;*=$A+kQleI51koed(I{jB9``y8_|D2q#@G+^!G%!C@rrf5(*DN zz)g~NB@m3QRx4XlMvRbZ2Vu)MAx5ZFDtWTs4x8z0TEL)}eTw^Uo!Y4o;&#AGkHG*$ zPL0RNAfsNiX+eems4}MpQ`%Dy7gSsoIT!6$5WGTPOa6YJHxPxOuJ{$N6sxfcv&tt2Jt?}^c|FtMr19C-+#J5(>UT8bww}ng@RTd z-6S|Uf&FWm6es%-wI)a zl7pK%ps11CBare1zzOmEJ}l#7BS3QK?ZbRFq^Ei|0tO)Piok!SCcY{I(W59l@A0&Q@Z86x6zsv7%MAW7*#2+}aTDsph`snubqW{+X|@dQqbTvkdMLHKm@6TWl`rQlbd zHo!Qp*1aO1rGS4_Ku30Y#(35VGPZO*0s4s%sfN@bZUq|xN&-q1kkSA_#+Fl0I(6bi zk95MKI7T&;6Y$OmhWitWp|VjwGHH@#MUC0dQHD#mbXcDRrNPnvGq701E zeAZ21a$3TVfmFxU3XNg(R3^(U!9*rS?P~wxIeCL0ZTf$4*UcVVogUqKP*Ns9Qysyn zC2!;w1roe(`HM9}X+rt5+!D&DaC4216r7$2c6JZ3=|!0_iv=8F>!EPZTBX7o(w{2Q z1uE#*maqbbQ+Np#WOV$9ckNMfl+b6K2{___8f9C-mi(G30ewRWeU!+$33+9z!ju9^ rfz{((n>QiKR{}BWz*bgPR{uqxGXf#oErd$M00000NkvXXu0mjfdGi4O delta 800 zcmV+*1K<3|2fPWessVrfNkl0|Q?CB$F1cfn|kyy_z=uhQ#}J^X7zBV>ODjtD50w~2e^=%uLD z53P$(0Qm4ja;J>l{OykXeOZ>{f0s8gh#QmE7D5P-sroN;a!-k_e!iHv6vg6M=E-pU z*n%>01|M$KC0tFo+~Jz!QWI1@!L5-{nWmpa-AU_nOKQoRnrzsSuZjNa)Dj9z?b)2d zw1k|0T>adT)2@H`3Xw`7PGO?%XkK_CEGK81H!_d!E|)bU11dM@Q%$FS7> zY&%C3r5=Bx(q>38ZO~#=DuX{MfUq$-WlT#(*8)qdH?7;Gmw9zH$3({t)TR4gO=}^U z>qCf_*Z;af^Lb=yP93WfN4@)PsFD|AXzDAgnDjkt4K&tgd(p-iIzN@_^yX7{YC_Y% zD{|XV)6|!+4&E4siVwG2N_>FDrR7ivb8lg#-B^DSBF8q*T$gx%{OJ9uhH*1=@8#d1 z{cgh2@B}{bpOl0~i|!c5!J0?R!HO$@P$|`&SHeD~l^d0Ul~%~lAW7Z>-PpD!ZIl*z z;G0C$*@f#U!}(>Adr$39xoY6@iT!0!70c+r+>8vmj`G!{rN#bo^~Sm8JcvXsgYzO< emN^*a7{xCwVMjmvbpV6_0000=waK4Q0b^dL zLXHS$@&24ic{Zf#D1i)_tkIE{*R|(d_TZ5BJd;ibCBVjp*x>>1hUTiSNrd7tonyaA zNGTm2KTSrw5hf zVuO9aC;bSu~wp|nAgoZwJxBa;mwpFh_Jxi6XQSmn@$!5Z$Z z$Vh*xah0uPzD<*~BE(AXuF|W?jT7m-8)wo9OqjGfWSm*sV9X(1s-*jeTrq<6NXR84A*`c~ z60o{{WRsY$6@H{Ja|p*g&m^B3C|FIU2qmQAt3-~LiFl?gnU$)7(0z%gwhT(Hym!{% j7rmxds8AW9!hgmWQHuxrRs;Ox00000NkvXXu0mjf7M}zM delta 798 zcmV+(1L6F?2f7KcssVrdNkl*$N_L)ikx4u?FzlQe8T67nNW)}F^J~vamHK7GEDNmWfqQ!sbP~L45$L)@p`St~< z0r58*7M792qcd|Hotp!`-tyDJe93C{6GAiB4Bd0LXbBr&BHzZ~5N}Gzfd{`|8pzab z8___;h;Qtv$Ud})9ymfST>0fh2zi!Hsi)(z z-zl|_IO}9lp&&<_Qgs(aJt%tI`XF^-*ZDL-*3535~x}RPf1iWzv221pUvdO zgkAzAwui1unhKY}yM?Rb@3!xVOV@bdb7AEzZ2W)2p0NG+$;X-N5|@w+Z7gn7&3Wox z^$l9lgfSR=(^B#E!T57stsP?ta>7LtUP1MQ9-U<$Eps6Z;v*nw6cRv=bj zsDM}ju>OM3UnHmyr^Tu7B7lp!;%i}j$!9%rsa_NXyH$L3R_1Sr@`9vQ|-5Uk*+*`r}Y^P1D;bEyEdOSlt3*&NJE&uua@vznWdh2YK)CI z1Ws)}3uVas{SAMHKmO*QX7$vN2$n`c8e(453T!c)Gqf5|!IUA)Ban0t+eLGZe zM!E>rG(%;gX8D@*r@df3%UDA?F3*e($n&K0t|22}r!y-LRt?p8s|vGSIRm5gNXQ|> zCA>umIGy&%sXa=s5_GKyNw5>4aHe7O)GWH2N)cKi6<;Mby+oXuvSeac1(9f~YYs|{ l4D|61|dp1=Vj zV|I>=8(*_o&}W+S7OqV~OYy3Vw(rG4gI)8ZIrTh4lN;W$+3+jpLMX7~SbPfqO33Pm z#w8u`46vr2DuaLgAi-eOFDwzmlN;+db*?z&(`9J)#kmuMo^m==aNO|CH+1j_f`n!n z7tk1aBAc*UVz0mvY074@lGf2+-Y;g)6&tVRNIC&xTKZN{LsRW znUdJxFu@HiS0FZKZH#6u7(T(1%6s2${s!@ z^FFp!)^w;$g7&I*NV_Ls`{rdtRYl0apVq|R=($)URC6a6QVj{`&;)UM_%MDfYeyj@ z*Fh_Nm9~hS$<{69BXH#Z*6G;yqRfbht+2OFYZ&(K+C=1X>dPceaK!M=P>P=&?8*sI zUp`+#7W02mC{OX600;`BRalJmxmIwPahIV5W*1Ae7 z#t@VzycFRLL?`r+ddtwMLprwfu_PR6m3#)#dHa6jDT#HFVw_0%qS1roKkAr#g@oot zuc-wRSrpe3TSY2rk+xqT4kSaZ`nYRurC+XIIK@(RRCodHmQ7B>Fc5{G6JWuH-hgrfSRr<_Cx9aWV!^VU z05}0<$AX{s1e6mHcEGCKpxht`3B*rr-lPeXkYa~aLP&X1YsYRqUuMQ*1EorpD)qNg z7^60qOijOGLHU?B26vu^;OI&PdDa*UP@`rl4^KEFMD3dah0cGZ!uH{n>ba~{7-(zB zR9`eM*sbyt8ilsf=(4R5W*H_L?@f8AyFg8#fWE*e^t3{~^=Y)V#(Ce+bHKu@!70b; zwlzHzP;4X%W`EI!b(O%hrQbJLwJljF zWXCtE!={rw4~Kt{t!P)i2;Gg_8QYq3oXkR-`X=$!5nXhcXQAxxh$$deu0SIjKi3MbZg~VcNmyw;u`f@Q4cum(2B9 z99?W#fn=+4m#pQ15wUXbCoowh;nzS~e;fyaD~yORx9NY9;38{M8;O5JhRbB^xsL{O zqWaU@pIoaZnB@@6oc@DdKz=B zK!xew3@0!>7aU(J>zOr5)*OG)bNz#zU>aG_C= z=S2tWp9jjf^>a`FK5gmBU1lN%KfYA!Cl_j!#LoE2{i7$cRy?6`lxT)o>3Nfx=$fEw zcu7L3!C$AJwdS%tf--UjwbRhR0dE5msO@g*0}8pPBe+o%zn9E)r}fWG)E~BVjR8-2 zTQNcVii9!&6^4Ju7it~PB_#gw>l%Cfpw1b)9LVR4`>c>|x+4l%$cO#FbOR3Q0C%Z&F4><~Skl%l3WSIY$ik<_7N4 z5`xYX3czZN;;<@0i;dfv4kQ>V?1<>&>^R(?jON(pEzq~b$t9a&Av(2vaJ->Y#?F5q z(9Hf+W1to4=E`9v?jJ*iyd#-QHdKLR?2IN_H%@;a;Gc=c&d=g$91m3Y*@T{hIIAI= z#x!Ga5?#HF=ABnjb1g$Wpogv6JS_Jk?E6hEoAEc%nVb?c?QisXyo?I_wtX-616t}3 z*0;8Y=*7RVdtIR?M%W`JI?@R2%{e0~napU^Z9WE5xl(bq{)PMvqK-VB1ola+U0T2} zx`j$O{2^qirszwM`?FF+Aj!Auwl3;+NC07*qoM6N<$f>)-RBme*a diff --git a/editor/resources/editor/icons/light/component/remix-link-red-18x18@2x.png b/editor/resources/editor/icons/light/component/remix-link-red-18x18@2x.png index 237779e435c43beda1c5c56946ae9a02055a0db9..c6c41471a7c422e87443093372533ff2d0e1c71f 100644 GIT binary patch delta 499 zcmV?$Em>$6;hko+Xav7Pw7oX_VFB_$;#{jC%oP*pa{iN1zJ zgLAZ2s7s}1Wxy1N0RqSgt}iHgkBJ4!7+_j3RXh-2GF+E@hvt78We(506PX;-U$}ma zzDo(z5k;s2qdP_mJ5KC5EMxVI`%B-P1BwzG+3f+_Rt&M`<+L&Ot3YaQW2Av$uT5yYmy`>4C?BB&)4sRS=udM zf5cc~$qQt+YIPF=dYB6EmC=Ub`tFMBc;I#*pD;#{g?*F7tMuX$3GZ?W6b1+9huc z*{!Njs5ZJe68d54-E>P468(Pk;Y&S&#wV>Ru#MU$=dnOhp2&e^? p+f$nl%IXtd5oO?{q@<+(qHo6k4Cgf?2gLvY002ovPDHLkV1kOz;_d(d delta 712 zcmV;(0yq7U2jmE_sR4firAb6VRCodHSKWEqKoHzh{2n^+QGrPZqythxl=nCy6&P1w zND44?5Gp_&7*`OLpaK$IX0>}D%O^V+o&CampU~-kxY6$H-iqji6OMzS$Z&Q#z-?4- zR?PF~=0_#uY<7d+X``zkNwcy7fR^$ce(Q@rODTF{CcJNpgo zWKE(W?nkp)b*=AB)X>cszqcw}{_C6xJ)UW{tSLH_kmQdl!;}ftZ^t3)a=h)TsS72- zZ$4_wyEetorHX$W(N^anwiq<^V@6NFbdbRxR2$u(je>It?OiaI&FYm*WKKuG1jtyB zxswgq?B-fX5c(Y~<|aC|)HxV)&_ptasFSf93o{4WI6|A4Tvm` zCgSlR>_s5b4PRFIIe63&ky zqL(m!>eTLqkh)_bPt~n%-Xh~R`Z$2Ve@kZW523JUVc)6S3JLw{9^B8-m(niz8QPZ< z29`44Ll)Bljj!^50-!4~T9BBb`8lv8$MuCpk9nykN2_B?&RaTW^(YxP)^2s}%L+8n zQH9H#iAmq)avAWsD|dy(&=xbm@;OrCe`>x;|+zzIi`P`JD|t8*Ks98sUHO))V?SW(}&uo(Ns8%;nblpUE3#n4EeNV|oWPPou^N4_wtU)+hc14r0; z&7lbs+F0(~vK9G4cH~Jjz1Xv6%Bg1VEy9PP%I3|O86ES@A<71KB|w-veRYu4(_`0u zt8L-*$piNbeW6{NpW>P`a!fM{iIYR}{O32uxCtD!W^D$NH_UAsF=UhYkGpd4!;X{%?KVL8#E(ygL;E{gQOGW zGJ&%}t`m?A$ObCZKaE1b4~gZx_`Bmcz_x@CKbUA{<}nte3^P~0TK*YZEDrQcyfa^X zjrC zih_1X1nnQ+fA)V>95bZs&{@mST_np<7oLgdl%pv?qQ>20=++s_*AlQMO%Nq33~qwH zaDSbUTiuH7-*MrdgYTJ#HUK`bjWFu) zyc2E9*UJA++Q6|kiO5zim2lj#rl2N{tzgs^#ygB>&plm@3tF7{p)kHjZE}O!H^v;% z;WJGE3*qEp9b3^<@I^8#q+yBNvP1c$=}-mD$zgfmzfAR4n)_oVXimtRlP^EMw74 { expect(navigatorItemElement.style.color).toEqual('var(--utopitheme-fg0)') }) - it('Remix Outlet navigator item label contains route component name', async () => { + it('Remix Outlet navigator item label contains the suffix of the full path', async () => { const project = createModifiedProject({ [StoryboardFilePath]: `import * as React from 'react' import { RemixScene, Storyboard } from 'utopia-api' @@ -277,7 +277,7 @@ describe('Remix navigator', () => { ), ), ) - expect(outletItemElement.textContent).toEqual('Outlet: Index') + expect(outletItemElement.textContent).toEqual('Outlet: (home)') }) }) describe('Reparenting in Remix projects in the navigator', () => { diff --git a/editor/src/components/canvas/remix/utopia-remix-root-component.tsx b/editor/src/components/canvas/remix/utopia-remix-root-component.tsx index f807eb9c77f6..24a6757d0919 100644 --- a/editor/src/components/canvas/remix/utopia-remix-root-component.tsx +++ b/editor/src/components/canvas/remix/utopia-remix-root-component.tsx @@ -27,7 +27,7 @@ interface RemixNavigationContext { entries: Array } -interface RemixNavigationAtomData { +export interface RemixNavigationAtomData { [pathString: string]: RemixNavigationContext | undefined } diff --git a/editor/src/components/navigator/navigator-drag-layer.tsx b/editor/src/components/navigator/navigator-drag-layer.tsx index 7f99b644f195..8425de04c07b 100644 --- a/editor/src/components/navigator/navigator-drag-layer.tsx +++ b/editor/src/components/navigator/navigator-drag-layer.tsx @@ -94,6 +94,7 @@ export const NavigatorDragLayer = React.memo(() => { selected={selected} dispatch={NO_OP} inputVisible={false} + remixItemType={'none'} /> diff --git a/editor/src/components/navigator/navigator-item/item-label.tsx b/editor/src/components/navigator/navigator-item/item-label.tsx index f2a9498c15aa..b55d89c35f42 100644 --- a/editor/src/components/navigator/navigator-item/item-label.tsx +++ b/editor/src/components/navigator/navigator-item/item-label.tsx @@ -13,11 +13,18 @@ import { getConditionalFlag, } from '../../../core/model/conditionals' import { colorTheme, flexRowStyle, StringInput } from '../../../uuiui' -import type { EditorDispatch } from '../../editor/action-types' +import type { EditorDispatch, ElementPaste } from '../../editor/action-types' import * as EditorActions from '../../editor/actions/action-creators' import { Substores, useEditorState } from '../../editor/store/store-hook' import { renameComponent } from '../actions' +import type { RemixItemType } from './navigator-item' import { NavigatorItemTestId } from './navigator-item' +import { useAtom } from 'jotai' +import type { RemixNavigationAtomData } from '../../canvas/remix/utopia-remix-root-component' +import { RemixNavigationAtom } from '../../canvas/remix/utopia-remix-root-component' +import * as EP from '../../../core/shared/element-path' +import type { ElementPath } from '../../../core/shared/project-file-types' +import type { Location } from 'react-router' export function itemLabelTestIdForEntry(navigatorEntry: NavigatorEntry): string { return `${NavigatorItemTestId(varSafeNavigatorEntryToKey(navigatorEntry))}-label` @@ -33,6 +40,7 @@ interface ItemLabelProps { suffix?: string inputVisible: boolean style?: CSSProperties + remixItemType: RemixItemType } export const ItemLabel = React.memo((props: ItemLabelProps) => { @@ -87,9 +95,35 @@ export const ItemLabel = React.memo((props: ItemLabelProps) => { } }, [inputVisible, testId]) - const value = React.useMemo(() => { - return suffix == null ? name : `${name} ${suffix}` - }, [suffix, name]) + const maybeLinkTarget = useEditorState( + Substores.metadata, + (store) => { + if (props.remixItemType !== 'link') { + return null + } + return store.editor.allElementProps[EP.toString(props.target.elementPath)]?.['to'] ?? null + }, + 'ItemLabel maybeLinkTarget', + ) + + const [remixNavigationData] = useAtom(RemixNavigationAtom) + + const maybePathForOutlet = React.useMemo(() => { + if (props.remixItemType !== 'outlet') { + return null + } + return remixSceneLocationFromOutletPath(props.target.elementPath, remixNavigationData)?.pathname + }, [props.remixItemType, props.target.elementPath, remixNavigationData]) + + const label = React.useMemo(() => { + if (maybeLinkTarget != null) { + return maybeLinkTarget + } + if (maybePathForOutlet != null) { + return maybePathForOutlet === '/' ? 'Outlet: (home)' : `Outlet: ${maybePathForOutlet}` + } + return suffix == null ? name : `Outlet: ${name} ${suffix}` + }, [maybeLinkTarget, maybePathForOutlet, suffix, name]) const cancelRename = React.useCallback(() => { setName(name) @@ -225,9 +259,7 @@ export const ItemLabel = React.memo((props: ItemLabelProps) => { key='item-label' data-testid={itemLabelTestIdForEntry(target)} style={{ - backgroundColor: 'transparent', - paddingTop: 3, - paddingBottom: 3, + padding: '3px 0px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', @@ -245,9 +277,20 @@ export const ItemLabel = React.memo((props: ItemLabelProps) => { } }} > - {value} + {label} )} ) }) + +// here +function remixSceneLocationFromOutletPath( + outletPath: ElementPath, + remixNavigationData: RemixNavigationAtomData, +): Location | null { + return EP.findAmongAncestorsOfPath( + outletPath, + (p) => remixNavigationData[EP.toString(p)]?.location ?? null, + ) +} diff --git a/editor/src/components/navigator/navigator-item/navigator-item-components.tsx b/editor/src/components/navigator/navigator-item/navigator-item-components.tsx index e2460c75ce0b..c8c105b18a94 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item-components.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item-components.tsx @@ -20,11 +20,17 @@ import type { SelectionLocked } from '../../canvas/canvas-types' export const NavigatorHintCircleDiameter = 8 +const outletAwareBackgroundColor = ( + colorTheme: ReturnType, + isOutlet: boolean, +) => (isOutlet ? colorTheme.aqua.value : colorTheme.navigatorResizeHintBorder.value) + interface NavigatorHintProps { testId: string shouldBeShown: boolean shouldAcceptMouseEvents: boolean margin: number + isOutletOrDescendantOfOutlet: boolean } export const NavigatorHintTop = React.forwardRef( @@ -61,7 +67,10 @@ export const NavigatorHintTop = React.forwardRef
@@ -118,7 +130,10 @@ export const NavigatorHintBottom = React.forwardRef
@@ -338,7 +356,7 @@ export const NavigatorItemActionSheet: React.FunctionComponent< return ( x, + (metadata, path) => { + return isDescendantOfOutletOrOutlet(path, metadata) + }, +)((_, x) => EP.toString(x)) + function onHoverDropTargetLine( propsOfDraggedItem: NavigatorItemDragAndDropWrapperProps, propsOfDropTargetItem: NavigatorItemDragAndDropWrapperProps, @@ -800,6 +813,12 @@ export const NavigatorItemContainer = React.memo((props: NavigatorItemDragAndDro [props.elementPath], ) + const isOutletOrDescendantOfOutlet = useEditorState( + Substores.metadata, + (store) => isDescendantOfOutletOrOutletSelector(store, props.elementPath), + 'NavigatorItemContainer isOutlet', + ) + const mouseEventStopPropagation = React.useCallback((event: React.MouseEvent) => { // Prevent mouse events from passing through this element so that the same event // on a containing element will only trigger de-selection if the event doesn't hit @@ -826,6 +845,7 @@ export const NavigatorItemContainer = React.memo((props: NavigatorItemDragAndDro shouldBeShown={shouldShowTopHint} shouldAcceptMouseEvents={shouldTopDropLineInterceptMouseEvents} margin={margin} + isOutletOrDescendantOfOutlet={isOutletOrDescendantOfOutlet} />, )}
) @@ -1002,6 +1024,7 @@ export const SyntheticNavigatorItemContainer = React.memo( selected={props.selected} parentOutline={parentOutline} visibleNavigatorTargets={props.visibleNavigatorTargets} + isOutletOrDescendantOfOutlet={props.isOutletOrDescendantOfOutlet} />
@@ -1048,6 +1071,7 @@ export const ConditionalClauseNavigatorItemContainer = React.memo( selected={props.selected} parentOutline={'none'} visibleNavigatorTargets={props.visibleNavigatorTargets} + isOutletOrDescendantOfOutlet={props.isOutletOrDescendantOfOutlet} /> @@ -1092,8 +1116,20 @@ export const ErrorNavigatorItemContainer = React.memo((props: ErrorNavigatorItem selected={props.selected} parentOutline={'none'} visibleNavigatorTargets={props.visibleNavigatorTargets} + isOutletOrDescendantOfOutlet={props.isOutletOrDescendantOfOutlet} /> ) }) + +function isDescendantOfOutletOrOutlet( + path: ElementPath, + metadata: ElementInstanceMetadataMap, +): boolean { + return ( + EP.findAmongAncestorsOfPath(path, (p) => + MetadataUtils.isProbablyRemixOutlet(metadata, p) ? true : null, + ) === true + ) +} diff --git a/editor/src/components/navigator/navigator-item/navigator-item-wrapper.tsx b/editor/src/components/navigator/navigator-item/navigator-item-wrapper.tsx index 0e8ddae4ba90..af307bba7ede 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item-wrapper.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item-wrapper.tsx @@ -350,6 +350,7 @@ export const NavigatorItemWrapper: React.FunctionComponent< ...navigatorItemProps, childOrAttribute: props.navigatorEntry.childOrAttribute, elementPath: props.navigatorEntry.elementPath, + isOutletOrDescendantOfOutlet: false, } return } @@ -358,6 +359,7 @@ export const NavigatorItemWrapper: React.FunctionComponent< const entryProps: ConditionalClauseNavigatorItemContainerProps = { ...navigatorItemProps, navigatorEntry: props.navigatorEntry, + isOutletOrDescendantOfOutlet: false, } return } @@ -366,6 +368,7 @@ export const NavigatorItemWrapper: React.FunctionComponent< const entryProps: ErrorNavigatorItemContainerProps = { ...navigatorItemProps, navigatorEntry: props.navigatorEntry, + isOutletOrDescendantOfOutlet: false, } return diff --git a/editor/src/components/navigator/navigator-item/navigator-item.tsx b/editor/src/components/navigator/navigator-item/navigator-item.tsx index 0b7fbb895229..3fcd299e6bc6 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item.tsx @@ -57,6 +57,7 @@ import { NavigatorItemActionSheet } from './navigator-item-components' import { assertNever } from '../../../core/shared/utils' import type { ElementPathTrees } from '../../../core/shared/element-path-tree' import { MapCounter } from './map-counter' +import { Outlet } from 'react-router' export function getItemHeight(navigatorEntry: NavigatorEntry): number { if (isConditionalClauseNavigatorEntry(navigatorEntry)) { @@ -392,6 +393,7 @@ const elementWarningsSelector = createCachedSelector( )((_, navigatorEntry) => navigatorEntryToKey(navigatorEntry)) type CodeItemType = 'conditional' | 'map' | 'code' | 'none' | 'remix' +export type RemixItemType = 'scene' | 'outlet' | 'link' | 'none' export interface NavigatorItemInnerProps { navigatorEntry: NavigatorEntry @@ -406,6 +408,7 @@ export interface NavigatorItemInnerProps { renamingTarget: ElementPath | null selected: boolean parentOutline: ParentOutline + isOutletOrDescendantOfOutlet: boolean visibleNavigatorTargets: Array } @@ -419,6 +422,7 @@ export const NavigatorItem: React.FunctionComponent< selected, collapsed, navigatorEntry, + isOutletOrDescendantOfOutlet, getSelectedViewsInRange, index, } = props @@ -551,7 +555,8 @@ export const NavigatorItem: React.FunctionComponent< } if ( MetadataUtils.isProbablyRemixOutletFromMetadata(elementMetadata) || - MetadataUtils.isProbablyRemixSceneFromMetadata(elementMetadata) + MetadataUtils.isProbablyRemixSceneFromMetadata(elementMetadata) || + MetadataUtils.isProbablyRemixLinkFromMetadata(elementMetadata) ) { return 'remix' } @@ -560,6 +565,27 @@ export const NavigatorItem: React.FunctionComponent< 'NavigatorItem codeItemType', ) + const remixItemType: RemixItemType = useEditorState( + Substores.metadata, + (store) => { + const elementMetadata = MetadataUtils.findElementByElementPath( + store.editor.jsxMetadata, + props.navigatorEntry.elementPath, + ) + if (MetadataUtils.isProbablyRemixSceneFromMetadata(elementMetadata)) { + return 'scene' + } + if (MetadataUtils.isProbablyRemixOutletFromMetadata(elementMetadata)) { + return 'outlet' + } + if (MetadataUtils.isProbablyRemixLinkFromMetadata(elementMetadata)) { + return 'link' + } + return 'none' + }, + 'NavigatorItem remixItemType', + ) + const isConditional = codeItemType === 'conditional' const isRemixItem = codeItemType === 'remix' const isCodeItem = codeItemType !== 'none' @@ -740,7 +766,9 @@ export const NavigatorItem: React.FunctionComponent<
{ const isComponentScene = useIsProbablyScene(props.navigatorEntry) && props.childComponentCount === 1 + const isRemixScene = props.remixItemType === 'scene' + const isOutlet = props.remixItemType === 'outlet' + const isLink = props.remixItemType === 'link' + + const backgroundLozengeColor = + isCodeItem && !props.selected + ? colorTheme.dynamicBlue10.value + : isOutlet && !props.selected + ? colorTheme.aqua10.value + : 'transparent' + + const textColor = isCodeItem + ? colorTheme.dynamicBlue.value + : isRemixItem + ? colorTheme.aqua.value + : isComponentScene + ? colorTheme.componentPurple.value + : undefined + return (
{ height: 22, paddingLeft: 10, paddingRight: props.codeItemType === 'map' ? 0 : 10, - backgroundColor: - isCodeItem && !props.selected ? colorTheme.dynamicBlue10.value : 'transparent', - color: isCodeItem - ? colorTheme.dynamicBlue.value - : isRemixItem - ? colorTheme.aqua.value - : isComponentScene - ? colorTheme.componentPurple.value - : undefined, + backgroundColor: backgroundLozengeColor, + color: textColor, textTransform: isCodeItem ? 'uppercase' : undefined, }} > @@ -895,6 +937,7 @@ export const NavigatorRowLabel = React.memo((props: NavigatorRowLabelProps) => { selected={props.selected} dispatch={props.dispatch} inputVisible={EP.pathsEqual(props.renamingTarget, props.navigatorEntry.elementPath)} + remixItemType={props.remixItemType} /> ( + path: ElementPath, + fn: (ancestor: ElementPath) => T | null, +): T | null { + const ancestors = getAncestors(path) + for (const ancestor of ancestors) { + const maybeFound = fn(ancestor) + if (maybeFound != null) { + return maybeFound + } + } + return null +} + export function isDescendantOf(target: ElementPath, maybeAncestor: ElementPath): boolean { const targetElementPath = target.parts const maybeAncestorElementPath = maybeAncestor.parts diff --git a/editor/src/uuiui/styles/theme/dark.ts b/editor/src/uuiui/styles/theme/dark.ts index 8699f627fbf5..9bae5e56b928 100644 --- a/editor/src/uuiui/styles/theme/dark.ts +++ b/editor/src/uuiui/styles/theme/dark.ts @@ -34,6 +34,7 @@ const darkBase = { unavailableGrey: createUtopiColor('oklch(100% 0 0 / 22%)'), unavailableGrey10: createUtopiColor('oklch(100% 0 0 / 10%)'), aqua: createUtopiColor('oklch(86% 0.135 208.71)'), + aqua10: createUtopiColor('oklch(86% 0.135 208.71 / 10%)'), aqua05solid: createUtopiColor('oklch(0.41 0.03 238.48)'), bg510solid: createUtopiColor('oklch(0.41 0.02 269.74)'), bg0: createUtopiColor('#000000'), diff --git a/editor/src/uuiui/styles/theme/light.ts b/editor/src/uuiui/styles/theme/light.ts index d4a8da90c3c6..751b4d156845 100644 --- a/editor/src/uuiui/styles/theme/light.ts +++ b/editor/src/uuiui/styles/theme/light.ts @@ -1,4 +1,3 @@ -import { MapLike } from 'typescript' import { UtopiColor, createUtopiColor, enforceUtopiColorTheme } from '../utopi-color-helpers' import type { dark } from './dark' @@ -35,6 +34,7 @@ const lightBase = { unavailableGrey: createUtopiColor('oklch(0% 0 0 / 22%)'), unavailableGrey10: createUtopiColor('oklch(0% 0 0 / 10%)'), aqua: createUtopiColor('oklch(0.74 0.18 218.28)'), + aqua10: createUtopiColor('oklch(0.74 0.18 218.28 / 10%)'), aqua05solid: createUtopiColor('oklch(0.95 0.02 208.7)'), bg510solid: createUtopiColor('oklch(0.95 0 0)'), bg0: createUtopiColor('hsl(0,0%,100%)'),