From 97b42da9595778c1b44550ff967ecbe2279bfd04 Mon Sep 17 00:00:00 2001 From: Guilherme Minozzi Date: Wed, 27 Mar 2024 17:47:24 -0300 Subject: [PATCH] feat: add dropdown menu --- package.json | 1 + pnpm-lock.yaml | 218 +++++++++++++++--- .../components/ui/dropdown/checkboxItem.tsx | 33 +++ .../components/ui/dropdown/content.tsx | 24 ++ .../components/ui/dropdown/index.stories.tsx | 90 ++++++++ .../components/ui/dropdown/index.ts | 36 +++ .../components/ui/dropdown/item.tsx | 24 ++ .../components/ui/dropdown/label.tsx | 24 ++ .../components/ui/dropdown/radioItem.tsx | 32 +++ .../components/ui/dropdown/separator.tsx | 18 ++ .../components/ui/dropdown/shortcut.tsx | 13 ++ .../components/ui/dropdown/subContent.tsx | 21 ++ .../components/ui/dropdown/subTrigger.tsx | 28 +++ 13 files changed, 533 insertions(+), 29 deletions(-) create mode 100644 src/presentation/components/ui/dropdown/checkboxItem.tsx create mode 100644 src/presentation/components/ui/dropdown/content.tsx create mode 100644 src/presentation/components/ui/dropdown/index.stories.tsx create mode 100644 src/presentation/components/ui/dropdown/index.ts create mode 100644 src/presentation/components/ui/dropdown/item.tsx create mode 100644 src/presentation/components/ui/dropdown/label.tsx create mode 100644 src/presentation/components/ui/dropdown/radioItem.tsx create mode 100644 src/presentation/components/ui/dropdown/separator.tsx create mode 100644 src/presentation/components/ui/dropdown/shortcut.tsx create mode 100644 src/presentation/components/ui/dropdown/subContent.tsx create mode 100644 src/presentation/components/ui/dropdown/subTrigger.tsx diff --git a/package.json b/package.json index 952b25c0..13e14065 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "storybook:build": "storybook build -o docs-build" }, "dependencies": { + "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-slot": "^1.0.2", "axios": "^1.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 81f4e0df..e49fff82 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,6 +5,9 @@ settings: excludeLinksFromLockfile: false dependencies: + '@radix-ui/react-dropdown-menu': + specifier: ^2.0.6 + version: 2.0.6(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-label': specifier: ^2.0.2 version: 2.0.2(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) @@ -1917,14 +1920,12 @@ packages: resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==} dependencies: '@floating-ui/utils': 0.2.1 - dev: true /@floating-ui/dom@1.6.1: resolution: {integrity: sha512-iA8qE43/H5iGozC3W0YSnVSW42Vh522yyM1gj+BqRwVsTNOyr231PsXDaV04yT39PsO0QL2QpbI/M0ZaLUQgRQ==} dependencies: '@floating-ui/core': 1.6.0 '@floating-ui/utils': 0.2.1 - dev: true /@floating-ui/react-dom@2.0.8(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==} @@ -1935,11 +1936,9 @@ packages: '@floating-ui/dom': 1.6.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - dev: true /@floating-ui/utils@0.2.1: resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} - dev: true /@humanwhocodes/config-array@0.11.14: resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} @@ -2150,7 +2149,6 @@ packages: resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==} dependencies: '@babel/runtime': 7.23.9 - dev: true /@radix-ui/react-arrow@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==} @@ -2171,7 +2169,6 @@ packages: '@types/react-dom': 18.2.18 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - dev: true /@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==} @@ -2195,7 +2192,6 @@ packages: '@types/react-dom': 18.2.18 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - dev: true /@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.48)(react@18.2.0): resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} @@ -2222,7 +2218,6 @@ packages: '@babel/runtime': 7.23.9 '@types/react': 18.2.48 react: 18.2.0 - dev: true /@radix-ui/react-direction@1.0.1(@types/react@18.2.48)(react@18.2.0): resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==} @@ -2236,7 +2231,6 @@ packages: '@babel/runtime': 7.23.9 '@types/react': 18.2.48 react: 18.2.0 - dev: true /@radix-ui/react-dismissable-layer@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg==} @@ -2263,6 +2257,58 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: true + /@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.48)(react@18.2.0) + '@types/react': 18.2.48 + '@types/react-dom': 18.2.18 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-dropdown-menu@2.0.6(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-menu': 2.0.6(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@types/react': 18.2.48 + '@types/react-dom': 18.2.18 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.48)(react@18.2.0): resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==} peerDependencies: @@ -2275,7 +2321,6 @@ packages: '@babel/runtime': 7.23.9 '@types/react': 18.2.48 react: 18.2.0 - dev: true /@radix-ui/react-focus-scope@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-upXdPfqI4islj2CslyfUBNlaJCPybbqRHAi1KER7Isel9Q2AtSJ0zRBZv8mWQiFXD2nyAJ4BhC3yXgZ6kMBSrQ==} @@ -2300,6 +2345,29 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: true + /@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@types/react': 18.2.48 + '@types/react-dom': 18.2.18 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-id@1.0.1(@types/react@18.2.48)(react@18.2.0): resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==} peerDependencies: @@ -2313,7 +2381,6 @@ packages: '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0) '@types/react': 18.2.48 react: 18.2.0 - dev: true /@radix-ui/react-label@2.0.2(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==} @@ -2336,6 +2403,44 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-menu@2.0.6(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@types/react': 18.2.48 + '@types/react-dom': 18.2.18 + aria-hidden: 1.2.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.2.48)(react@18.2.0) + dev: false + /@radix-ui/react-popper@1.1.2(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-1CnGGfFi/bbqtJZZ0P/NQY20xdG3E0LALJaLUEoKwPLwl6PPPfbeiCqMVQnhoFRAxjJj4RpBRJzDmUgsex2tSg==} peerDependencies: @@ -2366,6 +2471,36 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: true + /@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@floating-ui/react-dom': 2.0.8(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/rect': 1.0.1 + '@types/react': 18.2.48 + '@types/react-dom': 18.2.18 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-portal@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==} peerDependencies: @@ -2387,6 +2522,49 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: true + /@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.48 + '@types/react-dom': 18.2.18 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@types/react': 18.2.48 + '@types/react-dom': 18.2.18 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==} peerDependencies: @@ -2434,7 +2612,6 @@ packages: '@types/react-dom': 18.2.18 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - dev: true /@radix-ui/react-select@1.2.2(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-zI7McXr8fNaSrUY9mZe4x/HC0jTLY9fWNhO1oLWYMQGDXuV4UCivIGTxwioSzO0ZCYX9iSLyWmAh/1TOmX3Cnw==} @@ -2601,7 +2778,6 @@ packages: '@babel/runtime': 7.23.9 '@types/react': 18.2.48 react: 18.2.0 - dev: true /@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.48)(react@18.2.0): resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==} @@ -2616,7 +2792,6 @@ packages: '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) '@types/react': 18.2.48 react: 18.2.0 - dev: true /@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.48)(react@18.2.0): resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==} @@ -2631,7 +2806,6 @@ packages: '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) '@types/react': 18.2.48 react: 18.2.0 - dev: true /@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.48)(react@18.2.0): resolution: {integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==} @@ -2645,7 +2819,6 @@ packages: '@babel/runtime': 7.23.9 '@types/react': 18.2.48 react: 18.2.0 - dev: true /@radix-ui/react-use-previous@1.0.1(@types/react@18.2.48)(react@18.2.0): resolution: {integrity: sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==} @@ -2674,7 +2847,6 @@ packages: '@radix-ui/rect': 1.0.1 '@types/react': 18.2.48 react: 18.2.0 - dev: true /@radix-ui/react-use-size@1.0.1(@types/react@18.2.48)(react@18.2.0): resolution: {integrity: sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==} @@ -2689,7 +2861,6 @@ packages: '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0) '@types/react': 18.2.48 react: 18.2.0 - dev: true /@radix-ui/react-visually-hidden@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==} @@ -2716,7 +2887,6 @@ packages: resolution: {integrity: sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==} dependencies: '@babel/runtime': 7.23.9 - dev: true /@remix-run/router@1.14.2: resolution: {integrity: sha512-ACXpdMM9hmKZww21yEqWwiLws/UPLhNKvimN8RrYSqPSvB3ov7sLvAcfvaxePeLvccTQKGdkDIhLYApZVDFuKg==} @@ -4163,7 +4333,6 @@ packages: engines: {node: '>=10'} dependencies: tslib: 2.6.2 - dev: true /aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} @@ -5074,7 +5243,6 @@ packages: /detect-node-es@1.1.0: resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} - dev: true /detect-package-manager@2.0.1: resolution: {integrity: sha512-j/lJHyoLlWi6G1LDdLgvUtz60Zo5GEj+sVYtTVXnYLDPuzgC3llMxonXym9zIwhhUII8vjdw0LXxavpLqTbl1A==} @@ -6128,7 +6296,6 @@ packages: /get-nonce@1.0.1: resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} engines: {node: '>=6'} - dev: true /get-npm-tarball-url@2.1.0: resolution: {integrity: sha512-ro+DiMu5DXgRBabqXupW38h7WPZ9+Ad8UjwhvsmmN8w1sU7ab0nzAXvVZ4kqYg57OrqomRtJvepX5/xvFKNtjA==} @@ -6500,7 +6667,6 @@ packages: resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} dependencies: loose-envify: 1.4.0 - dev: true /ip@2.0.0: resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} @@ -8266,7 +8432,6 @@ packages: react: 18.2.0 react-style-singleton: 2.2.1(@types/react@18.2.48)(react@18.2.0) tslib: 2.6.2 - dev: true /react-remove-scroll@2.5.5(@types/react@18.2.48)(react@18.2.0): resolution: {integrity: sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==} @@ -8285,7 +8450,6 @@ packages: tslib: 2.6.2 use-callback-ref: 1.3.1(@types/react@18.2.48)(react@18.2.0) use-sidecar: 1.1.2(@types/react@18.2.48)(react@18.2.0) - dev: true /react-router-dom@6.21.3(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-kNzubk7n4YHSrErzjLK72j0B5i969GsuCGazRl3G6j1zqZBLjuSlYBdVdkDOgzGdPIffUOc9nmgiadTEVoq91g==} @@ -8325,7 +8489,6 @@ packages: invariant: 2.2.4 react: 18.2.0 tslib: 2.6.2 - dev: true /react@18.2.0: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} @@ -9260,7 +9423,6 @@ packages: /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - dev: true /tsutils@3.21.0(typescript@5.3.3): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} @@ -9497,7 +9659,6 @@ packages: '@types/react': 18.2.48 react: 18.2.0 tslib: 2.6.2 - dev: true /use-resize-observer@9.1.0(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==} @@ -9524,7 +9685,6 @@ packages: detect-node-es: 1.1.0 react: 18.2.0 tslib: 2.6.2 - dev: true /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} diff --git a/src/presentation/components/ui/dropdown/checkboxItem.tsx b/src/presentation/components/ui/dropdown/checkboxItem.tsx new file mode 100644 index 00000000..ce81e52c --- /dev/null +++ b/src/presentation/components/ui/dropdown/checkboxItem.tsx @@ -0,0 +1,33 @@ +import React from 'react' + +import { + CheckboxItem as CheckboxItemRadix, + ItemIndicator +} from '@radix-ui/react-dropdown-menu' +import { Check } from 'lucide-react' + +import { cn } from '@/main/utils' + +export const CheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) + +CheckboxItem.displayName = CheckboxItemRadix.displayName diff --git a/src/presentation/components/ui/dropdown/content.tsx b/src/presentation/components/ui/dropdown/content.tsx new file mode 100644 index 00000000..a84a5c70 --- /dev/null +++ b/src/presentation/components/ui/dropdown/content.tsx @@ -0,0 +1,24 @@ +import React from 'react' + +import { Content as ContentRadix, Portal } from '@radix-ui/react-dropdown-menu' + +import { cn } from '@/main/utils' + +export const Content = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) + +Content.displayName = ContentRadix.displayName diff --git a/src/presentation/components/ui/dropdown/index.stories.tsx b/src/presentation/components/ui/dropdown/index.stories.tsx new file mode 100644 index 00000000..0467825d --- /dev/null +++ b/src/presentation/components/ui/dropdown/index.stories.tsx @@ -0,0 +1,90 @@ +import { useState } from 'react' + +import { DropdownMenuCheckboxItemProps } from '@radix-ui/react-dropdown-menu' +import { Meta, StoryFn } from '@storybook/react/' + +import { Button } from '../button' + +import { DropdownMenu } from '.' + +export default { + title: 'Components/UI/DropdownMenu' +} as Meta + +type Checked = DropdownMenuCheckboxItemProps['checked'] + +const TemplateDefault: StoryFn = () => ( + + Open + + My Account + + Profile + Billing + Team + Subscription + + +) + +const TemplateCheckbox: StoryFn = () => { + const [showStatusBar, setShowStatusBar] = useState(true) + const [showActivityBar, setShowActivityBar] = useState(false) + const [showPanel, setShowPanel] = useState(false) + + return ( + + + + + + Appearance + + + Status Bar + + + Activity Bar + + + Panel + + + + ) +} + +const TemplateRadioGroup: StoryFn = () => { + const [position, setPosition] = useState('bottom') + + return ( + + + + + + Panel Position + + + Top + Bottom + Right + + + + ) +} + +export const Default = TemplateDefault.bind({}) +export const WithCheckbox = TemplateCheckbox.bind({}) +export const WithRadioGroup = TemplateRadioGroup.bind({}) diff --git a/src/presentation/components/ui/dropdown/index.ts b/src/presentation/components/ui/dropdown/index.ts new file mode 100644 index 00000000..1e6ce91b --- /dev/null +++ b/src/presentation/components/ui/dropdown/index.ts @@ -0,0 +1,36 @@ +import { + Group, + Portal, + RadioGroup, + Root, + Sub, + Trigger +} from '@radix-ui/react-dropdown-menu' + +import { CheckboxItem } from './checkboxItem' +import { Content } from './content' +import { Item } from './item' +import { Label } from './label' +import { RadioItem } from './radioItem' +import { Separator } from './separator' +import { Shortcut } from './shortcut' +import { SubContent } from './subContent' +import { SubTrigger } from './subTrigger' + +export const DropdownMenu = { + Root, + Trigger, + Content, + Item, + CheckboxItem, + RadioItem, + Label, + Separator, + Shortcut, + Group, + Portal, + Sub, + SubContent, + SubTrigger, + RadioGroup +} diff --git a/src/presentation/components/ui/dropdown/item.tsx b/src/presentation/components/ui/dropdown/item.tsx new file mode 100644 index 00000000..f46d314a --- /dev/null +++ b/src/presentation/components/ui/dropdown/item.tsx @@ -0,0 +1,24 @@ +import React from 'react' + +import { Item as ItemRadix } from '@radix-ui/react-dropdown-menu' + +import { cn } from '@/main/utils' + +export const Item = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) + +Item.displayName = ItemRadix.displayName diff --git a/src/presentation/components/ui/dropdown/label.tsx b/src/presentation/components/ui/dropdown/label.tsx new file mode 100644 index 00000000..65442789 --- /dev/null +++ b/src/presentation/components/ui/dropdown/label.tsx @@ -0,0 +1,24 @@ +import React from 'react' + +import { Label as LabelRadix } from '@radix-ui/react-dropdown-menu' + +import { cn } from '@/main/utils' + +export const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) + +Label.displayName = LabelRadix.displayName diff --git a/src/presentation/components/ui/dropdown/radioItem.tsx b/src/presentation/components/ui/dropdown/radioItem.tsx new file mode 100644 index 00000000..65845b01 --- /dev/null +++ b/src/presentation/components/ui/dropdown/radioItem.tsx @@ -0,0 +1,32 @@ +import React from 'react' + +import { + ItemIndicator, + RadioItem as RadioItemRadix +} from '@radix-ui/react-dropdown-menu' +import { Circle } from 'lucide-react' + +import { cn } from '@/main/utils' + +export const RadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) + +RadioItem.displayName = RadioItemRadix.displayName diff --git a/src/presentation/components/ui/dropdown/separator.tsx b/src/presentation/components/ui/dropdown/separator.tsx new file mode 100644 index 00000000..f7ac7347 --- /dev/null +++ b/src/presentation/components/ui/dropdown/separator.tsx @@ -0,0 +1,18 @@ +import React from 'react' + +import { Separator as SeparatorRadix } from '@radix-ui/react-dropdown-menu' + +import { cn } from '@/main/utils' + +export const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +Separator.displayName = SeparatorRadix.displayName diff --git a/src/presentation/components/ui/dropdown/shortcut.tsx b/src/presentation/components/ui/dropdown/shortcut.tsx new file mode 100644 index 00000000..7597a36e --- /dev/null +++ b/src/presentation/components/ui/dropdown/shortcut.tsx @@ -0,0 +1,13 @@ +import { cn } from '@/main/utils' + +export const Shortcut = ({ + className, + ...props +}: React.HTMLAttributes) => ( + +) + +Shortcut.displayName = 'DropdownMenuShortcut' diff --git a/src/presentation/components/ui/dropdown/subContent.tsx b/src/presentation/components/ui/dropdown/subContent.tsx new file mode 100644 index 00000000..1317e376 --- /dev/null +++ b/src/presentation/components/ui/dropdown/subContent.tsx @@ -0,0 +1,21 @@ +import React from 'react' + +import { SubContent as SubContentRadix } from '@radix-ui/react-dropdown-menu' + +import { cn } from '@/main/utils' + +export const SubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +SubContent.displayName = SubContentRadix.displayName diff --git a/src/presentation/components/ui/dropdown/subTrigger.tsx b/src/presentation/components/ui/dropdown/subTrigger.tsx new file mode 100644 index 00000000..c8904197 --- /dev/null +++ b/src/presentation/components/ui/dropdown/subTrigger.tsx @@ -0,0 +1,28 @@ +import React from 'react' + +import { SubTrigger as SubTriggerRadix } from '@radix-ui/react-dropdown-menu' +import { ChevronRight } from 'lucide-react' + +import { cn } from '@/main/utils' + +export const SubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) + +SubTrigger.displayName = SubTriggerRadix.displayName