From 920c6d4e7693a9040e82956e1e4ca93070043790 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Tue, 30 Jun 2026 16:26:49 +0200 Subject: [PATCH] :bug: Fix token tooltips on numeric-input, color and typography (#10480) --- .../workspace/get-file-token-tooltip.json | 382 ++++++++++++++++++ .../playwright/ui/specs/tokens/apply.spec.js | 374 ++++++++++++++++- .../ui/ds/controls/utilities/token_field.cljs | 28 +- .../options/menus/token_typography_row.cljs | 32 +- .../options/menus/token_typography_row.scss | 3 +- .../sidebar/options/rows/color_row.cljs | 56 ++- .../tokens/management/token_pill.cljs | 2 +- frontend/translations/en.po | 5 + frontend/translations/es.po | 4 + 9 files changed, 854 insertions(+), 32 deletions(-) create mode 100644 frontend/playwright/data/workspace/get-file-token-tooltip.json diff --git a/frontend/playwright/data/workspace/get-file-token-tooltip.json b/frontend/playwright/data/workspace/get-file-token-tooltip.json new file mode 100644 index 0000000000..55a35d9d60 --- /dev/null +++ b/frontend/playwright/data/workspace/get-file-token-tooltip.json @@ -0,0 +1,382 @@ +{ + "~:features": { + "~#set": [ + "design-tokens/v1", + "layout/grid", + "fdata/pointer-map", + "fdata/objects-map", + "components/v2", + "fdata/shape-data-type" + ] + }, + "~:permissions": { + "~:type": "~:membership", + "~:is-owner": true, + "~:is-admin": true, + "~:can-edit": true, + "~:can-read": true, + "~:is-logged": true + }, + "~:has-media-trimmed": false, + "~:comment-thread-seqn": 0, + "~:name": "Tooltip check", + "~:revn": 36, + "~:modified-at": "~m1737542758402", + "~:vern": 0, + "~:id": "~uc7ce0794-0992-8105-8004-38f280443849", + "~:is-shared": false, + "~:version": 60, + "~:project-id": "~u0df61468-6cbf-8067-8005-6b453ce996d0", + "~:created-at": "~m1737536563847", + "~:data": { + "~:pages": [ + "~u4530574a-7a0a-807b-8008-0107b2c4628e" + ], + "~:pages-index": { + "~u4530574a-7a0a-807b-8008-0107b2c4628e": { + "~:id": "~u4530574a-7a0a-807b-8008-0107b2c4628e", + "~:name": "Page 1", + "~:objects": { + "~#penpot/objects-map/v2": { + "~u00000000-0000-0000-0000-000000000000": "[\"~#shape\",[\"^ \",\"~:y\",0,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:name\",\"Root Frame\",\"~:width\",0.01,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",0.0,\"~:y\",0.0]],[\"^:\",[\"^ \",\"~:x\",0.01,\"~:y\",0.0]],[\"^:\",[\"^ \",\"~:x\",0.01,\"~:y\",0.01]],[\"^:\",[\"^ \",\"~:x\",0.0,\"~:y\",0.01]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u4530574a-7a0a-807b-8008-0107b2c4628e\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",0,\"~:proportion\",1.0,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",0,\"~:y\",0,\"^6\",0.01,\"~:height\",0.01,\"~:x1\",0,\"~:y1\",0,\"~:x2\",0.01,\"~:y2\",0.01]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^I\",0.01,\"~:flip-y\",null,\"~:shapes\",[\"~ua7df6ab8-bee5-802f-8008-010d9ff3da26\",\"~uf2256046-b127-808e-8008-411c4cba63d8\",\"~u1de8c150-538b-80b2-8008-40356208fc39\",\"~uf2256046-b127-808e-8008-411c4cba63d9\",\"~u1de8c150-538b-80b2-8008-4036773cc8d0\",\"~u886f2846-a2c5-808d-8008-4115e86119e9\",\"~u1de8c150-538b-80b2-8008-403b5150a59b\",\"~u886f2846-a2c5-808d-8008-4115e86119ea\",\"~u20f9ccb0-68e2-80d9-8008-413fa842a6b5\",\"~u20f9ccb0-68e2-80d9-8008-413fb1f2ef51\"]]]", + "~u1de8c150-538b-80b2-8008-403b5150a59b": "[\"~#shape\",[\"^ \",\"~:y\",419,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Deleted token rect\",\"~:width\",162,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",-147,\"~:y\",419]],[\"^<\",[\"^ \",\"~:x\",15,\"~:y\",419]],[\"^<\",[\"^ \",\"~:x\",15,\"~:y\",565]],[\"^<\",[\"^ \",\"~:x\",-147,\"~:y\",565]]],\"~:r2\",20,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",20,\"~:r1\",20,\"~:id\",\"~u1de8c150-538b-80b2-8008-403b5150a59b\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:applied-tokens\",[\"^ \",\"~:fill\",\"blue\",\"^A\",\"deleted\",\"^=\",\"deleted\",\"^@\",\"deleted\",\"~:r4\",\"deleted\"],\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",-147,\"~:proportion\",1,\"^F\",20,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",-147,\"~:y\",419,\"^8\",162,\"~:height\",146,\"~:x1\",-147,\"~:y1\",419,\"~:x2\",15,\"~:y2\",565]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#0a20bf\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^L\",146,\"~:flip-y\",null]]", + "~u20f9ccb0-68e2-80d9-8008-413fa842a6b5": "[\"~#shape\",[\"^ \",\"~:y\",369,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle with token\",\"~:width\",274.99999999999994,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",-536,\"~:y\",369]],[\"^<\",[\"^ \",\"~:x\",-261.00000000000006,\"~:y\",369]],[\"^<\",[\"^ \",\"~:x\",-261.00000000000006,\"~:y\",565]],[\"^<\",[\"^ \",\"~:x\",-536,\"~:y\",565]]],\"~:r2\",50,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",50,\"~:r1\",50,\"~:id\",\"~u20f9ccb0-68e2-80d9-8008-413fa842a6b5\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:applied-tokens\",[\"^ \",\"~:fill\",\"out-ref\",\"^A\",\"base-50\",\"^=\",\"base-50\",\"^@\",\"base-50\",\"~:r4\",\"base-50\"],\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",-536,\"~:proportion\",1,\"^F\",50,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",-536,\"~:y\",369,\"^8\",274.99999999999994,\"~:height\",196,\"~:x1\",-536,\"~:y1\",369,\"~:x2\",-261.00000000000006,\"~:y2\",565]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#da1fea\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^L\",196,\"~:flip-y\",null]]", + "~u1de8c150-538b-80b2-8008-4036773cc8d0": "[\"~#shape\",[\"^ \",\"~:y\",588,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:content\",[\"^ \",\"~:type\",\"root\",\"~:children\",[[\"^ \",\"^7\",\"paragraph-set\",\"^8\",[[\"^ \",\"~:line-height\",\"1.2\",\"~:font-style\",\"normal\",\"^8\",[[\"^ \",\"^9\",\"1.2\",\"^:\",\"normal\",\"~:text-transform\",\"none\",\"~:text-align\",\"left\",\"~:font-id\",\"gfont-alegreya-sans-sc\",\"~:font-size\",\"23\",\"~:font-weight\",\"400\",\"~:text-direction\",\"ltr\",\"~:font-variant-id\",\"regular\",\"~:text-decoration\",\"none\",\"~:letter-spacing\",\"0\",\"~:fills\",[[\"^ \",\"~:fill-color\",\"#000000\",\"~:fill-opacity\",1]],\"~:font-family\",\"Alegreya Sans SC\",\"~:text\",\"Text with deleted token\"]],\"^;\",\"none\",\"^<\",\"left\",\"^=\",\"gfont-alegreya-sans-sc\",\"~:key\",\"fu3vh\",\"^>\",\"23\",\"^?\",\"400\",\"^@\",\"ltr\",\"^7\",\"paragraph\",\"^A\",\"regular\",\"^B\",\"none\",\"^C\",\"0\",\"^D\",[[\"^ \",\"^E\",\"#000000\",\"^F\",1]],\"^G\",\"Alegreya Sans SC\"]]]]],\"~:hide-in-viewer\",false,\"~:name\",\"Text with deleted token\",\"~:width\",198,\"^7\",\"^H\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",-161,\"~:y\",588]],[\"^N\",[\"^ \",\"~:x\",37,\"~:y\",588]],[\"^N\",[\"^ \",\"~:x\",37,\"~:y\",641]],[\"^N\",[\"^ \",\"~:x\",-161,\"~:y\",641]]],\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:id\",\"~u1de8c150-538b-80b2-8008-4036773cc8d0\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:applied-tokens\",[\"^ \",\"~:typography\",\"deleted-typo\"],\"~:position-data\",[[\"~#rect\",[\"^ \",\"~:y\",613,\"^:\",\"normal\",\"^;\",\"none\",\"^>\",\"23px\",\"^?\",\"400\",\"~:y1\",2,\"^L\",176.203125,\"^B\",\"none\",\"^C\",\"normal\",\"~:x\",-161,\"~:x1\",0,\"~:y2\",25,\"^D\",[[\"^ \",\"^E\",\"#000000\",\"^F\",1]],\"~:x2\",176.203125,\"~:direction\",\"ltr\",\"^G\",\"\\\"Alegreya Sans SC\\\"\",\"~:height\",23,\"^H\",\"Text with deleted \"]],[\"^U\",[\"^ \",\"~:y\",640.59375,\"^:\",\"normal\",\"^;\",\"none\",\"^>\",\"23px\",\"^?\",\"400\",\"^V\",29.59375,\"^L\",56.9375,\"^B\",\"none\",\"^C\",\"normal\",\"~:x\",-161,\"^W\",0,\"^X\",52.59375,\"^D\",[[\"^ \",\"^E\",\"#000000\",\"^F\",1]],\"^Y\",56.9375,\"^Z\",\"ltr\",\"^G\",\"\\\"Alegreya Sans SC\\\"\",\"^[\",23,\"^H\",\"token\"]]],\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:x\",-161,\"~:selrect\",[\"^U\",[\"^ \",\"~:x\",-161,\"~:y\",588,\"^L\",198,\"^[\",53,\"^W\",-161,\"^V\",588,\"^Y\",37,\"^X\",641]],\"~:flip-x\",null,\"^[\",53,\"~:flip-y\",null]]", + "~u20f9ccb0-68e2-80d9-8008-413fb1f2ef51": "[\"~#shape\",[\"^ \",\"~:y\",609,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:content\",[\"^ \",\"~:type\",\"root\",\"~:children\",[[\"^ \",\"^7\",\"paragraph-set\",\"^8\",[[\"^ \",\"~:line-height\",\"1.2\",\"~:font-style\",\"normal\",\"^8\",[[\"^ \",\"^9\",\"1.2\",\"^:\",\"normal\",\"~:text-transform\",\"none\",\"~:text-align\",\"left\",\"~:font-id\",\"gfont-arizonia\",\"~:font-size\",\"23\",\"~:font-weight\",\"400\",\"~:text-direction\",\"ltr\",\"~:font-variant-id\",\"regular\",\"~:text-decoration\",\"none\",\"~:letter-spacing\",\"0\",\"~:fills\",[[\"^ \",\"~:fill-color\",\"#da1fea\",\"~:fill-opacity\",1]],\"~:font-family\",\"Arizonia\",\"~:text\",\"Text with token\"]],\"^;\",\"none\",\"^<\",\"left\",\"^=\",\"gfont-arizonia\",\"~:key\",\"fu3vh\",\"^>\",\"23\",\"^?\",\"400\",\"^@\",\"ltr\",\"^7\",\"paragraph\",\"^A\",\"regular\",\"^B\",\"none\",\"^C\",\"0\",\"^D\",[[\"^ \",\"^E\",\"#da1fea\",\"^F\",1]],\"^G\",\"Arizonia\"]]]]],\"~:hide-in-viewer\",false,\"~:name\",\"Text with token\",\"~:width\",198,\"^7\",\"^H\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",-516,\"~:y\",609]],[\"^N\",[\"^ \",\"~:x\",-318,\"~:y\",609]],[\"^N\",[\"^ \",\"~:x\",-318,\"~:y\",662]],[\"^N\",[\"^ \",\"~:x\",-516,\"~:y\",662]]],\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:id\",\"~u20f9ccb0-68e2-80d9-8008-413fb1f2ef51\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:applied-tokens\",[\"^ \",\"~:typography\",\"out-typo\",\"~:fill\",\"out-ref\"],\"~:position-data\",[[\"~#rect\",[\"^ \",\"~:y\",637,\"^:\",\"normal\",\"^;\",\"none\",\"^>\",\"23px\",\"^?\",\"400\",\"~:y1\",-1,\"^L\",117.453125,\"^B\",\"none\",\"^C\",\"normal\",\"~:x\",-516,\"~:x1\",0,\"~:y2\",28,\"^D\",[[\"^ \",\"^E\",\"#da1fea\",\"^F\",1]],\"~:x2\",117.453125,\"~:direction\",\"ltr\",\"^G\",\"Arizonia\",\"~:height\",29,\"^H\",\"Text with token\"]]],\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",-516,\"~:selrect\",[\"^V\",[\"^ \",\"~:x\",-516,\"~:y\",609,\"^L\",198,\"^10\",53,\"^X\",-516,\"^W\",609,\"^Z\",-318,\"^Y\",662]],\"~:flip-x\",null,\"^10\",53,\"~:flip-y\",null]]", + "~uf2256046-b127-808e-8008-411c4cba63d8": "[\"~#shape\",[\"^ \",\"~:y\",267,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle with not active reference\",\"~:width\",287,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",390,\"~:y\",267]],[\"^<\",[\"^ \",\"~:x\",677,\"~:y\",267]],[\"^<\",[\"^ \",\"~:x\",677,\"~:y\",579]],[\"^<\",[\"^ \",\"~:x\",390,\"~:y\",579]]],\"~:r2\",50,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u4530574a-7a0a-807b-8008-0107b2c4628e\",\"~:r3\",50,\"~:r1\",50,\"~:id\",\"~uf2256046-b127-808e-8008-411c4cba63d8\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:applied-tokens\",[\"^ \",\"~:fill\",\"in-color\",\"^=\",\"in-br\",\"^A\",\"in-br\",\"^B\",\"in-br\",\"~:r4\",\"in-br\"],\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",390,\"~:proportion\",1,\"^G\",50,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",390,\"~:y\",267,\"^8\",287,\"~:height\",312,\"~:x1\",390,\"~:y1\",267,\"~:x2\",677,\"~:y2\",579]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#da1fea\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^M\",312,\"~:flip-y\",null]]", + "~uf2256046-b127-808e-8008-411c4cba63d9": "[\"~#shape\",[\"^ \",\"~:y\",602,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:content\",[\"^ \",\"~:type\",\"root\",\"~:children\",[[\"^ \",\"^7\",\"paragraph-set\",\"^8\",[[\"^ \",\"~:line-height\",\"1.2\",\"^8\",[[\"^ \",\"^9\",\"1.2\",\"~:text-transform\",\"none\",\"~:text-align\",\"left\",\"~:font-id\",\"gfont-arizonia\",\"~:font-size\",\"14\",\"~:font-weight\",\"200\",\"~:text-direction\",\"ltr\",\"~:font-variant-id\",\"regular\",\"~:weight\",\"200\",\"~:text-decoration\",\"none\",\"~:letter-spacing\",\"0\",\"~:fills\",[[\"^ \",\"~:fill-color\",\"#da1fea\",\"~:fill-opacity\",1]],\"~:font-family\",\"Arizonia\",\"~:text\",\"Text with not active reference\"]],\"^:\",\"none\",\"^;\",\"left\",\"^<\",\"gfont-arizonia\",\"~:key\",\"d22fo\",\"^=\",\"14\",\"^>\",\"200\",\"^?\",\"ltr\",\"^7\",\"paragraph\",\"^@\",\"regular\",\"^A\",\"200\",\"^B\",\"none\",\"^C\",\"0\",\"^D\",[[\"^ \",\"^E\",\"#da1fea\",\"^F\",1]],\"^G\",\"Arizonia\"]]]]],\"~:hide-in-viewer\",false,\"~:name\",\"Text with not active reference\",\"~:width\",139,\"^7\",\"^H\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",479,\"~:y\",602]],[\"^N\",[\"^ \",\"~:x\",618,\"~:y\",602]],[\"^N\",[\"^ \",\"~:x\",618,\"~:y\",630]],[\"^N\",[\"^ \",\"~:x\",479,\"~:y\",630]]],\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:id\",\"~uf2256046-b127-808e-8008-411c4cba63d9\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:applied-tokens\",[\"^ \",\"~:fill\",\"in-color\",\"~:typography\",\"in-typo\"],\"~:position-data\",[[\"~#rect\",[\"^ \",\"~:y\",619,\"~:font-style\",\"normal\",\"^:\",\"none\",\"^=\",\"14px\",\"^>\",\"400\",\"~:y1\",-1,\"^L\",97.46875,\"^B\",\"none\",\"^C\",\"normal\",\"~:x\",479,\"~:x1\",0,\"~:y2\",17,\"^D\",[[\"^ \",\"^E\",\"#da1fea\",\"^F\",1]],\"~:x2\",97.46875,\"~:direction\",\"ltr\",\"^G\",\"Arizonia\",\"~:height\",18,\"^H\",\"Text with not active \"]],[\"^V\",[\"^ \",\"~:y\",635.796875,\"^W\",\"normal\",\"^:\",\"none\",\"^=\",\"14px\",\"^>\",\"400\",\"^X\",15.796875,\"^L\",42.8125,\"^B\",\"none\",\"^C\",\"normal\",\"~:x\",479,\"^Y\",0,\"^Z\",33.796875,\"^D\",[[\"^ \",\"^E\",\"#da1fea\",\"^F\",1]],\"^[\",42.8125,\"^10\",\"ltr\",\"^G\",\"Arizonia\",\"^11\",18,\"^H\",\"reference\"]]],\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:x\",479,\"~:selrect\",[\"^V\",[\"^ \",\"~:x\",479,\"~:y\",602,\"^L\",139,\"^11\",28,\"^Y\",479,\"^X\",602,\"^[\",618,\"^Z\",630]],\"~:flip-x\",null,\"^11\",28,\"~:flip-y\",null]]", + "~u1de8c150-538b-80b2-8008-40356208fc39": "[\"~#shape\",[\"^ \",\"~:y\",609,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:content\",[\"^ \",\"~:type\",\"root\",\"~:children\",[[\"^ \",\"^7\",\"paragraph-set\",\"^8\",[[\"^ \",\"~:line-height\",\"1.2\",\"^8\",[[\"^ \",\"^9\",\"1.2\",\"~:text-transform\",\"none\",\"~:text-align\",\"left\",\"~:font-id\",\"gfont-ar-one-sans\",\"~:font-size\",\"14\",\"~:font-weight\",\"200\",\"~:text-direction\",\"ltr\",\"~:font-variant-id\",\"regular\",\"~:weight\",\"200\",\"~:text-decoration\",\"none\",\"~:letter-spacing\",\"0\",\"~:fills\",[[\"^ \",\"~:fill-color\",\"#ef0c0c\",\"~:fill-opacity\",1]],\"~:font-family\",\"AR One Sans\",\"~:text\",\"Text with not active token\"]],\"^:\",\"none\",\"^;\",\"left\",\"^<\",\"gfont-ar-one-sans\",\"~:key\",\"d22fo\",\"^=\",\"14\",\"^>\",\"200\",\"^?\",\"ltr\",\"^7\",\"paragraph\",\"^@\",\"regular\",\"^A\",\"200\",\"^B\",\"none\",\"^C\",\"0\",\"^D\",[[\"^ \",\"^E\",\"#ef0c0c\",\"^F\",1]],\"^G\",\"AR One Sans\"]]]]],\"~:hide-in-viewer\",false,\"~:name\",\"Text with not active token\",\"~:width\",139,\"^7\",\"^H\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",812,\"~:y\",609]],[\"^N\",[\"^ \",\"~:x\",951,\"~:y\",609]],[\"^N\",[\"^ \",\"~:x\",951,\"~:y\",637]],[\"^N\",[\"^ \",\"~:x\",812,\"~:y\",637]]],\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:id\",\"~u1de8c150-538b-80b2-8008-40356208fc39\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:applied-tokens\",[\"^ \",\"~:fill\",\"red\",\"~:typography\",\"typo-2\"],\"~:position-data\",[[\"~#rect\",[\"^ \",\"~:y\",626,\"~:font-style\",\"normal\",\"^:\",\"none\",\"^=\",\"14px\",\"^>\",\"400\",\"~:y1\",-2,\"^L\",134.625,\"^B\",\"none\",\"^C\",\"normal\",\"~:x\",812,\"~:x1\",0,\"~:y2\",17,\"^D\",[[\"^ \",\"^E\",\"#ef0c0c\",\"^F\",1]],\"~:x2\",134.625,\"~:direction\",\"ltr\",\"^G\",\"\\\"AR One Sans\\\"\",\"~:height\",19,\"^H\",\"Text with not active \"]],[\"^V\",[\"^ \",\"~:y\",642.796875,\"^W\",\"normal\",\"^:\",\"none\",\"^=\",\"14px\",\"^>\",\"400\",\"^X\",14.796875,\"^L\",37.40625,\"^B\",\"none\",\"^C\",\"normal\",\"~:x\",812,\"^Y\",0,\"^Z\",33.796875,\"^D\",[[\"^ \",\"^E\",\"#ef0c0c\",\"^F\",1]],\"^[\",37.40625,\"^10\",\"ltr\",\"^G\",\"\\\"AR One Sans\\\"\",\"^11\",19,\"^H\",\"token\"]]],\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:x\",812,\"~:selrect\",[\"^V\",[\"^ \",\"~:x\",812,\"~:y\",609,\"^L\",139,\"^11\",28,\"^Y\",812,\"^X\",609,\"^[\",951,\"^Z\",637]],\"~:flip-x\",null,\"^11\",28,\"~:flip-y\",null]]", + "~u886f2846-a2c5-808d-8008-4115e86119ea": "[\"~#shape\",[\"^ \",\"~:y\",399,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle with deleted reference\",\"~:width\",162,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",193,\"~:y\",399]],[\"^<\",[\"^ \",\"~:x\",355,\"~:y\",399]],[\"^<\",[\"^ \",\"~:x\",355,\"~:y\",545]],[\"^<\",[\"^ \",\"~:x\",193,\"~:y\",545]]],\"~:r2\",20,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",20,\"~:r1\",20,\"~:id\",\"~u886f2846-a2c5-808d-8008-4115e86119ea\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:applied-tokens\",[\"^ \",\"~:fill\",\"ref-grfeen\",\"^A\",\"ref-1\",\"^=\",\"ref-1\",\"^@\",\"ref-1\",\"~:r4\",\"ref-1\"],\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",193,\"~:proportion\",1,\"^F\",20,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",193,\"~:y\",399,\"^8\",162,\"~:height\",146,\"~:x1\",193,\"~:y1\",399,\"~:x2\",355,\"~:y2\",545]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#0a20bf\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^L\",146,\"~:flip-y\",null]]", + "~u886f2846-a2c5-808d-8008-4115e86119e9": "[\"~#shape\",[\"^ \",\"~:y\",586,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:content\",[\"^ \",\"~:type\",\"root\",\"~:children\",[[\"^ \",\"^7\",\"paragraph-set\",\"^8\",[[\"^ \",\"~:line-height\",\"1.2\",\"~:font-style\",\"normal\",\"^8\",[[\"^ \",\"^9\",\"1.2\",\"^:\",\"normal\",\"~:text-transform\",\"none\",\"~:text-align\",\"left\",\"~:font-id\",\"gfont-adlam-display\",\"~:font-size\",\"23\",\"~:font-weight\",\"400\",\"~:text-direction\",\"ltr\",\"~:font-variant-id\",\"regular\",\"~:text-decoration\",\"none\",\"~:letter-spacing\",\"0\",\"~:fills\",[[\"^ \",\"~:fill-color\",\"#000000\",\"~:fill-opacity\",1]],\"~:font-family\",\"ADLaM Display\",\"~:text\",\"Text with deleted reference\"]],\"^;\",\"none\",\"^<\",\"left\",\"^=\",\"gfont-adlam-display\",\"~:key\",\"fu3vh\",\"^>\",\"23\",\"^?\",\"400\",\"^@\",\"ltr\",\"^7\",\"paragraph\",\"^A\",\"regular\",\"^B\",\"none\",\"^C\",\"0\",\"^D\",[[\"^ \",\"^E\",\"#000000\",\"^F\",1]],\"^G\",\"ADLaM Display\"]]]]],\"~:hide-in-viewer\",false,\"~:name\",\"Text with deleted reference\",\"~:width\",137,\"^7\",\"^H\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",198,\"~:y\",586]],[\"^N\",[\"^ \",\"~:x\",335,\"~:y\",586]],[\"^N\",[\"^ \",\"~:x\",335,\"~:y\",683]],[\"^N\",[\"^ \",\"~:x\",198,\"~:y\",683]]],\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:id\",\"~u886f2846-a2c5-808d-8008-4115e86119e9\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:applied-tokens\",[\"^ \",\"~:fill\",\"ref-grfeen\",\"~:typography\",\"ref-typo\"],\"~:position-data\",[[\"~#rect\",[\"^ \",\"~:y\",614,\"^:\",\"normal\",\"^;\",\"none\",\"^>\",\"23px\",\"^?\",\"400\",\"~:y1\",-2,\"^L\",107.921875,\"^B\",\"none\",\"^C\",\"normal\",\"~:x\",198,\"~:x1\",0,\"~:y2\",28,\"^D\",[[\"^ \",\"^E\",\"#000000\",\"^F\",1]],\"~:x2\",107.921875,\"~:direction\",\"ltr\",\"^G\",\"\\\"ADLaM Display\\\"\",\"~:height\",30,\"^H\",\"Text with \"]],[\"^V\",[\"^ \",\"~:y\",641.59375,\"^:\",\"normal\",\"^;\",\"none\",\"^>\",\"23px\",\"^?\",\"400\",\"^W\",25.59375,\"^L\",88.890625,\"^B\",\"none\",\"^C\",\"normal\",\"~:x\",198,\"^X\",0,\"^Y\",55.59375,\"^D\",[[\"^ \",\"^E\",\"#000000\",\"^F\",1]],\"^Z\",88.890625,\"^[\",\"ltr\",\"^G\",\"\\\"ADLaM Display\\\"\",\"^10\",30,\"^H\",\"deleted \"]],[\"^V\",[\"^ \",\"~:y\",669.1875,\"^:\",\"normal\",\"^;\",\"none\",\"^>\",\"23px\",\"^?\",\"400\",\"^W\",53.1875,\"^L\",103.46875,\"^B\",\"none\",\"^C\",\"normal\",\"~:x\",198,\"^X\",0,\"^Y\",83.1875,\"^D\",[[\"^ \",\"^E\",\"#000000\",\"^F\",1]],\"^Z\",103.46875,\"^[\",\"ltr\",\"^G\",\"\\\"ADLaM Display\\\"\",\"^10\",30,\"^H\",\"reference\"]]],\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:x\",198,\"~:selrect\",[\"^V\",[\"^ \",\"~:x\",198,\"~:y\",586,\"^L\",137,\"^10\",97,\"^X\",198,\"^W\",586,\"^Z\",335,\"^Y\",683]],\"~:flip-x\",null,\"^10\",97,\"~:flip-y\",null]]", + "~ua7df6ab8-bee5-802f-8008-010d9ff3da26": "[\"~#shape\",[\"^ \",\"~:y\",274,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle with not active token\",\"~:width\",287,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",723,\"~:y\",274]],[\"^<\",[\"^ \",\"~:x\",1010,\"~:y\",274]],[\"^<\",[\"^ \",\"~:x\",1010,\"~:y\",586]],[\"^<\",[\"^ \",\"~:x\",723,\"~:y\",586]]],\"~:r2\",100,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u4530574a-7a0a-807b-8008-0107b2c4628e\",\"~:r3\",100,\"~:r1\",100,\"~:id\",\"~ua7df6ab8-bee5-802f-8008-010d9ff3da26\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:applied-tokens\",[\"^ \",\"~:fill\",\"red\",\"^B\",\"border-radius\",\"^=\",\"border-radius\",\"^A\",\"border-radius\",\"~:r4\",\"border-radius\"],\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",723,\"~:proportion\",1,\"^G\",100,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",723,\"~:y\",274,\"^8\",287,\"~:height\",312,\"~:x1\",723,\"~:y1\",274,\"~:x2\",1010,\"~:y2\",586]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#ef0c0c\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^M\",312,\"~:flip-y\",null]]" + } + } + } + }, + "~:tokens-lib": { + "~#penpot/tokens-lib": { + "~:sets": { + "~#ordered-map": [ + [ + "S-Global", + { + "~#penpot/token-set": { + "~:id": "~uf71719b3-63a1-8157-8008-40346917de8c", + "~:name": "Global", + "~:description": "", + "~:modified-at": "~m1782813028640", + "~:tokens": { + "~#ordered-map": [ + [ + "base-50", + { + "~#penpot/token": { + "~:id": "~uf71719b3-63a1-8157-8008-40346917de87", + "~:name": "base-50", + "~:type": "~:border-radius", + "~:value": "50", + "~:description": "", + "~:modified-at": "~m1782742859871" + } + } + ], + [ + "out-ref", + { + "~#penpot/token": { + "~:id": "~uf2256046-b127-808e-8008-411bec9b1109", + "~:name": "out-ref", + "~:type": "~:color", + "~:value": "rgb(218, 31, 234)", + "~:description": "", + "~:modified-at": "~m1782803549804" + } + } + ], + [ + "out-typo", + { + "~#penpot/token": { + "~:id": "~uf2256046-b127-808e-8008-411bf90df57e", + "~:name": "out-typo", + "~:type": "~:typography", + "~:value": { + "~:font-family": [ + "Arizonia" + ] + }, + "~:description": "", + "~:modified-at": "~m1782803562551" + } + } + ] + ] + } + } + } + ], + [ + "G-Mode", + { + "~#ordered-map": [ + [ + "S-Dark", + { + "~#penpot/token-set": { + "~:id": "~uf71719b3-63a1-8157-8008-40346917de8d", + "~:name": "Mode/Dark", + "~:description": "", + "~:modified-at": "~m1782803647245", + "~:tokens": { + "~#ordered-map": [ + [ + "red", + { + "~#penpot/token": { + "~:id": "~uf71719b3-63a1-8157-8008-40346917de88", + "~:name": "red", + "~:type": "~:color", + "~:value": "#ef0c0c", + "~:description": "", + "~:modified-at": "~m1782742859871" + } + } + ], + [ + "ref-grfeen", + { + "~#penpot/token": { + "~:id": "~u886f2846-a2c5-808d-8008-4115e5fdae2e", + "~:name": "ref-grfeen", + "~:type": "~:color", + "~:value": "{green}", + "~:description": "", + "~:modified-at": "~m1782801970166" + } + } + ], + [ + "ref-typo", + { + "~#penpot/token": { + "~:id": "~u886f2846-a2c5-808d-8008-41160c4641f4", + "~:name": "ref-typo", + "~:type": "~:typography", + "~:value": "{typo1}", + "~:description": "", + "~:modified-at": "~m1782802009369" + } + } + ], + [ + "ref-1", + { + "~#penpot/token": { + "~:id": "~u886f2846-a2c5-808d-8008-411628261dc7", + "~:name": "ref-1", + "~:type": "~:border-radius", + "~:value": "{b1}", + "~:description": "", + "~:modified-at": "~m1782802037912" + } + } + ], + [ + "in-br", + { + "~#penpot/token": { + "~:id": "~uf2256046-b127-808e-8008-411c0aced089", + "~:name": "in-br", + "~:type": "~:border-radius", + "~:value": "{base-50}", + "~:description": "", + "~:modified-at": "~m1782803580731" + } + } + ], + [ + "in-color", + { + "~#penpot/token": { + "~:id": "~uf2256046-b127-808e-8008-411c263c999b", + "~:name": "in-color", + "~:type": "~:color", + "~:value": "{out-ref}", + "~:description": "", + "~:modified-at": "~m1782803608818" + } + } + ], + [ + "in-typo", + { + "~#penpot/token": { + "~:id": "~uf2256046-b127-808e-8008-411c472f33d3", + "~:name": "in-typo", + "~:type": "~:typography", + "~:value": "{out-typo}", + "~:description": "", + "~:modified-at": "~m1782803642556" + } + } + ] + ] + } + } + } + ], + [ + "S-Light", + { + "~#penpot/token-set": { + "~:id": "~uf71719b3-63a1-8157-8008-40346917de8e", + "~:name": "Mode/Light", + "~:description": "", + "~:modified-at": "~m1782812999332", + "~:tokens": { + "~#ordered-map": [ + [ + "red", + { + "~#penpot/token": { + "~:id": "~uf71719b3-63a1-8157-8008-40346917de89", + "~:name": "red", + "~:type": "~:color", + "~:value": "#ec9090", + "~:description": "", + "~:modified-at": "~m1782742859871" + } + } + ], + [ + "typo-2", + { + "~#penpot/token": { + "~:id": "~u1de8c150-538b-80b2-8008-40357ed6d13a", + "~:name": "typo-2", + "~:type": "~:typography", + "~:value": { + "~:font-family": [ + "AR One Sans" + ], + "~:font-weight": "200" + }, + "~:description": "", + "~:modified-at": "~m1782812999332" + } + } + ], + [ + "border-radius", + { + "~#penpot/token": { + "~:id": "~uf2256046-b127-808e-8008-4134c130c292", + "~:name": "border-radius", + "~:type": "~:border-radius", + "~:value": "{base-50} * 2", + "~:description": "", + "~:modified-at": "~m1782810058947" + } + } + ] + ] + } + } + } + ] + ] + } + ] + ] + }, + "~:themes": { + "~#ordered-map": [ + [ + "", + { + "~#ordered-map": [ + [ + "__PENPOT__HIDDEN__TOKEN__THEME__", + { + "~#penpot/token-theme": { + "~:id": "~u00000000-0000-0000-0000-000000000000", + "~:name": "__PENPOT__HIDDEN__TOKEN__THEME__", + "~:group": "", + "~:description": "", + "~:is-source": false, + "~:external-id": "", + "~:modified-at": "~m1782812922760", + "~:sets": { + "~#set": [ + "Global" + ] + } + } + } + ] + ] + } + ], + [ + "App", + { + "~#ordered-map": [ + [ + "Web", + { + "~#penpot/token-theme": { + "~:id": "~u37900259-7f15-8003-8007-9ee75dd2f2d2", + "~:name": "Web", + "~:group": "App", + "~:description": "", + "~:is-source": false, + "~:external-id": "37900259-7f15-8003-8007-9ee75dd2f2d2", + "~:modified-at": "~m1782810072529", + "~:sets": { + "~#set": [ + "Mode/Dark", + "Global" + ] + } + } + } + ], + [ + "Mobile", + { + "~#penpot/token-theme": { + "~:id": "~u37900259-7f15-8003-8007-9ee77eb567bd", + "~:name": "Mobile", + "~:group": "App", + "~:description": "", + "~:is-source": false, + "~:external-id": "37900259-7f15-8003-8007-9ee77eb567bd", + "~:modified-at": "~m1782810072529", + "~:sets": { + "~#set": [ + "Mode/Light", + "Global" + ] + } + } + } + ] + ] + } + ] + ] + }, + "~:active-themes": { + "~#set": [ + "/__PENPOT__HIDDEN__TOKEN__THEME__" + ] + } + } + }, + "~:id": "~u55608328-aed3-807a-8008-41341f2f7247", + "~:options": { + "~:components-v2": true, + "~:base-font-size": "16px" + } + } +} \ No newline at end of file diff --git a/frontend/playwright/ui/specs/tokens/apply.spec.js b/frontend/playwright/ui/specs/tokens/apply.spec.js index 1fb605acf2..5e9033de85 100644 --- a/frontend/playwright/ui/specs/tokens/apply.spec.js +++ b/frontend/playwright/ui/specs/tokens/apply.spec.js @@ -907,7 +907,7 @@ test.describe("Tokens: Detach token", () => { await expect(page.getByText("Don't remap")).toBeVisible(); await page.getByText("Don't remap").click(); const brokenPill = borderRadiusSection.getByRole("button", { - name: "is not in any active set", + name: "{borderRadius.sm} does not exists or has been deleted", }); await expect(brokenPill).toBeVisible(); @@ -1775,3 +1775,375 @@ test("BUG: 14234, Numeric input token filtering must be case sensitive", async ( measuresSection.getByText("dim-up", { exact: true }), ).not.toBeVisible(); }); + +test("BUG: 10471, Correct tooltip on right sidebar tokens", async ({ + page, +}) => { + const { + workspacePage, + tokensSidebar, + tokenContextMenuForToken, + tokenThemesSetsSidebar, + tokenSetGroupItems, + } = await setupTokensFileRender(page, { + file: "workspace/get-file-token-tooltip.json", + }); + + await page.getByRole("tab", { name: "Layers" }).click(); + const borderRadiusSection = page.getByRole("region", { + name: "Border radius section", + }); + + const fillSection = workspacePage.rightSidebar.getByRole("region", { + name: "Fill section", + }); + + const typographySection = workspacePage.rightSidebar.getByRole("region", { + name: "Text section", + }); + // ---------------------------------- + // Select rectangle with active token + // ---------------------------------- + await workspacePage.layers + .getByTestId("layer-row") + .filter({ hasText: "Rectangle with token" }) + .click(); + await expect(borderRadiusSection).toBeVisible(); + const brPill = borderRadiusSection.getByRole("button", { name: "base-50" }); + await expect(brPill).toBeVisible(); + await brPill.hover(); + await expect(page.getByRole("tooltip", { name: "base-50" })).toBeVisible(); + await expect(fillSection).toBeVisible(); + const fillTokenPill = fillSection.getByLabel("out-ref", { + exact: true, + }); + await expect(fillTokenPill).toBeVisible(); + await fillTokenPill.hover(); + const colorTokenTooltip = page.getByRole("tooltip", { + name: "out-ref", + }); + await expect(colorTokenTooltip).toBeVisible(); + await expect(colorTokenTooltip).toHaveText( + "Name: out-refResolved value: #da1fea", + ); + // ---------------------------------- + // Select text with active token + // ---------------------------------- + await workspacePage.layers + .getByTestId("layer-row") + .filter({ hasText: "Text with token" }) + .click(); + await expect(fillSection).toBeVisible(); + const textFillTokenPill = fillSection.getByLabel("out-ref", { + exact: true, + }); + await expect(textFillTokenPill).toBeVisible(); + await textFillTokenPill.hover(); + await expect(colorTokenTooltip).toBeVisible(); + await expect(colorTokenTooltip).toHaveText( + "Name: out-refResolved value: #da1fea", + ); + await expect(typographySection).toBeVisible(); + const typographyTokenPill = typographySection.getByLabel("out-typo", { + exact: true, + }); + await expect(typographyTokenPill).toBeVisible(); + await typographyTokenPill.hover(); + const typographyTokenTooltip = page.getByRole("tooltip", { + name: "out-typo", + }); + await expect(typographyTokenTooltip).toBeVisible(); + await expect(typographyTokenTooltip).toHaveText( + 'Name: out-typoResolved value:- font-family: "Arizonia"', + ); + // ----------------------------------------- + // Select rectangle layer with deleted token + // ----------------------------------------- + await workspacePage.layers + .getByTestId("layer-row") + .filter({ hasText: "Deleted token rect" }) + .click(); + + await expect(borderRadiusSection).toBeVisible(); + const deletedBrPill = borderRadiusSection.getByRole("button", { + name: "{deleted} does not exists or", + }); + await expect(deletedBrPill).toBeVisible(); + await deletedBrPill.hover(); + await expect( + page.getByRole("tooltip", { name: "{deleted} does not exists or" }), + ).toBeVisible(); + await expect(fillSection).toBeVisible(); + const fillBrokenTokenPill = fillSection.getByLabel("blue", { + exact: true, + }); + await expect(fillBrokenTokenPill).toBeVisible(); + await fillBrokenTokenPill.hover(); + const fillBrokenTokenTooltip = page.getByRole("tooltip", { + name: "blue", + }); + await expect(fillBrokenTokenTooltip).toBeVisible(); + await expect(fillBrokenTokenTooltip).toHaveText( + "{blue} does not exists or has been deleted.", + ); + // ------------------------------------ + // Select text layer with deleted token + // ------------------------------------ + await workspacePage.layers + .getByTestId("layer-row") + .filter({ hasText: "Text with deleted token" }) + .click(); + await expect(typographySection).toBeVisible(); + const brokenTypographyTokenPill = typographySection.getByLabel( + "deleted-typo", + { exact: true }, + ); + await expect(brokenTypographyTokenPill).toBeVisible(); + await brokenTypographyTokenPill.hover(); + const brokenTypographyTokenTooltip = page.getByRole("tooltip", { + name: "deleted-typo", + }); + await expect(brokenTypographyTokenTooltip).toBeVisible(); + await expect(brokenTypographyTokenTooltip).toHaveText( + "{deleted-typo} does not exists or has been deleted.", + ); + + // --------------------------------------------------- + // Select rectangle layer with deleted reference token + // --------------------------------------------------- + await page.getByRole("tab", { name: "Tokens" }).click(); + await tokenThemesSetsSidebar.getByRole("button", { name: "Dark" }).click(); + + await tokenThemesSetsSidebar + .getByRole("button", { name: "Dark" }) + .getByRole("checkbox") + .click(); + await page.getByRole("tab", { name: "Layers" }).click(); + await workspacePage.layers + .getByTestId("layer-row") + .filter({ hasText: "Rectangle with deleted reference" }) + .click(); + await expect(borderRadiusSection).toBeVisible(); + const deletedReferenceBrPill = borderRadiusSection.getByRole("button", { + name: "Reference is not valid or is not in any active set", + }); + await expect(deletedReferenceBrPill).toBeVisible(); + await deletedReferenceBrPill.hover(); + await expect( + page.getByRole("tooltip", { + name: "Reference is not valid or is not in any active set", + }), + ).toBeVisible(); + await expect(fillSection).toBeVisible(); + const fillDeletedReferenceTokenPill = fillSection.getByLabel("ref-grfeen", { + exact: true, + }); + await expect(fillDeletedReferenceTokenPill).toBeVisible(); + await fillDeletedReferenceTokenPill.hover(); + const fillDeletedReferenceTokenTooltip = page.getByRole("tooltip", { + name: "Reference is not valid or is not in any active set", + }); + await expect(fillDeletedReferenceTokenTooltip).toBeVisible(); + await expect(fillDeletedReferenceTokenTooltip).toHaveText( + "Reference is not valid or is not in any active set", + ); + + // ---------------------------------------------- + // Select text layer with deleted reference token + // ---------------------------------------------- + + await workspacePage.layers + .getByTestId("layer-row") + .filter({ hasText: "Text with deleted reference" }) + .click(); + + await expect(typographySection).toBeVisible(); + const deletedRefTypographyTokenPill = typographySection.getByLabel( + "ref-typo", + { exact: true }, + ); + await expect(deletedRefTypographyTokenPill).toBeVisible(); + await deletedRefTypographyTokenPill.hover(); + const deletedRefTypographyTokenTooltip = page.getByRole("tooltip", { + name: "Reference is not valid or is", + }); + await expect(deletedRefTypographyTokenTooltip).toBeVisible(); + await expect(deletedRefTypographyTokenTooltip).toHaveText( + "Reference is not valid or is not in any active set", + ); + await expect(fillSection).toBeVisible(); + const fillTextDeletedReferenceTokenPill = fillSection.getByLabel( + "ref-grfeen", + { + exact: true, + }, + ); + await expect(fillTextDeletedReferenceTokenPill).toBeVisible(); + await fillTextDeletedReferenceTokenPill.hover(); + const fillTextDeletedReferenceTokenTooltip = page.getByRole("tooltip", { + name: "Reference is not valid or is not in any active set", + }); + await expect(fillTextDeletedReferenceTokenTooltip).toBeVisible(); + await expect(fillTextDeletedReferenceTokenTooltip).toHaveText( + "Reference is not valid or is not in any active set", + ); + + // ----------------------------------------------------------- + // Select rectangle layer with reference token on inactive set + // ----------------------------------------------------------- + await page.getByRole("tab", { name: "Tokens" }).click(); + await tokenThemesSetsSidebar.getByRole("button", { name: "Global" }).click(); + + await tokenThemesSetsSidebar + .getByRole("button", { name: "Global" }) + .getByRole("checkbox") + .click(); + await page.getByRole("tab", { name: "Layers" }).click(); + await workspacePage.layers + .getByTestId("layer-row") + .filter({ hasText: "Rectangle with not active reference" }) + .click(); + await expect(borderRadiusSection).toBeVisible(); + const nonActiveReferenceBrPill = borderRadiusSection.getByRole("button", { + name: "Reference is not valid or is not in any active set", + }); + await expect(nonActiveReferenceBrPill).toBeVisible(); + await nonActiveReferenceBrPill.hover(); + await expect( + page.getByRole("tooltip", { + name: "Reference is not valid or is not in any active set", + }), + ).toBeVisible(); + await expect(fillSection).toBeVisible(); + const fillNonActiveReferenceTokenPill = fillSection.getByLabel("in-color", { + exact: true, + }); + await expect(fillNonActiveReferenceTokenPill).toBeVisible(); + await fillNonActiveReferenceTokenPill.hover(); + const fillNonActiveReferenceTokenTooltip = page.getByRole("tooltip", { + name: "Reference is not valid or is not in any active set", + }); + await expect(fillNonActiveReferenceTokenTooltip).toBeVisible(); + await expect(fillNonActiveReferenceTokenTooltip).toHaveText( + "Reference is not valid or is not in any active set", + ); + // ------------------------------------------------------ + // Select text layer with reference token on inactive set + // ------------------------------------------------------ + + await workspacePage.layers + .getByTestId("layer-row") + .filter({ hasText: "Text with not active reference" }) + .click(); + + await expect(typographySection).toBeVisible(); + const notActiveRefTypographyTokenPill = typographySection.getByLabel( + "in-typo", + { exact: true }, + ); + await expect(notActiveRefTypographyTokenPill).toBeVisible(); + await notActiveRefTypographyTokenPill.hover(); + const notActiveRefTypographyTokenTooltip = page.getByRole("tooltip", { + name: "Reference is not valid or is", + }); + await expect(notActiveRefTypographyTokenTooltip).toBeVisible(); + await expect(notActiveRefTypographyTokenTooltip).toHaveText( + "Reference is not valid or is not in any active set", + ); + await expect(fillSection).toBeVisible(); + const fillTextNotActiveReferenceTokenPill = fillSection.getByLabel( + "in-color", + { + exact: true, + }, + ); + await expect(fillTextNotActiveReferenceTokenPill).toBeVisible(); + await fillTextNotActiveReferenceTokenPill.hover(); + const fillTextNotActiveReferenceTokenTooltip = page.getByRole("tooltip", { + name: "Reference is not valid or is not in any active set", + }); + await expect(fillTextNotActiveReferenceTokenTooltip).toBeVisible(); + await expect(fillTextNotActiveReferenceTokenTooltip).toHaveText( + "Reference is not valid or is not in any active set", + ); + + // ------------------------------------------------- + // Select rectangle layer with token on inactive set + // ------------------------------------------------- + await page.getByRole("tab", { name: "Tokens" }).click(); + await tokenThemesSetsSidebar.getByRole("button", { name: "Dark" }).click(); + + await tokenThemesSetsSidebar + .getByRole("button", { name: "Dark" }) + .getByRole("checkbox") + .click(); + await page.getByRole("tab", { name: "Layers" }).click(); + await workspacePage.layers + .getByTestId("layer-row") + .filter({ hasText: "Rectangle with not active token" }) + .click(); + await expect(borderRadiusSection).toBeVisible(); + const nonActiveBrPill = borderRadiusSection.getByRole("button", { + name: "{border-radius} is not in any active set", + }); + await expect(nonActiveBrPill).toBeVisible(); + await nonActiveBrPill.hover(); + await expect( + page.getByRole("tooltip", { + name: "{border-radius} is not in any active set or has an invalid value", + }), + ).toBeVisible(); + await expect(fillSection).toBeVisible(); + const fillNonActiveTokenPill = fillSection.getByLabel("red", { + exact: true, + }); + await expect(fillNonActiveTokenPill).toBeVisible(); + await fillNonActiveTokenPill.hover(); + const fillNonActiveTokenTooltip = page.getByRole("tooltip", { + name: "{red} is not in any active set or has an invalid value.", + }); + await expect(fillNonActiveTokenTooltip).toBeVisible(); + await expect(fillNonActiveTokenTooltip).toHaveText( + "{red} is not in any active set or has an invalid value.", + ); + + // -------------------------------------------- + // Select text layer with token on inactive set + // -------------------------------------------- + + await workspacePage.layers + .getByTestId("layer-row") + .filter({ hasText: "Text with not active token" }) + .click(); + + await expect(typographySection).toBeVisible(); + const notActiveTypographyTokenPill = typographySection.getByLabel( + "typo-2", + { exact: true }, + ); + await expect(notActiveTypographyTokenPill).toBeVisible(); + await notActiveTypographyTokenPill.hover(); + const notActiveTypographyTokenTooltip = page.getByRole("tooltip", { + name: "{typo-2} is not in any active set or has an invalid value.", + }); + await expect(notActiveTypographyTokenTooltip).toBeVisible(); + await expect(notActiveTypographyTokenTooltip).toHaveText( + "{typo-2} is not in any active set or has an invalid value.", + ); + await expect(fillSection).toBeVisible(); + const fillTextNotActiveTokenPill = fillSection.getByLabel( + "red", + { + exact: true, + }, + ); + await expect(fillTextNotActiveTokenPill).toBeVisible(); + await fillTextNotActiveTokenPill.hover(); + const fillTextNotActiveTokenTooltip = page.getByRole("tooltip", { + name: "{red} is not in any active set or has an invalid value.", + }); + await expect(fillTextNotActiveTokenTooltip).toBeVisible(); + await expect(fillTextNotActiveTokenTooltip).toHaveText( + "{red} is not in any active set or has an invalid value.", + ); +}); diff --git a/frontend/src/app/main/ui/ds/controls/utilities/token_field.cljs b/frontend/src/app/main/ui/ds/controls/utilities/token_field.cljs index 5be77b6ef9..22291eca66 100644 --- a/frontend/src/app/main/ui/ds/controls/utilities/token_field.cljs +++ b/frontend/src/app/main/ui/ds/controls/utilities/token_field.cljs @@ -9,6 +9,7 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] + [app.main.refs :as refs] [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] [app.main.ui.ds.foundations.assets.icon :as i] [app.main.ui.ds.tooltip :refer [tooltip*]] @@ -43,10 +44,25 @@ token-has-errors]}] (let [set-active? (some? id) + all-tokens-map (mf/deref refs/workspace-all-tokens-map) + token-exists? (contains? all-tokens-map label) + token-not-active (and token-exists? (not set-active?)) content (cond - token-has-errors (tr "workspace.tokens.ref-not-valid") - (not set-active?) (tr "ds.inputs.token-field.no-active-token-option" label) - :else label) + (not token-exists?) + (tr "options.deleted-token-with-name" label) + + (and token-exists? (not set-active?)) + (tr "ds.inputs.token-field.no-active-token-option" label) + + (and token-exists? token-has-errors) + (tr "workspace.tokens.ref-not-valid") + + :else + label) + + broken-state (or (not token-exists?) + token-has-errors + token-not-active) default-id (mf/use-id) id (d/nilv id default-id) @@ -84,15 +100,13 @@ [:button {:on-click on-click :ref pill-ref :class (stl/css-case :pill true - :no-set-pill (or (not set-active?) - token-has-errors) + :no-set-pill broken-state :pill-disabled disabled) :disabled disabled :aria-labelledby (dm/str id "-pill") :on-key-down on-token-key-down} value - (when (or (not set-active?) - token-has-errors) + (when broken-state [:div {:class (stl/css :pill-dot)}])]]] (when-not ^boolean disabled diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/token_typography_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/token_typography_row.cljs index 645ccb5c8c..743038cbbe 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/token_typography_row.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/token_typography_row.cljs @@ -9,6 +9,7 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] + [app.main.refs :as refs] [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] [app.main.ui.ds.controls.shared.token-option :as to] [app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i] @@ -25,31 +26,46 @@ token (->> (:typography active-tokens) (d/seek #(= (:name %) token-name))) - has-errors (some? (:errors token)) display-name (or (:name token) token-name) resolved-value (:resolved-value token) - not-active (or (nil? token) - (empty? (:typography active-tokens))) on-detach (mf/use-fn (mf/deps display-name) (fn [] (detach-token display-name))) + all-tokens-map (mf/deref refs/workspace-all-tokens-map) + + token-exists? (contains? all-tokens-map token-name) + has-errors (and token-exists? + (some? (:errors token))) + + not-active (and + token-exists? + (or (nil? token) + (empty? (:typography active-tokens)))) + + broken-state (or (not token-exists?) + has-errors + not-active) tooltip-content (cond not-active - (tr "options.deleted-token") + (tr "ds.inputs.token-field.no-active-token-option" token-name) + + (not token-exists?) + (tr "options.deleted-token-with-name" token-name) + has-errors - (tr "not-active-token.no-name") + (tr "workspace.tokens.ref-not-valid") + :else (mf/html [:> to/resolved-value-tooltip* {:token-name token-name :resolved-value resolved-value}]))] [:div {:class (stl/css-case :token-typography-row true - :token-typography-row-with-errors has-errors - :token-typography-row-not-active not-active)} - (when (or has-errors not-active) + :token-typography-row-with-errors broken-state)} + (when broken-state [:div {:class (stl/css :error-dot)}]) [:> icon* {:icon-id i/text-typography :class (stl/css :icon)}] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/token_typography_row.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/token_typography_row.scss index 5d6ac3d6ac..615e8379c5 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/token_typography_row.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/token_typography_row.scss @@ -35,8 +35,7 @@ } } -.token-typography-row-with-errors, -.token-typography-row-not-active { +.token-typography-row-with-errors { --token-typography-row-background-color: var(--color-background-primary); --token-typography-row-foreground-color: var(--color-foreground-secondary); --token-typography-row-border-color: var(--color-token-border); diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs index 1dcfa53306..41f63f3a32 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs @@ -89,42 +89,72 @@ (let [token-name (or (:name token) applied-token-name)] (detach-token token-name)))) - has-errors (some? (:errors token)) token-name (:name token) resolved (:resolved-value token) - not-active (or (empty? active-tokens) - (nil? token)) + + + ;; Tooltip content for the swatch and token name, based on the token's state + all-tokens-map (mf/deref refs/workspace-all-tokens-map) + + token-exists? (contains? all-tokens-map applied-token-name) + has-errors (and token-exists? + (some? (:errors token))) + + not-active (and + token-exists? + (or (empty? active-tokens) + (nil? token))) + id (dm/str (:id token) "-name") token-name-ref (mf/use-ref nil) + + broken-state (or (not token-exists?) + has-errors + not-active) + swatch-tooltip-content (cond not-active - (tr "options.deleted-token") + (tr "ds.inputs.token-field.no-active-token-option" applied-token-name) + + (not token-exists?) + (tr "options.deleted-token-with-name" applied-token-name) + has-errors - (tr "not-active-token.no-name") + (tr "workspace.tokens.ref-not-valid") + :else (tr "workspace.tokens.resolved-value" resolved)) + name-tooltip-content (cond - not-active - (tr "options.deleted-token") has-errors - (tr "not-active-token.no-name") + (tr "workspace.tokens.ref-not-valid") + + not-active + (tr "ds.inputs.token-field.no-active-token-option" applied-token-name) + + (not token-exists?) + (tr "options.deleted-token-with-name" applied-token-name) + :else #(mf/html [:div [:span (dm/str (tr "workspace.tokens.token-name") ": ")] - [:span {:class (stl/css :token-name-tooltip)} applied-token-name]]))] + [:span {:class (stl/css :token-name-tooltip)} applied-token-name] + [:div + [:span (tr "inspect.tabs.styles.token-resolved-value")] + [:span {:class (stl/css :resolved-value)} (dm/str " " resolved)]]]))] + [:div {:class (stl/css :color-info)} [:div {:class (stl/css-case :token-color-wrapper true - :token-color-with-errors has-errors - :token-color-not-active not-active)} + :token-color-with-errors broken-state)} [:div {:class (stl/css :color-bullet-wrapper)} - (when (or has-errors not-active) + (when broken-state [:div {:class (stl/css :error-dot)}]) [:> swatch* {:background color :tooltip-content swatch-tooltip-content :on-click on-swatch-click-token - :has-errors (or has-errors not-active) + :has-errors broken-state :size "small"}]] [:> tooltip* {:content name-tooltip-content :id id diff --git a/frontend/src/app/main/ui/workspace/tokens/management/token_pill.cljs b/frontend/src/app/main/ui/workspace/tokens/management/token_pill.cljs index 85c5846035..64191793a9 100644 --- a/frontend/src/app/main/ui/workspace/tokens/management/token_pill.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/token_pill.cljs @@ -290,7 +290,7 @@ :token-pill-disabled disabled? :token-pill-applied (and can-edit? has-selected? (or half-applied? full-applied?)) :token-pill-invalid (and can-edit? errors?) - :token-pill-invalid-applied (and full-applied? errors? can-edit?) + :token-pill-invalid-applied (and (or half-applied? full-applied?) errors? can-edit?) :token-pill-viewer is-viewer? :token-pill-applied-viewer (and is-viewer? has-selected? (or half-applied? full-applied?)) diff --git a/frontend/translations/en.po b/frontend/translations/en.po index fa3f61cae6..2befc9634b 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -5028,6 +5028,11 @@ msgstr "Penpot" msgid "options.deleted-token" msgstr "This token does not exists or has been deleted." + +#: src/app/main/ui/ds/controls/utilities/token_field.cljs +msgid "options.deleted-token-with-name" +msgstr "{%s} does not exists or has been deleted." + #: src/app/plugins/utils.cljs:318 msgid "plugins.validation.message" msgstr "Field %s is invalid: %s" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index 6c4a7b6ed0..cac40d58be 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -4897,6 +4897,10 @@ msgstr "Penpot" msgid "options.deleted-token" msgstr "Este token no existe o ha sido borrado." +#: src/app/main/ui/ds/controls/utilities/token_field.cljs +msgid "options.deleted-token-with-name" +msgstr "{%s} no existe o ha sido borrado." + #: src/app/main/ui/auth/recovery.cljs:88 msgid "profile.recovery.go-to-login" msgstr "Ir al login"