From c9bf40907bdcdd43dcd42751792c97e80e43dd77 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Thu, 19 Dec 2024 19:00:38 +0000 Subject: [PATCH 1/8] chore: add DropdownMenu component --- site/package.json | 7 +- site/pnpm-lock.yaml | 226 +++++++++++++++++- .../DropdownMenu/DropdownMenu.stories.tsx | 54 +++++ .../components/DropdownMenu/DropdownMenu.tsx | 198 +++++++++++++++ site/src/index.css | 15 +- site/tailwind.config.js | 10 + 6 files changed, 507 insertions(+), 3 deletions(-) create mode 100644 site/src/components/DropdownMenu/DropdownMenu.stories.tsx create mode 100644 site/src/components/DropdownMenu/DropdownMenu.tsx diff --git a/site/package.json b/site/package.json index 84b00a4a6d17f..87bbb6b904d5f 100644 --- a/site/package.json +++ b/site/package.json @@ -52,6 +52,7 @@ "@mui/x-tree-view": "7.18.0", "@radix-ui/react-avatar": "1.1.2", "@radix-ui/react-dialog": "1.1.2", + "@radix-ui/react-dropdown-menu": "2.1.4", "@radix-ui/react-label": "2.1.0", "@radix-ui/react-popover": "1.1.3", "@radix-ui/react-slider": "1.2.1", @@ -184,7 +185,11 @@ "vite-plugin-checker": "0.8.0", "vite-plugin-turbosnap": "1.0.3" }, - "browserslist": ["chrome 110", "firefox 111", "safari 16.0"], + "browserslist": [ + "chrome 110", + "firefox 111", + "safari 16.0" + ], "resolutions": { "optionator": "0.9.3", "semver": "7.6.2" diff --git a/site/pnpm-lock.yaml b/site/pnpm-lock.yaml index d0eaa9cf78815..e48475affd74e 100644 --- a/site/pnpm-lock.yaml +++ b/site/pnpm-lock.yaml @@ -69,6 +69,9 @@ importers: '@radix-ui/react-dialog': specifier: 1.1.2 version: 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-dropdown-menu': + specifier: 2.1.4 + version: 2.1.4(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-label': specifier: 2.1.0 version: 2.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -1598,6 +1601,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-collection@1.1.1': + resolution: {integrity: sha512-LwT3pSho9Dljg+wY2KN2mrrh6y3qELfftINERIzBUO9e0N+t0oMTyn3k9iv+ZqgrwGkRnLpNJrsMv9BZlt2yuA==} + 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.0.1': resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} peerDependencies: @@ -1726,6 +1742,32 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-dismissable-layer@1.1.3': + resolution: {integrity: sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg==} + 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-dropdown-menu@2.1.4': + resolution: {integrity: sha512-iXU1Ab5ecM+yEepGAWK8ZhMyKX4ubFdCNtol4sT9D0OVErG9PNElfx3TQhjw7n7BC5nFVz68/5//clWy+8TXzA==} + 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.0.1': resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==} peerDependencies: @@ -1814,6 +1856,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-menu@2.1.4': + resolution: {integrity: sha512-BnOgVoL6YYdHAG6DtXONaR29Eq4nvbi8rutrV/xlr3RQCMMb3yqP85Qiw/3NReozrSW+4dfLkK+rc1hb4wPU/A==} + 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-popover@1.1.3': resolution: {integrity: sha512-MBDKFwRe6fi0LT8m/Jl4V8J3WbS/UfXJtsgg8Ym5w5AyPG3XfHH4zhBp1P8HmZK83T8J7UzVm6/JpDE3WMl1Dw==} peerDependencies: @@ -1957,6 +2012,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-roving-focus@1.1.1': + resolution: {integrity: sha512-QE1RoxPGJ/Nm8Qmk0PxP8ojmoaS67i0s7hVssS7KuI2FQoc/uzVlZsqKfQvxPE6D8hICCPHJ4D88zNhT3OOmkw==} + 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-slider@1.2.1': resolution: {integrity: sha512-bEzQoDW0XP+h/oGbutF5VMWJPAl/UU8IJjr7h02SOHDIIIxq+cep8nItVNoBV+OMmahCdqdF38FTpmXoqQUGvw==} peerDependencies: @@ -3669,7 +3737,6 @@ packages: eslint@8.52.0: resolution: {integrity: sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true espree@9.6.1: @@ -5254,6 +5321,16 @@ packages: '@types/react': optional: true + react-remove-scroll-bar@2.3.8: + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + react-remove-scroll@2.5.5: resolution: {integrity: sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==} engines: {node: '>=10'} @@ -5274,6 +5351,16 @@ packages: '@types/react': optional: true + react-remove-scroll@2.6.2: + resolution: {integrity: sha512-KmONPx5fnlXYJQqC62Q+lwIeAk64ws/cUw6omIumRzMRPqgnYqhSSti99nbj0Ry13bv7dF+BKn7NB+OqkdZGTw==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + react-router-dom@6.26.2: resolution: {integrity: sha512-z7YkaEW0Dy35T3/QKPYB1LjMK2R1fxnHO8kWpUMTBdfVzZrWOiY9a7CtN8HqdWtDUWd5FY6Dl8HFsqVwH4uOtQ==} engines: {node: '>=14.0.0'} @@ -5297,6 +5384,16 @@ packages: '@types/react': optional: true + react-style-singleton@2.2.3: + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + react-syntax-highlighter@15.5.0: resolution: {integrity: sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg==} peerDependencies: @@ -5962,6 +6059,16 @@ packages: '@types/react': optional: true + use-callback-ref@1.3.3: + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + use-sidecar@1.1.2: resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} engines: {node: '>=10'} @@ -7404,6 +7511,18 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 + '@radix-ui/react-collection@1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.1(@types/react@18.3.12)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + '@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.12)(react@18.3.1)': dependencies: '@babel/runtime': 7.25.6 @@ -7533,6 +7652,34 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 + '@radix-ui/react-dismissable-layer@1.1.3(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.3.12)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + + '@radix-ui/react-dropdown-menu@2.1.4(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-menu': 2.1.4(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.12)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + '@radix-ui/react-focus-guards@1.0.1(@types/react@18.3.12)(react@18.3.1)': dependencies: '@babel/runtime': 7.25.6 @@ -7604,6 +7751,32 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 + '@radix-ui/react-menu@2.1.4(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-collection': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.3(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-popper': 1.2.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1) + aria-hidden: 1.2.4 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-remove-scroll: 2.6.2(@types/react@18.3.12)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + '@radix-ui/react-popover@1.1.3(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 @@ -7734,6 +7907,23 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 + '@radix-ui/react-roving-focus@1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-collection': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.12)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + '@radix-ui/react-slider@1.2.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/number': 1.1.0 @@ -11539,6 +11729,14 @@ snapshots: optionalDependencies: '@types/react': 18.3.12 + react-remove-scroll-bar@2.3.8(@types/react@18.3.12)(react@18.3.1): + dependencies: + react: 18.3.1 + react-style-singleton: 2.2.3(@types/react@18.3.12)(react@18.3.1) + tslib: 2.6.2 + optionalDependencies: + '@types/react': 18.3.12 + react-remove-scroll@2.5.5(@types/react@18.3.12)(react@18.3.1): dependencies: react: 18.3.1 @@ -11561,6 +11759,17 @@ snapshots: optionalDependencies: '@types/react': 18.3.12 + react-remove-scroll@2.6.2(@types/react@18.3.12)(react@18.3.1): + dependencies: + react: 18.3.1 + react-remove-scroll-bar: 2.3.8(@types/react@18.3.12)(react@18.3.1) + react-style-singleton: 2.2.1(@types/react@18.3.12)(react@18.3.1) + tslib: 2.6.2 + use-callback-ref: 1.3.3(@types/react@18.3.12)(react@18.3.1) + use-sidecar: 1.1.2(@types/react@18.3.12)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + react-router-dom@6.26.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@remix-run/router': 1.19.2 @@ -11582,6 +11791,14 @@ snapshots: optionalDependencies: '@types/react': 18.3.12 + react-style-singleton@2.2.3(@types/react@18.3.12)(react@18.3.1): + dependencies: + get-nonce: 1.0.1 + react: 18.3.1 + tslib: 2.6.2 + optionalDependencies: + '@types/react': 18.3.12 + react-syntax-highlighter@15.5.0(react@18.3.1): dependencies: '@babel/runtime': 7.22.6 @@ -12343,6 +12560,13 @@ snapshots: optionalDependencies: '@types/react': 18.3.12 + use-callback-ref@1.3.3(@types/react@18.3.12)(react@18.3.1): + dependencies: + react: 18.3.1 + tslib: 2.6.2 + optionalDependencies: + '@types/react': 18.3.12 + use-sidecar@1.1.2(@types/react@18.3.12)(react@18.3.1): dependencies: detect-node-es: 1.1.0 diff --git a/site/src/components/DropdownMenu/DropdownMenu.stories.tsx b/site/src/components/DropdownMenu/DropdownMenu.stories.tsx new file mode 100644 index 0000000000000..f4267d56d9913 --- /dev/null +++ b/site/src/components/DropdownMenu/DropdownMenu.stories.tsx @@ -0,0 +1,54 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuPortal, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuTrigger, +} from "./DropdownMenu"; +import { Button } from "components/Button/Button"; +import { userEvent, within } from "@storybook/test"; + +const meta: Meta = { + title: "components/DropdownMenu", + component: DropdownMenu, + args: { + children: ( + <> + + + + + Deployment + Organizations + Audit logs + Health check + + + ), + }, +}; + +export default meta; +type Story = StoryObj; + +export const Close: Story = {}; + +export const OpenWithHover: Story = { + play: async ({ canvasElement }) => { + const user = userEvent.setup(); + const canvas = within(canvasElement); + const button = canvas.getByText("Admin Settings"); + await user.click(button); + const body = canvasElement.ownerDocument.body; + const menuItem = await within(body).findByText("Audit logs"); + await user.hover(menuItem); + }, +}; diff --git a/site/src/components/DropdownMenu/DropdownMenu.tsx b/site/src/components/DropdownMenu/DropdownMenu.tsx new file mode 100644 index 0000000000000..cefeb59a4c0a1 --- /dev/null +++ b/site/src/components/DropdownMenu/DropdownMenu.tsx @@ -0,0 +1,198 @@ +import * as React from "react"; +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; +import { Check, ChevronRight, Circle } from "lucide-react"; +import { cn } from "utils/cn"; + +const DropdownMenu = DropdownMenuPrimitive.Root; + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; + +const DropdownMenuGroup = DropdownMenuPrimitive.Group; + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal; + +const DropdownMenuSub = DropdownMenuPrimitive.Sub; + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup; + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean; + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)); +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName; + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName; + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)); +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName; + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean; + } +>(({ className, inset, ...props }, ref) => ( + svg]:size-4 [&>svg]:shrink-0", + inset && "pl-8", + className, + )} + {...props} + /> +)); +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName; + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)); +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName; + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)); +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName; + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean; + } +>(({ className, inset, ...props }, ref) => ( + +)); +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName; + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName; + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ); +}; +DropdownMenuShortcut.displayName = "DropdownMenuShortcut"; + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +}; diff --git a/site/src/index.css b/site/src/index.css index 1353b200745c0..b1d4b0ca43219 100644 --- a/site/src/index.css +++ b/site/src/index.css @@ -31,6 +31,10 @@ --border: 240 5.9% 90%; --input: 240 5.9% 90%; --ring: 240 10% 3.9%; + --muted: 240, 6%, 90%; + --popover: 0, 0%, 98%; + --accent: 240, 5%, 96%; + --accent-foreground: 240, 10%, 4%; } .dark { --content-primary: 0, 0%, 98%; @@ -59,11 +63,20 @@ --border: 240 3.7% 15.9%; --input: 240 3.7% 15.9%; --ring: 240 4.9% 83.9%; + --muted: 240, 4%, 16%; + --popover: 240, 10%, 4%; + --accent: 240, 6%, 10%; + --accent-foreground: 0, 0%, 98%; } } @layer base { * { - @apply border-border; + /* + * TODO: Since we’re not using TailwindCSS preflight (check site/tailwind.config.js), + * we need to apply this reset manually. Eventually, we should enable preflight + * and remove the border-0 and border-solid styles. + */ + @apply border-border border-0 border-solid; } } diff --git a/site/tailwind.config.js b/site/tailwind.config.js index 61d35ee0338aa..28257959de7b3 100644 --- a/site/tailwind.config.js +++ b/site/tailwind.config.js @@ -52,6 +52,16 @@ module.exports = { 4: "hsl(var(--chart-4))", 5: "hsl(var(--chart-5))", }, + muted: { + DEFAULT: "hsl(var(--muted))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, }, }, }, From 59dc1ee9f8cfc40665950e1a7b19c5cae38b2578 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Thu, 19 Dec 2024 19:03:06 +0000 Subject: [PATCH 2/8] Remove unused components and add details on component --- .../DropdownMenu/DropdownMenu.stories.tsx | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/site/src/components/DropdownMenu/DropdownMenu.stories.tsx b/site/src/components/DropdownMenu/DropdownMenu.stories.tsx index f4267d56d9913..89d016b25fedb 100644 --- a/site/src/components/DropdownMenu/DropdownMenu.stories.tsx +++ b/site/src/components/DropdownMenu/DropdownMenu.stories.tsx @@ -1,16 +1,15 @@ +/** + * Copied from shadc/ui on 12/19/2024 + * @see {@link https://ui.shadcn.com/docs/components/dropdown-menu} + * + * This component was updated to match the styles from the Figma design: + * @see {@link https://www.figma.com/design/WfqIgsTFXN2BscBSSyXWF8/Coder-kit?node-id=656-2354&t=CiGt5le3yJEwMH4M-0} + */ import type { Meta, StoryObj } from "@storybook/react"; import { DropdownMenu, DropdownMenuContent, - DropdownMenuGroup, DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuPortal, - DropdownMenuSeparator, - DropdownMenuShortcut, - DropdownMenuSub, - DropdownMenuSubContent, - DropdownMenuSubTrigger, DropdownMenuTrigger, } from "./DropdownMenu"; import { Button } from "components/Button/Button"; From 49629655a4eec5b481fa0277407c255bdbd06583 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Thu, 19 Dec 2024 19:57:12 +0000 Subject: [PATCH 3/8] Fix fmt --- site/package.json | 6 +----- site/src/components/DropdownMenu/DropdownMenu.stories.tsx | 4 ++-- site/src/components/DropdownMenu/DropdownMenu.tsx | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/site/package.json b/site/package.json index 87bbb6b904d5f..dac25790e8084 100644 --- a/site/package.json +++ b/site/package.json @@ -185,11 +185,7 @@ "vite-plugin-checker": "0.8.0", "vite-plugin-turbosnap": "1.0.3" }, - "browserslist": [ - "chrome 110", - "firefox 111", - "safari 16.0" - ], + "browserslist": ["chrome 110", "firefox 111", "safari 16.0"], "resolutions": { "optionator": "0.9.3", "semver": "7.6.2" diff --git a/site/src/components/DropdownMenu/DropdownMenu.stories.tsx b/site/src/components/DropdownMenu/DropdownMenu.stories.tsx index 89d016b25fedb..3cbcdd8590c87 100644 --- a/site/src/components/DropdownMenu/DropdownMenu.stories.tsx +++ b/site/src/components/DropdownMenu/DropdownMenu.stories.tsx @@ -6,14 +6,14 @@ * @see {@link https://www.figma.com/design/WfqIgsTFXN2BscBSSyXWF8/Coder-kit?node-id=656-2354&t=CiGt5le3yJEwMH4M-0} */ import type { Meta, StoryObj } from "@storybook/react"; +import { userEvent, within } from "@storybook/test"; +import { Button } from "components/Button/Button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "./DropdownMenu"; -import { Button } from "components/Button/Button"; -import { userEvent, within } from "@storybook/test"; const meta: Meta = { title: "components/DropdownMenu", diff --git a/site/src/components/DropdownMenu/DropdownMenu.tsx b/site/src/components/DropdownMenu/DropdownMenu.tsx index cefeb59a4c0a1..62ae0babae712 100644 --- a/site/src/components/DropdownMenu/DropdownMenu.tsx +++ b/site/src/components/DropdownMenu/DropdownMenu.tsx @@ -1,6 +1,6 @@ -import * as React from "react"; import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; import { Check, ChevronRight, Circle } from "lucide-react"; +import * as React from "react"; import { cn } from "utils/cn"; const DropdownMenu = DropdownMenuPrimitive.Root; From ae72c248f033c8a5fcd9c37f5a29fd8f060ca3f2 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Fri, 20 Dec 2024 12:42:32 +0000 Subject: [PATCH 4/8] Remove invalid tokens --- site/src/components/DropdownMenu/DropdownMenu.tsx | 14 +++++++------- site/src/index.css | 6 ------ site/tailwind.config.js | 10 ---------- 3 files changed, 7 insertions(+), 23 deletions(-) diff --git a/site/src/components/DropdownMenu/DropdownMenu.tsx b/site/src/components/DropdownMenu/DropdownMenu.tsx index 62ae0babae712..781805b31c36f 100644 --- a/site/src/components/DropdownMenu/DropdownMenu.tsx +++ b/site/src/components/DropdownMenu/DropdownMenu.tsx @@ -24,7 +24,7 @@ const DropdownMenuSubTrigger = React.forwardRef< svg]:size-4 [&>svg]:shrink-0", + "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-2 text-sm text-content-secondary font-medium outline-none transition-colors focus:bg-surface-secondary focus:text-content-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0", inset && "pl-8", className, )} @@ -97,7 +97,7 @@ const DropdownMenuCheckboxItem = React.forwardRef< (({ className, ...props }, ref) => ( )); diff --git a/site/src/index.css b/site/src/index.css index b1d4b0ca43219..315d7fc655968 100644 --- a/site/src/index.css +++ b/site/src/index.css @@ -31,8 +31,6 @@ --border: 240 5.9% 90%; --input: 240 5.9% 90%; --ring: 240 10% 3.9%; - --muted: 240, 6%, 90%; - --popover: 0, 0%, 98%; --accent: 240, 5%, 96%; --accent-foreground: 240, 10%, 4%; } @@ -63,10 +61,6 @@ --border: 240 3.7% 15.9%; --input: 240 3.7% 15.9%; --ring: 240 4.9% 83.9%; - --muted: 240, 4%, 16%; - --popover: 240, 10%, 4%; - --accent: 240, 6%, 10%; - --accent-foreground: 0, 0%, 98%; } } diff --git a/site/tailwind.config.js b/site/tailwind.config.js index 28257959de7b3..61d35ee0338aa 100644 --- a/site/tailwind.config.js +++ b/site/tailwind.config.js @@ -52,16 +52,6 @@ module.exports = { 4: "hsl(var(--chart-4))", 5: "hsl(var(--chart-5))", }, - muted: { - DEFAULT: "hsl(var(--muted))", - }, - popover: { - DEFAULT: "hsl(var(--popover))", - }, - accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", - }, }, }, }, From fc5c0a1c52dccee18653eec9f0d38b49d5bc2cc4 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Fri, 20 Dec 2024 12:44:32 +0000 Subject: [PATCH 5/8] Remove missed variables --- site/src/index.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/site/src/index.css b/site/src/index.css index 315d7fc655968..3ff4f8e36d7e8 100644 --- a/site/src/index.css +++ b/site/src/index.css @@ -31,8 +31,6 @@ --border: 240 5.9% 90%; --input: 240 5.9% 90%; --ring: 240 10% 3.9%; - --accent: 240, 5%, 96%; - --accent-foreground: 240, 10%, 4%; } .dark { --content-primary: 0, 0%, 98%; From b776a4e910470b8c7ed94a852695bd414d01dbb0 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Fri, 20 Dec 2024 13:13:20 +0000 Subject: [PATCH 6/8] Remove border reset --- site/src/components/DropdownMenu/DropdownMenu.tsx | 4 ++-- site/src/index.css | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/site/src/components/DropdownMenu/DropdownMenu.tsx b/site/src/components/DropdownMenu/DropdownMenu.tsx index 781805b31c36f..c1e12186f2972 100644 --- a/site/src/components/DropdownMenu/DropdownMenu.tsx +++ b/site/src/components/DropdownMenu/DropdownMenu.tsx @@ -44,7 +44,7 @@ const DropdownMenuSubContent = React.forwardRef< Date: Fri, 20 Dec 2024 17:01:22 +0000 Subject: [PATCH 7/8] Apply review comments --- .../DropdownMenu/DropdownMenu.stories.tsx | 7 - .../components/DropdownMenu/DropdownMenu.tsx | 144 ++++++++++-------- 2 files changed, 81 insertions(+), 70 deletions(-) diff --git a/site/src/components/DropdownMenu/DropdownMenu.stories.tsx b/site/src/components/DropdownMenu/DropdownMenu.stories.tsx index 3cbcdd8590c87..f9ba8cd290902 100644 --- a/site/src/components/DropdownMenu/DropdownMenu.stories.tsx +++ b/site/src/components/DropdownMenu/DropdownMenu.stories.tsx @@ -1,10 +1,3 @@ -/** - * Copied from shadc/ui on 12/19/2024 - * @see {@link https://ui.shadcn.com/docs/components/dropdown-menu} - * - * This component was updated to match the styles from the Figma design: - * @see {@link https://www.figma.com/design/WfqIgsTFXN2BscBSSyXWF8/Coder-kit?node-id=656-2354&t=CiGt5le3yJEwMH4M-0} - */ import type { Meta, StoryObj } from "@storybook/react"; import { userEvent, within } from "@storybook/test"; import { Button } from "components/Button/Button"; diff --git a/site/src/components/DropdownMenu/DropdownMenu.tsx b/site/src/components/DropdownMenu/DropdownMenu.tsx index c1e12186f2972..c4608af6e02be 100644 --- a/site/src/components/DropdownMenu/DropdownMenu.tsx +++ b/site/src/components/DropdownMenu/DropdownMenu.tsx @@ -1,31 +1,47 @@ +/** + * Copied from shadc/ui on 12/19/2024 + * @see {@link https://ui.shadcn.com/docs/components/dropdown-menu} + * + * This component was updated to match the styles from the Figma design: + * @see {@link https://www.figma.com/design/WfqIgsTFXN2BscBSSyXWF8/Coder-kit?node-id=656-2354&t=CiGt5le3yJEwMH4M-0} + */ + import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; import { Check, ChevronRight, Circle } from "lucide-react"; -import * as React from "react"; +import { + forwardRef, + type ElementRef, + type ComponentPropsWithoutRef, + type HTMLAttributes, +} from "react"; import { cn } from "utils/cn"; -const DropdownMenu = DropdownMenuPrimitive.Root; +export const DropdownMenu = DropdownMenuPrimitive.Root; -const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; +export const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; -const DropdownMenuGroup = DropdownMenuPrimitive.Group; +export const DropdownMenuGroup = DropdownMenuPrimitive.Group; -const DropdownMenuPortal = DropdownMenuPrimitive.Portal; +export const DropdownMenuPortal = DropdownMenuPrimitive.Portal; -const DropdownMenuSub = DropdownMenuPrimitive.Sub; +export const DropdownMenuSub = DropdownMenuPrimitive.Sub; -const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup; +export const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup; -const DropdownMenuSubTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { +export const DropdownMenuSubTrigger = forwardRef< + ElementRef, + ComponentPropsWithoutRef & { inset?: boolean; } >(({ className, inset, children, ...props }, ref) => ( , - React.ComponentPropsWithoutRef +export const DropdownMenuSubContent = forwardRef< + ElementRef, + ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( , - React.ComponentPropsWithoutRef +export const DropdownMenuContent = forwardRef< + ElementRef, + ComponentPropsWithoutRef >(({ className, sideOffset = 4, ...props }, ref) => ( , - React.ComponentPropsWithoutRef & { +export const DropdownMenuItem = forwardRef< + ElementRef, + ComponentPropsWithoutRef & { inset?: boolean; } >(({ className, inset, ...props }, ref) => ( svg]:size-4 [&>svg]:shrink-0", - inset && "pl-8", + [ + "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-2 text-sm text-content-secondary font-medium outline-none transition-colors", + "focus:bg-surface-secondary focus:text-content-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50", + "[&>svg]:size-4 [&>svg]:shrink-0", + inset && "pl-8", + ], className, )} {...props} @@ -90,14 +121,17 @@ const DropdownMenuItem = React.forwardRef< )); DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName; -const DropdownMenuCheckboxItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef +export const DropdownMenuCheckboxItem = forwardRef< + ElementRef, + ComponentPropsWithoutRef >(({ className, children, checked, ...props }, ref) => ( , - React.ComponentPropsWithoutRef +export const DropdownMenuRadioItem = forwardRef< + ElementRef, + ComponentPropsWithoutRef >(({ className, children, ...props }, ref) => ( , - React.ComponentPropsWithoutRef & { +export const DropdownMenuLabel = forwardRef< + ElementRef, + ComponentPropsWithoutRef & { inset?: boolean; } >(({ className, inset, ...props }, ref) => ( , - React.ComponentPropsWithoutRef +export const DropdownMenuSeparator = forwardRef< + ElementRef, + ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( )); DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName; -const DropdownMenuShortcut = ({ +export const DropdownMenuShortcut = ({ className, ...props -}: React.HTMLAttributes) => { +}: HTMLAttributes) => { return ( Date: Fri, 20 Dec 2024 17:02:50 +0000 Subject: [PATCH 8/8] Fix fmt --- site/src/components/DropdownMenu/DropdownMenu.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/src/components/DropdownMenu/DropdownMenu.tsx b/site/src/components/DropdownMenu/DropdownMenu.tsx index c4608af6e02be..8008ea9d6c27e 100644 --- a/site/src/components/DropdownMenu/DropdownMenu.tsx +++ b/site/src/components/DropdownMenu/DropdownMenu.tsx @@ -9,10 +9,10 @@ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; import { Check, ChevronRight, Circle } from "lucide-react"; import { - forwardRef, - type ElementRef, type ComponentPropsWithoutRef, + type ElementRef, type HTMLAttributes, + forwardRef, } from "react"; import { cn } from "utils/cn";