diff --git a/package.json b/package.json index fe8edd200..0e7fe7149 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "prepare": "husky" }, "dependencies": { + "@base-ui/react": "^1.7.0", "@codemirror/lang-css": "^6.3.1", "@codemirror/lang-html": "^6.4.12", "@codemirror/lang-javascript": "^6.2.5", @@ -60,9 +61,6 @@ "@modelcontextprotocol/sdk": "^1.29.0", "@octokit/graphql": "^9.0.3", "@phosphor-icons/react": "^2.1.10", - "@radix-ui/react-dialog": "^1.1.15", - "@radix-ui/react-dropdown-menu": "^2.1.16", - "@radix-ui/react-tooltip": "^1.2.8", "@react-three/drei": "^10.7.7", "@react-three/fiber": "^9.5.0", "@sentry/browser": "^10.47.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ceb12bc47..6dca03388 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,6 +24,9 @@ importers: .: dependencies: + '@base-ui/react': + specifier: ^1.7.0 + version: 1.7.0(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@codemirror/lang-css': specifier: ^6.3.1 version: 6.3.1 @@ -63,15 +66,6 @@ importers: '@phosphor-icons/react': specifier: ^2.1.10 version: 2.1.10(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-dialog': - specifier: ^1.1.15 - version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-dropdown-menu': - specifier: ^2.1.16 - version: 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-tooltip': - specifier: ^1.2.8 - version: 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@react-three/drei': specifier: ^10.7.7 version: 10.7.7(@react-three/fiber@9.5.0(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(three@0.183.2))(@types/react@19.2.14)(@types/three@0.183.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(three@0.183.2) @@ -593,6 +587,33 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} + '@base-ui/react@1.7.0': + resolution: {integrity: sha512-j+8QjX44C32jrXD/qyEAGpFr70FRpGL2CY61mQd9nBPWN737CK0xxD1ceJ055rW4RtdvFDT1e7otzdlfxvsYug==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@date-fns/tz': ^1.2.0 + '@types/react': ^17 || ^18 || ^19 + date-fns: ^4.0.0 + react: ^17 || ^18 || ^19 + react-dom: ^17 || ^18 || ^19 + peerDependenciesMeta: + '@date-fns/tz': + optional: true + '@types/react': + optional: true + date-fns: + optional: true + + '@base-ui/utils@0.3.2': + resolution: {integrity: sha512-oWy1aq/I2GmYjpl4PhEAhzflF8VPGKgZeq0xAWTbfD5KBWyxcN0ZP2+WHSUm/5Z6lVMBDLReLcoXwSYoRc/zNQ==} + peerDependencies: + '@types/react': ^17 || ^18 || ^19 + react: ^17 || ^18 || ^19 + react-dom: ^17 || ^18 || ^19 + peerDependenciesMeta: + '@types/react': + optional: true + '@braintree/sanitize-url@7.1.2': resolution: {integrity: sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==} @@ -736,11 +757,11 @@ packages: '@esbuild-kit/core-utils@3.3.2': resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} - deprecated: 'Merged into tsx: https://tsx.is' + deprecated: 'Merged into tsx: https://tsx.hirok.io' '@esbuild-kit/esm-loader@2.6.5': resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==} - deprecated: 'Merged into tsx: https://tsx.is' + deprecated: 'Merged into tsx: https://tsx.hirok.io' '@esbuild/aix-ppc64@0.25.12': resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} @@ -1359,15 +1380,27 @@ packages: '@floating-ui/core@1.7.5': resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} + '@floating-ui/core@1.8.0': + resolution: {integrity: sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==} + '@floating-ui/dom@1.7.6': resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==} + '@floating-ui/dom@1.8.0': + resolution: {integrity: sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==} + '@floating-ui/react-dom@2.1.8': resolution: {integrity: sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' + '@floating-ui/react-dom@2.1.9': + resolution: {integrity: sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + '@floating-ui/react@0.27.19': resolution: {integrity: sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog==} peerDependencies: @@ -1377,6 +1410,9 @@ packages: '@floating-ui/utils@0.2.11': resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} + '@floating-ui/utils@0.2.12': + resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==} + '@google/model-viewer@4.2.0': resolution: {integrity: sha512-RjpAI5cLs9CdvPcMRsOs8Bea/lNmGTTyaPyl16o9Fv6Qn8VSpgBMmXFr/11yb0hTrsojp2dOACEcY77R8hVUVA==} engines: {node: '>=6.0.0'} @@ -2356,32 +2392,6 @@ packages: '@radix-ui/primitive@1.1.3': resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} - '@radix-ui/react-arrow@1.1.7': - resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-collection@1.1.7': - resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-compose-refs@1.1.2': resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} peerDependencies: @@ -2413,15 +2423,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-direction@1.1.1': - resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@radix-ui/react-dismissable-layer@1.1.11': resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} peerDependencies: @@ -2435,19 +2436,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-dropdown-menu@2.1.16': - resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-focus-guards@1.1.3': resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} peerDependencies: @@ -2479,32 +2467,6 @@ packages: '@types/react': optional: true - '@radix-ui/react-menu@2.1.16': - resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-popper@1.2.8': - resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-portal@1.1.9': resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} peerDependencies: @@ -2557,19 +2519,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-roving-focus@1.1.11': - resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-slot@1.2.3': resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} peerDependencies: @@ -2588,19 +2537,6 @@ packages: '@types/react': optional: true - '@radix-ui/react-tooltip@1.2.8': - resolution: {integrity: sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-use-callback-ref@1.1.1': resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} peerDependencies: @@ -2646,40 +2582,6 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-rect@1.1.1': - resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-size@1.1.1': - resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-visually-hidden@1.2.3': - resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/rect@1.1.1': - resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} - '@react-three/drei@10.7.7': resolution: {integrity: sha512-ff+J5iloR0k4tC++QtD/j9u3w5fzfgFAWDtAGQah9pF2B1YgOq/5JxqY0/aVoQG5r3xSZz0cv5tk2YuBob4xEQ==} peerDependencies: @@ -6231,6 +6133,9 @@ packages: resolution: {integrity: sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==} engines: {node: '>=9.3.0 || >=8.10.0 <9.0.0'} + reselect@5.2.0: + resolution: {integrity: sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==} + resend@6.10.0: resolution: {integrity: sha512-i7CwZpYj4Oho1RxsTpLcCUkO08+HiL4NXrm6jLJ2WzJ89UGI8eROSieLONJA3hnUrf1OYnCyfq5F6POnHUMv1Q==} engines: {node: '>=20'} @@ -6802,6 +6707,7 @@ packages: uuid@10.0.0: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true uuid@11.1.0: @@ -7302,6 +7208,29 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@base-ui/react@1.7.0(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@babel/runtime': 7.29.2 + '@base-ui/utils': 0.3.2(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@floating-ui/react-dom': 2.1.9(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@floating-ui/utils': 0.2.12 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + use-sync-external-store: 1.6.0(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.14 + + '@base-ui/utils@0.3.2(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@babel/runtime': 7.29.2 + '@floating-ui/utils': 0.2.12 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + reselect: 5.2.0 + use-sync-external-store: 1.6.0(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.14 + '@braintree/sanitize-url@7.1.2': {} '@chevrotain/cst-dts-gen@11.1.2': @@ -7831,17 +7760,32 @@ snapshots: dependencies: '@floating-ui/utils': 0.2.11 + '@floating-ui/core@1.8.0': + dependencies: + '@floating-ui/utils': 0.2.12 + '@floating-ui/dom@1.7.6': dependencies: '@floating-ui/core': 1.7.5 '@floating-ui/utils': 0.2.11 + '@floating-ui/dom@1.8.0': + dependencies: + '@floating-ui/core': 1.8.0 + '@floating-ui/utils': 0.2.12 + '@floating-ui/react-dom@2.1.8(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@floating-ui/dom': 1.7.6 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) + '@floating-ui/react-dom@2.1.9(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@floating-ui/dom': 1.8.0 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + '@floating-ui/react@0.27.19(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@floating-ui/react-dom': 2.1.8(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -7852,6 +7796,8 @@ snapshots: '@floating-ui/utils@0.2.11': {} + '@floating-ui/utils@0.2.12': {} + '@google/model-viewer@4.2.0(three@0.183.2)': dependencies: '@monogrid/gainmap-js': 3.4.0(three@0.183.2) @@ -8659,27 +8605,6 @@ snapshots: '@radix-ui/primitive@1.1.3': {} - '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.14)(react@19.2.3)': dependencies: react: 19.2.3 @@ -8714,12 +8639,6 @@ snapshots: '@types/react': 19.2.14 '@types/react-dom': 19.2.3(@types/react@19.2.14) - '@radix-ui/react-direction@1.1.1(@types/react@19.2.14)(react@19.2.3)': - dependencies: - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.14 - '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/primitive': 1.1.3 @@ -8733,21 +8652,6 @@ snapshots: '@types/react': 19.2.14 '@types/react-dom': 19.2.3(@types/react@19.2.14) - '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - '@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.14)(react@19.2.3)': dependencies: react: 19.2.3 @@ -8772,50 +8676,6 @@ snapshots: optionalDependencies: '@types/react': 19.2.14 - '@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.3) - aria-hidden: 1.2.6 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@floating-ui/react-dom': 2.1.8(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/rect': 1.1.1 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -8854,23 +8714,6 @@ snapshots: '@types/react': 19.2.14 '@types/react-dom': 19.2.3(@types/react@19.2.14) - '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - '@radix-ui/react-slot@1.2.3(@types/react@19.2.14)(react@19.2.3)': dependencies: '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.3) @@ -8885,26 +8728,6 @@ snapshots: optionalDependencies: '@types/react': 19.2.14 - '@radix-ui/react-tooltip@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.3) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.14)(react@19.2.3)': dependencies: react: 19.2.3 @@ -8939,31 +8762,6 @@ snapshots: optionalDependencies: '@types/react': 19.2.14 - '@radix-ui/react-use-rect@1.1.1(@types/react@19.2.14)(react@19.2.3)': - dependencies: - '@radix-ui/rect': 1.1.1 - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-size@1.1.1(@types/react@19.2.14)(react@19.2.3)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.3) - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/rect@1.1.1': {} - '@react-three/drei@10.7.7(@react-three/fiber@9.5.0(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(three@0.183.2))(@types/react@19.2.14)(@types/three@0.183.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(three@0.183.2)': dependencies: '@babel/runtime': 7.29.2 @@ -12681,6 +12479,8 @@ snapshots: transitivePeerDependencies: - supports-color + reselect@5.2.0: {} + resend@6.10.0: dependencies: postal-mime: 2.7.4 diff --git a/src/components/AiDock.tsx b/src/components/AiDock.tsx index 6d3315428..888d9575e 100644 --- a/src/components/AiDock.tsx +++ b/src/components/AiDock.tsx @@ -825,27 +825,29 @@ function KapaHistoryButton({ } }} > - - - + + + {compact ? ( + Chat history + ) : ( + History + )} + + } + /> - -
- - -
-
+ + + + + } + />
{user?.email}
- - - - Account - - - - - - My Projects - - - - - - My Showcases - - - {canApiKeys && ( - - - - Integrations + + + Account - + } + /> + + + My Projects + + } + /> + + + My Showcases + + } + /> + {canApiKeys && ( + + + Integrations + + } + /> )} {canAdmin && ( - - - - Admin - - + + + Admin + + } + /> )} diff --git a/src/components/BlogAuthorFilter.tsx b/src/components/BlogAuthorFilter.tsx index 28341357d..caf04f7fa 100644 --- a/src/components/BlogAuthorFilter.tsx +++ b/src/components/BlogAuthorFilter.tsx @@ -34,46 +34,48 @@ export function BlogAuthorFilter({ return (
- - - + + + + + {activeAuthor ?? 'All authors'} + + + + + } + /> - - - + + {SelectedTopicIcon ? ( + + ) : null} + {topicLabel} + + + } + /> - - - + + + {activeAuthor ?? 'All authors'} + + + + } + /> - - - + + + {selectedYear ?? 'All years'} + + + + } + /> {children} - - - + + } + /> - - - + + On this page + + + } + /> {headings.map((heading) => ( - - - - - + + + + } + /> ))} diff --git a/src/components/CopyPageDropdown.tsx b/src/components/CopyPageDropdown.tsx index 2aa3eec67..dbe99e987 100644 --- a/src/components/CopyPageDropdown.tsx +++ b/src/components/CopyPageDropdown.tsx @@ -318,18 +318,20 @@ export function CopyPageDropdown({ )} - - - + + + + } + /> {menuItems.map((item) => ( — e.g. the virtual anchor + // BrandContextMenu positions at the cursor. + nativeButton?: boolean } type DropdownContentProps = { @@ -27,10 +34,10 @@ type DropdownContentProps = { } type DropdownItemProps = { - children: React.ReactNode + children?: React.ReactNode className?: string onSelect?: () => void - asChild?: boolean + render?: React.ReactElement } type DropdownSeparatorProps = { @@ -44,21 +51,23 @@ export function Dropdown({ modal = false, }: DropdownProps) { return ( - + {children} - + ) } export function DropdownTrigger({ - children, + render, className, - asChild = true, + nativeButton, }: DropdownTriggerProps) { return ( - - {children} - + ) } @@ -73,58 +82,62 @@ export function DropdownContent({ onPointerLeave, }: DropdownContentProps) { const content = ( - - {children} - + + + {children} + + ) if (!portal) { return content } - return {content} + return {content} } export function DropdownItem({ children, className, onSelect, - asChild, + render, }: DropdownItemProps) { + const itemClassName = twMerge( + 'flex cursor-pointer select-none items-center gap-2 rounded-md px-2 py-1.5 outline-none', + 'text-sm text-gray-700 dark:text-gray-300', + 'hover:bg-gray-100 dark:hover:bg-gray-700/50', + 'data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-700/50', + 'transition-colors duration-150', + className, + ) + + if (render) { + return ( + + ) + } + return ( - + {children} - + ) } export function DropdownSeparator({ className }: DropdownSeparatorProps) { return ( - ) diff --git a/src/components/LibrariesBrowser.tsx b/src/components/LibrariesBrowser.tsx index cfbaa2612..199bb4f53 100644 --- a/src/components/LibrariesBrowser.tsx +++ b/src/components/LibrariesBrowser.tsx @@ -142,26 +142,28 @@ export function LibrariesBrowser({
- - - + + {activeFrameworkOption ? ( + + ) : null} + + {activeFrameworkOption + ? activeFrameworkOption.label + : 'All frameworks'} + + + + } + /> { + onOpenChange={(next, details) => { + // The browser portals its own menus. A press inside one is outside the + // takeover as far as the dialog is concerned, so it would dismiss the + // whole overlay; keep it open and let the menu handle its own press. + if ( + details.reason === 'outside-press' && + details.event.target instanceof Element && + details.event.target.closest('[role="menu"]') + ) { + details.cancel() + return + } if (!next) onClose() }} > @@ -33,12 +44,6 @@ export function LibrariesOverlay({ ) : null } - onInteractOutside={(event) => { - const target = event.detail.originalEvent.target - if (target instanceof Element && target.closest('[role="menu"]')) { - event.preventDefault() - } - }} > diff --git a/src/components/LibraryLayout.tsx b/src/components/LibraryLayout.tsx index aaf76ddfa..cae821b9a 100644 --- a/src/components/LibraryLayout.tsx +++ b/src/components/LibraryLayout.tsx @@ -1292,7 +1292,7 @@ export function LibraryLayout({ onPointerLeave={(e) => { if (e.pointerType === 'touch') return // Keep sidebar open while a dropdown opened from inside it is active (e.g. FrameworkSelect, VersionSelect) - if (expandedMenuRef.current?.querySelector('[data-state="open"]')) + if (expandedMenuRef.current?.querySelector('[data-popup-open]')) return if (window.innerWidth < 1280) { leaveTimer.current = setTimeout(() => { diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 6d2a637b3..179afd763 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -1733,42 +1733,47 @@ function SocialStack() { return ( - - - + + + {stackTop.map(({ label, Icon }, i) => ( + 0 && '-ml-3', + )} + style={{ zIndex: stackTop.length - i }} + > + + + ))} + + + } + /> {SOCIAL_LINKS.map(({ label, href, Icon }) => ( - - - - {label} - - + + + {label} + + } + /> ))} diff --git a/src/components/SearchModal.tsx b/src/components/SearchModal.tsx index 880c746ac..cad6ec258 100644 --- a/src/components/SearchModal.tsx +++ b/src/components/SearchModal.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import * as DialogPrimitive from '@radix-ui/react-dialog' +import { Dialog } from '@base-ui/react/dialog' import { Command } from 'cmdk' import { twMerge } from 'tailwind-merge' import { @@ -291,13 +291,9 @@ function isSearchModalPortalTarget(target: EventTarget | null) { return target instanceof Element && !!target.closest('.dropdown-content') } -const searchModalTransitionMs = 140 - export function SearchModal() { const { isOpen, closeSearch } = useSearchContext() const contentRef = React.useRef(null) - const bodyPointerEventsRef = React.useRef('') - const [shouldRenderSearch, setShouldRenderSearch] = React.useState(isOpen) const [isFullHeight, setIsFullHeight] = React.useState(() => { if (typeof window === 'undefined') return false return localStorage.getItem('search-full-height') === 'true' @@ -311,22 +307,6 @@ export function SearchModal() { }) }, []) - React.useEffect(() => { - if (isOpen) { - setShouldRenderSearch(true) - return - } - - const timeout = window.setTimeout(() => { - setShouldRenderSearch(false) - requestAnimationFrame(() => { - document.body.style.pointerEvents = bodyPointerEventsRef.current - }) - }, searchModalTransitionMs) - - return () => window.clearTimeout(timeout) - }, [isOpen]) - React.useEffect(() => { if (!isOpen) { return @@ -341,96 +321,59 @@ export function SearchModal() { return () => cancelAnimationFrame(frame) }, [isOpen]) - React.useEffect(() => { - if (typeof document === 'undefined') { - return - } - - if (isOpen) { - document.body.style.pointerEvents = 'none' - return - } - - const frame = requestAnimationFrame(() => { - document.body.style.pointerEvents = bodyPointerEventsRef.current - }) - - return () => cancelAnimationFrame(frame) - }, [isOpen]) - - React.useEffect(() => { - if (typeof document === 'undefined') { - return - } - - bodyPointerEventsRef.current = - document.body.style.pointerEvents === 'none' - ? '' - : document.body.style.pointerEvents - - return () => { - document.body.style.pointerEvents = bodyPointerEventsRef.current - } - }, []) - - const shouldMountSearch = isOpen || shouldRenderSearch - return ( - { - if (!open) { - closeSearch() + onOpenChange={(open, eventDetails) => { + if (open) return + + // The panel portals its own dropdowns. A press inside one is outside + // the dialog, so it would close the whole palette. + if ( + eventDetails.reason === 'outside-press' && + isSearchModalPortalTarget(eventDetails.event.target) + ) { + eventDetails.cancel() + return } + + closeSearch() }} > - - {shouldMountSearch ? ( - <> - - { - if (isSearchModalPortalTarget(event.target)) { - event.preventDefault() - } - }} + + + + Search TanStack + + Search TanStack and open TanStack AI from the current query. + +
+ - - Search TanStack - - - Search TanStack and open TanStack AI from the current query. - -
- - - - - - -
- - - ) : null} - - + + + + +
+
+
+
+ ) } diff --git a/src/components/SearchShared.tsx b/src/components/SearchShared.tsx index 116749ac4..53575e7bc 100644 --- a/src/components/SearchShared.tsx +++ b/src/components/SearchShared.tsx @@ -771,27 +771,29 @@ export function LibraryRefinement({ compact = false }: SearchScopePickerProps) { return ( - - - + ) : ( + All Libraries + )} + + + } + /> setSelectedLibrary('')} @@ -845,33 +847,35 @@ export function FrameworkRefinement({ return ( - - - + + {currentFramework && ( + + )} + + {currentFramework + ? capitalize(currentFramework.label) + : 'All Frameworks'} + + + + } + /> handleSelect('')} className="font-bold"> All Frameworks diff --git a/src/components/Select.tsx b/src/components/Select.tsx index c3821fc96..e26a2d17b 100644 --- a/src/components/Select.tsx +++ b/src/components/Select.tsx @@ -45,37 +45,41 @@ export function Select({ return (
- - - + + } + /> {available.map((option) => ( + {children} - + ) } @@ -640,19 +640,16 @@ function StarterHoverTooltip({ content: React.ReactNode }) { return ( - - {children} - - - {content} - - - + + + + + + {content} + + + + ) } diff --git a/src/components/builder/BuilderAssistant.client.tsx b/src/components/builder/BuilderAssistant.client.tsx index 12feff5ff..e549c8298 100644 --- a/src/components/builder/BuilderAssistant.client.tsx +++ b/src/components/builder/BuilderAssistant.client.tsx @@ -2846,22 +2846,24 @@ export const BuilderAssistant = React.forwardRef< {threads.length > 1 ? ( - - - + + - - - + + {selected.label} +
) } diff --git a/src/components/ds/BrandAssets.tsx b/src/components/ds/BrandAssets.tsx index 21bf1ca08..b2e993d44 100644 --- a/src/components/ds/BrandAssets.tsx +++ b/src/components/ds/BrandAssets.tsx @@ -234,12 +234,14 @@ function BrandLogoPicker() {
- - - + + {logo.label} + + + } + /> {BRAND_LOGOS.map((option) => ( - - - + +
- + ) diff --git a/src/components/ds/overlay-audit/CartDrawerSpecimen.tsx b/src/components/ds/overlay-audit/CartDrawerSpecimen.tsx index 3f1813134..46cf01130 100644 --- a/src/components/ds/overlay-audit/CartDrawerSpecimen.tsx +++ b/src/components/ds/overlay-audit/CartDrawerSpecimen.tsx @@ -1,4 +1,4 @@ -import * as Dialog from '@radix-ui/react-dialog' +import { Dialog } from '@base-ui/react/dialog' import { ShoppingCartIcon, XIcon } from '@phosphor-icons/react' import { twMerge } from 'tailwind-merge' import type { SpecimenProps } from './types' @@ -19,8 +19,8 @@ export function CartDrawerSpecimen({ open, onOpenChange }: SpecimenProps) { return ( - - + - + ) diff --git a/src/components/ds/overlay-audit/ExampleDeployDialogSpecimen.tsx b/src/components/ds/overlay-audit/ExampleDeployDialogSpecimen.tsx index 300bbf191..29c0eb686 100644 --- a/src/components/ds/overlay-audit/ExampleDeployDialogSpecimen.tsx +++ b/src/components/ds/overlay-audit/ExampleDeployDialogSpecimen.tsx @@ -22,7 +22,7 @@ const STEPS: Array = [ * * Note the shell is byte-identical to StarterDeployDialogSpecimen: same * `fixed inset-0 z-50`, same button-as-backdrop, same - * `max-w-md ... rounded-xl shadow-2xl border` panel. Neither uses Radix, so + * `max-w-md ... rounded-xl shadow-2xl border` panel. Neither used Base UI, so * neither traps focus, restores focus on close, or closes on Escape. * * The step switcher is an audit affordance, not part of the original — it diff --git a/src/components/ds/overlay-audit/LibrariesOverlaySpecimen.tsx b/src/components/ds/overlay-audit/LibrariesOverlaySpecimen.tsx index cfd1e3ade..1dab501b0 100644 --- a/src/components/ds/overlay-audit/LibrariesOverlaySpecimen.tsx +++ b/src/components/ds/overlay-audit/LibrariesOverlaySpecimen.tsx @@ -1,4 +1,4 @@ -import * as DialogPrimitive from '@radix-ui/react-dialog' +import { Dialog as DialogPrimitive } from '@base-ui/react/dialog' import { XIcon } from '@phosphor-icons/react' import type { SpecimenProps } from './types' @@ -18,8 +18,8 @@ export function LibrariesOverlaySpecimen({ return ( - - + + Libraries @@ -57,7 +57,7 @@ export function LibrariesOverlaySpecimen({
))} -
+
) diff --git a/src/components/ds/overlay-audit/LoginModalSpecimen.tsx b/src/components/ds/overlay-audit/LoginModalSpecimen.tsx index 0ba27230f..9fbd508d3 100644 --- a/src/components/ds/overlay-audit/LoginModalSpecimen.tsx +++ b/src/components/ds/overlay-audit/LoginModalSpecimen.tsx @@ -1,4 +1,4 @@ -import * as DialogPrimitive from '@radix-ui/react-dialog' +import { Dialog as DialogPrimitive } from '@base-ui/react/dialog' import { XIcon } from '@phosphor-icons/react/X' import type { SpecimenProps } from './types' @@ -13,8 +13,8 @@ export function LoginModalSpecimen({ open, onOpenChange }: SpecimenProps) { return ( - - + +
Sign in to continue @@ -45,7 +45,7 @@ export function LoginModalSpecimen({ open, onOpenChange }: SpecimenProps) { Continue with Google
-
+
) diff --git a/src/components/ds/overlay-audit/NpmStatsDialogSpecimen.tsx b/src/components/ds/overlay-audit/NpmStatsDialogSpecimen.tsx index d41585da9..3170ebb74 100644 --- a/src/components/ds/overlay-audit/NpmStatsDialogSpecimen.tsx +++ b/src/components/ds/overlay-audit/NpmStatsDialogSpecimen.tsx @@ -1,19 +1,19 @@ -import * as DialogPrimitive from '@radix-ui/react-dialog' +import { Dialog as DialogPrimitive } from '@base-ui/react/dialog' import { XIcon } from '@phosphor-icons/react' import type { SpecimenProps } from './types' /** * AUDIT SPECIMEN — verbatim shell of the inline dialog in * `src/routes/stats/npm/index.tsx` (~line 1084). A fourth independent - * re-declaration of the centered Radix panel, defined inside a route file + * re-declaration of the centered Base UI panel, defined inside a route file * rather than a component. */ export function NpmStatsDialogSpecimen({ open, onOpenChange }: SpecimenProps) { return ( - - + +
Compare packages @@ -28,7 +28,7 @@ export function NpmStatsDialogSpecimen({ open, onOpenChange }: SpecimenProps) {

Add up to five npm packages to chart their download trends together.

- + ) diff --git a/src/components/ds/overlay-audit/ProductDrawerSpecimen.tsx b/src/components/ds/overlay-audit/ProductDrawerSpecimen.tsx index e56be6664..ae8ea80de 100644 --- a/src/components/ds/overlay-audit/ProductDrawerSpecimen.tsx +++ b/src/components/ds/overlay-audit/ProductDrawerSpecimen.tsx @@ -7,7 +7,7 @@ import type { SpecimenProps } from './types' * AUDIT SPECIMEN — verbatim shell of `src/components/shop/ProductDrawer.tsx`. * * The only bottom-sheet posture on the site, and hand-rolled rather than - * Radix: the Escape handler below is copied from the original because there is + * Base UI: the Escape handler below is copied from the original because there is * no primitive supplying it. Uses three separate z-tiers (`60` scrim, `70` * sheet, `71` side arrows) and is the one overlay already wired to the motion * tokens (`--motion-duration-fast`, `--motion-ease-standard`). @@ -60,7 +60,8 @@ export function ProductDrawerSpecimen({ open, onOpenChange }: SpecimenProps) {

Classic Tee

A bottom-anchored sheet. Note there is no focus trap and no - focus restoration on close — both would come free from Radix. + focus restoration on close — both come free from the DS Drawer + it was migrated onto.

-
+
) diff --git a/src/components/ds/overlay-audit/specimen-meta.ts b/src/components/ds/overlay-audit/specimen-meta.ts index fa3ab110f..93ff5fd58 100644 --- a/src/components/ds/overlay-audit/specimen-meta.ts +++ b/src/components/ds/overlay-audit/specimen-meta.ts @@ -11,7 +11,7 @@ export type Posture = | 'top-anchored' | 'full-bleed' -export type Base = 'radix' | 'hand-rolled' +export type Base = 'base-ui' | 'hand-rolled' export type TokenLayer = 'semantic' | 'raw-tailwind' | 'shop-scope' @@ -26,7 +26,7 @@ export type SpecimenMeta = { zIndex: string overlay: string width: string - /** Radix supplies these for free; hand-rolled dialogs must implement them. */ + /** Base UI supplies these for free; hand-rolled dialogs must implement them. */ focusTrap: boolean focusRestore: boolean escape: boolean @@ -42,7 +42,7 @@ export const SPECIMENS: Array = [ source: 'src/components/LoginModal.tsx', sourceLines: 73, posture: 'centered', - base: 'radix', + base: 'base-ui', tokens: 'raw-tailwind', zIndex: '999 / 1000', overlay: 'bg-black/60 backdrop-blur-sm', @@ -61,7 +61,7 @@ export const SPECIMENS: Array = [ source: 'src/components/AvatarCropModal.tsx', sourceLines: 176, posture: 'centered', - base: 'radix', + base: 'base-ui', tokens: 'raw-tailwind', zIndex: '999 / 1000', overlay: 'bg-black/60 backdrop-blur-sm', @@ -80,7 +80,7 @@ export const SPECIMENS: Array = [ source: 'src/routes/stats/npm/index.tsx', sourceLines: 40, posture: 'centered', - base: 'radix', + base: 'base-ui', tokens: 'raw-tailwind', zIndex: '999 / 1000', overlay: 'bg-black/60 backdrop-blur-sm', @@ -156,7 +156,7 @@ export const SPECIMENS: Array = [ source: 'src/components/charts/BuilderGuideDialog.tsx', sourceLines: 150, posture: 'edge-sheet', - base: 'radix', + base: 'base-ui', tokens: 'semantic', zIndex: '999 / 1000', overlay: 'bg-black/45 backdrop-blur-[1px]', @@ -175,7 +175,7 @@ export const SPECIMENS: Array = [ source: 'src/components/shop/CartDrawer.tsx', sourceLines: 257, posture: 'anchored-panel', - base: 'radix', + base: 'base-ui', tokens: 'shop-scope', zIndex: '100', overlay: 'bg-black/40 (no blur)', @@ -205,7 +205,7 @@ export const SPECIMENS: Array = [ scrollLock: false, animated: true, notes: - 'MIGRATED — now Drawer side="bottom" fit. Was the last hand-rolled overlay on the site; Radix now supplies the focus trap, focus restoration, Escape and scroll lock it never had. Its prev/next arrows moved from viewport-fixed on a third z-tier to panel-absolute, because Radix traps focus inside the panel and viewport-level siblings would have been unreachable by keyboard.', + 'MIGRATED — now Drawer side="bottom" fit. Was the last hand-rolled overlay on the site; Base UI now supplies the focus trap, focus restoration, Escape and scroll lock it never had. Its prev/next arrows moved from viewport-fixed on a third z-tier to panel-absolute, because focus is trapped inside the panel and viewport-level siblings would have been unreachable by keyboard.', }, { id: 'libraries-overlay', @@ -213,7 +213,7 @@ export const SPECIMENS: Array = [ source: 'src/components/LibrariesOverlay.tsx', sourceLines: 57, posture: 'full-bleed', - base: 'radix', + base: 'base-ui', tokens: 'semantic', zIndex: '110 / 111 / 112', overlay: 'bespoke .libraries-overlay-glass', @@ -224,7 +224,7 @@ export const SPECIMENS: Array = [ scrollLock: true, animated: true, notes: - 'MIGRATED — now Takeover with scrim="glass". Its bespoke glass treatment became the DS\'s second scrim, which is the pair the audit asked for after finding seven. LibrariesBrowser also dropped its direct Radix import in favour of TakeoverTitle / TakeoverDescription.', + 'MIGRATED — now Takeover with scrim="glass". Its bespoke glass treatment became the DS\'s second scrim, which is the pair the audit asked for after finding seven. LibrariesBrowser also dropped its direct Base UI import in favour of TakeoverTitle / TakeoverDescription.', }, { id: 'search-modal', @@ -232,7 +232,7 @@ export const SPECIMENS: Array = [ source: 'src/components/SearchModal.tsx', sourceLines: 3766, posture: 'top-anchored', - base: 'radix', + base: 'base-ui', tokens: 'raw-tailwind', zIndex: '999 / 1000', overlay: 'bg-black/60 → xl:bg-black/30', @@ -243,7 +243,7 @@ export const SPECIMENS: Array = [ scrollLock: true, animated: true, notes: - 'TOKENS ADOPTED, POSTURE NOT EXTRACTED. Now on bg-scrim and the --z-scrim / --z-overlay / --z-above-overlay tiers, which closes the last bespoke values in the audit. The shell itself stays: it is already Radix, already accessible, and already has real data-state animation, so extracting a CommandPalette buys no correctness — and it would need five caller-specific escape hatches (forceMount on Portal/Overlay/Content to keep InstantSearch state alive; animation on an inner panel because Content is a full-bleed hit area on mobile; the top-anchored responsive posture; a conditional sm:bottom-4; and a scrim that lightens at xl). One caller is below the extraction threshold. Revisit if a second command palette appears.', + 'TOKENS ADOPTED, POSTURE NOT EXTRACTED. Now on bg-scrim and the --z-scrim / --z-overlay / --z-above-overlay tiers, which closes the last bespoke values in the audit. The shell itself stays: it is already on the dialog primitive, already accessible, and already animates, so extracting a CommandPalette buys no correctness — and it would need four caller-specific escape hatches (animation on an inner panel because the popup is a full-bleed hit area on mobile; the top-anchored responsive posture; a conditional sm:bottom-4; and a scrim that lightens at xl). One caller is below the extraction threshold. Revisit if a second command palette appears.', }, ] @@ -271,9 +271,9 @@ export const DIVERGENCE = [ }, { property: 'Base', - values: ['Radix (7)', 'hand-rolled (4)'], + values: ['Base UI (7)', 'hand-rolled (4)'], verdict: - 'The 4 hand-rolled ones accounted for every a11y failure in the audit. All four are now migrated — every overlay on the site is Radix-backed.', + 'The 4 hand-rolled ones accounted for every a11y failure in the audit. All four are now migrated — every overlay on the site is Base UI-backed.', }, { property: 'Token layer', diff --git a/src/components/ds/ui/Dialog.tsx b/src/components/ds/ui/Dialog.tsx index 88e86077f..5e523c2d6 100644 --- a/src/components/ds/ui/Dialog.tsx +++ b/src/components/ds/ui/Dialog.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import * as DialogPrimitive from '@radix-ui/react-dialog' +import { Dialog as DialogPrimitive } from '@base-ui/react/dialog' import { CircleNotchIcon } from '@phosphor-icons/react/CircleNotch' import { XIcon } from '@phosphor-icons/react/X' import { twMerge } from 'tailwind-merge' @@ -7,7 +7,7 @@ import { twMerge } from 'tailwind-merge' /** * Centered modal dialog. * - * Always Radix-backed, which is the whole point: focus trapping, focus + * Always Base UI-backed, which is the whole point: focus trapping, focus * restoration on close, Escape-to-dismiss and scroll lock come from the * primitive rather than from each call site remembering to implement them. * The overlay audit at /ds/overlays found that every accessibility failure on @@ -43,27 +43,21 @@ type DialogContentProps = { children: React.ReactNode size?: DialogSize className?: string - /** Escape hatch for content that manages its own dismissal (e.g. a wizard mid-submit). */ - onInteractOutside?: DialogPrimitive.DialogContentProps['onInteractOutside'] } export const DialogContent = React.forwardRef< HTMLDivElement, DialogContentProps ->(function DialogContent( - { children, size = 'sm', className, onInteractOutside }, - ref, -) { +>(function DialogContent({ children, size = 'sm', className }, ref) { return ( - - {children} - + ) }) @@ -92,8 +86,8 @@ export const DialogContent = React.forwardRef< type DialogHeaderProps = { title: React.ReactNode /** - * Rendered under the title. Radix warns when a dialog has no description, so - * when this is omitted the description is still emitted, visually hidden. + * Rendered under the title. A dialog without one is an accessibility gap, + * so when this is omitted the description is still emitted, visually hidden. */ description?: React.ReactNode /** Extra controls placed left of the close button. */ diff --git a/src/components/ds/ui/Drawer.tsx b/src/components/ds/ui/Drawer.tsx index d3502682d..d9ffc561b 100644 --- a/src/components/ds/ui/Drawer.tsx +++ b/src/components/ds/ui/Drawer.tsx @@ -1,12 +1,12 @@ import * as React from 'react' -import * as DialogPrimitive from '@radix-ui/react-dialog' +import { Dialog as DialogPrimitive } from '@base-ui/react/dialog' import { XIcon } from '@phosphor-icons/react/X' import { twMerge } from 'tailwind-merge' /** * Edge-anchored panel — the drawer / side sheet. * - * Same Radix foundation as Dialog (focus trap, focus restoration, Escape, + * Same Base UI foundation as Dialog (focus trap, focus restoration, Escape, * scroll lock) and the same three-region layout, but anchored to an edge * instead of centred. `side` covers right, left and bottom: they are one * mechanism — a surface arriving from off-screen — differing only in axis. @@ -119,7 +119,6 @@ type DrawerContentProps = { */ fit?: boolean className?: string - onInteractOutside?: DialogPrimitive.DialogContentProps['onInteractOutside'] } export const DrawerContent = React.forwardRef< @@ -133,21 +132,19 @@ export const DrawerContent = React.forwardRef< anchor = 'viewport', fit = false, className, - onInteractOutside, }, ref, ) { return ( - - {children} - + ) }) diff --git a/src/components/ds/ui/Takeover.tsx b/src/components/ds/ui/Takeover.tsx index 0adddc8ae..478d013eb 100644 --- a/src/components/ds/ui/Takeover.tsx +++ b/src/components/ds/ui/Takeover.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import * as DialogPrimitive from '@radix-ui/react-dialog' +import { Dialog as DialogPrimitive } from '@base-ui/react/dialog' import { XIcon } from '@phosphor-icons/react/X' import { twMerge } from 'tailwind-merge' @@ -50,7 +50,6 @@ type TakeoverContentProps = { */ dismissOnBackdropClick?: boolean className?: string - onInteractOutside?: DialogPrimitive.DialogContentProps['onInteractOutside'] } export const TakeoverContent = React.forwardRef< @@ -64,25 +63,23 @@ export const TakeoverContent = React.forwardRef< closeLabel = 'Close', dismissOnBackdropClick = true, className, - onInteractOutside, }, ref, ) { - // The content fills the viewport, so Radix never sees a click as "outside". + // The content fills the viewport, so a click is never "outside" it. // Backdrop dismissal therefore routes through the close button we already // render, rather than a second dismissal path that could drift from it. const closeRef = React.useRef(null) return ( - - { @@ -112,7 +109,7 @@ export const TakeoverContent = React.forwardRef< {children} - + ) }) diff --git a/src/components/ds/ui/index.tsx b/src/components/ds/ui/index.tsx index b3725f4f6..ae9c34e0a 100644 --- a/src/components/ds/ui/index.tsx +++ b/src/components/ds/ui/index.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { twMerge } from 'tailwind-merge' -import * as DropdownMenu from '@radix-ui/react-dropdown-menu' +import { Menu } from '@base-ui/react/menu' import { Link } from '@tanstack/react-router' import { CaretDownIcon } from '@phosphor-icons/react/CaretDown' import { CircleNotchIcon } from '@phosphor-icons/react/CircleNotch' @@ -713,26 +713,20 @@ export function Dropdown({ modal?: boolean }) { return ( - + {children} - + ) } export function DropdownTrigger({ - children, + render, className, - asChild = true, }: { - children: React.ReactNode + render: React.ReactElement className?: string - asChild?: boolean }) { - return ( - - {children} - - ) + return } export function DropdownContent({ @@ -762,29 +756,33 @@ export function DropdownContent({ }) { const scrollable = maxHeight !== undefined return ( - - + - {children} - - + + {children} + + + ) } @@ -792,30 +790,34 @@ export function DropdownItem({ children, className, onSelect, - asChild, + render, }: { - children: React.ReactNode + children?: React.ReactNode className?: string onSelect?: () => void - asChild?: boolean + render?: React.ReactElement }) { + const itemClassName = twMerge( + 'flex cursor-pointer select-none items-center gap-2 rounded-md px-2 py-1.5 text-sm text-text-secondary outline-none transition-colors hover:bg-background-subtle hover:text-text-primary data-highlighted:bg-background-subtle data-highlighted:text-text-primary', + className, + ) + + if (render) { + return ( + + ) + } + return ( - + {children} - + ) } export function DropdownSeparator({ className }: { className?: string }) { return ( - - - - + + On this page + + + } + /> {headings.map((heading) => ( - - - - - + + + + } + /> ))}
diff --git a/src/components/examples/ExampleWorkbench.client.tsx b/src/components/examples/ExampleWorkbench.client.tsx index 2d0054cf5..619113ea7 100644 --- a/src/components/examples/ExampleWorkbench.client.tsx +++ b/src/components/examples/ExampleWorkbench.client.tsx @@ -3474,7 +3474,7 @@ export function ExampleWorkbench({ if (!open) setBuilderArrangeTabId(undefined) }} > - {tabButton} + - - - + +