diff --git a/.vscode/settings.json b/.vscode/settings.json index e78b37319b32b..93b329f8a21a5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -47,10 +47,11 @@ "playwright.reuseBrowser": true, "[javascript][javascriptreact][json][jsonc][typescript][typescriptreact]": { - "editor.defaultFormatter": "biomejs.biome" - // "editor.codeActionsOnSave": { - // "source.organizeImports.biome": "explicit" - // } + "editor.defaultFormatter": "biomejs.biome", + "editor.codeActionsOnSave": { + "quickfix.biome": "explicit" + // "source.organizeImports.biome": "explicit" + } }, "[css][html][markdown][yaml]": { diff --git a/site/components.json b/site/components.json new file mode 100644 index 0000000000000..8f7ae7d9d6da5 --- /dev/null +++ b/site/components.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "tailwind.config.js", + "css": "src/index.css", + "baseColor": "zinc", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "/components", + "utils": "/utils", + "ui": "/components/ui", + "lib": "/lib", + "hooks": "/hooks" + } +} diff --git a/site/package.json b/site/package.json index 710bd7e49787b..1e83bf30030cb 100644 --- a/site/package.json +++ b/site/package.json @@ -36,6 +36,7 @@ "@alwaysmeticulous/recorder-loader": "2.137.0", "@emoji-mart/data": "1.2.1", "@emoji-mart/react": "1.1.1", + "@emotion/cache": "11.13.1", "@emotion/css": "11.13.4", "@emotion/react": "11.13.3", "@emotion/styled": "11.13.0", @@ -49,6 +50,7 @@ "@mui/system": "5.16.7", "@mui/utils": "5.16.6", "@mui/x-tree-view": "7.18.0", + "@radix-ui/react-slot": "1.1.0", "@tanstack/react-query-devtools": "4.35.3", "@xterm/addon-canvas": "0.7.0", "@xterm/addon-fit": "0.10.0", @@ -63,6 +65,8 @@ "chartjs-adapter-date-fns": "3.0.0", "chartjs-plugin-annotation": "3.0.1", "chroma-js": "2.4.2", + "class-variance-authority": "0.7.0", + "clsx": "2.1.1", "color-convert": "2.0.1", "cron-parser": "4.9.0", "cronstrue": "2.50.0", @@ -74,6 +78,7 @@ "front-matter": "4.0.2", "jszip": "3.10.1", "lodash": "4.17.21", + "lucide-react": "0.454.0", "monaco-editor": "0.52.0", "pretty-bytes": "6.1.1", "react": "18.3.1", @@ -93,6 +98,8 @@ "resize-observer-polyfill": "1.5.1", "rollup-plugin-visualizer": "5.12.0", "semver": "7.6.2", + "tailwind-merge": "2.5.4", + "tailwindcss-animate": "1.0.7", "tzdata": "1.0.40", "ua-parser-js": "1.0.33", "ufuzzy": "npm:@leeoniya/ufuzzy@1.0.10", @@ -141,6 +148,7 @@ "@types/ua-parser-js": "0.7.36", "@types/uuid": "9.0.2", "@vitejs/plugin-react": "4.3.3", + "autoprefixer": "10.4.20", "chromatic": "11.16.3", "eventsourcemock": "2.0.0", "express": "4.21.0", @@ -151,6 +159,7 @@ "jest-websocket-mock": "2.5.0", "jest_workaround": "0.1.14", "msw": "2.3.5", + "postcss": "8.4.47", "prettier": "3.3.3", "protobufjs": "7.4.0", "rxjs": "7.8.1", @@ -158,6 +167,7 @@ "storybook": "8.3.5", "storybook-addon-remix-react-router": "3.0.1", "storybook-react-context": "0.6.0", + "tailwindcss": "3.4.13", "ts-node": "10.9.1", "ts-proto": "1.164.0", "ts-prune": "0.10.3", @@ -166,11 +176,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/pnpm-lock.yaml b/site/pnpm-lock.yaml index e7ddc66058018..aa7e4aa709c6d 100644 --- a/site/pnpm-lock.yaml +++ b/site/pnpm-lock.yaml @@ -21,6 +21,9 @@ importers: '@emoji-mart/react': specifier: 1.1.1 version: 1.1.1(emoji-mart@5.6.0)(react@18.3.1) + '@emotion/cache': + specifier: 11.13.1 + version: 11.13.1 '@emotion/css': specifier: 11.13.4 version: 11.13.4 @@ -60,6 +63,9 @@ importers: '@mui/x-tree-view': specifier: 7.18.0 version: 7.18.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@mui/material@5.16.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/system@5.16.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@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': + specifier: 1.1.0 + version: 1.1.0(@types/react@18.3.12)(react@18.3.1) '@tanstack/react-query-devtools': specifier: 4.35.3 version: 4.35.3(@tanstack/react-query@4.35.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -102,6 +108,12 @@ importers: chroma-js: specifier: 2.4.2 version: 2.4.2 + class-variance-authority: + specifier: 0.7.0 + version: 0.7.0 + clsx: + specifier: 2.1.1 + version: 2.1.1 color-convert: specifier: 2.0.1 version: 2.0.1 @@ -135,6 +147,9 @@ importers: lodash: specifier: 4.17.21 version: 4.17.21 + lucide-react: + specifier: 0.454.0 + version: 0.454.0(react@18.3.1) monaco-editor: specifier: 0.52.0 version: 0.52.0 @@ -192,6 +207,12 @@ importers: semver: specifier: 7.6.2 version: 7.6.2 + tailwind-merge: + specifier: 2.5.4 + version: 2.5.4 + tailwindcss-animate: + specifier: 1.0.7 + version: 1.0.7(tailwindcss@3.4.13(ts-node@10.9.1(@swc/core@1.3.38)(@types/node@20.17.6)(typescript@5.6.3))) tzdata: specifier: 1.0.40 version: 1.0.40 @@ -331,6 +352,9 @@ importers: '@vitejs/plugin-react': specifier: 4.3.3 version: 4.3.3(vite@5.4.10(@types/node@20.17.6)) + autoprefixer: + specifier: 10.4.20 + version: 10.4.20(postcss@8.4.47) chromatic: specifier: 11.16.3 version: 11.16.3 @@ -361,6 +385,9 @@ importers: msw: specifier: 2.3.5 version: 2.3.5(typescript@5.6.3) + postcss: + specifier: 8.4.47 + version: 8.4.47 prettier: specifier: 3.3.3 version: 3.3.3 @@ -382,6 +409,9 @@ importers: storybook-react-context: specifier: 0.6.0 version: 0.6.0(react-dom@18.3.1(react@18.3.1)) + tailwindcss: + specifier: 3.4.13 + version: 3.4.13(ts-node@10.9.1(@swc/core@1.3.38)(@types/node@20.17.6)(typescript@5.6.3)) ts-node: specifier: 10.9.1 version: 10.9.1(@swc/core@1.3.38)(@types/node@20.17.6)(typescript@5.6.3) @@ -416,6 +446,10 @@ packages: '@adobe/css-tools@4.4.0': resolution: {integrity: sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==} + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + '@alwaysmeticulous/recorder-loader@2.137.0': resolution: {integrity: sha512-ux/xGYCNsOe8BzquEg7k7YSNJiw/0Sg2Pd/7fppYiVr5xEefpPeIhh3qwuupZgx6sB2t5KpKQdodNWVmGeyh/w==} @@ -1666,15 +1700,6 @@ packages: '@radix-ui/primitive@1.1.0': resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==} - '@radix-ui/react-compose-refs@1.0.1': - resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@radix-ui/react-compose-refs@1.1.0': resolution: {integrity: sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==} peerDependencies: @@ -1789,15 +1814,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-slot@1.0.2': - resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@radix-ui/react-slot@1.1.0': resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==} peerDependencies: @@ -2788,6 +2804,9 @@ packages: engines: {node: '>=8.0.0'} hasBin: true + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} @@ -2798,6 +2817,9 @@ packages: arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -2836,6 +2858,13 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + autoprefixer@10.4.20: + resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + available-typed-arrays@1.0.5: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} @@ -2945,6 +2974,10 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + camelcase@5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} @@ -3046,6 +3079,9 @@ packages: cjs-module-lexer@1.3.1: resolution: {integrity: sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==} + class-variance-authority@0.7.0: + resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==} + classnames@2.3.2: resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==} @@ -3061,6 +3097,10 @@ packages: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} + clsx@2.0.0: + resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} + engines: {node: '>=6'} + clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -3098,6 +3138,10 @@ packages: comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + commander@6.2.1: resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} engines: {node: '>= 6'} @@ -3185,6 +3229,11 @@ packages: css.escape@1.5.1: resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + cssfontparser@1.2.1: resolution: {integrity: sha512-6tun4LoZnj7VN6YeegOVb67KBX/7JJsqvj+pv3ZA7F878/eN33AbGa5b/S/wXxS/tcp8nc40xRUrsPlxIyNUPg==} @@ -3324,6 +3373,9 @@ packages: devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -3332,6 +3384,9 @@ packages: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + doctrine@3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} @@ -3484,7 +3539,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: @@ -3651,6 +3705,9 @@ packages: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} @@ -4296,6 +4353,10 @@ packages: '@swc/core': ^1.3.3 '@swc/jest': ^0.2.22 + jiti@1.21.6: + resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + hasBin: true + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -4373,6 +4434,14 @@ packages: lie@3.3.0: resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -4415,6 +4484,11 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lucide-react@0.454.0: + resolution: {integrity: sha512-hw7zMDwykCLnEzgncEEjHeA6+45aeEzRYuKHuyRSOPkhko+J3ySGjGIzu+mmMfDFG1vazHepMaYFYHbTFAZAAQ==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc + luxon@3.3.0: resolution: {integrity: sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==} engines: {node: '>=12'} @@ -4692,6 +4766,9 @@ packages: resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + nan@2.20.0: resolution: {integrity: sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==} @@ -4739,6 +4816,10 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} @@ -4750,6 +4831,10 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + object-inspect@1.13.1: resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} @@ -4873,6 +4958,10 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} @@ -4899,6 +4988,43 @@ packages: resolution: {integrity: sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==} engines: {node: '>=10'} + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + postcss@8.4.47: resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} engines: {node: ^10 || ^12 || >=14} @@ -5195,6 +5321,9 @@ packages: peerDependencies: react: '*' + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} @@ -5542,6 +5671,11 @@ packages: stylis@4.2.0: resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + superjson@1.13.3: resolution: {integrity: sha512-mJiVjfd2vokfDxsQPOwJ/PtanO87LhpYY88ubI5dUB1Ab58Txbyje3+jpm+/83R/fevaq/107NNhtYBLuoTrFg==} engines: {node: '>=10'} @@ -5565,6 +5699,19 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + tailwind-merge@2.5.4: + resolution: {integrity: sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q==} + + tailwindcss-animate@1.0.7: + resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders' + + tailwindcss@3.4.13: + resolution: {integrity: sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==} + engines: {node: '>=14.0.0'} + hasBin: true + tar-fs@2.1.1: resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} @@ -5593,6 +5740,13 @@ packages: text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + tiny-case@1.0.3: resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==} @@ -5659,6 +5813,9 @@ packages: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + ts-morph@13.0.3: resolution: {integrity: sha512-pSOfUMx8Ld/WUreoSzvMFQG5i9uEiWIsBYjpU9+TTASOeUa89j5HykomeqVULm1oqWtBdleI3KEFRLrlA3zGIw==} @@ -6078,6 +6235,11 @@ packages: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} + yaml@2.6.0: + resolution: {integrity: sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==} + engines: {node: '>= 14'} + hasBin: true + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} @@ -6109,6 +6271,8 @@ snapshots: '@adobe/css-tools@4.4.0': {} + '@alloc/quick-lru@5.2.0': {} + '@alwaysmeticulous/recorder-loader@2.137.0': {} '@ampproject/remapping@2.3.0': @@ -6528,7 +6692,7 @@ snapshots: '@emotion/hash': 0.9.2 '@emotion/memoize': 0.9.0 '@emotion/unitless': 0.10.0 - '@emotion/utils': 1.4.0 + '@emotion/utils': 1.4.1 csstype: 3.1.3 '@emotion/serialize@1.3.2': @@ -7352,13 +7516,6 @@ snapshots: '@radix-ui/primitive@1.1.0': {} - '@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.12)(react@18.3.1)': - dependencies: - '@babel/runtime': 7.25.6 - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.12 - '@radix-ui/react-compose-refs@1.1.0(@types/react@18.3.12)(react@18.3.1)': dependencies: react: 18.3.1 @@ -7459,14 +7616,6 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 - '@radix-ui/react-slot@1.0.2(@types/react@18.3.12)(react@18.3.1)': - dependencies: - '@babel/runtime': 7.25.6 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.12)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.12 - '@radix-ui/react-slot@1.1.0(@types/react@18.3.12)(react@18.3.1)': dependencies: '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1) @@ -7848,7 +7997,7 @@ snapshots: '@storybook/components@8.1.11(@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-dialog': 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.0.2(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(@types/react@18.3.12)(react@18.3.1) '@storybook/client-logger': 8.1.11 '@storybook/csf': 0.1.9 '@storybook/global': 5.0.0 @@ -8753,6 +8902,8 @@ snapshots: dependencies: entities: 2.2.0 + any-promise@1.3.0: {} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 @@ -8762,6 +8913,8 @@ snapshots: arg@4.1.3: {} + arg@5.0.2: {} + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -8808,6 +8961,16 @@ snapshots: asynckit@0.4.0: {} + autoprefixer@10.4.20(postcss@8.4.47): + dependencies: + browserslist: 4.24.2 + caniuse-lite: 1.0.30001677 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.4.47 + postcss-value-parser: 4.2.0 + available-typed-arrays@1.0.5: {} axios@1.7.4: @@ -8972,6 +9135,8 @@ snapshots: callsites@3.1.0: {} + camelcase-css@2.0.1: {} + camelcase@5.3.1: {} camelcase@6.3.0: {} @@ -9063,6 +9228,10 @@ snapshots: cjs-module-lexer@1.3.1: {} + class-variance-authority@0.7.0: + dependencies: + clsx: 2.0.0 + classnames@2.3.2: {} cli-spinners@2.9.2: {} @@ -9075,6 +9244,8 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + clsx@2.0.0: {} + clsx@2.1.1: {} co@4.6.0: {} @@ -9103,6 +9274,8 @@ snapshots: comma-separated-tokens@2.0.3: {} + commander@4.1.1: {} + commander@6.2.1: {} commander@8.3.0: {} @@ -9186,6 +9359,8 @@ snapshots: css.escape@1.5.1: {} + cssesc@3.0.0: {} + cssfontparser@1.2.1: {} cssom@0.3.8: {} @@ -9310,10 +9485,14 @@ snapshots: dependencies: dequal: 2.0.3 + didyoumean@1.2.2: {} + diff-sequences@29.6.3: {} diff@4.0.2: {} + dlv@1.1.3: {} + doctrine@3.0.0: dependencies: esutils: 2.0.3 @@ -9776,6 +9955,8 @@ snapshots: forwarded@0.2.0: {} + fraction.js@4.3.7: {} + fresh@0.5.2: {} front-matter@4.0.2: @@ -9846,7 +10027,6 @@ snapshots: glob-parent@6.0.2: dependencies: is-glob: 4.0.3 - optional: true glob-promise@4.2.2(glob@7.2.3): dependencies: @@ -10629,6 +10809,8 @@ snapshots: '@swc/core': 1.3.38 '@swc/jest': 0.2.37(@swc/core@1.3.38) + jiti@1.21.6: {} + js-tokens@4.0.0: {} js-yaml@3.14.1: @@ -10733,6 +10915,10 @@ snapshots: dependencies: immediate: 3.0.6 + lilconfig@2.1.0: {} + + lilconfig@3.1.2: {} + lines-and-columns@1.2.4: {} locate-path@5.0.0: @@ -10773,6 +10959,10 @@ snapshots: dependencies: yallist: 3.1.1 + lucide-react@0.454.0(react@18.3.1): + dependencies: + react: 18.3.1 + luxon@3.3.0: {} lz-string@1.5.0: {} @@ -11205,6 +11395,12 @@ snapshots: mute-stream@1.0.0: {} + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + nan@2.20.0: optional: true @@ -11234,6 +11430,8 @@ snapshots: normalize-path@3.0.0: {} + normalize-range@0.1.2: {} + npm-run-path@4.0.1: dependencies: path-key: 3.1.1 @@ -11242,6 +11440,8 @@ snapshots: object-assign@4.1.1: {} + object-hash@3.0.0: {} + object-inspect@1.13.1: {} object-is@1.1.5: @@ -11363,6 +11563,8 @@ snapshots: picomatch@2.3.1: {} + pify@2.3.0: {} + pirates@4.0.6: {} pkg-dir@4.2.0: @@ -11385,6 +11587,38 @@ snapshots: dependencies: '@babel/runtime': 7.25.6 + postcss-import@15.1.0(postcss@8.4.47): + dependencies: + postcss: 8.4.47 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + + postcss-js@4.0.1(postcss@8.4.47): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.47 + + postcss-load-config@4.0.2(postcss@8.4.47)(ts-node@10.9.1(@swc/core@1.3.38)(@types/node@20.17.6)(typescript@5.6.3)): + dependencies: + lilconfig: 3.1.2 + yaml: 2.6.0 + optionalDependencies: + postcss: 8.4.47 + ts-node: 10.9.1(@swc/core@1.3.38)(@types/node@20.17.6)(typescript@5.6.3) + + postcss-nested@6.2.0(postcss@8.4.47): + dependencies: + postcss: 8.4.47 + postcss-selector-parser: 6.1.2 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + postcss@8.4.47: dependencies: nanoid: 3.3.7 @@ -11721,6 +11955,10 @@ snapshots: lodash: 4.17.21 react: 18.3.1 + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + readable-stream@2.3.8: dependencies: core-util-is: 1.0.3 @@ -12141,6 +12379,16 @@ snapshots: stylis@4.2.0: {} + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + commander: 4.1.1 + glob: 10.3.10 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + superjson@1.13.3: dependencies: copy-anything: 3.0.5 @@ -12161,6 +12409,39 @@ snapshots: symbol-tree@3.2.4: {} + tailwind-merge@2.5.4: {} + + tailwindcss-animate@1.0.7(tailwindcss@3.4.13(ts-node@10.9.1(@swc/core@1.3.38)(@types/node@20.17.6)(typescript@5.6.3))): + dependencies: + tailwindcss: 3.4.13(ts-node@10.9.1(@swc/core@1.3.38)(@types/node@20.17.6)(typescript@5.6.3)) + + tailwindcss@3.4.13(ts-node@10.9.1(@swc/core@1.3.38)(@types/node@20.17.6)(typescript@5.6.3)): + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.6 + lilconfig: 2.1.0 + micromatch: 4.0.8 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.1 + postcss: 8.4.47 + postcss-import: 15.1.0(postcss@8.4.47) + postcss-js: 4.0.1(postcss@8.4.47) + postcss-load-config: 4.0.2(postcss@8.4.47)(ts-node@10.9.1(@swc/core@1.3.38)(@types/node@20.17.6)(typescript@5.6.3)) + postcss-nested: 6.2.0(postcss@8.4.47) + postcss-selector-parser: 6.1.2 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + tar-fs@2.1.1: dependencies: chownr: 1.1.4 @@ -12209,6 +12490,14 @@ snapshots: text-table@0.2.0: optional: true + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + tiny-case@1.0.3: {} tiny-invariant@1.3.3: {} @@ -12261,6 +12550,8 @@ snapshots: ts-dedent@2.2.0: {} + ts-interface-checker@0.1.13: {} + ts-morph@13.0.3: dependencies: '@ts-morph/common': 0.12.3 @@ -12648,6 +12939,8 @@ snapshots: yaml@1.10.2: {} + yaml@2.6.0: {} + yargs-parser@21.1.1: {} yargs@17.7.2: diff --git a/site/postcss.config.js b/site/postcss.config.js new file mode 100644 index 0000000000000..33ad091d26d8a --- /dev/null +++ b/site/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/site/src/components/ui/button.tsx b/site/src/components/ui/button.tsx new file mode 100644 index 0000000000000..d3a708d48a82a --- /dev/null +++ b/site/src/components/ui/button.tsx @@ -0,0 +1,53 @@ +import { Slot } from "@radix-ui/react-slot"; +import { type VariantProps, cva } from "class-variance-authority"; +import * as React from "react"; + +import { cn } from "utils/cn"; + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 font-semibold border-solid", + { + variants: { + variant: { + default: + "bg-surface-invert-primary text-content-invert hover:bg-surface-invert-secondary", + outline: + "border border-border-default text-content-primary bg-transparent hover:bg-surface-secondary", + subtle: + "border-none bg-transparent text-content-secondary hover:text-content-primary", + warning: + "border border-border-error text-content-primary bg-surface-error hover:bg-transparent", + }, + size: { + default: "h-10 px-3 py-2", + sm: "h-8 px-2 text-xs", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +); + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button"; + return ( + + ); + }, +); +Button.displayName = "Button"; + +export { Button, buttonVariants }; diff --git a/site/src/contexts/ThemeProvider.tsx b/site/src/contexts/ThemeProvider.tsx index fc0d3d7ac4918..fd953d17e23f0 100644 --- a/site/src/contexts/ThemeProvider.tsx +++ b/site/src/contexts/ThemeProvider.tsx @@ -1,4 +1,6 @@ +import createCache from "@emotion/cache"; import { ThemeProvider as EmotionThemeProvider } from "@emotion/react"; +import { CacheProvider } from "@emotion/react"; import CssBaseline from "@mui/material/CssBaseline"; import { ThemeProvider as MuiThemeProvider, @@ -55,6 +57,21 @@ export const ThemeProvider: FC = ({ children }) => { // The janky casting here is find because of the much more type safe fallback // We need to support `themePreference` being wrong anyway because the database // value could be anything, like an empty string. + + useEffect(() => { + const root = document.documentElement; + + if (themePreference === "auto") { + root.classList.add(preferredColorScheme); + } else { + root.classList.add(themePreference); + } + + return () => { + root.classList.remove("light", "dark"); + }; + }, [themePreference, preferredColorScheme]); + const theme = themes[themePreference as keyof typeof themes] ?? themes[preferredColorScheme]; @@ -66,6 +83,12 @@ export const ThemeProvider: FC = ({ children }) => { ); }; +// This is being added to allow Tailwind classes to be used with MUI components. https://mui.com/material-ui/integrations/interoperability/#tailwind-css +const cache = createCache({ + key: "css", + prepend: true, +}); + interface ThemeOverrideProps { theme: Theme; children?: ReactNode; @@ -73,11 +96,13 @@ interface ThemeOverrideProps { export const ThemeOverride: FC = ({ theme, children }) => { return ( - - - - {children} - - + + + + + {children} + + + ); }; diff --git a/site/src/index.css b/site/src/index.css new file mode 100644 index 0000000000000..07b0819fe4a3d --- /dev/null +++ b/site/src/index.css @@ -0,0 +1,41 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --content-primary: #27272a; + --content-secondary: #52525b; + --content-link: #2563eb; + --content-invert: #fafafa; + --content-disabled: #a1a1aa; + --content-success: #15803d; + --content-danger: #ef4444; + --surface-primary: #fafafa; + --surface-secondary: #f4f4f5; + --surface-tertiary: #e4e4e7; + --surface-invert-primary: #27272a; + --surface-invert-secondary: #3f3f46; + --surface-error: #450a0a; + --border-default: #e4e4e7; + --border-error: #ef4444; + --radius: 0.5rem; + } + .dark { + --content-primary: #fafafa; + --content-secondary: #a1a1aa; + --content-link: #60a5fa; + --content-invert: #09090b; + --content-disabled: #3f3f46; + --content-success: #16a34a; + --content-danger: #f87171; + --surface-primary: #09090b; + --surface-secondary: #18181b; + --surface-tertiary: #27272a; + --surface-invert-primary: #e4e4e7; + --surface-invert-secondary: #a1a1aa; + --surface-error: #450a0a; + --border-default: #27272a; + --border-error: #f87171; + } +} diff --git a/site/src/index.tsx b/site/src/index.tsx index e721fbb2293b7..aef10d6c64f4d 100644 --- a/site/src/index.tsx +++ b/site/src/index.tsx @@ -1,4 +1,5 @@ import { createRoot } from "react-dom/client"; +import "./index.css"; import { App } from "./App"; console.info(` ▄█▀ ▀█▄ diff --git a/site/src/modules/management/SidebarView.tsx b/site/src/modules/management/SidebarView.tsx index e6c99769e529f..eabcac8f30ccc 100644 --- a/site/src/modules/management/SidebarView.tsx +++ b/site/src/modules/management/SidebarView.tsx @@ -11,6 +11,7 @@ import { UserAvatar } from "components/UserAvatar/UserAvatar"; import type { Permissions } from "contexts/auth/permissions"; import { type ClassName, useClassName } from "hooks/useClassName"; import { useDashboard } from "modules/dashboard/useDashboard"; +import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; import type { FC, ReactNode } from "react"; import { Link, NavLink } from "react-router-dom"; @@ -39,6 +40,7 @@ export const SidebarView: FC = ({ permissions, }) => { const { showOrganizations } = useDashboard(); + const { multiple_organizations: hasPremiumLicense } = useFeatureVisibility(); // TODO: Do something nice to scroll to the active org. return ( @@ -52,6 +54,7 @@ export const SidebarView: FC = ({ {showOrganizations && ( = ({ active, permissions, + isPremium, }) => { return (
@@ -150,6 +155,9 @@ const DeploymentSettingsNavigation: FC = ({ )} + {!isPremium && ( + Premium + )} )}
diff --git a/site/src/pages/DeploymentSettingsPage/PremiumPage/PremiumPage.tsx b/site/src/pages/DeploymentSettingsPage/PremiumPage/PremiumPage.tsx new file mode 100644 index 0000000000000..9ba30d464befc --- /dev/null +++ b/site/src/pages/DeploymentSettingsPage/PremiumPage/PremiumPage.tsx @@ -0,0 +1,20 @@ +import { useDashboard } from "modules/dashboard/useDashboard"; +import type { FC } from "react"; +import { Helmet } from "react-helmet-async"; +import { pageTitle } from "utils/page"; +import { PremiumPageView } from "./PremiumPageView"; + +const PremiumPage: FC = () => { + const { entitlements } = useDashboard(); + + return ( + <> + + Codestin Search App + + + + ); +}; + +export default PremiumPage; diff --git a/site/src/pages/DeploymentSettingsPage/PremiumPage/PremiumPageView.tsx b/site/src/pages/DeploymentSettingsPage/PremiumPage/PremiumPageView.tsx new file mode 100644 index 0000000000000..b0da13a0839f8 --- /dev/null +++ b/site/src/pages/DeploymentSettingsPage/PremiumPage/PremiumPageView.tsx @@ -0,0 +1,253 @@ +import { Button } from "components/ui/button"; +import { Activity, Coins, Expand, SquareArrowOutUpRight } from "lucide-react"; +import type { FC } from "react"; +import { docs } from "utils/docs"; + +export type PremiumPageViewProps = { isEnterprise: boolean }; + +export const PremiumPageView: FC = ({ isEnterprise }) => { + return isEnterprise ? : ; +}; + +const EnterpriseVersion: FC = () => { + return ( +
+
+
+

Premium

+

+ As an Enterprise license holder, you already benefit from Coder’s + features for secure, large-scale deployments. Upgrade to Coder + Premium for enhanced multi-tenant control and flexibility. +

+
+ +
+ +
+ + +

+ Multi-Organization access controls  +

+ +
+
+

+ Manage multiple teams and projects within a single deployment, each + with isolated access. +

+
+ +
+ + +

Custom role 

+ +
+
+

+ Configure specific permissions for teams or contractors with tailored + roles. +

+
+ +
+ + +

+ Org-Level quotas for chargeback  +

+ +
+
+

+ Set and monitor resource quotas at the organization level to support + internal cost tracking. +

+
+ +
+

+ These Premium features enable you to manage team structure and budget + allocation across multiple platform teams. +

+
+
+ ); +}; + +const OSSVersion: FC = () => { + return ( +
+
+
+

+ Premium +

+

+ Coder Premium is designed for enterprises that need to scale their + Coder deployment efficiently, securely, and with full control. By + upgrading, your team gains access to advanced features enabling + governance across all environments. +

+
+ +
+ +
+

+ + +   Deploy coder at scale + +

+

+ Equip your enterprise to deploy and manage thousands of workspaces + with performance and reliability. +

+
    +
  • + + High availability + +
    + + Scale with automatic failover and load balancing across multiple + Coder instances. + +
  • +
  • + + Multi-Organization access control + +
    + + Isolate teams, projects, and environments within a single Coder + deployment. + +
  • +
  • + + Unlimited external authentication integrations + +
    + + Integrate with external service providers like GitHub, JFrog, and + Vault. + +
  • +
+
+ +
+

+ + +   Control infrastructure costs + +

+

+ Optimize cloud usage and maintain cost-effective resource management + for your teams. +

+
    +
  • + + Auto-Stop idle workspaces + +
    + + Automatically shut down inactive workspaces to prevent unnecessary + costs. + +
  • +
  • + + Resource quotas + +
    + + Set user and team-specific limits to control spending and resource + allocation. + +
  • +
  • + + Usage insights + +
    + + Track workspace usage patterns to make data-driven decisions about + infrastructure needs. + +
  • +
+
+ +
+

+ + +   Govern workspace activity + +

+

+ Maintain security and compliance across your organization with robust + governance features. +

+
    +
  • + + Audit logging + +
    + + Capture detailed records of user actions and workspace activity + for compliance and security. + +
  • +
  • + + Template permissions + +
    + + Control who can create, modify, and access workspace templates + across teams. + +
  • +
  • + + Workspace command logging + +
    + + Monitor and log critical commands to ensure security and + compliance standards are met. + +
  • +
+
+
+ ); +}; diff --git a/site/src/router.tsx b/site/src/router.tsx index c9d8736979c34..1b23b55245e8f 100644 --- a/site/src/router.tsx +++ b/site/src/router.tsx @@ -270,6 +270,9 @@ const TemplateInsightsPage = lazy( () => import("./pages/TemplatePage/TemplateInsightsPage/TemplateInsightsPage"), ); +const PremiumPage = lazy( + () => import("./pages/DeploymentSettingsPage/PremiumPage/PremiumPage"), +); const GroupsPage = lazy(() => import("./pages/GroupsPage/GroupsPage")); const IconsPage = lazy(() => import("./pages/IconsPage/IconsPage")); const AccessURLPage = lazy(() => import("./pages/HealthPage/AccessURLPage")); @@ -450,6 +453,7 @@ export const router = createBrowserRouter( path="notifications" element={} /> + } /> diff --git a/site/src/utils/cn.ts b/site/src/utils/cn.ts new file mode 100644 index 0000000000000..ac680b303c9f4 --- /dev/null +++ b/site/src/utils/cn.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/site/tailwind.config.js b/site/tailwind.config.js new file mode 100644 index 0000000000000..b9343b7add92c --- /dev/null +++ b/site/tailwind.config.js @@ -0,0 +1,49 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + corePlugins: { + preflight: false, + }, + darkMode: ["selector"], + content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], + important: "#root", + theme: { + fontSize: { + "2xs": ["0.626rem","0.875rem"], + sm: ["0.875rem", "1.5rem"], + "3xl": ["2rem", "2.5rem"], + }, + extend: { + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + colors: { + content: { + primary: "var(--content-primary)", + secondary: "var(--content-secondary)", + disabled: "var(--content-disabled)", + invert: "var(--content-invert)", + success: "var(--content-success)", + danger: "var(--content-danger)", + link: "var(--content-link)", + }, + surface: { + primary: "var(--surface-primary)", + secondary: "var(--surface-secondary)", + tertiary: "var(--surface-tertiary)", + invert: { + primary: "var(--surface-invert-primary)", + secondary: "var(--surface-invert-secondary)", + }, + error: "var(--surface-error)", + }, + border: { + default: "var(--border-default)", + error: "var(--border-error)", + }, + }, + }, + }, + plugins: [require("tailwindcss-animate")], +}; diff --git a/site/tsconfig.json b/site/tsconfig.json index 0ff5945f6d47a..7e969d18c42dd 100644 --- a/site/tsconfig.json +++ b/site/tsconfig.json @@ -1,24 +1,24 @@ { - "compilerOptions": { - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "incremental": true, - "isolatedModules": true, - "jsx": "react-jsx", - "jsxImportSource": "@emotion/react", - "lib": ["dom", "dom.iterable", "esnext"], - "module": "esnext", - "moduleResolution": "node", - "noEmit": true, - "outDir": "build/", - "preserveWatchOutput": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "es2020", - "baseUrl": "src/" - }, - "include": ["**/*.ts", "**/*.tsx"], - "exclude": ["node_modules/", "_jest"], - "types": ["@emotion/react", "@testing-library/jest-dom", "jest", "node"] + "compilerOptions": { + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "incremental": true, + "isolatedModules": true, + "jsx": "react-jsx", + "jsxImportSource": "@emotion/react", + "lib": ["dom", "dom.iterable", "esnext"], + "module": "esnext", + "moduleResolution": "node", + "noEmit": true, + "outDir": "build/", + "preserveWatchOutput": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "target": "es2020", + "baseUrl": "src/" + }, + "include": ["**/*.ts", "**/*.tsx"], + "exclude": ["node_modules/", "_jest"], + "types": ["@emotion/react", "@testing-library/jest-dom", "jest", "node"] }