diff --git a/package-lock.json b/package-lock.json index 303914840..e35373fa6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,16 +8,20 @@ "name": "code-sandbox", "version": "0.0.0", "dependencies": { - "@abgov/react-components": "5.4.0", - "@abgov/web-components": "1.29.0", + "@abgov/react-components": "6.2.1", + "@abgov/ui-components-common": "1.2.1", + "@abgov/web-components": "1.32.1", "@faker-js/faker": "^8.3.1", "highlight.js": "^11.8.0", + "js-cookie": "^3.0.5", "octokit": "^4.0.2", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.13.0" }, "devDependencies": { + "@types/js-cookie": "^3.0.6", + "@types/lodash": "^4.17.16", "@types/react": "^18.2.13", "@types/react-dom": "^18.2.6", "@types/react-router-dom": "^5.3.3", @@ -27,11 +31,32 @@ "eslint": "^8.43.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.3.5", + "lodash": "^4.17.21", "prettier": "2.4.1", "typescript": "^5.4.2", "vite": "^5.4.6" } }, + "../ui-components/dist/libs/angular-components": { + "name": "@abgov/angular-components", + "version": "0.0.1", + "extraneous": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "@angular/core": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "@angular/forms": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "../ui-components/dist/libs/ui-commons": { + "extraneous": true + }, + "../ui-components/dist/libs/ui-components-common": { + "extraneous": true + }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", @@ -42,19 +67,24 @@ } }, "node_modules/@abgov/react-components": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@abgov/react-components/-/react-components-5.4.0.tgz", - "integrity": "sha512-vN1Ktjkw5IWaeJYmf9i8gKJpjn6px7D9lEt6USg1qjQzf5IKxR28aIuowBS7M2kmJ4Vk7AP+Z1yjB2g5Pw4J3w==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@abgov/react-components/-/react-components-6.2.1.tgz", + "integrity": "sha512-CQ2Grpv5R/QR2UifwGP9VvAGDFxCwCpUlfSkcOKMXFUvwT+IQ6FbHPjgKkGViF2Td813/m7Qz7woo8DvoIIQfQ==", "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0", "react": "^17.0.0 || ^18.0.0", "react-dom": "^17.0.0 || ^18.0.0" } }, + "node_modules/@abgov/ui-components-common": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@abgov/ui-components-common/-/ui-components-common-1.2.1.tgz", + "integrity": "sha512-RIvetCp7das7VmxiOqudQ2CGFIsWlt9poL65R03SOhpgHPco5PqDNYLF+QiFlHu1Aeq9YMhIk5miHjpNBUWLSQ==" + }, "node_modules/@abgov/web-components": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@abgov/web-components/-/web-components-1.29.0.tgz", - "integrity": "sha512-4Y5mzHaNjq/unrs81EP7/mjiauj9mtowNillvPIpFFTUo+9DN2XL1TKPliG0B3Z8WRSS9ayrt3KXzV1WRQh2oQ==", + "version": "1.32.1", + "resolved": "https://registry.npmjs.org/@abgov/web-components/-/web-components-1.32.1.tgz", + "integrity": "sha512-Ezj17LYk5RgnNN3TVazuvlPjyOSfo4ArtpOE2VrnC0XJ0wIBKfmtcXwhdFATtLCtR/ILix829QUU0kxXzkRcSA==", "peerDependencies": { "@sveltejs/vite-plugin-svelte": "3.x", "glob": "10.x", @@ -568,9 +598,9 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "peer": true, "dependencies": { "@jridgewell/set-array": "^1.2.1", @@ -984,9 +1014,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.4.tgz", + "integrity": "sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw==", "cpu": [ "arm" ], @@ -996,9 +1026,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.4.tgz", + "integrity": "sha512-j4nrEO6nHU1nZUuCfRKoCcvh7PIywQPUCBa2UsootTHvTHIoIu2BzueInGJhhvQO/2FTRdNYpf63xsgEqH9IhA==", "cpu": [ "arm64" ], @@ -1008,9 +1038,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.4.tgz", + "integrity": "sha512-GmU/QgGtBTeraKyldC7cDVVvAJEOr3dFLKneez/n7BvX57UdhOqDsVwzU7UOnYA7AAOt+Xb26lk79PldDHgMIQ==", "cpu": [ "arm64" ], @@ -1020,9 +1050,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.4.tgz", + "integrity": "sha512-N6oDBiZCBKlwYcsEPXGDE4g9RoxZLK6vT98M8111cW7VsVJFpNEqvJeIPfsCzbf0XEakPslh72X0gnlMi4Ddgg==", "cpu": [ "x64" ], @@ -1031,10 +1061,34 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.4.tgz", + "integrity": "sha512-py5oNShCCjCyjWXCZNrRGRpjWsF0ic8f4ieBNra5buQz0O/U6mMXCpC1LvrHuhJsNPgRt36tSYMidGzZiJF6mw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.4.tgz", + "integrity": "sha512-L7VVVW9FCnTTp4i7KrmHeDsDvjB4++KOBENYtNYAiYl96jeBThFfhP6HVxL74v4SiZEVDH/1ILscR5U9S4ms4g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.4.tgz", + "integrity": "sha512-10ICosOwYChROdQoQo589N5idQIisxjaFE/PAnX2i0Zr84mY0k9zul1ArH0rnJ/fpgiqfu13TFZR5A5YJLOYZA==", "cpu": [ "arm" ], @@ -1044,9 +1098,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.4.tgz", + "integrity": "sha512-ySAfWs69LYC7QhRDZNKqNhz2UKN8LDfbKSMAEtoEI0jitwfAG2iZwVqGACJT+kfYvvz3/JgsLlcBP+WWoKCLcw==", "cpu": [ "arm" ], @@ -1056,9 +1110,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.4.tgz", + "integrity": "sha512-uHYJ0HNOI6pGEeZ/5mgm5arNVTI0nLlmrbdph+pGXpC9tFHFDQmDMOEqkmUObRfosJqpU8RliYoGz06qSdtcjg==", "cpu": [ "arm64" ], @@ -1068,9 +1122,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.4.tgz", + "integrity": "sha512-38yiWLemQf7aLHDgTg85fh3hW9stJ0Muk7+s6tIkSUOMmi4Xbv5pH/5Bofnsb6spIwD5FJiR+jg71f0CH5OzoA==", "cpu": [ "arm64" ], @@ -1080,9 +1134,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.4.tgz", + "integrity": "sha512-q73XUPnkwt9ZNF2xRS4fvneSuaHw2BXuV5rI4cw0fWYVIWIBeDZX7c7FWhFQPNTnE24172K30I+dViWRVD9TwA==", "cpu": [ "ppc64" ], @@ -1092,9 +1146,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.4.tgz", + "integrity": "sha512-Aie/TbmQi6UXokJqDZdmTJuZBCU3QBDA8oTKRGtd4ABi/nHgXICulfg1KI6n9/koDsiDbvHAiQO3YAUNa/7BCw==", "cpu": [ "riscv64" ], @@ -1104,9 +1158,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.4.tgz", + "integrity": "sha512-P8MPErVO/y8ohWSP9JY7lLQ8+YMHfTI4bAdtCi3pC2hTeqFJco2jYspzOzTUB8hwUWIIu1xwOrJE11nP+0JFAQ==", "cpu": [ "s390x" ], @@ -1116,9 +1170,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.4.tgz", + "integrity": "sha512-K03TljaaoPK5FOyNMZAAEmhlyO49LaE4qCsr0lYHUKyb6QacTNF9pnfPpXnFlFD3TXuFbFbz7tJ51FujUXkXYA==", "cpu": [ "x64" ], @@ -1128,9 +1182,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.4.tgz", + "integrity": "sha512-VJYl4xSl/wqG2D5xTYncVWW+26ICV4wubwN9Gs5NrqhJtayikwCXzPL8GDsLnaLU3WwhQ8W02IinYSFJfyo34Q==", "cpu": [ "x64" ], @@ -1140,9 +1194,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.4.tgz", + "integrity": "sha512-ku2GvtPwQfCqoPFIJCqZ8o7bJcj+Y54cZSr43hHca6jLwAiCbZdBUOrqE6y29QFajNAzzpIOwsckaTFmN6/8TA==", "cpu": [ "arm64" ], @@ -1152,9 +1206,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.4.tgz", + "integrity": "sha512-V3nCe+eTt/W6UYNr/wGvO1fLpHUrnlirlypZfKCT1fG6hWfqhPgQV/K/mRBXBpxc0eKLIF18pIOFVPh0mqHjlg==", "cpu": [ "ia32" ], @@ -1164,9 +1218,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.4.tgz", + "integrity": "sha512-LTw1Dfd0mBIEqUVCxbvTE/LLo+9ZxVC9k99v1v4ahg9Aak6FpqOfNu5kRkeTAn0wphoC4JU7No1/rL+bBCEwhg==", "cpu": [ "x64" ], @@ -1433,9 +1487,9 @@ "integrity": "sha512-dtByW6WiFk5W5Jfgz1VM+YPA21xMXTuSFoLYIDY0L44jDLLflVPtZkYuu3/YxpGcvjzKFBZLU+GyKjR0HOYtyw==" }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" }, "node_modules/@types/history": { "version": "4.7.11", @@ -1443,12 +1497,24 @@ "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", "dev": true }, + "node_modules/@types/js-cookie": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", + "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.17.16", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz", + "integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==", + "dev": true + }, "node_modules/@types/prop-types": { "version": "15.7.11", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", @@ -2374,12 +2440,12 @@ "dev": true }, "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "peer": true, "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -2621,12 +2687,12 @@ } }, "node_modules/is-reference": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", - "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", + "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", "peer": true, "dependencies": { - "@types/estree": "*" + "@types/estree": "^1.0.6" } }, "node_modules/isexe": { @@ -2649,6 +2715,15 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2736,6 +2811,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -2755,16 +2836,13 @@ }, "node_modules/lru-cache": { "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", - "engines": { - "node": "14 || >=16.14" - } + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, "node_modules/magic-string": { - "version": "0.30.12", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", - "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "peer": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" @@ -2825,9 +2903,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -3010,9 +3088,9 @@ } }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -3211,11 +3289,11 @@ } }, "node_modules/rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.4.tgz", + "integrity": "sha512-vGorVWIsWfX3xbcyAS+I047kFKapHYivmkaT63Smj77XwvLSJos6M1xGqZnBPFQFBRZDOcG1QnYEIxAvTr/HjA==", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -3225,22 +3303,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", + "@rollup/rollup-android-arm-eabi": "4.24.4", + "@rollup/rollup-android-arm64": "4.24.4", + "@rollup/rollup-darwin-arm64": "4.24.4", + "@rollup/rollup-darwin-x64": "4.24.4", + "@rollup/rollup-freebsd-arm64": "4.24.4", + "@rollup/rollup-freebsd-x64": "4.24.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.4", + "@rollup/rollup-linux-arm-musleabihf": "4.24.4", + "@rollup/rollup-linux-arm64-gnu": "4.24.4", + "@rollup/rollup-linux-arm64-musl": "4.24.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.4", + "@rollup/rollup-linux-riscv64-gnu": "4.24.4", + "@rollup/rollup-linux-s390x-gnu": "4.24.4", + "@rollup/rollup-linux-x64-gnu": "4.24.4", + "@rollup/rollup-linux-x64-musl": "4.24.4", + "@rollup/rollup-win32-arm64-msvc": "4.24.4", + "@rollup/rollup-win32-ia32-msvc": "4.24.4", + "@rollup/rollup-win32-x64-msvc": "4.24.4", "fsevents": "~2.3.2" } }, @@ -3596,9 +3676,9 @@ } }, "node_modules/vite": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz", - "integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==", + "version": "5.4.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz", + "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==", "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", diff --git a/package.json b/package.json index e8b78b596..8998475e8 100644 --- a/package.json +++ b/package.json @@ -12,16 +12,19 @@ "prettier": "npx prettier . --write" }, "dependencies": { - "@abgov/react-components": "5.4.0", - "@abgov/web-components": "1.29.0", + "@abgov/react-components": "6.2.1", + "@abgov/ui-components-common": "1.2.1", + "@abgov/web-components": "1.32.1", "@faker-js/faker": "^8.3.1", "highlight.js": "^11.8.0", + "js-cookie": "^3.0.5", "octokit": "^4.0.2", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.13.0" }, "devDependencies": { + "@types/js-cookie": "^3.0.6", "@types/react": "^18.2.13", "@types/react-dom": "^18.2.6", "@types/react-router-dom": "^5.3.3", @@ -33,6 +36,8 @@ "eslint-plugin-react-refresh": "^0.3.5", "prettier": "2.4.1", "typescript": "^5.4.2", - "vite": "^5.4.6" + "vite": "^5.4.6", + "lodash": "^4.17.21", + "@types/lodash": "^4.17.16" } } diff --git a/public/images/text.png b/public/images/text.png new file mode 100644 index 000000000..eb928309b Binary files /dev/null and b/public/images/text.png differ diff --git a/src/App.tsx b/src/App.tsx index 225523351..a207abd59 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import React, { ReactNode } from "react"; +import React from "react"; import ReactDOM from "react-dom/client"; import { Route, @@ -6,63 +6,16 @@ import { createBrowserRouter, createRoutesFromElements, } from "react-router-dom"; - import "@abgov/web-components"; import Root from "@routes/root"; -import { useMediaQuery } from "@hooks/useMediaQuery"; -import { DeviceWidthContext } from "@contexts/DeviceWidthContext"; +import { DeviceWidthProvider } from "@contexts/DeviceWidthContext"; import "./index.css"; // Support import HomePage from "@routes/home"; -// Components - -import ComponentsPage from "@routes/components/Components"; - -import AllComponentsPage from "@routes/components/AllComponents"; -import AccordionPage from "@routes/components/Accordion.tsx"; -import BadgePage from "@routes/components/Badge"; -import BlockPage from "@routes/components/Block"; -import ButtonGroupPage from "@routes/components/ButtonGroup"; -import ButtonPage from "@routes/components/Button"; -import CalloutPage from "@routes/components/Callout"; -import CheckboxPage from "@routes/components/Checkbox"; -import ComponentNotFoundPage from "@routes/not-found/NotFound"; -import ContainerPage from "@routes/components/Container"; -import DatePickerPage from "@routes/components/DatePicker"; -import DetailsPage from "@routes/components/Details"; -import DividerPage from "@routes/components/Divider"; -import DropdownPage from "@routes/components/Dropdown"; -import FileUploaderPage from "@routes/components/FileUploader"; -import FilterChipPage from "@routes/components/FilterChip"; -import FormItemPage from "@routes/components/FormItemPage.tsx"; -import FormStepperPage from "@routes/components/FormStepper"; -import GridPage from "@routes/components/Grid"; -import HeroBannerPage from "@routes/components/HeroBanner"; -import IconsPage from "@routes/components/Icons"; -import IconButtonPage from "@routes/components/IconButton"; -import ListPage from "@routes/components/List"; -import ModalPage from "@routes/components/Modal"; -import NotificationBannerPage from "@routes/components/Notificationbanner"; -import PaginationPage from "@routes/components/Pagination"; -import PopoverPage from "@routes/components/Popover"; -import ProgressIndicatorPage from "@routes/components/ProgressIndicator"; -import RadioPage from "@routes/components/Radio"; -import SkeletonPage from "@routes/components/Skeleton.tsx"; -import SpacerPage from "@routes/components/Spacer"; -import TablePage from "@routes/components/Table"; -import TabsPage from "@routes/components/Tabs.tsx"; -import TooltipPage from "@routes/components/Tooltip"; -import TextFieldPage from "@routes/components/TextField"; -import TextAreaPage from "@routes/components/TextArea"; -import MicrositeHeaderPage from "@routes/components/MicrositeHeader"; -import AppHeaderPage from "@routes/components/AppHeader"; -import AppFooterPage from "@routes/components/AppFooter"; -import SideMenuPage from "@routes/components/SideMenu"; - // Design Tokens import DesignTokensOverviewPage from "@routes/design-tokens/overview/Overview"; @@ -103,88 +56,18 @@ import ErrorMessagesPage from "@routes/content/ErrorMessages"; import HelperTextPage from "@routes/content/HelperText"; import UserExperienceGuidelinesPage from "@routes/get-started/UserExperienceGuidelines"; -// Patterns Pages - -import PatternsLayout from "@routes/patterns/PatternsLayout"; -import LayoutPage from "@routes/patterns/LayoutPage"; -import PatternsOverviewPage from "@routes/patterns/PatternsOverview"; -import SimpleFormPage from "@routes/patterns/SimpleFormPage"; -import StartPage from "@routes/patterns/StartPage"; -import TaskListPage from "@routes/patterns/TaskListPage"; -import QuestionPage from "@routes/patterns/QuestionPage"; -import ReviewPage from "@routes/patterns/ReviewPage"; -import ResultPage from "@routes/patterns/ResultPage"; - -interface DeviceWidthProviderProps { - children: ReactNode; -} - -const DeviceWidthProvider: React.FC = ({ children }) => { - const isDesktop = useMediaQuery("(min-width: 1232px)"); - const isMobile = useMediaQuery("(max-width: 623px)"); - - return ( - - {children} - - ); -}; +import { VersionFromUrlProvider } from "@contexts/VersionFromUrlContext.tsx"; +import { ComponentsRouter, PatternsRouter } from "./versioned-router"; +import ComponentNotFound from "@routes/not-found/NotFound.tsx"; +import { LanguageVersionProvider } from "@contexts/LanguageVersionContext.tsx"; +import DevelopersUpgradePage from "@routes/get-started/developers/upgrade-guide/DevelopersUpgrade.tsx"; const router = createBrowserRouter( createRoutesFromElements( }> } /> - } - errorElement={}> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - - } - errorElement={}> + }> + } errorElement={}> } /> } /> } /> @@ -208,6 +91,7 @@ const router = createBrowserRouter( } /> } /> } /> + } /> } /> @@ -233,24 +117,19 @@ const router = createBrowserRouter( } /> - } errorElement={}> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - + }> ) ); ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( - - - + + + + + + + ); diff --git a/src/components/code-snippet/CodeSnippet.tsx b/src/components/code-snippet/CodeSnippet.tsx index 8d8fcd895..395e46067 100644 --- a/src/components/code-snippet/CodeSnippet.tsx +++ b/src/components/code-snippet/CodeSnippet.tsx @@ -1,7 +1,7 @@ -import { FC, ReactElement, ReactNode, useEffect, useRef, useState } from "react"; +import { FC, ReactElement, ReactNode, useContext, useEffect, useRef, useState } from "react"; import "./CodeSnippet.css"; -import { GoAButton, GoAIconButton, GoATooltip } from "@abgov/react-components"; +import { GoabButton, GoabIconButton, GoabTooltip } from "@abgov/react-components"; import { renderToString } from "react-dom/server"; import hljs from "highlight.js/lib/core"; @@ -10,6 +10,7 @@ import html from "highlight.js/lib/languages/xml"; import css from "highlight.js/lib/languages/css"; import "highlight.js/styles/github.css"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; type Language = "typescript" | "javascript" | "tsx" | "jsx" | "html" | "css" | string; @@ -23,7 +24,8 @@ interface Props { tags?: string[] | string; } -export const CodeSnippet: FC = ({ lang, allowCopy, code, children }) => { +export const CodeSnippet: FC = ({ lang, allowCopy, code, children, tags }) => { + const {language} = useContext(LanguageVersionContext); const [output, setOutput] = useState(""); const [isCopied, setIsCopied] = useState(false); const [isExpanded, setIsExpanded] = useState(false); @@ -39,7 +41,7 @@ export const CodeSnippet: FC = ({ lang, allowCopy, code, children }) => { }); resizeObserver.observe(codeSnippetRef.current); return () => resizeObserver.disconnect(); // clean up - }, []); + }, [language]); const cleanTabs = (code = "", tabSize: number): string => { const lines = code.trim().split("\n"); @@ -105,33 +107,37 @@ export const CodeSnippet: FC = ({ lang, allowCopy, code, children }) => { } return ( -
+ (tags == null || tags?.includes(language)) && ( +
         {output}
       
- {showMore && !isExpanded &&
} - {showMore && ( -
- setIsExpanded(!isExpanded)}> - Show {isExpanded ? "less" : "more"} - -
- )} - - {allowCopy && ( -
- - - -
- )} -
+ {showMore && !isExpanded &&
} + {showMore && ( +
+ setIsExpanded(!isExpanded)} + > + Show {isExpanded ? "less" : "more"} + +
+ )} + + {allowCopy && ( +
+ + + +
+ )} +
+ ) ); }; diff --git a/src/components/component-header/ComponentHeader.tsx b/src/components/component-header/ComponentHeader.tsx index 14e700bc8..0dd5c8f95 100644 --- a/src/components/component-header/ComponentHeader.tsx +++ b/src/components/component-header/ComponentHeader.tsx @@ -1,4 +1,4 @@ -import { GoABadge } from "@abgov/react-components"; +import { GoabBadge } from "@abgov/react-components"; import "./ComponentHeader.css"; import { Link } from "react-router-dom"; @@ -21,7 +21,7 @@ export enum Category { export const ComponentHeader: React.FC = (props: Props) => { return (
- +

{props.name}

diff --git a/src/components/component-properties/ComponentProperties.tsx b/src/components/component-properties/ComponentProperties.tsx index 14357d5af..6d129939d 100644 --- a/src/components/component-properties/ComponentProperties.tsx +++ b/src/components/component-properties/ComponentProperties.tsx @@ -1,9 +1,8 @@ -import { GoAAccordion, GoABadge } from "@abgov/react-components"; +import { GoabAccordion, GoabBadge } from "@abgov/react-components"; import { useContext, useEffect, useState } from "react"; -import { LanguageContext } from "@components/sandbox"; import css from "./ComponentProperties.module.css"; - +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; export type ComponentProperty = { name: string; type?: string | string[]; @@ -15,23 +14,29 @@ export type ComponentProperty = { interface Props { properties: ComponentProperty[]; + oldProperties?: ComponentProperty[]; heading?: string; } export const ComponentProperties = (props: Props) => { - const lang = useContext(LanguageContext); + const {language, version} = useContext(LanguageVersionContext); + const [filteredProperties, setFilteredProperties] = useState([]); const filterBy = (properties: ComponentProperty[]) => { const result = properties.filter((child: ComponentProperty) => { - return !child.lang || child.lang === lang; + return !child.lang || child.lang === language; }); return result; }; useEffect(() => { + if (version === "old") { + setFilteredProperties([...filterBy(props.oldProperties || props.properties)]); // If no old properties are provided, use the current properties + return; + } setFilteredProperties([...filterBy(props.properties)]); - }, [lang]); + }, [language, version]); function dasherize(str: string): string { return str.replace(" ", "-").toLowerCase(); @@ -46,13 +51,14 @@ export const ComponentProperties = (props: Props) => { > {props.heading || "Properties"} - +
{filteredProperties.map((props, index) => ( + ))}
-
+ ); }; @@ -67,7 +73,7 @@ function ComponentProperty({ props }: ComponentPropertyProps) {
{props.name} - {props.required && } + {props.required && } {props.type && ( diff --git a/src/components/component-properties/common-properties.ts b/src/components/component-properties/common-properties.ts new file mode 100644 index 000000000..30e85f774 --- /dev/null +++ b/src/components/component-properties/common-properties.ts @@ -0,0 +1,31 @@ +import { ComponentProperty } from "@components/component-properties/ComponentProperties.tsx"; + +export const LegacyMarginProperty: ComponentProperty = { + name: "mt,mr,mb,ml", + type: "none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl", + description: "Apply margin to the top, right, bottom, and/or left of the component.", +}; +export const MarginProperty: ComponentProperty = { + name: "mt,mr,mb,ml", + type: "Spacing (none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl)", + description: "Apply margin to the top, right, bottom, and/or left of the component.", +}; +export const TestIdProperty: ComponentProperty = { + name: "testId", + type: "string", + description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", +}; +export const LegacyTestIdProperties: ComponentProperty[] = [ + { + name: "testId", + type: "string", + lang: "react", + description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", + }, + { + name: "testid", + type: "string", + lang: "angular", + description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", + }, +] diff --git a/src/components/do-dont/DoDont.tsx b/src/components/do-dont/DoDont.tsx index 82104499e..1cf19e3e6 100644 --- a/src/components/do-dont/DoDont.tsx +++ b/src/components/do-dont/DoDont.tsx @@ -1,4 +1,4 @@ -import { GoAIcon } from "@abgov/react-components"; +import { GoabIcon } from "@abgov/react-components"; import "./DoDont.css"; import { ReactNode } from "react"; @@ -15,7 +15,7 @@ export function DoDont({ type, children, description }: Props) {
{children}
{(type === "do" || type === "dont") && (
- {type === "do" ? : } + {type === "do" ? : }
{type === "do" ? "Do" : "Dont"}
)} diff --git a/src/components/icon-snippet/IconSnippet.tsx b/src/components/icon-snippet/IconSnippet.tsx index 56ba19015..bcb27bfe7 100644 --- a/src/components/icon-snippet/IconSnippet.tsx +++ b/src/components/icon-snippet/IconSnippet.tsx @@ -1,9 +1,10 @@ import { FC, useState } from "react"; -import { GoAIcon, GoAIconType } from "@abgov/react-components"; +import { GoabIcon } from "@abgov/react-components"; import "./IconSnippet.css"; +import { GoabIconType } from "@abgov/ui-components-common"; interface Props { - type: GoAIconType; + type: GoabIconType; } export const IconSnippet: FC = ({ type }) => { @@ -19,7 +20,7 @@ export const IconSnippet: FC = ({ type }) => { return ( <>
- + {type}
= ({ children }) => { + return {children}; +}; diff --git a/src/components/mock-modal/Modal.tsx b/src/components/mock-modal/Modal.tsx index 1f2e1a5dd..ae65f9ce5 100644 --- a/src/components/mock-modal/Modal.tsx +++ b/src/components/mock-modal/Modal.tsx @@ -1,6 +1,7 @@ import { ReactNode } from "react"; import css from "./Modal.module.css"; -import { GoAIcon, GoAIconType } from "@abgov/react-components"; +import { GoabIcon } from "@abgov/react-components"; +import { GoabIconType } from "@abgov/ui-components-common"; type Variant = "information" | "important" | "emergency" | "success" | "event"; @@ -10,12 +11,12 @@ interface Props { children: ReactNode; } -export function GoAModal({ heading, calloutVariant, children }: Props) { +export function GoabModal({ heading, calloutVariant, children }: Props) { return (
{calloutVariant && (
- +
)}
@@ -26,4 +27,4 @@ export function GoAModal({ heading, calloutVariant, children }: Props) { ); } -export default GoAModal; +export default GoabModal; diff --git a/src/components/sandbox/AngularReactiveSerializer.ts b/src/components/sandbox/AngularReactiveSerializer.ts index 049a11b98..ab3bb5c0c 100644 --- a/src/components/sandbox/AngularReactiveSerializer.ts +++ b/src/components/sandbox/AngularReactiveSerializer.ts @@ -1,24 +1,25 @@ import { ComponentBinding } from "./ComponentBinding"; import { BaseSerializer, Serializer, SerializerState } from "./BaseSerializer"; +import { LanguageVersion } from "@components/version-language-switcher/version-language-constants.ts"; const ReactiveComponents = [ - "goa-input", - "goa-textarea", - "goa-dropdown", - "goa-checkbox", - "goa-radio-group", - "goa-date-picker", + "goab-input", + "goab-textarea", + "goab-dropdown", + "goab-checkbox", + "goab-radio-group", + "goab-date-picker", ]; export class AngularReactiveSerializer extends BaseSerializer implements Serializer { public isRoot = false; private nativeEls = - "div span p br header footer blockquote input textarea a button h2 h2 h3 h4 img label ul li ol hr section dt dl dd".split( + "div form span p br header footer blockquote input textarea a button h2 h2 h3 h4 h5 h6 img label ul li ol hr section dt dl dd strong".split( " " ); - constructor(properties: ComponentBinding[]) { - super(properties); + constructor(properties: ComponentBinding[], version: LanguageVersion) { + super(properties, version); } setIsRoot(isRoot: boolean) { @@ -38,6 +39,10 @@ export class AngularReactiveSerializer extends BaseSerializer implements Seriali return ""; } + if (this.version === "new" && name === "onClick") { + return `(${name})="${name}()"`; + } + let _name = name.replace(/^on/, ""); _name = _name.substring(0, 1).toLowerCase() + _name.substring(1); @@ -45,7 +50,7 @@ export class AngularReactiveSerializer extends BaseSerializer implements Seriali } stringToProp(name: string, item: string): string { - if (ReactiveComponents.includes(this.state.element) && name === "value") { + if (ReactiveComponents.includes(this.state.element) && name === "value" && this.version === "old") { return `goaValue`; } if (this.isDynamic(name)) { @@ -53,7 +58,8 @@ export class AngularReactiveSerializer extends BaseSerializer implements Seriali } if (item === "") return ""; if (name === "className") name = "class"; - return `${name.toLowerCase()}="${item}"`; + + return `${this.version === "old" ? name.toLowerCase() : name}="${item}"`; } dateToProp(name: string, item: Date): string { @@ -64,18 +70,18 @@ export class AngularReactiveSerializer extends BaseSerializer implements Seriali if (this.isDynamic(name)) { return this.#dynamicProp(name); } - return `${name.toLowerCase()}="${item}"`; + return `${this.version === "old" ? name.toLowerCase() : `[${name}]`}="${item}"`; } booleanToProp(propName: string, propValue: boolean): string { - if (ReactiveComponents.includes(this.state.element) && propName === "checked") { + if (this.version === "old" && ReactiveComponents.includes(this.state.element) && propName === "checked") { return `goaChecked`; } if (this.isDynamic(propName)) { return this.#dynamicProp(propName); } if (!propValue) return ""; - return `${propName.toLowerCase()}="${propValue}"`; + return this.version === "old" ? `${propName.toLowerCase()}="${propValue}"` : `[${propName.toLowerCase()}]="${propValue}"`; } funcToProp(name: string, _item: Object): string { @@ -93,9 +99,15 @@ export class AngularReactiveSerializer extends BaseSerializer implements Seriali if (this.nativeEls.includes(name)) { return name; } - const prefix = "GoA"; - const tail = name.replace(prefix, ""); - return `${prefix.toLowerCase()}-${this.dasherize(tail)}`; + const currentPrefix = "Goab"; + const oldPrefix = "goa"; + const tail = name.replace(currentPrefix, ""); + + if (this.version === "old") { + return `${oldPrefix}-${this.dasherize(tail)}`; + } + + return `${currentPrefix.toLowerCase()}-${this.dasherize(tail)}`; } componentToString(name: string): string { @@ -103,30 +115,55 @@ export class AngularReactiveSerializer extends BaseSerializer implements Seriali return `<${name} />`; } - addReactiveProperties(props: string, propName: string): string { - const additionalProps = `[formControl]="${propName}FormCtrl" [value]="${propName}FormCtrl.value"`; - props = props ? `${props} ${additionalProps}` : additionalProps; - return props; - } - modifyProps(props: string, propName: string, elementType: string): string { if (ReactiveComponents.includes(elementType)) { - const additionalProps = `[formControl]="${propName}FormCtrl" [value]="${propName}FormCtrl.value"`; + const additionalProps = + this.version === "old" + ? `[formControl]="${propName}FormCtrl" [value]="${propName}FormCtrl.value"` + : `formControlName="${propName}"`; props = props ? `${props} ${additionalProps}` : additionalProps; } return props; } postProcess(children: string): string { - if (children.startsWith("]*\[formGroup\]="form")/g, + ']*)>/g, (match, attrs) => { + if (attrs.includes('formControlName')) { + // Remove the value attribute (with any numeric value) + const newAttrs = attrs.replace(/ ?value="\d+"/, ''); + return ``; + } + return match; + }); + } + + if (children.startsWith(" string; @@ -21,14 +22,26 @@ export interface SerializerState { props: { name: string }; } -export function propsToString(props: Record, lang: "angular" | "react"): string { +export function propsToString(props: Record, lang: "angular" | "react", version: LanguageVersion): string { if (lang === "angular") { - return Object.entries(props) - .map(e => `${e[0].toLowerCase()}="${e[1]}"`) - .join(" "); + if (version === "old") { + return Object.entries(props).filter(e => e[1] !== '' && e[1] != undefined) + .map((e) => { + return typeof e[1] === 'number' || typeof e[1] === 'boolean' ? `${e[0].toLowerCase()}="${e[1]}"` : `${e[0].toLowerCase()}="${e[1]}"` + }) + .join(" "); + } else { + return Object.entries(props).filter(e => e[1] !== '' && e[1] != undefined) + .map((e) => { + return typeof e[1] === 'number' || typeof e[1] === 'boolean' ? `[${e[0]}]="${e[1]}"` : `${e[0]}="${e[1]}"` + }) + .join(" "); + } } - return Object.entries(props) - .map(e => `${e[0]}="${e[1]}"`) + return Object.entries(props).filter(e => e[1] !== '' && e[1] != undefined) + .map((e) => { + return typeof e[1] === 'number' || typeof e[1] === 'boolean' ? `${e[0]}={${e[1]}}` : `${e[0]}="${e[1]}"` + }) .join(" "); } @@ -36,7 +49,7 @@ export class BaseSerializer { protected isRoot = false; protected state: SerializerState = { element: "", props: { name: "" } }; - constructor(protected properties: ComponentBinding[]) {} + constructor(protected properties: ComponentBinding[], protected version: LanguageVersion) {} getProperty(name: string): ComponentBinding | undefined { return this.properties.find(p => p.name === name); @@ -68,4 +81,21 @@ export class BaseSerializer { } + protected getNewVersionFunctionName(functionName: string): string { + let element = this.state.element || 'goab-'; + let componentName = ''; + if (element.includes('-')) { + const parts = element.split('-'); + componentName = parts[1] || ''; + } else if (element.toLowerCase().startsWith('goab')) { + componentName = element.substring(4); + if (componentName.length > 0) { + componentName = componentName[0].toLowerCase() + componentName.slice(1); + } + } + // So onChange for GoabInput will be: inputOnChange, onChange for Dropdown will be dropdownOnChange + // The event passed on onChange.. now is strict with type of Event, so we must handle it + functionName = functionName[0].toUpperCase() + functionName.slice(1); + return `${componentName}${functionName}`; + } } diff --git a/src/components/sandbox/ComponentBinding.ts b/src/components/sandbox/ComponentBinding.ts index 7a941c336..201dd9c30 100644 --- a/src/components/sandbox/ComponentBinding.ts +++ b/src/components/sandbox/ComponentBinding.ts @@ -31,6 +31,8 @@ export interface BooleanBinding extends BaseBinding { export interface NumberBinding extends BaseBinding { type: "number"; value?: number; + step?: number; + width?: string; } export interface StringBinding extends BaseBinding { @@ -69,5 +71,5 @@ export interface RadioBinding extends BaseBinding { export interface DateBinding extends BaseBinding { type: "date", - value?: Date; + value?: Date|string; } diff --git a/src/components/sandbox/ComponentSerializer.ts b/src/components/sandbox/ComponentSerializer.ts index eed6297a8..aa1494803 100644 --- a/src/components/sandbox/ComponentSerializer.ts +++ b/src/components/sandbox/ComponentSerializer.ts @@ -92,8 +92,18 @@ export class ComponentSerializer { props = " " + props; } + // Define void elements (HTML elements that should be self-closing) + const voidElements = [ + 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', + 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr' + ]; + + if (!component.props.children) { - return `<${elementType}${props}>`; + if (voidElements.includes(elementType.toLowerCase())) { + return `<${elementType}${props} />`; + } + return `<${elementType}${props}>`; } let children: string = ""; diff --git a/src/components/sandbox/ReactSerializer.ts b/src/components/sandbox/ReactSerializer.ts index a9f279981..d2495ab29 100644 --- a/src/components/sandbox/ReactSerializer.ts +++ b/src/components/sandbox/ReactSerializer.ts @@ -1,17 +1,22 @@ import { ComponentBinding } from "./ComponentBinding"; -import { BaseSerializer, Serializer } from "./BaseSerializer"; +import { BaseSerializer, Serializer, SerializerState } from "./BaseSerializer"; +import { LanguageVersion } from "@components/version-language-switcher/version-language-constants.ts"; export class ReactSerializer extends BaseSerializer implements Serializer { public isRoot = false; - constructor(properties: ComponentBinding[]) { - super(properties); + constructor(properties: ComponentBinding[], version: LanguageVersion, protected variableNames: string[]) { + super(properties, version); } setIsRoot(isRoot: boolean) { this.isRoot = isRoot; } + setState(state: SerializerState) { + super.setState(state); + } + getProperty(name: string): ComponentBinding | undefined { return this.properties.find(p => p.name === name); } @@ -24,6 +29,10 @@ export class ReactSerializer extends BaseSerializer implements Serializer { if (this.isDynamic(name)) { return this.dynamicProp(name); } + if (this.variableNames.includes(name)) { + return `${name}={${name}}`; + } + if (name === "value" && value === "") return `value=""`; if (value === "") return ""; @@ -34,6 +43,9 @@ export class ReactSerializer extends BaseSerializer implements Serializer { if (this.isDynamic(name)) { return this.dynamicProp(name); } + if (this.variableNames.includes(name)) { + return `${name}={${name}}`; + } return `${name}={${value}}`; } @@ -41,12 +53,19 @@ export class ReactSerializer extends BaseSerializer implements Serializer { if (this.isDynamic(name)) { return this.dynamicProp(name); } + if (this.variableNames.includes(name)) { + return `${name}={${name}}`; + } if (!value) return ""; return `${name}={${value}}`; } funcToProp(name: string, _callback: Object): string { - return `${name}={${name}}`; + if (this.version === "old" || name === "onClick") { + return `${name}={${name}}`; + } + + return `${name}={${this.getNewVersionFunctionName(name)}}`; } dateToProp(name: string, item: Date): string { @@ -64,6 +83,9 @@ export class ReactSerializer extends BaseSerializer implements Serializer { } componentNameToString(name: string): string { + if (this.version === "old") { + return name.replace(/^Goab/, "GoA"); + } return name; } diff --git a/src/components/sandbox/Sandbox.tsx b/src/components/sandbox/Sandbox.tsx index a481b759b..4fb227253 100644 --- a/src/components/sandbox/Sandbox.tsx +++ b/src/components/sandbox/Sandbox.tsx @@ -3,7 +3,6 @@ import { ReactElement, ReactNode, useContext, useEffect, useState } from "react" import SandboxProperties from "./SandboxProperties"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet"; import { ComponentBinding } from "./ComponentBinding"; -import { LanguageContext } from "./LanguageContext"; import { ReactSerializer } from "./ReactSerializer"; import { AngularSerializer } from "./AngularSerializer"; import { AngularReactiveSerializer } from "./AngularReactiveSerializer"; @@ -11,8 +10,11 @@ import ComponentSerializer from "./ComponentSerializer"; import "./Sandbox.css"; import React from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { AngularTemplateDrivenSerializer } from "@components/sandbox/AngularTemplateDrivenSerializer.ts"; +import { LanguageVersion } from "@components/version-language-switcher/version-language-constants.ts"; -type Flag = "reactive"; +type Flag = "reactive" | "template-driven" | "event"; type ComponentType = "goa" | "codesnippet"; type Serializer = (el: any, properties: ComponentBinding[]) => string; @@ -25,36 +27,42 @@ interface SandboxProps { onChangeFormItemBindings?: (bindings: ComponentBinding[], props: Record) => void; flags?: Flag[]; skipRender?: boolean; // prevent rendering the snippet, to allow custom code to be shown - allow?: string[]; // Be default the Sandbox is selective to what it renders out. This adds - // additional elements to what is allowed to be rendered out + skipRenderOnly?: string; // prevent rendering the snippet for a specific language. Ex: react/angular + allow?: string[]; // Be default the Sandbox is selective to what it renders out. This adds + // additional elements to what is allowed to be rendered out + variableNames?: string[]; // If we want to assign a variable such as step={step} render in code snippet, provides variableNames=["step"] children: ReactNode; } type SandboxViewProps = { fullWidth?: boolean; sandboxProps: SandboxProps; -} +}; export const Sandbox = (props: SandboxProps) => { - - const lang = useContext(LanguageContext); + const {language: lang, version} = useContext(LanguageVersionContext); const [formatLang, setFormatLang] = useState(""); const serializers: Record = { "react": (els: ReactElement[], properties) => { - const serializer = new ComponentSerializer(new ReactSerializer(properties)); + const serializer = new ComponentSerializer(new ReactSerializer(properties, version, props.variableNames || [])); return serializer.componentsToString(els); }, "angular": (els: ReactElement[], properties) => { - const serializer = new ComponentSerializer(new AngularSerializer(properties)); + const serializer = new ComponentSerializer(new AngularSerializer(properties, version, props.variableNames || [])); return serializer.componentsToString(els); }, "angular-reactive": (els: ReactElement[], properties) => { - const serializer = new ComponentSerializer(new AngularReactiveSerializer(properties)); + const serializer = new ComponentSerializer(new AngularReactiveSerializer(properties, version)); return serializer.componentsToString(els); }, + + "angular-template-driven": (els: ReactElement[], properties) => { + const serializer = new ComponentSerializer(new AngularTemplateDrivenSerializer(properties, version, props.variableNames || [])); + return serializer.componentsToString(els); + } }; const formatMap: Record = { @@ -111,7 +119,7 @@ export const Sandbox = (props: SandboxProps) => { {props.properties && props.properties.length > 0 && ( )} - + {props.note && (
{props.note}
)} ); @@ -122,20 +130,54 @@ type SandboxCodeProps = { lang: string; formatLang: string; serializers: Record; + version?: LanguageVersion; } function SandboxCode(p: SandboxCodeProps) { // reactive angular if (p.lang === "angular" && p.props.flags?.includes("reactive")) { return ( <> -

Event based

- - {!p.props.skipRender && } + {(p.version === "old" || p.props.flags?.includes("event")) && <> +

Event based

+ + {!p.props.skipRender && p.props?.skipRenderOnly !== p.lang && ( + + )} + }

Reactive forms (FormControl)

- {!p.props.skipRender && } + {!p.props.skipRender && ( + + )} + + {/*If flags have reactive, it means that the possibility we have template-driven as well*/} + + {p.props.flags?.includes("template-driven") && ( + <> +

Template driven (ngModel)

+ + {!p.props.skipRender && ( + + )} + + )} ); } @@ -145,7 +187,7 @@ function SandboxCode(p: SandboxCodeProps) { return ( <> - {!p.props.skipRender && } + {!p.props.skipRender && p.props.skipRenderOnly !== "angular" && } ); } @@ -155,7 +197,7 @@ function SandboxCode(p: SandboxCodeProps) { return ( <> - {!p.props.skipRender && } + {!p.props.skipRender && p.props.skipRenderOnly !== "react" && } ); } @@ -199,19 +241,18 @@ function ComponentList(props: ComponentListProps): ReactElement[] { const isValidGOAComponent = (el: ReactElement) => typeof el.type === "function" && el.type.name.toLowerCase().startsWith(props.type); const isAllowedInSandbox = (el: ReactElement) => - typeof el.type === "string" && props.sandboxProps.allow?.includes(el.type) || + typeof el.type === "string" && props.sandboxProps.allow?.includes(el.type) || typeof el.type === "function" && props.sandboxProps.allow?.includes(el.type.name); return children.filter( el => React.isValidElement(el) && (isValidGOAComponent(el) || isAllowedInSandbox(el)) ); } - // CodeSnippet output. To show code the root element *must* start with goa (case-insensitive). // This allows type ComponentOutputProps = { formatLang: string; - type: "angular" | "angular-reactive" | "react"; + type: "angular" | "angular-reactive" | "angular-template-driven" | "react"; sandboxProps: SandboxProps; serializer: Serializer; } @@ -232,6 +273,7 @@ function ComponentOutput(props: ComponentOutputProps): ReactElement { return ( diff --git a/src/components/sandbox/SandboxProperties.tsx b/src/components/sandbox/SandboxProperties.tsx index 7cf7c06ec..549f830ac 100644 --- a/src/components/sandbox/SandboxProperties.tsx +++ b/src/components/sandbox/SandboxProperties.tsx @@ -1,15 +1,20 @@ import { - GoACheckbox, - GoADatePicker, - GoADropdown, - GoADropdownItem, - GoAFormItem, - GoAInput, - GoARadioGroup, - GoARadioItem, + GoabCheckbox, + GoabDatePicker, + GoabDropdown, + GoabDropdownItem, + GoabFormItem, + GoabInput, + GoabRadioGroup, + GoabRadioItem, } from "@abgov/react-components"; import { ComponentBinding } from "./ComponentBinding"; -import { GoAFormItemRequirement } from "@abgov/react-components"; +import { + GoabCheckboxOnChangeDetail, GoabDatePickerOnChangeDetail, + GoabDropdownOnChangeDetail, + GoabFormItemRequirement, + GoabRadioGroupOnChangeDetail +} from "@abgov/ui-components-common"; interface Props { properties?: ComponentBinding[]; @@ -17,24 +22,24 @@ interface Props { } export function SandboxProperties({ properties = [], onChange }: Props) { - function onListChange(name: string, value: string | string[]) { - const prop = properties.find(p => ["list", "dropdown"].includes(p.type) && p.name === name); + function onListChange(event: GoabDropdownOnChangeDetail) { + const prop = properties.find(p => ["list", "dropdown"].includes(p.type) && p.name === event.name); if (!prop || !["list", "dropdown"].includes(prop.type)) return; - prop.value = !value ? "" : typeof value === "string" ? value : value[0]; + prop.value = !event.value ? "" : event.value; onChange([...properties]); } - function onRadioChange(name: string, value: string | string[]) { - const prop = properties.find(p => p.type === "radio" && p.name === name); + function onRadioChange(event: GoabRadioGroupOnChangeDetail) { + const prop = properties.find(p => p.type === "radio" && p.name === event.name); if (!prop || prop.type !== "radio") return; - prop.value = !value ? "" : typeof value === "string" ? value : value[0]; + prop.value = !event.value ? "" : event.value; onChange([...properties]); } - function onComboboxChange(name: string, value: string | string[]) { - const prop = properties.find(p => p.type === "combobox" && p.name === name); + function onComboboxChange(event: GoabDropdownOnChangeDetail) { + const prop = properties.find(p => p.type === "combobox" && p.name === event.name); if (!prop || prop.type !== "combobox") return; - prop.value = !value ? "" : typeof value === "string" ? value : value[0]; + prop.value = !event.value ? "" : event.value; onChange([...properties]); } @@ -52,17 +57,17 @@ export function SandboxProperties({ properties = [], onChange }: Props) { onChange([...properties]); } - function onCheckboxChange(name: string, checked: boolean, _value: string): void { - const prop = properties.find(p => p.type === "boolean" && p.name === name); + function onCheckboxChange(event: GoabCheckboxOnChangeDetail): void { + const prop = properties.find(p => p.type === "boolean" && p.name === event.name); if (!prop || prop.type !== "boolean") return; - prop.value = checked; + prop.value = event.checked; onChange([...properties]); } - function onDateChange(name: string, value: Date | undefined): void { - const prop = properties.find(p => p.type === "date" && p.name === name); + function onDateChange(event: GoabDatePickerOnChangeDetail): void { + const prop = properties.find(p => p.type === "date" && p.name === event.name); if (!prop || prop.type !== "date") return; - prop.value = value; + prop.value = event.value; onChange([...properties]); } @@ -75,19 +80,19 @@ export function SandboxProperties({ properties = [], onChange }: Props) { case "list": case "dropdown": return ( - + {p.options.map(option => ( - ))} - + ); case "combobox": return ( - {p.options.map(option => ( - ))} - + ); case "radio": return ( - + {p.options.map(option => { - return ; + return ; })} - + ); case "boolean": return ( - ); case "string": - return ; + return onTextChange(p.name, event.value)} />; case "number": return ( - + onNumberChange(p.name, event.value)} /> ); case "date": return ( - + ) } } @@ -138,9 +143,9 @@ export function SandboxProperties({ properties = [], onChange }: Props) { return (
{properties.filter(p => !p.hidden).map(p => ( - + {renderProps(p)} - + ))}
); diff --git a/src/components/sandbox/index.ts b/src/components/sandbox/index.ts index 22a9d61e1..916a72d88 100644 --- a/src/components/sandbox/index.ts +++ b/src/components/sandbox/index.ts @@ -2,6 +2,5 @@ export * from "./AngularSerializer"; export * from "./ReactSerializer"; export * from "./ComponentBinding"; export * from "./ComponentSerializer"; -export * from "./LanguageContext"; export * from "./Sandbox"; export * from "./SandboxProperties"; diff --git a/src/components/support-info/SupportInfo.tsx b/src/components/support-info/SupportInfo.tsx index 6c6d7792d..11e66ab78 100644 --- a/src/components/support-info/SupportInfo.tsx +++ b/src/components/support-info/SupportInfo.tsx @@ -1,4 +1,4 @@ -import { GoACallout } from "@abgov/react-components"; +import { GoabCallout } from "@abgov/react-components"; import "./SupportInfo.css"; export const SupportInfo = (props: { hidden?: boolean }) => { @@ -7,7 +7,7 @@ export const SupportInfo = (props: { hidden?: boolean }) => { } return (
- @@ -17,7 +17,7 @@ export const SupportInfo = (props: { hidden?: boolean }) => { Book time in drop in hours {" "} - +
); }; diff --git a/src/components/token-snippet/TokenSnippet.tsx b/src/components/token-snippet/TokenSnippet.tsx index fc2ed0e1c..fbcff33c0 100644 --- a/src/components/token-snippet/TokenSnippet.tsx +++ b/src/components/token-snippet/TokenSnippet.tsx @@ -1,8 +1,8 @@ import { FC, useContext, useState } from "react"; import "./TokenSnippet.css"; -import { GoAIcon } from "@abgov/react-components"; -import { DesignTokensLanguageContext } from "@components/sandbox"; +import { GoabIcon } from "@abgov/react-components"; +import { DesignTokensLanguageContext } from "@contexts/DesignTokensLanguageContext"; interface Props { code: string; @@ -29,7 +29,7 @@ export const TokenSnippet: FC = ({ code }) => { {code} - + diff --git a/src/components/version-language-switcher/VersionLanguageSwitcher.tsx b/src/components/version-language-switcher/VersionLanguageSwitcher.tsx new file mode 100644 index 000000000..d3b1ce766 --- /dev/null +++ b/src/components/version-language-switcher/VersionLanguageSwitcher.tsx @@ -0,0 +1,109 @@ +import { + GoabIcon, + GoabPopover, +} from "@abgov/react-components"; +import { + ANGULAR_VERSIONS, getVersionedUrlPath, Language, LanguageVersion, + VERSIONED_ANGULAR_URL_SEGMENT, + VERSIONED_REACT_URL_SEGMENT, REACT_VERSIONS +} from "./version-language-constants.ts"; +import { useLocation, useNavigate } from "react-router-dom"; +import React, { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import "./version-language-switcher.css"; + +export const VersionLanguageSwitcher = () => { + const {language, version, setLanguage, setVersion} = useContext(LanguageVersionContext); + const location = useLocation(); + const navigate = useNavigate(); + + const updateURL = (key: "language" | "version", newValue: LanguageVersion | Language) => { + const isComponentRoute = + location.pathname.startsWith("/components/") && location.pathname.split("/").length > 2; + let newLanguageValue = language; // fallback value from localStorage + let newVersionValue = version; // fallback value from localStorage + + if (key === "language") newLanguageValue = newValue as Language; + if (key === "version") newVersionValue = newValue as LanguageVersion; + + const combineSegment = getVersionedUrlPath(newVersionValue, newLanguageValue); + if (isComponentRoute) { + const pathSegments = location.pathname.split("/"); + const componentName = pathSegments[pathSegments.length -1]; + if (VERSIONED_REACT_URL_SEGMENT === combineSegment || VERSIONED_ANGULAR_URL_SEGMENT === combineSegment) { + const newPath = `/components/${combineSegment}/${componentName}${location.hash}`; + navigate(newPath, {replace: true}); + } else { + const newPath = `/components/${componentName}${location.hash}`; + navigate(newPath, {replace: true}); + } + } + } + + const updateLanguage = (newValue: "react" | "angular") => { + setLanguage(newValue); + updateURL("language", newValue); + } + + const updateVersion = (newValue: "old" | "new") => { + setVersion(newValue); + updateURL("version", newValue); + } + + const capitalizeFirstLetter = (str: string): string => { + if (!str) return str; + return str.charAt(0).toUpperCase() + str.slice(1); + } + + const openLanguagePopOver = (e: React.MouseEvent) => { + e.preventDefault(); + }; + + const openVersionPopOver = (e: React.MouseEvent) => { + e.preventDefault(); + }; + + const getCurrentVersionLabel = (language: string, version: string) => { + if (language === "react") { + return version === "new" ? REACT_VERSIONS.NEW.label : REACT_VERSIONS.OLD.label; + } if (language === "angular") { + return version === "new" ? ANGULAR_VERSIONS.NEW.label : ANGULAR_VERSIONS.OLD.label; + } + } + + return ( + <> + openLanguagePopOver(e)}> + {capitalizeFirstLetter(language)} + + } + padded={false}> + <> + {["angular", "react"].map(lang => ( + updateLanguage(lang as "react" | "angular")}> + {capitalizeFirstLetter(lang)} + )) + } + + + + openVersionPopOver(e)}> + {getCurrentVersionLabel(language, version)} + + } padded={false}> + <> + {["new", "old"].map(ver => ( + updateVersion(ver as "old" | "new")}> + {getCurrentVersionLabel(language, ver)} + + ))} + + + + + ); +} diff --git a/src/components/version-language-switcher/version-language-constants.ts b/src/components/version-language-switcher/version-language-constants.ts new file mode 100644 index 000000000..d180184d8 --- /dev/null +++ b/src/components/version-language-switcher/version-language-constants.ts @@ -0,0 +1,32 @@ +export type LanguageVersion = "old" | "new"; +export type Language = "react" | "angular"; +export const ANGULAR_VERSIONS = { + OLD: { + label: "v3.2.2 (lts)", + value: "old" + }, + NEW: { + label: "v4.0.0+", + value: "new" + } +} +export const REACT_VERSIONS = { + OLD: { + label: "v5.4.1 (lts)", + value: "old" + }, + NEW: { + label: "v6.0.0+", + value: "new" + } +} + +export const LOCAL_STORAGE_LANGUAGE_KEY = "goa-docs-lang"; +export const LOCAL_STORAGE_VERSION_KEY = "goa-docs-version"; + +export const VERSIONED_REACT_URL_SEGMENT = `${REACT_VERSIONS.NEW.label}-react`; +export const VERSIONED_ANGULAR_URL_SEGMENT = `${ANGULAR_VERSIONS.NEW.label}-angular`; + +export const getVersionedUrlPath = (version: string, language: string) => { + return version === "new" ? `${language === "react" ? REACT_VERSIONS.NEW.label : ANGULAR_VERSIONS.NEW.label}-${language}` : ""; +} diff --git a/src/components/version-language-switcher/version-language-switcher.css b/src/components/version-language-switcher/version-language-switcher.css new file mode 100644 index 000000000..23531cd77 --- /dev/null +++ b/src/components/version-language-switcher/version-language-switcher.css @@ -0,0 +1,21 @@ +.version-language-switcher__heading { + display: inline-flex; + align-items: center; + gap: var(--goa-space-2xs); + font-size: var(--goa-font-size-2); + margin-left: var(--goa-space-m); +} +.version-language-switcher__menu { + display: block; + font: var(--goa-typography-body-s); + padding: var(--goa-space-s) var(--goa-space-s) var(--goa-space-s) var(--goa-space-s); + text-decoration: none; + color: var(--goa-color-text-default)!important; +} +.version-language-switcher__menu:hover:not(.version-language-switcher__menu--current) { + background: #cedfee; +} +.version-language-switcher__menu--current { + color: var(--goa-color-text-light)!important;; + background-color: var(--goa-color-interactive-default); +} diff --git a/src/components/sandbox/LanguageContext.ts b/src/contexts/DesignTokensLanguageContext.ts similarity index 65% rename from src/components/sandbox/LanguageContext.ts rename to src/contexts/DesignTokensLanguageContext.ts index 9ff382afe..9b52d6869 100644 --- a/src/components/sandbox/LanguageContext.ts +++ b/src/contexts/DesignTokensLanguageContext.ts @@ -1,5 +1,3 @@ import { createContext } from "react"; -export const LanguageContext = createContext(""); - export const DesignTokensLanguageContext = createContext(""); diff --git a/src/contexts/DeviceWidthContext.ts b/src/contexts/DeviceWidthContext.ts deleted file mode 100644 index 81ca38c45..000000000 --- a/src/contexts/DeviceWidthContext.ts +++ /dev/null @@ -1,6 +0,0 @@ -import React from "react"; - -export const DeviceWidthContext = React.createContext({ - isDesktop: true, - isMobile: false, -}); diff --git a/src/contexts/DeviceWidthContext.tsx b/src/contexts/DeviceWidthContext.tsx new file mode 100644 index 000000000..c4a2d494e --- /dev/null +++ b/src/contexts/DeviceWidthContext.tsx @@ -0,0 +1,22 @@ +import React, { ReactNode } from "react"; +import { useMediaQuery } from "@hooks/useMediaQuery.tsx"; + +interface DeviceWidthProviderProps { + children: ReactNode; +} + +export const DeviceWidthContext = React.createContext({ + isDesktop: true, + isMobile: false, +}); + +export const DeviceWidthProvider: React.FC = ({ children }) => { + const isDesktop = useMediaQuery("(min-width: 1232px)"); + const isMobile = useMediaQuery("(max-width: 623px)"); + + return ( + + {children} + +); +}; diff --git a/src/contexts/LanguageVersionContext.tsx b/src/contexts/LanguageVersionContext.tsx new file mode 100644 index 000000000..212edbf4f --- /dev/null +++ b/src/contexts/LanguageVersionContext.tsx @@ -0,0 +1,41 @@ +import React, { createContext, useEffect, useState } from "react"; +import { + Language, + LanguageVersion, + LOCAL_STORAGE_LANGUAGE_KEY, + LOCAL_STORAGE_VERSION_KEY +} from "@components/version-language-switcher/version-language-constants.ts"; +import { DEFAULT_LANGUAGE, DEFAULT_VERSION } from "../global-constants"; + +interface LanguageVersionContextProps { + language: Language; + version: LanguageVersion; + setLanguage: (lang: Language) => void; + setVersion: (version: LanguageVersion) => void; +} + +export const LanguageVersionContext = createContext({ + language: DEFAULT_LANGUAGE, + version: DEFAULT_VERSION, + setLanguage: () => {}, + setVersion: () => {}, +}); + +export const LanguageVersionProvider: React.FC<{children: React.ReactNode}> = ({children}) => { + const [language, setLanguage] = useState(() => (localStorage.getItem(LOCAL_STORAGE_LANGUAGE_KEY) || DEFAULT_LANGUAGE) as Language); + const [version, setVersion] = useState(() => localStorage.getItem(LOCAL_STORAGE_VERSION_KEY) as LanguageVersion || DEFAULT_VERSION); + + useEffect(() => { + localStorage.setItem(LOCAL_STORAGE_LANGUAGE_KEY, language); + }, [language]); + + useEffect(() => { + localStorage.setItem(LOCAL_STORAGE_VERSION_KEY, version); + }, [version]); + + return( + + {children} + + ) +} diff --git a/src/contexts/VersionFromUrlContext.tsx b/src/contexts/VersionFromUrlContext.tsx new file mode 100644 index 000000000..6ca569480 --- /dev/null +++ b/src/contexts/VersionFromUrlContext.tsx @@ -0,0 +1,43 @@ +import React, { createContext, useEffect, useState, ReactNode } from "react"; +import { + LOCAL_STORAGE_LANGUAGE_KEY, + LOCAL_STORAGE_VERSION_KEY, +} from "@components/version-language-switcher/version-language-constants.ts"; +import { DEFAULT_VERSION } from "../global-constants"; + +interface VersionFromUrlContextProps { + version: string | null; +} + +const VersionFromUrlContext = createContext({ version: null }); + +interface VersionProviderProps { + children: ReactNode; +} + +export const VersionFromUrlProvider: React.FC = ({ children }) => { + const [versionFromPath, setVersionFromPath] = useState(null); + + useEffect(() => { + const updateVersion = () => { + const pathSegments = window.location.pathname.split("/"); + const versionSegment = pathSegments.find(segment => segment.startsWith("v")); + if (versionSegment) { + setVersionFromPath(versionSegment); + localStorage.setItem(LOCAL_STORAGE_LANGUAGE_KEY, versionSegment.includes("angular") ? "angular" : "react"); + } else { + setVersionFromPath(null); + localStorage.setItem(LOCAL_STORAGE_VERSION_KEY, DEFAULT_VERSION); + } + }; + + updateVersion(); + + window.addEventListener("popstate", updateVersion); + + return () => { + window.removeEventListener("popstate", updateVersion); + }; + }, []); + return {children}; +}; diff --git a/src/examples/accordion/AccordionExamples.tsx b/src/examples/accordion/AccordionExamples.tsx index 236deb702..29b35537a 100644 --- a/src/examples/accordion/AccordionExamples.tsx +++ b/src/examples/accordion/AccordionExamples.tsx @@ -1,252 +1,16 @@ -import { GoAAccordion, GoABadge, GoAButton } from "@abgov/react-components"; -import { Sandbox } from "@components/sandbox"; import "./accordion-example.css"; -import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; -import { useState } from "react"; +import { AccordionExpandOrCollapseExample } from "@examples/accordion/AccordionExpandOrCollapseExample.tsx"; +import { AccordionHideOrShowSectionExample } from "@examples/accordion/AccordionHideOrShowSectionExample.tsx"; export default function AccordionExamples() { - const [open, setOpen] = useState(false); // for accordion group - const [accordionStatus, setAccordionStatus] = useState("Show all sections"); - const onClick = () => { - setOpen(!open); - const status = !open ? "Hide all sections" : "Show all sections"; - setAccordionStatus(status); - } return ( <>

Expand or collapse part of a form

- - - {/*Angular*/} - Review your application - - -
-
Date of referral
-
January 27, 2021
-
Work safety concerns
-
None
-
Type of referral
-
Word of mouth, internet search
-
Intake received from another site
-
Yes
-
-
- - -
-
Name
-
Joan Smith
-
Contact preference
-
Text message
-
-
- `} - /> - {/*React*/} - ; - `} - /> - Review your application - - -
-
Date of referral
-
January 27, 2021
-
Work safety concerns
-
None
-
Type of referral
-
Word of mouth, internet search
-
Intake received from another site
-
Yes
-
-
- - -
-
Name
-
Joan Smith
-
Contact preference
-
Text message
-
-
- `} - /> - -

Review your application

- }> -
-
Date of referral
-
January 27, 2021
-
Work safety concerns
-
None
-
Type of referral
-
Word of mouth, internet search
-
Intake received from another site
-
Yes
-
-
- - -
-
Name
-
Joan Smith
-
Contact preference
-
Text message
-
-
-
+

Hide and show many sections of information (FAQ)

- - {/*Angular*/} - - - {{ accordionStatus }} - - - - To create an account you will need to contact your office admin. - - - - You will need to verify your identity through our two factor authentication in addition to the digital signature. - - - - Yes, you can see the status of your application on the main service dashboard when you login. You will receive updates and notifications in your email as your request progresses. - - - - Yes, our digital service is designed with accessibility in mind. More information on accessibility. - - `} - /> - {/*React*/} - (false); - const [accordionStatus, setAccordionStatus] = useState("Show all sections"); - const onClick = () => { - setOpen(!open); - const status = !open ? "Hide all sections" : "Show all sections"; - setAccordionStatus(status); - } - `} - /> - onClick()}> - { accordionStatus } - - - - To create an account you will need to contact your office admin. - - - - You will need to verify your identity through our two factor authentication in addition to the digital signature. - - - - Yes, you can see the status of your application on the main service dashboard when you login. You will receive updates and notifications in your email as your request progresses. - - - - Yes, our digital service is designed with accessibility in mind. More information on accessibility. - - `} - /> - - onClick()}> - { accordionStatus } - - - - To create an account you will need to contact your office admin. - - - - You will need to verify your identity through our two factor authentication in addition to - the digital signature. - - - - Yes, you can see the status of your application on the main service dashboard when you - login. You will receive updates and notifications in your email as your request - progresses. - - - - Yes, our digital service is designed with accessibility in mind. More information on accessibility. - - + ); } diff --git a/src/examples/accordion/AccordionExpandOrCollapseExample.tsx b/src/examples/accordion/AccordionExpandOrCollapseExample.tsx new file mode 100644 index 000000000..d0cfc96c7 --- /dev/null +++ b/src/examples/accordion/AccordionExpandOrCollapseExample.tsx @@ -0,0 +1,206 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabAccordion, GoabBadge } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const AccordionExpandOrCollapseExample = () => { + const {version} = useContext(LanguageVersionContext); + return ( + + + + {/*Angular*/} + {version === "old" && Review your application + + +
+
Date of referral
+
January 27, 2021
+
Work safety concerns
+
None
+
Type of referral
+
Word of mouth, internet search
+
Intake received from another site
+
Yes
+
+
+ + +
+
Name
+
Joan Smith
+
Contact preference
+
Text message
+
+
+ `} + />} + + {version === "new" && Review your application + + + + +
+
Date of referral
+
January 27, 2021
+
Work safety concerns
+
None
+
Type of referral
+
Word of mouth, internet search
+
Intake received from another site
+
Yes
+
+
+ + +
+
Name
+
Joan Smith
+
Contact preference
+
Text message
+
+
+ `} + />} + + {/*React*/} + {version === "old" && ; + `} + />} + + {version === "new" && ; + `} + />} + + {version === "old" && Review your application + + +
+
Date of referral
+
January 27, 2021
+
Work safety concerns
+
None
+
Type of referral
+
Word of mouth, internet search
+
Intake received from another site
+
Yes
+
+
+ + +
+
Name
+
Joan Smith
+
Contact preference
+
Text message
+
+
+ `} + />} + + {version === "new" && Review your application + + +
+
Date of referral
+
January 27, 2021
+
Work safety concerns
+
None
+
Type of referral
+
Word of mouth, internet search
+
Intake received from another site
+
Yes
+
+
+ + +
+
Name
+
Joan Smith
+
Contact preference
+
Text message
+
+
+ `} + />} + +

Review your application

+ }> +
+
Date of referral
+
January 27, 2021
+
Work safety concerns
+
None
+
Type of referral
+
Word of mouth, internet search
+
Intake received from another site
+
Yes
+
+
+ + +
+
Name
+
Joan Smith
+
Contact preference
+
Text message
+
+
+
+ ) +} diff --git a/src/examples/accordion/AccordionHideOrShowSectionExample.tsx b/src/examples/accordion/AccordionHideOrShowSectionExample.tsx new file mode 100644 index 000000000..c81a09c91 --- /dev/null +++ b/src/examples/accordion/AccordionHideOrShowSectionExample.tsx @@ -0,0 +1,264 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabAccordion, GoabButton } from "@abgov/react-components"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { useContext, useEffect, useState } from "react"; + +export const AccordionHideOrShowSectionExample = () => { + const {version} = useContext(LanguageVersionContext); + const [expandedAll, setExpandedAll] = useState(false); + const [expandedList, setExpandedList] = useState([]); + + useEffect(() => { + setExpandedAll(expandedList.length === 4); + }, [expandedList.length]); + + const expandOrCollapseAll = () => { + setExpandedAll((prev) => { + const newState = !prev; + setExpandedList(newState ? [1, 2, 3, 4] : []); + return newState; + }); + }; + + const updateAccordion = (order: number, isOpen: boolean) => { + setExpandedList((prev) => { + if (isOpen) { + return prev.includes(order) ? prev: [...prev, order]; + } + return prev.filter((item) => item !== order); + }); + } + return ( + + {/*Angular*/} + {version === "old" && !isOpen) + this.expandedList = this.expandedList.map(() => isExpanding); + this.updateAccordionStatus(); + } + + private updateAccordionStatus(): void { + this.expandedAll = this.expandedList.every(isOpen => isOpen); + this.accordionStatus = this.expandedList.every(isOpen => isOpen) ? "Hide all sections" : "Show all sections"; + } + } + `} + />} + + {version === "old" && + {{ accordionStatus }} + + + + To create an account, you will need to contact your office admin. + + + + You will need to verify your identity through our two-factor authentication in addition to the digital signature. + + + + Yes, you can see the status of your application on the main service dashboard when you log in. You will receive updates and notifications in your email as your request progresses. + + + + Yes, our digital service is designed with accessibility in mind. More information on accessibility. + + `} + />} + + {version === "new" && !isOpen) + this.expandedList = this.expandedList.map(() => isExpanding); + this.updateAccordionStatus(); + } + + private updateAccordionStatus(): void { + this.expandedAll = this.expandedList.every(isOpen => isOpen); + this.accordionStatus = this.expandedList.every(isOpen => isOpen) ? "Hide all sections" : "Show all sections"; + } + } + `} + />} + + {version === "new" && + {{ accordionStatus }} + + + + To create an account you will need to contact your office admin. + + + + You will need to verify your identity through our two factor authentication in addition to the digital signature. + + + + Yes, you can see the status of your application on the main service dashboard when you login. You will receive updates and notifications in your email as your request progresses. + + + + Yes, our digital service is designed with accessibility in mind. More information on accessibility. + + `} + />} + + {/*React*/} + (false); + const [expandedList, setExpandedList] = useState([]); + useEffect(() => { + setExpandedAll(expandedList.length === 4); + }, [expandedList.length]); + + const expandOrCollapseAll = () => { + setExpandedAll((prev) => { + const newState = !prev; + setExpandedList(newState ? [1, 2, 3, 4] : []); + return newState; + }); + }; + + const updateAccordion = (order: number, isOpen: boolean) => { + setExpandedList((prev) => { + if (isOpen) { + return prev.includes(order) ? prev: [...prev, order]; + } + return prev.filter((item) => item !== order); + }); + } + `} + /> + + {version === "old" && expandOrCollapseAll()}> + {expandedAll ? "Hide all sections" : "Show all sections"} + + + updateAccordion(1, open)}> + To create an account you will need to contact your office admin. + + + updateAccordion(2, open)}> + You will need to verify your identity through our two factor authentication in addition to the digital signature. + + + updateAccordion(3, open)}> + Yes, you can see the status of your application on the main service dashboard when you login. You will receive updates and notifications in your email as your request progresses. + + + updateAccordion(4, open)}> + Yes, our digital service is designed with accessibility in mind. More information on accessibility. + + `} + />} + + {version === "new" && expandOrCollapseAll()}> + {expandedAll ? "Hide all sections" : "Show all sections"} + + + updateAccordion(1, open)}> + To create an account you will need to contact your office admin. + + + updateAccordion(2, open)}> + You will need to verify your identity through our two factor authentication in addition to the digital signature. + + + updateAccordion(3, open)}> + Yes, you can see the status of your application on the main service dashboard when you login. You will receive updates and notifications in your email as your request progresses. + + + updateAccordion(4, open)}> + Yes, our digital service is designed with accessibility in mind. More information on accessibility. + + `} + />} + + expandOrCollapseAll()}> + {expandedAll ? "Hide all sections" : "Show all sections"} + + + updateAccordion(1, open)}> + To create an account you will need to contact your office admin. + + + updateAccordion(2, open)}> + You will need to verify your identity through our two factor authentication in addition to + the digital signature. + + + updateAccordion(3, open)}> + Yes, you can see the status of your application on the main service dashboard when you + login. You will receive updates and notifications in your email as your request + progresses. + + + updateAccordion(4, open)}> + Yes, our digital service is designed with accessibility in mind. More information on accessibility. + + + ) +} diff --git a/src/examples/app-footer/AppFooterExamples.tsx b/src/examples/app-footer/AppFooterExamples.tsx new file mode 100644 index 000000000..8f6e5eee3 --- /dev/null +++ b/src/examples/app-footer/AppFooterExamples.tsx @@ -0,0 +1,19 @@ +import { AppFooterShowQuickLinkExample } from "@examples/app-footer/AppFooterShowQuickLinkExample.tsx"; +import { AppFooterShowNavigationItemsExample } from "@examples/app-footer/AppFooterShowNavigationItemsExample.tsx"; + +export const AppFooterExamples = () => { + return ( + <> + + + + + + + + ) +} diff --git a/src/examples/app-footer/AppFooterShowNavigationItemsExample.tsx b/src/examples/app-footer/AppFooterShowNavigationItemsExample.tsx new file mode 100644 index 000000000..6e37da23a --- /dev/null +++ b/src/examples/app-footer/AppFooterShowNavigationItemsExample.tsx @@ -0,0 +1,203 @@ +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { + GoabAppFooter, + GoabAppFooterMetaSection, + GoabAppFooterNavSection, GoabAppFooterProps, + GoabFooterNavSectionProps +} from "@abgov/react-components"; +import { ComponentBinding, Sandbox } from "@components/sandbox"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { propsToString } from "@components/sandbox/BaseSerializer.ts"; + +type FooterNavPropsType = GoabFooterNavSectionProps; +type FooterPropsType = GoabAppFooterProps; +type CastingType = { + // add any required props here + [key: string]: unknown; +}; + +export const AppFooterShowNavigationItemsExample = () => { + const {version} = useContext(LanguageVersionContext); + + const [appFooterNavBindings, setAppFooterNavBindings] = useState([ + { + label: "Max content width", + type: "string", + name: "maxContentWidth", + value: "100%", + }, + { + label: "Max footer nav columns", + type: "number", + name: "maxColumnCount", + value: 1, + }, + { + label: "Heading", + type: "string", + name: "heading", + value: "", + }, + ]); + const [footerNavSectionProps, setFooterNavSectionProps] = useState({ + maxColumnCount: 1, + heading: "", + }); + const [footerProps, setFooterProps] = useState({ + maxContentWidth: "100%" + }); + + function onSandbox2Change(bindings: ComponentBinding[], props: Record) { + const footerProps = { maxContentWidth: props.maxContentWidth }; + const footerNavSectionProps = { + heading: props.heading || "", + maxColumnCount: props.maxColumnCount || 1 + }; + + setFooterProps(footerProps as CastingType); + setFooterNavSectionProps(footerNavSectionProps as CastingType); + setAppFooterNavBindings(bindings); + } + + return ( + + {version === "old" && , "angular", "old")}> + , "angular", "old")}> + + Arts and culture + + + Education and training + + + Family and social supports + + + Housing and community + + + Life events + + + Business and economy + + + Emergencies and public safety + + + Government + + + Jobs and employment + + + Moving to Alberta + + + + + Privacy + + + Disclaimer + + + Accessibility + + + Using Alberta.ca + + + + `} + />} + + {version === "new" && , "angular", "new")}> + , "angular", "new")}> + + Arts and culture + + + Education and training + + + Family and social supports + + + Housing and community + + + Life events + + + Business and economy + + + Emergencies and public safety + + + Government + + + Jobs and employment + + + Moving to Alberta + + + + + Privacy + + + Disclaimer + + + Accessibility + + + Using Alberta.ca + + + + `} + />} + + + + Arts and culture + Education and training + Family and social supports + Housing and community + Life events + Business and economy + Emergencies and public safety + Government + Jobs and employment + Moving to Alberta + + + Privacy + Disclaimer + Accessibility + Using Alberta.ca + + + + ) +} diff --git a/src/examples/app-footer/AppFooterShowQuickLinkExample.tsx b/src/examples/app-footer/AppFooterShowQuickLinkExample.tsx new file mode 100644 index 000000000..a6b131f00 --- /dev/null +++ b/src/examples/app-footer/AppFooterShowQuickLinkExample.tsx @@ -0,0 +1,120 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabAppFooter, GoabAppFooterMetaSection } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const AppFooterShowQuickLinkExample = () => { + const {version} = useContext(LanguageVersionContext); + return ( + + {/*********** Angular code **************/} + {version === "old" && + + + Privacy + + + Disclaimer + + + Accessibility + + + Using Alberta.ca + + + + `} + />} + + {version === "new" && + + + Privacy + + + Disclaimer + + + Accessibility + + + Using Alberta.ca + + + + `} + />} + + {/*********** React code **************/} + + {version === "old" && + + + Privacy + + + Disclaimer + + + Accessibility + + + Using Alberta.ca + + + + `} + />} + + {version === "new" && + + + Privacy + + + Disclaimer + + + Accessibility + + + Using Alberta.ca + + + + `} + />} + + + + Privacy + Disclaimer + Accessibility + Using Alberta.ca + + + + ) +} diff --git a/src/examples/app-header/AppHeaderExamples.tsx b/src/examples/app-header/AppHeaderExamples.tsx new file mode 100644 index 000000000..8ecccb849 --- /dev/null +++ b/src/examples/app-header/AppHeaderExamples.tsx @@ -0,0 +1,18 @@ +import { AppHeaderWithNavigationExample } from "@examples/app-header/AppHeaderWithNavigationExample.tsx"; +import { AppHeaderWithMenuClickEventExample } from "@examples/app-header/AppHeaderWithMenuClickEventExample.tsx"; + +export const AppHeaderExamples = () => { + return ( + <> + + +

Header with navigation

+ + +

Header with menu click event

+ + + ); +}; diff --git a/src/examples/app-header/AppHeaderWithMenuClickEventExample.tsx b/src/examples/app-header/AppHeaderWithMenuClickEventExample.tsx new file mode 100644 index 000000000..cbafb55e5 --- /dev/null +++ b/src/examples/app-header/AppHeaderWithMenuClickEventExample.tsx @@ -0,0 +1,205 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabAppHeader, GoabAppHeaderMenu, GoabRadioGroup, GoabRadioItem } from "@abgov/react-components"; +import { GoabRadioGroupOnChangeDetail } from "@abgov/ui-components-common"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const AppHeaderWithMenuClickEventExample = () => { + const {version} = useContext(LanguageVersionContext); + const [deviceWidth, setDeviceWidth] = useState("5000"); + function handleMenuClick() { + alert("Menu not being displayed and you can do anything"); + } + return ( + + setDeviceWidth(event.value)}> + + + + + Support + + Cases + Payments + Outstanding + + + Sign in + + + + {/*Angular code*/} + {version === "old" && ( + + )} + + {version === "new" && ( + + )} + + {version === "old" && ( + + + + + + + Support + + Cases + Payments + Outstanding + + Sign in + + `} + /> + )} + + {version === "new" && ( + + + + + + + Support + + Cases + Payments + Outstanding + + Sign in + + `} + /> + )} + + {/*React code*/} + + + {version === "old" && ( + setDeviceWidth(value)}> + + + + + + Support + + Cases + Payments + Outstanding + + Sign in + + `} + /> + )} + {version === "new" && ( + setDeviceWidth(event.value)}> + + + + + + Support + + Cases + Payments + Outstanding + + Sign in + + `} + /> + )} + + ) +} diff --git a/src/examples/app-header/AppHeaderWithNavigationExample.tsx b/src/examples/app-header/AppHeaderWithNavigationExample.tsx new file mode 100644 index 000000000..43c1380dd --- /dev/null +++ b/src/examples/app-header/AppHeaderWithNavigationExample.tsx @@ -0,0 +1,101 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabAppHeader, GoabAppHeaderMenu } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const AppHeaderWithNavigationExample = () => { + const {version} = useContext(LanguageVersionContext); + + return ( + + {/*Angular code*/} + {version === "old" && ( + + + Support + + Cases + Payments + Outstanding + + Sign in + + `} + /> + )} + {version === "new" && ( + + + Support + + Cases + Payments + Outstanding + + Sign in + + `} + /> + )} + + {/*React code*/} + {version === "old" && ( + + Support + + Cases + Payments + Outstanding + + Sign in + + `} + /> + )} + {version === "new" && ( + + Support + + Cases + Payments + Outstanding + + Sign in + + `} + /> + )} + + + Support + + Cases + Payments + Outstanding + + Sign in + + + ) +} diff --git a/src/examples/badge/BadgeExamples.tsx b/src/examples/badge/BadgeExamples.tsx index b886c0f92..a98d74e68 100644 --- a/src/examples/badge/BadgeExamples.tsx +++ b/src/examples/badge/BadgeExamples.tsx @@ -1,281 +1,32 @@ -import { GoABadge, GoABadgeType, GoABlock, GoAContainer, GoAButton, GoATable } from "@abgov/react-components"; -import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { + GoabBadge, + GoabBlock, +} from "@abgov/react-components"; import { Sandbox } from "@components/sandbox"; - -const noop = () => {}; -const badgeValues = [ - { - key: 1, - type: "important", - content: "Pending" - }, - { - key: 2, - type: "emergency", - content: "Failed" - }, - { - key: 3, - type: "success", - content: "Complete" - }, - { - key: 4, - type: "information", - content: "In progress" - }, - { - key: 5, - type: "midtone", - content: "Closed" - }, - { - key: 6, - type: "success", - content: "Complete" - } -] - -export default function CheckboxExamples () { - return ( - <> - {/* Examples*/} - - -

Show status in a table

- - - - - - - Status - Name - File number - - - - - - - - - - Lorem ipsum dolor sit amet consectetur. - 1234567890 - - Assign - - - - - `} - /> - - - - - - - Status - Name - File number - - - - - {badgeValues.map((badge) => ( - - - - - - Lorem ipsum dolor sit amet consectetur - - - 1234567890 - - - - Assign - - - - ))} - - - `} - /> - - - - Status - Name - File number - - - - - {badgeValues.map((badge) => ( - - - - - - Lorem ipsum dolor sit amet consectetur - - - 1234567890 - - - - Assign - - - - ))} - - - - -

Show multiple tags together

- - - - - - - - -

Show a status on a card

- - - -
Heading
-
- -
- Content - - `} - /> - - }> - Content - - `} - /> - - }> - Content - -
- - ) -} \ No newline at end of file +import { BadgeShowStatusInTableExample } from "@examples/badge/BadgeShowStatusInTableExample.tsx"; +import { BadgeShowStatusOnCardExample } from "@examples/badge/BadgeShowStatusOnCardExample.tsx"; + +export default function BadgeExamples() { + return ( + <> + + +

Show status in a table

+ + +

Show multiple tags together

+ + + + + + + + +

Show a status on a card

+ + + ); +} diff --git a/src/examples/badge/BadgeShowStatusInTableExample.tsx b/src/examples/badge/BadgeShowStatusInTableExample.tsx new file mode 100644 index 000000000..dedd06e77 --- /dev/null +++ b/src/examples/badge/BadgeShowStatusInTableExample.tsx @@ -0,0 +1,330 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabBadge, GoabButton, GoabTable } from "@abgov/react-components"; +import { GoabBadgeType } from "@abgov/ui-components-common"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { useContext } from "react"; + +export const BadgeShowStatusInTableExample = () => { + const noop = () => {}; + const {version} = useContext(LanguageVersionContext); + const badgeValues = [ + { + key: 1, + type: "important", + content: "Pending", + }, + { + key: 2, + type: "emergency", + content: "Failed", + }, + { + key: 3, + type: "success", + content: "Complete", + }, + { + key: 4, + type: "information", + content: "In progress", + }, + { + key: 5, + type: "midtone", + content: "Closed", + }, + { + key: 6, + type: "success", + content: "Complete", + }, + ]; + return ( + + {/*Angular code*/} + {version === "old" && } + {version === "new" && } + + {version === "old" && + + + Status + Name + File number + + + + + + + + + + Lorem ipsum dolor sit amet consectetur. + 1234567890 + + Assign + + + + + `} + />} + {version === "new" && + + + Status + Name + File number + + + + + + + + + + Lorem ipsum dolor sit amet consectetur. + 1234567890 + + Assign + + + + + `} + />} + + {/*React code*/} + + + {version === "old" && + + + Status + Name + File number + + + + + {badgeValues.map((badge) => ( + + + + + + Lorem ipsum dolor sit amet consectetur + + + 1234567890 + + + + Assign + + + + ))} + + + `} + />} + {version === "new" && + + + Status + Name + File number + + + + + {badgeValues.map((badge) => ( + + + + + + Lorem ipsum dolor sit amet consectetur + + + 1234567890 + + + + Assign + + + + ))} + + + `} + />} + + + + + Status + Name + File number + + + + + {badgeValues.map(badge => ( + + + + + Lorem ipsum dolor sit amet consectetur + 1234567890 + + + Assign + + + + ))} + + + + ) +} diff --git a/src/examples/badge/BadgeShowStatusOnCardExample.tsx b/src/examples/badge/BadgeShowStatusOnCardExample.tsx new file mode 100644 index 000000000..66ff7288a --- /dev/null +++ b/src/examples/badge/BadgeShowStatusOnCardExample.tsx @@ -0,0 +1,80 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabBadge, GoabContainer } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const BadgeShowStatusOnCardExample = () => { + const {version} = useContext(LanguageVersionContext); + return ( + + {/*Angular code*/} + {version === "old" && +
Heading
+
+ +
+ Content + + `} + />} + {version === "new" && + Heading + + + + Content + + `} + />} + + {/*React code*/} + {version === "old" && }> + Content + + `} + />} + {version === "new" && }> + Content + + `} + />} + + }> + Content + +
+ ) +} diff --git a/src/examples/button/ButtonAskUserAddressExample.tsx b/src/examples/button/ButtonAskUserAddressExample.tsx new file mode 100644 index 000000000..89c557280 --- /dev/null +++ b/src/examples/button/ButtonAskUserAddressExample.tsx @@ -0,0 +1,141 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { + GoabBlock, + GoabButton, + GoabButtonGroup, + GoabDropdown, + GoabDropdownItem, + GoabFormItem, + GoabInput, +} from "@abgov/react-components"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { useContext } from "react"; + +export const ButtonAskUserAddressExample = () => { + const {version} = useContext(LanguageVersionContext); + const noop = () => {} + return ( + + {/*Reactive FormControl Angular Code Snippet*/} + {version === "new" && } + + + + {/*Template driven Angular Code Snippet*/} + + + {version === "new" && } + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + Submit and continue + + + Cancel + + +
+ ); +}; diff --git a/src/examples/button/ButtonConfirmDestructiveActionExample.tsx b/src/examples/button/ButtonConfirmDestructiveActionExample.tsx new file mode 100644 index 000000000..8446c5204 --- /dev/null +++ b/src/examples/button/ButtonConfirmDestructiveActionExample.tsx @@ -0,0 +1,7 @@ +import { ModalConfirmDestructiveActionExample } from "@examples/modal/ModalConfirmDestructiveActionExample.tsx"; + +export const ButtonConfirmDestructiveActionExample = () => { + return ( + + ); +}; diff --git a/src/examples/button/ButtonDisabledWithRequiredFieldExample.tsx b/src/examples/button/ButtonDisabledWithRequiredFieldExample.tsx new file mode 100644 index 000000000..f0b2f0411 --- /dev/null +++ b/src/examples/button/ButtonDisabledWithRequiredFieldExample.tsx @@ -0,0 +1,105 @@ +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { Sandbox } from "@components/sandbox"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { GoabButtonGroup, GoabButton, GoabFormItem, GoabInput } from "@abgov/react-components"; + + +export const ButtonDisabledWithRequiredFieldExample = () => { + const { version } = useContext(LanguageVersionContext); + const noop = () => {} + return ( + + {/*Reactive FormControl Angular Code Snippet*/} + + {version === "new" && } + {version === "new" && } + + {/*Template driven Angular Code Snippet*/} + + + {/*React*/} + {version === "new" && } + {version === "old" && } + +
+ + + + + + + Confirm + + + Cancel + + +
+
+); +}; diff --git a/src/examples/button/ButtonExamples.tsx b/src/examples/button/ButtonExamples.tsx new file mode 100644 index 000000000..1b04bbc12 --- /dev/null +++ b/src/examples/button/ButtonExamples.tsx @@ -0,0 +1,21 @@ +import { ButtonAskUserAddressExample } from "@examples/button/ButtonAskUserAddressExample.tsx"; +import { ButtonConfirmDestructiveActionExample } from "@examples/button/ButtonConfirmDestructiveActionExample.tsx"; +import { ButtonDisabledWithRequiredFieldExample } from "@examples/button/ButtonDisabledWithRequiredFieldExample.tsx"; + +export const ButtonExamples = () => { + + return <> + + {/*Button Example 1*/} +

Ask a user for an address

+ + + {/*Button example 2*/} +

Confirm a destructive action

+ + + {/*Button example */} +

Disabled button with a required field

+ + ; +}; diff --git a/src/examples/callout/CalloutExamples.tsx b/src/examples/callout/CalloutExamples.tsx new file mode 100644 index 000000000..c4ae797bb --- /dev/null +++ b/src/examples/callout/CalloutExamples.tsx @@ -0,0 +1,142 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabButton, GoabButtonGroup, GoabCallout, GoabSpacer } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const CalloutExamples = () => { + const {version} = useContext(LanguageVersionContext); + return ( + <> +

Confirm that an application was submitted

+ + {/*Angular code*/} + {version === "old" && You have completed the application + + + Your application was successful +

You will receive a copy of the confirmation to the email person@email.com

+

Confirmation number: 1234ABC

+
+ +

Go back to the dashboard, or direct your user somewhere else useful.

+

+ Other information about what was just completed, other tertiary information, and/or contact information. + Phone: 780 123 4567 + Email: information@gov.ab.ca +

+ + + Go to application + Back to dashboard + + `} + />} + + {version === "new" && You have completed the application + + +

You will receive a copy of the confirmation to the email person@email.com

+

Confirmation number: 1234ABC

+
+ +

Go back to the dashboard, or direct your user somewhere else useful.

+

Other information about what was just completed, other tertiary information, and/or contact information. +
+ Phone: 780 123 4567 +
+ Email: information@gov.ab.ca +

+ + + Go to application + Back to dashboard + + `} + />} + + {/*React code*/} + {version === "old" && You have completed the application + + +

You will receive a copy of the confirmation to the email person@email.com

+

Confirmation number: 1234ABC

+
+ +

Go back to the dashboard, or direct your user somewhere else useful.

+

+ Other information about what was just completed, other tertiary information, and/or contact information. + Phone: 780 123 4567 + Email: information@gov.ab.ca +

+ + + Go to application + Back to dashboard + + `} + />} + + {version === "new" && You have completed the application + + +

You will receive a copy of the confirmation to the email person@email.com

+

Confirmation number: 1234ABC

+
+ +

Go back to the dashboard, or direct your user somewhere else useful.

+

+ Other information about what was just completed, other tertiary information, and/or contact information. +
+ Phone: 780 123 4567 +
+ Email: information@gov.ab.ca +

+ + + Go to application + Back to dashboard + + `} + />} + +

You have completed the application

+ +

You will receive a copy of the confirmation to the email person@email.com

+

Confirmation number: 1234ABC

+
+

Go back to the dashboard, or direct your user somewhere else useful.

+

+ Other information about what was just completed, other tertiary information, and/or contact information.
+ Phone: 780 123 4567
+ Email: information@gov.ab.ca +

+ + + Go to application + Back to dashboard + +
+ + ) +} diff --git a/src/examples/checkbox/CheckboxExamples.tsx b/src/examples/checkbox/CheckboxExamples.tsx index abb5203db..7b4f1f317 100644 --- a/src/examples/checkbox/CheckboxExamples.tsx +++ b/src/examples/checkbox/CheckboxExamples.tsx @@ -1,15 +1,19 @@ -import { GoACheckbox, GoAFormItem } from "@abgov/react-components"; +import { GoabCheckbox, GoabFormItem } from "@abgov/react-components"; import { Sandbox } from "@components/sandbox"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; export default function CheckboxExamples () { + const {version} = useContext(LanguageVersionContext); return ( <>

Use tags in the description

{/*Angular*/} - `} - /> + />} + + {version === "new" && + + + Help text with a link. + + + + +
+ `} + />} + {/*React*/} - `} - /> - - } + + {version === "new" && + Help text with a link.} + /> + + + + `} + />} + + + Help text with a link.} /> - - - + + + ); -} \ No newline at end of file +} diff --git a/src/examples/container/ContainerCardGridExample.tsx b/src/examples/container/ContainerCardGridExample.tsx new file mode 100644 index 000000000..ec7b8cd78 --- /dev/null +++ b/src/examples/container/ContainerCardGridExample.tsx @@ -0,0 +1,87 @@ +import "./container-card-grid-example.css"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabContainer, GoabGrid } from "@abgov/react-components"; +import { Sandbox } from "@components/sandbox"; + +export const ContainerCardGridExample = () => { + return ( + + + + + + + Waitlist submission + +
+ Enter and maintain information about the households waiting for affordable housing + with your organization. +
+
+ + + + Lodge assistance program + +
+ Keep track of the individuals who are placed in lodges and may qualify for the Lodge + Assistance Program subsidy. +
+
+ + + Education Support +
+ Explore educational resources, enroll in courses, and track your academic progress + effortlessly. +
+
+ + + + Social Assistance + +
+ Learn about available support programs, apply for financial aid, and access community + resources. +
+
+ + + + Employment Opportunity + +
+ Search for job openings, access career development tools, and receive + employment-related updates. +
+
+ + + + Housing Assistance + +
+ Find affordable housing options, apply for housing subsidies, and report maintenance + issues seamlessly. +
+
+
+
+ ) +} diff --git a/src/examples/container/ContainerCaseFilesExample.tsx b/src/examples/container/ContainerCaseFilesExample.tsx new file mode 100644 index 000000000..977da0199 --- /dev/null +++ b/src/examples/container/ContainerCaseFilesExample.tsx @@ -0,0 +1,95 @@ +import "./container-case-files-example.css"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabBadge, GoabBlock, GoabButton, GoabContainer } from "@abgov/react-components"; +import { Sandbox } from "@components/sandbox"; + +export const ContainerCaseFilesExample = () => { + return ( + + + + +
+ + Fiscal year: 2021/2022 + Submitted: April 23, 2023 + +
+ + + + Edit + + +
+
+
+ + +
+ + Fiscal year: 2020/2021 + Submitted: April 9, 2022 + +
+ + + + View + + +
+
+
+ + +
+ + Fiscal year: 2019/2020 + Submitted: April 14, 2021 + +
+ + + + View + + +
+
+
+
+ ) +} diff --git a/src/examples/container/ContainerExamples.tsx b/src/examples/container/ContainerExamples.tsx index 4a31e438e..2024aa90b 100644 --- a/src/examples/container/ContainerExamples.tsx +++ b/src/examples/container/ContainerExamples.tsx @@ -1,501 +1,26 @@ -import { - GoABadge, - GoABlock, - GoAButton, - GoAContainer, GoADropdown, GoADropdownItem, GoAFormItem, - GoAGrid, GoARadioGroup, GoARadioItem, - GoATable, GoATextArea -} from "@abgov/react-components"; -import { Sandbox } from "@components/sandbox"; -import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; -import "./container-example.css"; +import { ContainerUserInformationExample } from "@examples/container/ContainerUserInformationExample.tsx"; +import { ContainerCaseFilesExample } from "@examples/container/ContainerCaseFilesExample.tsx"; +import { ContainerCardGridExample } from "@examples/container/ContainerCardGridExample.tsx"; +import { ContainerReviewActionExample } from "@examples/container/ContainerReviewActionExample.tsx"; export default function ContainerExamples() { return ( <> {/*Container examples*/} - +

User information

- - {/*CSS Code Snippet*/} - - - {/*Angular Code Snippet*/} - - Housing Advisor -

Tracy Hero

- - - Email - Phone - - - - tracyhero@email.com - 283-203-4921 - - -
- - - -
Upcoming important due dates
-
- - Add to calendar - -
- -
- - - - Business plan submission - June 30, 2024 - - - Annual review - October 3, 2024 - - - Application submission - December 20, 2024 - - - Application review - January 3, 2025 - - - -
-
- `} - /> - - {/*React*/} - {}}> - Add to calendar - ); - `} - /> - - - Housing Advisor -

Tracy Hero

- - - Email - Phone - - - - tracyhero@email.com - 283-203-4921 - - - - - -
- - - - Business plan submission - June 30, 2024 - - - Annual review - October 3, 2024 - - - Application submission - December 20, 2024 - - - Application review - January 3, 2025 - - - -
-
- `} - /> - - {/*Code Block*/} - - Housing Advisor -

Tracy Hero

- - - Email - Phone - - - - tracyhero@email.com - 283-203-4921 - - -
- - {}}> - Add to calendar - - }> -
- - - - Business plan submission - June 30, 2024 - - - Annual review - October 3, 2024 - - - Application submission - December 20, 2024 - - - Application review - January 3, 2025 - - - -
-
- +

Card view of case files

- - - - -
- - Fiscal year: 2021/2022 - Submitted: April 23, 2023 - -
- - - - Edit - - -
-
-
- - -
- - Fiscal year: 2020/2021 - Submitted: April 9, 2022 - -
- - - - View - - -
-
-
- - -
- - Fiscal year: 2019/2020 - Submitted: April 14, 2021 - -
- - - - View - - -
-
-
-
+

Card grid that links to different sections

- - - - - - Waitlist submission -
- Enter and maintain information about the households waiting for affordable housing - with your organization. -
-
- - - Lodge assistance program -
- Keep track of the individuals who are placed in lodges and may qualify for the Lodge - Assistance Program subsidy. -
-
- - - Education Support -
- Explore educational resources, enroll in courses, and track your academic progress - effortlessly. -
-
- - - Social Assistance -
- Learn about available support programs, apply for financial aid, and access community - resources. -
-
- - - Employment Opportunity -
- Search for job openings, access career development tools, and receive - employment-related updates. -
-
- - - Housing Assistance -
- Find affordable housing options, apply for housing subsidies, and report maintenance - issues seamlessly. -
-
-
-
+

Review and action

- - - - - - -

Appearance details

- - - - Doe, John Scott - - - - - Mar 14, 2021 - - - - - Calgary - - - - - Sep 20, 2021 - - - -
Docket number(s) $ charges
- -
1) 12345678
-

CC 334(1) - Theft under $5000

-

CC 268(1) - Aggravated assult

-
- - -
2) 12345678
-

CC 334(1) - Theft under $5000

-

CC 268(1) - Aggravated assult

-
- - -
3) 12345678
-

- CC 334(1) - Theft under $5000 -

-

- CC 268(1) - Aggravated assult -

-
-
- -

Adjournment request

-

Keep track of the individuals who are placed in lodges and may qualify for the Lodge Assistance Program subsidy.

- - - {}}> - - - - - - - {}}> - - - - - - - - {}}/> - - - {}}>Confirm -
-
-
+ ); } diff --git a/src/examples/container/ContainerReviewActionExample.tsx b/src/examples/container/ContainerReviewActionExample.tsx new file mode 100644 index 000000000..131e8100c --- /dev/null +++ b/src/examples/container/ContainerReviewActionExample.tsx @@ -0,0 +1,184 @@ +import "./container-review-action-example.css"; +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { + GoabBlock, GoabButton, + GoabContainer, GoabDropdown, GoabDropdownItem, + GoabFormItem, + GoabGrid, + GoabRadioGroup, GoabRadioItem, GoabTextarea +} from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const ContainerReviewActionExample = () => { + const {version} = useContext(LanguageVersionContext); + return ( + + + + {version === "new" && } + + {version === "new" && { + console.log(event.value); + }; + const dropdownOnChange = (event: GoabDropdownOnChangeDetail) => { + console.log(event.value); + }; + const textareaOnChange = (event: GoabTextAreaOnChangeDetail) => { + console.log(event.value); + }; + const onClick = () => { + console.log('clicked!'); + }; + `} + />} + + + +

Appearance details

+ + + + Doe, John Scott + + + + + Mar 14, 2021 + + + + + Calgary + + + + + Sep 20, 2021 + + + +
Docket number(s) $ charges
+ +
1) 12345678
+

+ CC 334(1) - Theft under $5000 +

+

+ CC 268(1) - Aggravated assult +

+
+ + +
2) 12345678
+

+ CC 334(1) - Theft under $5000 +

+

+ CC 268(1) - Aggravated assult +

+
+ + +
3) 12345678
+

+ CC 334(1) - Theft under $5000 +

+

+ CC 268(1) - Aggravated assult +

+
+
+ +
+

Adjournment request

+

+ Keep track of the individuals who are placed in lodges and may qualify for the Lodge + Assistance Program subsidy. +

+ + + {}}> + + + + + + + {}}> + + + + + + + + {}} /> + + + {}}> + Confirm + +
+
+
+
+ ) +} diff --git a/src/examples/container/ContainerUserInformationExample.tsx b/src/examples/container/ContainerUserInformationExample.tsx new file mode 100644 index 000000000..85d395d44 --- /dev/null +++ b/src/examples/container/ContainerUserInformationExample.tsx @@ -0,0 +1,367 @@ +import "./container-user-information-example.css"; +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabBlock, GoabButton, GoabContainer, GoabTable } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const ContainerUserInformationExample = () => { + const {version} = useContext(LanguageVersionContext); + + return ( + + {/*CSS Code Snippet*/} + + + {/*Angular Code Snippet*/} + {version === "old" && ( + + Housing Advisor +

Tracy Hero

+ + + Email + Phone + + + + tracyhero@email.com + 283-203-4921 + + +
+ + + +
Upcoming important due dates
+
+ + Add to calendar + +
+ +
+ + + + Business plan submission + June 30, 2024 + + + Annual review + October 3, 2024 + + + Application submission + December 20, 2024 + + + Application review + January 3, 2025 + + + +
+
+ `} + /> + )} + + {version === "new" && ( + + )} + {version === "new" && ( + + Housing Advisor +

Tracy Hero

+ + + Email + Phone + + + + tracyhero@email.com + 283-203-4921 + + + + + +
Upcoming important due dates
+
+ + Add to calendar + +
+ +
+ + + + Business plan submission + June 30, 2024 + + + Annual review + October 3, 2024 + + + Application submission + December 20, 2024 + + + Application review + January 3, 2025 + + + +
+
+ `} + /> + )} + + {/*React*/} + {version === "old" && ( + {/* do nothing */}}> + Add to calendar + ); + `} + /> + )} + + {version === "new" && ( + {/* do nothing */}}> + Add to calendar + ); + `} + /> + )} + + {version === "old" && ( + + Housing Advisor +

Tracy Hero

+ + + Email + Phone + + + + tracyhero@email.com + 283-203-4921 + + + + + +
+ + + + Business plan submission + June 30, 2024 + + + Annual review + October 3, 2024 + + + Application submission + December 20, 2024 + + + Application review + January 3, 2025 + + + +
+
+ `} + /> + )} + + {version === "new" && ( + + Housing Advisor +

Tracy Hero

+ + + Email + Phone + + + + tracyhero@email.com + 283-203-4921 + + + + + +
+ + + + Business plan submission + June 30, 2024 + + + Annual review + October 3, 2024 + + + Application submission + December 20, 2024 + + + Application review + January 3, 2025 + + + +
+
+ `} + /> + )} + {/*Code Block*/} + + Housing Advisor +

Tracy Hero

+ + + Email + Phone + + + + tracyhero@email.com + 283-203-4921 + + +
+ + {/* do nothing */}}> + Add to calendar + + }> +
+ + + + Business plan submission + June 30, 2024 + + + Annual review + October 3, 2024 + + + Application submission + December 20, 2024 + + + Application review + January 3, 2025 + + + +
+
+ + ) +} diff --git a/src/examples/container/container-card-grid-example.css b/src/examples/container/container-card-grid-example.css new file mode 100644 index 000000000..3ba870198 --- /dev/null +++ b/src/examples/container/container-card-grid-example.css @@ -0,0 +1,10 @@ +.container-example-3--container-title { + color: var(--goa-color-interactive-default); + font: var(--goa-typography-heading-m); + text-decoration-line: underline; + margin-top:0; + margin-bottom: var(--goa-space-m); +} +.container-example-3--container-content { + font: var(--goa-typography-body-m); +} diff --git a/src/examples/container/container-case-files-example.css b/src/examples/container/container-case-files-example.css new file mode 100644 index 000000000..887acd0d8 --- /dev/null +++ b/src/examples/container/container-case-files-example.css @@ -0,0 +1,27 @@ +.container-example-2--container { + display: flex; + justify-content: space-between; + align-items: center; +} + +span.container-example-2--body-text { + font: var(--goa-typography-body-s); +} + +.container-example-2--right-content { + display: flex; + flex-direction: column; + align-items: center; +} + +@media screen and (max-width: 623px) { + .container-example-2--container { + flex-direction: column; + justify-content: center; + align-items: stretch; + } + .container-example-2--right-content { + display:block; + margin-top: var(--goa-space-xs); + } +} diff --git a/src/examples/container/container-example.css b/src/examples/container/container-example.css deleted file mode 100644 index d344438a0..000000000 --- a/src/examples/container/container-example.css +++ /dev/null @@ -1,102 +0,0 @@ -/*Example 1*/ -/*User information example*/ -.container-example-1--sub-header { - color: var(--goa-color-greyscale-700); - font: var(--goa-typography-body-m); -} - -.container-example-1--header { - color: var(--goa-color-greyscale-700); - font-size: var(--goa-font-size-7); - font-weight: var(--goa-font-weight-bold); - line-height: var(--goa-line-height-4); - margin-bottom: var(--goa-space-s); -} - -span.container-example-1--contact-label { - color: var(--goa-color-greyscale-700); - font: var(--goa-typography-heading-s); -} - -span.container-example-1--contact-value { - color: var(--goa-color-greyscale-700); - font: var(--goa-typography-body-m); -} - -/*Upcoming important due dates example*/ -.container-example-1 goa-table tbody.striped tr:nth-child(even) { - background-color: #F8F8F8; -} -.container-example-1 goa-table td.align-right { - text-align: right; -} - -/*Example 2*/ -.container-example-2--container { - display: flex; - justify-content: space-between; - align-items: center; -} - -span.container-example-2--body-text { - font: var(--goa-typography-body-s); -} - -.container-example-2--right-content { - display: flex; - flex-direction: column; - align-items: center; -} - -@media screen and (max-width: 623px) { - .container-example-2--container { - flex-direction: column; - justify-content: center; - align-items: stretch; - } - .container-example-2--right-content { - display:block; - margin-top: var(--goa-space-xs); - } -} - -/*Example 3*/ -.container-example-3--container-title { - color: var(--goa-color-interactive-default); - font: var(--goa-typography-heading-m); - text-decoration-line: underline; - margin-top:0; - margin-bottom: var(--goa-space-m); -} -.container-example-3--container-content { - font: var(--goa-typography-body-m); -} - - -/*Example 4*/ -h3.container-example-4--h3 { - margin-bottom: var(--goa-space-m); -} -label.container-example-4--label { - font: var(--goa-typography-body-s); - color: var(--goa-color-text-secondary); -} -.container-example-4--container-content { - font: var(--goa-typography-body-m); -} -p.container-example-4--container-content { - margin-bottom: 0; -} - -h5.container-example-4--h5 { - font: var(--goa-typography-body-m); - color: var(--goa-color-text-secondary); - margin-top: var(--goa-space-m); - margin-bottom: var(--goa-space-m); -} - -h6.container-example-4--h6 { - font: var(--goa-typography-heading-s); - margin-top:0; - margin-bottom: 0; -} diff --git a/src/examples/container/container-review-action-example.css b/src/examples/container/container-review-action-example.css new file mode 100644 index 000000000..688cf0c1b --- /dev/null +++ b/src/examples/container/container-review-action-example.css @@ -0,0 +1,26 @@ +h3.container-example-4--h3 { + margin-bottom: var(--goa-space-m); +} +label.container-example-4--label { + font: var(--goa-typography-body-s); + color: var(--goa-color-text-secondary); +} +.container-example-4--container-content { + font: var(--goa-typography-body-m); +} +p.container-example-4--container-content { + margin-bottom: 0; +} + +h5.container-example-4--h5 { + font: var(--goa-typography-body-m); + color: var(--goa-color-text-secondary); + margin-top: var(--goa-space-m); + margin-bottom: var(--goa-space-m); +} + +h6.container-example-4--h6 { + font: var(--goa-typography-heading-s); + margin-top:0; + margin-bottom: 0; +} diff --git a/src/examples/container/container-user-information-example.css b/src/examples/container/container-user-information-example.css new file mode 100644 index 000000000..37da263de --- /dev/null +++ b/src/examples/container/container-user-information-example.css @@ -0,0 +1,30 @@ +.container-example-1--sub-header { + color: var(--goa-color-greyscale-700); + font: var(--goa-typography-body-m); +} + +.container-example-1--header { + color: var(--goa-color-greyscale-700); + font-size: var(--goa-font-size-7); + font-weight: var(--goa-font-weight-bold); + line-height: var(--goa-line-height-4); + margin-bottom: var(--goa-space-s); +} + +span.container-example-1--contact-label { + color: var(--goa-color-greyscale-700); + font: var(--goa-typography-heading-s); +} + +span.container-example-1--contact-value { + color: var(--goa-color-greyscale-700); + font: var(--goa-typography-body-m); +} + +/*Upcoming important due dates example*/ +.container-example-1 goa-table tbody.striped tr:nth-child(even) { + background-color: #F8F8F8; +} +.container-example-1 goa-table td.align-right { + text-align: right; +} diff --git a/src/examples/date-picker/DatePickerExamples.tsx b/src/examples/date-picker/DatePickerExamples.tsx new file mode 100644 index 000000000..d7bdc2e8c --- /dev/null +++ b/src/examples/date-picker/DatePickerExamples.tsx @@ -0,0 +1,14 @@ +import { DatePickerResetExample } from "@examples/date-picker/DatePickerResetExample.tsx"; + +export const DatePickerExamples = () => { + return ( + <> + + +

Reset example

+ + + ) +} diff --git a/src/examples/date-picker/DatePickerResetExample.tsx b/src/examples/date-picker/DatePickerResetExample.tsx new file mode 100644 index 000000000..97f57f657 --- /dev/null +++ b/src/examples/date-picker/DatePickerResetExample.tsx @@ -0,0 +1,253 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabButton, GoabButtonGroup, GoabDatePicker, GoabFormItem } from "@abgov/react-components"; +import { GoabDatePickerOnChangeDetail } from "@abgov/ui-components-common"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const DatePickerResetExample = () => { + const {version} = useContext(LanguageVersionContext); + const [date, setDate] = useState(); + + const setNewDate = (value: Date | undefined) => { + setDate(value); + }; + + function setValue() { + const d = new Date(); + d.setDate(d.getDate() - 7); + + setDate(d); + } + + function clearValue() { + setDate(undefined); + } + return ( + + {/*React*/} + {version === "old" && (); + + const setNewDate = (value: Date | undefined) => { + setDate(value); + }; + + function setValue() { + const d = new Date(); + d.setDate(d.getDate() - 7); + + setDate(d); + } + + function clearValue() { + setDate(undefined); + } + + return ( + <> + + setNewDate(value)} + mb="xl" + > + + + + Set Value + Clear Value + + + ); + } + `} + />} + + {version === "new" && (); + + const setNewDate = (value: Date | undefined) => { + setDate(value); + }; + + function setValue() { + const d = new Date(); + d.setDate(d.getDate() - 7); + + setDate(d); + } + + function clearValue() { + setDate(undefined); + } + + return ( + <> + + setNewDate(e.value as Date)} + mb="xl"> + + + + + Set Value + + Clear Value + + + ); + } + `} + />} + + {/*Angular*/} + + {version === "old" && } + + {version === "old" && + + + + + Set Value + Clear Value + + `} + />} + + {version === "old" && } + {version === "old" && + + + + + Set Value + Clear Value + + `} + />} + + {/*New version*/} + {version === "new" && } + + {version === "new" && + + + + + Set Value + Clear Value + + `} + />} + + + setNewDate(e.value as Date)} + mb="xl"> + + + + + Set Value + + Clear Value + + + ) +} diff --git a/src/examples/details/DetailsAdditionalInformationHelpUserExample.tsx b/src/examples/details/DetailsAdditionalInformationHelpUserExample.tsx new file mode 100644 index 000000000..92e32e966 --- /dev/null +++ b/src/examples/details/DetailsAdditionalInformationHelpUserExample.tsx @@ -0,0 +1,79 @@ +import { Sandbox } from "@components/sandbox"; +import { GoabBlock, GoabDetails, GoabFormItem, GoabRadioGroup, GoabRadioItem } from "@abgov/react-components"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const DetailsAdditionalInformationHelpUserExample = () => { + const {version} = useContext(LanguageVersionContext); + const noop = () => {} + + return ( + + {/*Angular code*/} + {version === "new" && } + + {/*React code*/} + {version === "new" && { + console.log("value is ", event.value); + } + `} + />} + +
+ + + + + + + + + +
+ Examples of education expenses +
    +
  • Laptop and computer hardware
  • +
  • Computer apps and subscriptions
  • +
  • Home internet
  • +
  • Testing and exam fees
  • +
  • Work or school clothing, like work boots
  • +
+
+
+ Do not include +
    +
  • Tuition
  • +
  • Mandatory fees
  • +
  • Books and supplies
  • +
  • School association fees
  • +
+
+
+
+
+
+ ) +} diff --git a/src/examples/details/DetailsExamples.tsx b/src/examples/details/DetailsExamples.tsx new file mode 100644 index 000000000..7268c6fc7 --- /dev/null +++ b/src/examples/details/DetailsExamples.tsx @@ -0,0 +1,32 @@ +import { + DetailsMoreInformationBasicQuestionExample +} from "@examples/details/DetailsMoreInformationBasicQuestionExample.tsx"; +import { + DetailsAdditionalInformationHelpUserExample +} from "@examples/details/DetailsAdditionalInformationHelpUserExample.tsx"; +import { + DetailsShowDirectDepositInformationExample +} from "@examples/details/DetailsShowDirectDepositInformationExample.tsx"; + +export const DetailsExamples = () => { + return ( + <> + + +

+ Show more information for a basic question +

+ + +

+ Additional information to help a user understand and answer a question +

+ + +

+ Show more information to help a user fill out direct deposit information +

+ + + ) +} diff --git a/src/examples/details/DetailsMoreInformationBasicQuestionExample.tsx b/src/examples/details/DetailsMoreInformationBasicQuestionExample.tsx new file mode 100644 index 000000000..e24e9ec90 --- /dev/null +++ b/src/examples/details/DetailsMoreInformationBasicQuestionExample.tsx @@ -0,0 +1,53 @@ +import { Sandbox } from "@components/sandbox"; +import { GoabDetails, GoabFormItem, GoabRadioGroup, GoabRadioItem } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; + +export const DetailsMoreInformationBasicQuestionExample = () => { + const {version} = useContext(LanguageVersionContext); + return ( + + + {/*Angular code*/} + {version === "new" && } + + {/*React code*/} + {version === "new" && { + console.log("value is ", event.value); + } + `} + />} + + + { }}> + + + + + + +

+ This question helps us better understand your situation and ensure that you receive + the right information and support. +

+
+
+ ) +} diff --git a/src/examples/details/DetailsShowDirectDepositInformationExample.tsx b/src/examples/details/DetailsShowDirectDepositInformationExample.tsx new file mode 100644 index 000000000..7bc5af659 --- /dev/null +++ b/src/examples/details/DetailsShowDirectDepositInformationExample.tsx @@ -0,0 +1,151 @@ +import { Sandbox } from "@components/sandbox"; +import { GoabDetails, GoabFormItem, GoabInput } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; + +export const DetailsShowDirectDepositInformationExample = () => { + const {version} = useContext(LanguageVersionContext); + const noop = () => {}; + + return ( + + + {/*Angular code*/} + {version === "new" && } + + {/*React code*/} + {version === "new" && (""); + const [transitNumber, setTransitNumber] = useState(""); + const [accountNumber, setAccountNumber] = useState(""); + `} + />} + {version === "new" && Direct deposit information +

+ Find this information on your bank's website or on your personal cheques. Contact your bank if you can't find + this information. +

+ + + setBankNumber(event.value)} value={bankNumber} ariaLabel="bankNumber" + width="88px"> + + + setTransitNumber(event.value)} value={transitNumber} ariaLabel="transitNumber" + width="143px"> + + + setAccountNumber(event.value)} + ariaLabel="accountNumber"> + + +

Below is an example of where you can find the required bank information on a personal cheque.

+ +
+ `} + />} + + {version === "old" && + + + + + + + + + +

Below is an example of where you can find the required bank information on a personal cheque.

+ +
+ `} + />} + + +

Direct deposit information

+

+ Find this information on your bank's website or on your personal cheques. Contact your bank + if you can't find this information. +

+
+ + + + + + + + + +
+ + +

+ Below is an example of where you can find the required bank information on a personal + cheque. +

+ +
+
+ ); +}; diff --git a/src/examples/dropdown/DropdownAddItemExample.tsx b/src/examples/dropdown/DropdownAddItemExample.tsx new file mode 100644 index 000000000..ef919f2e3 --- /dev/null +++ b/src/examples/dropdown/DropdownAddItemExample.tsx @@ -0,0 +1,622 @@ +import { + GoabButton, + GoabButtonGroup, + GoabContainer, + GoabDivider, + GoabDropdown, + GoabDropdownItem, + GoabFormItem, + GoabInput, + GoabRadioGroup, + GoabRadioItem, +} from "@abgov/react-components"; +import { + GoabDropdownItemMountType, + GoabDropdownOnChangeDetail, + GoabInputOnChangeDetail, + GoabRadioGroupOnChangeDetail, +} from "@abgov/ui-components-common"; +import { useContext, useState } from "react"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +type Task = { + value: string; + label: string; + mount: GoabDropdownItemMountType; +}; + +export const DropdownAddItemExample = () => { + const { version } = useContext(LanguageVersionContext); + const [taskError, setTaskError] = useState(false); + const [newTask, setNewTask] = useState(""); + const [mountType, setNewMountType] = useState("append"); + const DEFAULT_TASKS: Task[] = [ + { label: "Finish Report", value: "finish-report", mount: "append" }, + { label: "Attend Meeting", value: "attend-meeting", mount: "append" }, + { label: "Reply Emails", value: "reply-emails", mount: "append" }, + ]; + const [tasks, setTasks] = useState(DEFAULT_TASKS); + const [isReset, setIsReset] = useState(false); + const [selectedTask, setSelectedTask] = useState(""); + + function onMountTypeChange(value: string | undefined) { + setNewMountType(value as string); + } + + function addTask() { + if (newTask === "") { + setTaskError(true); + return; + } + setTaskError(false); + + const task = { + label: newTask, + value: newTask.toLowerCase().replace(" ", "-"), + mount: mountType as GoabDropdownItemMountType, + }; + setTasks([...tasks, task]); + setIsReset(false); + } + + function reset() { + setTasks(DEFAULT_TASKS); + setNewMountType("append"); + setNewTask(""); + setSelectedTask(""); + setTaskError(false); + setIsReset(true); + } + + return ( + <> + +
+ + setNewTask(event.value)} + name="item" + placeholder="" + value={newTask}> + + + + onMountTypeChange(event.value)} + value={mountType} + orientation="horizontal"> + + + + + + + + Add new item + + + Reset list + + + + + + +
+ + setSelectedTask(event.value as string) + } + value={selectedTask} + name="selectedTask"> + {tasks.map(task => ( + + ))} + +
+
+
+
+ + {/***************** Angular code ***********/} + {version === "old" && ( + { + this.renderTrigger = true; + }, 0); + } + trackByFn(index: number, item: Task): string { + return item.value; + } + }`} + /> + )} + + {version === "new" && ( + { + this.renderTrigger = true; + }, 0); + } + trackByFn(index: number, item: Task): string { + return item.value; + } + }`} + /> + )} + + {version === "old" && ( + +
+ + + + + + + + + + + + + Add new item + + + Reset list + + + + + + + + + + + +
+ + `} + /> + )} + + {version === "new" && ( + +
+ + + + + + + + + + + + + Add new item + + + Reset list + + + + + + + + + + + +
+ `} + /> + )} + + {/**************** React code **********************/} + + {version === "old" && ( + (DEFAULT_TASKS); + const [newTask, setNewTask] = useState(""); + const [mountType, setNewMountType] = useState("append"); + const [selectedTask, setSelectedTask] = useState(""); + const [taskError, setTaskError] = useState(false); + + function onMountTypeChange(value: string) { + setNewMountType(value); + } + function addTask() { + if (newTask === "") { + setTaskError(true); + return; + } + setTaskError(false); + const task = { + label: newTask, + value: newTask.toLowerCase().replace(" ", "-"), + mount: mountType as DropdownItemMountType, + }; + setTasks([...tasks, task]); + } + + function reset() { + setTasks(DEFAULT_TASKS); + setNewMountType("append"); + setNewTask(""); + setSelectedTask(""); + setTaskError(false); + } + `} + /> + )} + + {version === "new" && ( + (DEFAULT_TASKS); + const [newTask, setNewTask] = useState(""); + const [mountType, setNewMountType] = useState("append"); + const [selectedTask, setSelectedTask] = useState(""); + const [taskError, setTaskError] = useState(false); + + function onMountTypeChange(value: string | undefined) { + setNewMountType(value as string); + } + function addTask() { + if (newTask === "") { + setTaskError(true); + return; + } + setTaskError(false); + const task = { + label: newTask, + value: newTask.toLowerCase().replace(" ", "-"), + mount: mountType as GoabDropdownItemMountType + }; + setTasks([...tasks, task]); + } + + function reset() { + setTasks(DEFAULT_TASKS); + setNewMountType("append"); + setNewTask(""); + setSelectedTask(""); + setTaskError(false); + } + `} + /> + )} + + {version === "old" && ( + +
+ + setNewTask(value)} + name="item" + placeholder="" + value={newTask}> + + + onMountTypeChange(value)} + value={mountType} + orientation="horizontal"> + + + + + + + Add new item + + + Reset list + + + + + setSelectedTask(values as string)} + value={selectedTask} + name="selectedTask"> + {tasks.map(task => ( + + ))} + + +
+ + `} + /> + )} + + {version === "new" && ( + +
+ + setNewTask(event.value)} + name="item" + placeholder="" + value={newTask}> + + + onMountTypeChange(event.value)} + value={mountType} + orientation="horizontal"> + + + + + + + Add new item + + + Reset list + + + + + setSelectedTask(event.value as string)} + value={selectedTask} + name="selectedTask"> + {tasks.map(task => ( + + ))} + + +
+ + `} + /> + )} + + ); +}; diff --git a/src/examples/dropdown/DropdownChangeItemExample.tsx b/src/examples/dropdown/DropdownChangeItemExample.tsx new file mode 100644 index 000000000..a8904494b --- /dev/null +++ b/src/examples/dropdown/DropdownChangeItemExample.tsx @@ -0,0 +1,252 @@ +import { GoabContainer, GoabDropdown, GoabDropdownItem, GoabFormItem } from "@abgov/react-components"; +import { GoabDropdownOnChangeDetail } from "@abgov/ui-components-common"; +import { useContext, useState } from "react"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const DropdownChangeItemExample = () => { + const {version} = useContext(LanguageVersionContext); + const [children, setChildren] = useState([]); + const parents = ["All", "Big", "Small"]; + const childrenAll = ["Bus", "Elephant", "Key", "Pen", "Watch", "Truck"]; + const childrenBig = ["Elephant", "Truck", "Bus"]; + const childrenSmall = ["Key", "Pen", "Watch"]; + + const loadSchemas = (_name: string, values: string[] | string) => { + if (typeof values === "string") { + if (values === "All") setChildren(childrenAll); + else if (values === "Big") setChildren(childrenBig); + else setChildren(childrenSmall); + } + }; + + const log = () => { + console.log("Children Changed"); + }; + return ( + <> + +
+ + + loadSchemas(event.name as string, event.value as string) + }> + {parents.map(parent => ( + + ))} + + + + + {" "} + {children.map((child, _index) => ( + + ))} + + +
+
+ + ([]); + + const loadSchemas = (name: string, values: string[] | string) => { + if (typeof values === "string") { + if (values === "All") setChildren(childrenAll); + else if (values === "Big") setChildren(childrenBig); + else setChildren(childrenSmall); + } + }; + + const log = () => { + console.log("Children Changed"); + }; + `} + /> + + {version === "old" && ( + + + {parents.map((parent) => ( + + ))} + + + + + {" "} + {children.map((child, index) => ( + + ))} + + + `} + /> + )} + + {version === "new" && ( + + loadSchemas(event.name as string, event.value as string)}> + {parents.map(parent => ( + + ))} + + + + + {" "} + {children.map((child, _index) => ( + + ))} + + + `} + /> + )} + + { + if (value === "All") this.children = this.childrenAll; + else if (value === "Big") this.children = this.childrenBig; + else this.children = this.childrenSmall; + }); + } + + generateUniqueKey(index: number, item: string): string { + return \`$\{item}_$\{index}_$\{Math.random()}\`; + } + } + `} + /> + + {version === "old" && ( + + + + + + + + + + + + + +
+ `} + /> + )} + {version === "new" && ( + + + + + + + + + + + + + +
+ `} + /> + )} + + ); +} diff --git a/src/examples/dropdown/DropdownExamples.tsx b/src/examples/dropdown/DropdownExamples.tsx index bc5d70463..86b8fdc34 100644 --- a/src/examples/dropdown/DropdownExamples.tsx +++ b/src/examples/dropdown/DropdownExamples.tsx @@ -1,553 +1,18 @@ -import { useContext, useState } from "react"; -import { - DropdownItemMountType, - GoAButton, - GoAButtonGroup, - GoAContainer, - GoADivider, - GoADropdown, - GoADropdownItem, - GoAFormItem, - GoAInput, - GoARadioGroup, - GoARadioItem, -} from "@abgov/react-components"; -import { LanguageContext } from "@components/sandbox"; -import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; - -type Task = { - value: string; - label: string; - mount: DropdownItemMountType; -}; +import { DropdownAddItemExample } from "@examples/dropdown/DropdownAddItemExample.tsx"; +import { DropdownChangeItemExample } from "@examples/dropdown/DropdownChangeItemExample.tsx"; export const DropdownExamples = () => { - const language = useContext(LanguageContext); - const [tasks, setTasks] = useState([ - { label: "Finish Report", value: "finish-report", mount: "append" }, - { label: "Attend Meeting", value: "attend-meeting", mount: "append" }, - { label: "Reply Emails", value: "reply-emails", mount: "append" }, - ]); - const [newTask, setNewTask] = useState(""); - const [mountType, setNewMountType] = useState("append"); - const [selectedTask, setSelectedTask] = useState(""); - const [taskError, setTaskError] = useState(false); - const [isReset, setIsReset] = useState(false); - - function onMountTypeChange(value: string) { - setNewMountType(value); - } - - function addTask() { - if (newTask === "") { - setTaskError(true); - return; - } - setTaskError(false); - - const task = { - label: newTask, - value: newTask.toLowerCase().replace(" ", "-"), - mount: mountType as DropdownItemMountType, - }; - setTasks([...tasks, task]); - setIsReset(false); - } - - function reset() { - setTasks([]); - setNewMountType("append"); - setNewTask(""); - setSelectedTask(""); - setTaskError(false); - setIsReset(true); - } - - // ------------------------------------------------------------------ - // Parent child edge case - // ------------------------------------------------------------------ - const parents = ["All", "Big", "Small"]; - const childrenAll = ["Bus", "Elephant", "Key", "Pen", "Watch", "Truck"]; - const childrenBig = ["Elephant", "Truck", "Bus"]; - const childrenSmall = ["Key", "Pen", "Watch"]; - const [children, setChildren] = useState([]); - - const loadSchemas = (_name: string, values: string[] | string) => { - if (typeof values === "string") { - if (values === "All") setChildren(childrenAll); - else if (values === "Big") setChildren(childrenBig); - else setChildren(childrenSmall); - } - }; - - const log = () => { - console.log("Children Changed"); - }; - return ( <>

Dynamically add an item to a dropdown list

- -
- - setNewTask(value)} - name="item" - placeholder="" - value={newTask}> - - - - onMountTypeChange(value)} - value={mountType} - orientation="horizontal"> - - - - - - - - Add new item - - - Reset list - - - - - - -
- setSelectedTask(values as string)} - value={selectedTask} - name="selectedTask"> - {tasks.map(task => ( - - ))} - -
-
-
-
- {language === "angular" && ( - <> - { - this.renderTrigger = true; - }, 0); - } - trackByFn(index: number, item: Task): string { - return item.value; - } - }`} - /> - -
- - - - - - - - - - - - - Add new item - - - Reset list - - - - - - - - - - - -
- - `} - /> - - )} - {language === "react" && ( - <> - ([ - { label: "Finish Report", value: "finish-report", mount: "append" }, - { label: "Attend Meeting", value: "attend-meeting", mount: "append" }, - { label: "Reply Emails", value: "reply-emails", mount: "append" } - ]); - const [newTask, setNewTask] = useState(""); - const [mountType, setNewMountType] = useState("append"); - const [selectedTask, setSelectedTask] = useState(""); - const [taskError, setTaskError] = useState(false); - - function onMountTypeChange(value: string) { - setNewMountType(value); - } - function addTask() { - if (newTask === "") { - setTaskError(true); - return; - } - setTaskError(false); - const task = { - label: newTask, - value: newTask.toLowerCase().replace(" ", "-"), - mount: mountType as DropdownItemMountType, - }; - setTasks([...tasks, task]); - } - - function reset() { - setTasks([]); - setNewMountType("append"); - setNewTask(""); - setSelectedTask(""); - setTaskError(false); - } - `} - /> - - -
- - setNewTask(value)} - name="item" - placeholder="" - value={newTask}> - - - onMountTypeChange(value)} - value={mountType} - orientation="horizontal"> - - - - - - - Add new item - - - Reset list - - - - - setSelectedTask(values as string)} - value={selectedTask} - name="selectedTask"> - {tasks.map(task => ( - - ))} - - -
- - `} - /> - - )} - - {/* ---------------------------------------- */} - {/* Parent child edge case */} - {/* ---------------------------------------- */} +

Dynamically change items in a dropdown

- -
- - - {parents.map(parent => ( - - ))} - - - - - {" "} - {children.map((child, _index) => ( - - ))} - - -
-
- - {language === "react" && ( - <> - ([]); - - const loadSchemas = (name: string, values: string[] | string) => { - if (typeof values === "string") { - if (values === "All") setChildren(childrenAll); - else if (values === "Big") setChildren(childrenBig); - else setChildren(childrenSmall); - } - }; - - const log = () => { - console.log("Children Changed"); - }; - `} - /> - - - - {parents.map((parent) => ( - - ))} - - - - - {" "} - {children.map((child, index) => ( - - ))} - - - `} - /> - - )} - - {language === "angular" && ( - <> - { - if (value === "All") this.children = this.childrenAll; - else if (value === "Big") this.children = this.childrenBig; - else this.children = this.childrenSmall; - }); - } - - generateUniqueKey(index: number, item: string): string { - return \`$\{item}_$\{index}_$\{Math.random()}\`; - } - } - `} - /> - - - - - - - - - - - - - -
- `} - /> - - )} + ); -}; +} diff --git a/src/examples/filter-chip/FilterChipDeleteEventExample.tsx b/src/examples/filter-chip/FilterChipDeleteEventExample.tsx new file mode 100644 index 000000000..d1cf464d6 --- /dev/null +++ b/src/examples/filter-chip/FilterChipDeleteEventExample.tsx @@ -0,0 +1,113 @@ +import { Sandbox } from "@components/sandbox"; +import { GoabFilterChip } from "@abgov/react-components"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const FilterChipDeleteEventExample = () => { + const {version} = useContext(LanguageVersionContext); + const [chips, setChips] = useState(["Chip 1", "Chip 2", "Chip 3"]); + const deleteChip = (chip: string) => { + setChips(prevChips => prevChips.filter(c => c !== chip)); + }; + + return ( + + {chips.map(chip => ( + deleteChip(chip)} mr="s" /> + ))} + + c !== chip); + } + `} + /> + + {version === "old" && ( + + + `} + /> + )} + {version === "new" && ( + + + `} + /> + )} + + { + setChips((prevChips) => prevChips.filter((c) => c !== chip)); + }; + `} + /> + + {version === "old" && ( + ( + deleteChip(chip)} + mr="s" + /> + ))} + `} + /> + )} + {version === "new" && ( + ( + deleteChip(chip)} + mr="s" + /> + ))} + `} + /> + )} + + ) +} diff --git a/src/examples/filter-chip/FilterChipExamples.tsx b/src/examples/filter-chip/FilterChipExamples.tsx new file mode 100644 index 000000000..488c9a5ca --- /dev/null +++ b/src/examples/filter-chip/FilterChipExamples.tsx @@ -0,0 +1,21 @@ +import { FilterChipDeleteEventExample } from "@examples/filter-chip/FilterChipDeleteEventExample.tsx"; +import { FilterChipInteractiveExample } from "@examples/filter-chip/FilterChipInteractiveExample.tsx"; +import { FilterChipTypedChipExample } from "@examples/filter-chip/FilterChipTypedChipExample.tsx"; + +export const FilterChipExamples = () => { + return ( + <> + +

Delete Event

+ + +

Interactive Example

+ + +

Typed Chips Example

+ + + ) +} diff --git a/src/examples/filter-chip/FilterChipInteractiveExample.tsx b/src/examples/filter-chip/FilterChipInteractiveExample.tsx new file mode 100644 index 000000000..88adcf008 --- /dev/null +++ b/src/examples/filter-chip/FilterChipInteractiveExample.tsx @@ -0,0 +1,171 @@ +import { Sandbox } from "@components/sandbox"; +import { GoabButton, GoabButtonGroup, GoabFilterChip } from "@abgov/react-components"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const FilterChipInteractiveExample = () => { + const {version} = useContext(LanguageVersionContext); + const [activeFilters, setActiveFilters] = useState([]); + const addFilter = () => { + const randomFilter = `Filter ${Math.floor(Math.random() * 100)}`; + if (!activeFilters.includes(randomFilter)) { + setActiveFilters(prevFilters => [...prevFilters, randomFilter]); + } + }; + + const removeFilter = (filter: string) => { + setActiveFilters(prevFilters => prevFilters.filter(f => f !== filter)); + }; + + return ( + + {activeFilters.map(filter => ( + removeFilter(filter)} + mr="s" + mb="s" + mt="s" + /> + ))} + + + Add Random Filter + + + f !== filter); + } + + addFilter(): void { + const randomFilter = "Filter " + Math.floor(Math.random() * 100); + if (!this.activeFilters.includes(randomFilter)) { + this.activeFilters.push(randomFilter); + } + } + } + `} + /> + + {version === "old" && ( + + + +
+ + Add Random Filter + + `} + /> + )} + {version === "new" && ( + + + + + + Add Random Filter + + `} + /> + )} + + ([]); + + const removeFilter = (filter: string) => { + setActiveFilters((prevFilters) => prevFilters.filter((f) => f !== filter)); + }; + + const addFilter = () => { + const randomFilter = 'Filter ' + Math.floor(Math.random() * 100); + if (!activeFilters.includes(randomFilter)) { + setActiveFilters(prevFilters => [...prevFilters, randomFilter]); + } + }; + `} + /> + + {version === "old" && ( + + {activeFilters.map((filter) => ( + removeFilter(filter)} + mr="s" + mb="s" + mt="s" + /> + ))} + + + Add Random Filter + + `} + /> + )} + {version === "new" && ( + + {activeFilters.map((filter) => ( + removeFilter(filter)} + mr="s" + mb="s" + mt="s" + /> + ))} + + + Add Random Filter + + `} + /> + )} + + ) +} diff --git a/src/examples/filter-chip/FilterChipTypedChipExample.tsx b/src/examples/filter-chip/FilterChipTypedChipExample.tsx new file mode 100644 index 000000000..2ae8f0f6c --- /dev/null +++ b/src/examples/filter-chip/FilterChipTypedChipExample.tsx @@ -0,0 +1,294 @@ +import { GoabContainer, GoabFilterChip, GoabInput } from "@abgov/react-components"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const FilterChipTypedChipExample = () => { + const {version} = useContext(LanguageVersionContext); + const [typedChips, setTypedChips] = useState([ + "Typed Chip 1", + "Typed Chip 2", + "Typed Chip 3", + ]); + + const [inputValue, setInputValue] = useState(""); + const handleInputChange = (_name: string, value: string) => { + setInputValue(value); + }; + const handleInputKeyDown = (_name: string, value: string, key: string) => { + if (key === "Enter" && value.trim() !== "") { + setTypedChips(prevChips => [...prevChips, value.trim()]); + setTimeout(() => { + setInputValue(""); + }, 0); + } else if (key === "Backspace" && value === "" && typedChips.length > 0) { + setTypedChips(prevChips => prevChips.slice(0, -1)); + } + }; + + const removeTypedChip = (chip: string) => { + setTypedChips(prevChips => prevChips.filter(c => c !== chip)); + }; + return ( + <> + +
+ handleInputChange(detail.name, detail.value)} + onKeyPress={detail => handleInputKeyDown(detail.name, detail.value, detail.key)} + width="30ch" + mr="s" + /> + {typedChips.map((chip, index) => ( + removeTypedChip(chip)} + mr="s" + mt="s" + mb="s" + /> + ))} +
+
+ {version === "old" && ( + <> + c !== chip); + } + + handleBackspace(event: KeyboardEvent): void { + if (!this.inputValue && this.typedChips.length > 0 && event.key === "Backspace") { + this.typedChips.pop(); + event.preventDefault(); + } + } + } + + `} + /> + + + + + `} + /> + + )} + + {version === "new" && ( + <> + c !== chip); + } + + handleBackspace(event: KeyboardEvent): void { + if (!this.inputValue && this.typedChips.length > 0 && event.key === "Backspace") { + this.typedChips.pop(); + event.preventDefault(); + } + } + `} + /> + Typed Chip + + + + + `} + /> + + )} + + ([ + "Typed Chip 1", + "Typed Chip 2", + "Typed Chip 3", + ]); + const [inputValue, setInputValue] = useState(""); + const handleInputChange = (name: string, value: string) => { + setInputValue(value); + }; + + const handleInputKeyDown = (name: string, + value: string, + key: string) => { + if (key === "Enter" && value.trim() !== "") { + setTypedChips((prevChips) => [...prevChips, value.trim()]); + setTimeout(() => { + setInputValue(""); + }, 0); + } else if (key === "Backspace" + && value === "" + && typedChips.length > 0) { + setTypedChips((prevChips) => prevChips.slice(0, -1)); + } + }; + + const removeTypedChip = (chip: string) => { + setTypedChips((prevChips) => prevChips.filter((c) => c !== chip)); + }; + `} + /> + {version === "old" && ( + + {typedChips.map((chip, index) => ( + removeTypedChip(chip)} + mr="s" + mt="s" + mb="s"/> + ))} + `} + /> + )} + {version === "new" && ( + handleInputChange(detail.name, detail.value)} + onKeyPress={(detail) => handleInputKeyDown(detail.name, detail.value, detail.key)} + width="30ch" + mr="s" + /> + {typedChips.map((chip, index) => ( + removeTypedChip(chip)} + mr="s" + mt="s" + mb="s"/> + ))} + `} + /> + )} + + ); +} diff --git a/src/examples/form-item/FormItemExamples.tsx b/src/examples/form-item/FormItemExamples.tsx new file mode 100644 index 000000000..cab52ed8b --- /dev/null +++ b/src/examples/form-item/FormItemExamples.tsx @@ -0,0 +1,18 @@ +import { FormItemSlottedHelperTextExample } from "@examples/form-item/FormItemSlottedHelperTextExample.tsx"; +import { FormItemSlottedErrorTextExample } from "@examples/form-item/FormItemSlottedErrorTextExample.tsx"; + +export const FormItemExamples = () => { + return ( + <> + + +

Slotted Helper Text

+ + +

Slotted Error Text

+ + + ) +} diff --git a/src/examples/form-item/FormItemSlottedErrorTextExample.tsx b/src/examples/form-item/FormItemSlottedErrorTextExample.tsx new file mode 100644 index 000000000..7450f1805 --- /dev/null +++ b/src/examples/form-item/FormItemSlottedErrorTextExample.tsx @@ -0,0 +1,120 @@ +import { Sandbox } from "@components/sandbox"; +import { GoabFormItem, GoabInput } from "@abgov/react-components"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const FormItemSlottedErrorTextExample = () => { + const { version } = useContext(LanguageVersionContext); + const errorReactNode: React.ReactNode = ( + <> + This is slotted error text. + + ); + const noop = () => {}; + + return ( + + + + + + {/* *********** React code ************/} + (""); + const onChange = (event: GoabInputOnChangeDetail) => { + setValue(event.value); + } + `} + /> + {version === "old" && ( + This is slotted error text.}> + + + `} + /> + )} + + {version === "new" && ( + This is slotted error text.}> + + + `} + /> + )} + + {/* *********** Angular code ************/} + {version === "old" && ( + + + +
+ This is + slotted + error text. +
+ + + `} + /> + )} + + + + {version === "new" && ( + + + + This is + slotted + error text. + + + `} + /> + )} +
+ ); +}; diff --git a/src/examples/form-item/FormItemSlottedHelperTextExample.tsx b/src/examples/form-item/FormItemSlottedHelperTextExample.tsx new file mode 100644 index 000000000..1ecfb1a65 --- /dev/null +++ b/src/examples/form-item/FormItemSlottedHelperTextExample.tsx @@ -0,0 +1,96 @@ +import { Sandbox } from "@components/sandbox"; +import { GoabFormItem, GoabInput } from "@abgov/react-components"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const FormItemSlottedHelperTextExample = () => { + const {version} = useContext(LanguageVersionContext); + const noop = () => {} + const reactNode = <>This is slotted help text.; + + return ( + // Must skip render because we use slotted that isn't supported by sandbox + + {/*React*/} + (""); + const onChange = (event: GoabInputOnChangeDetail) => { + setValue(event.value); + } + `} + /> + + {version === "old" && ( + This is slotted help text.}> + + + `} + /> + )} + + {version === "new" && ( + This is slotted help text.}> + + + `} + /> + )} + + {/*Angular*/} + {version === "old" && + + +
+ This is + slotted + help text. +
+ + + `} + />} + + {version === "new" && + + + This is + slotted + help text. + + + `} + />} + + + + +
+ ) +} diff --git a/src/examples/form-stepper/FormStepperControlledNavigationExample.tsx b/src/examples/form-stepper/FormStepperControlledNavigationExample.tsx new file mode 100644 index 000000000..92879341d --- /dev/null +++ b/src/examples/form-stepper/FormStepperControlledNavigationExample.tsx @@ -0,0 +1,228 @@ +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { + GoabButton, + GoabFormStep, + GoabFormStepper, + GoabPages, + GoabSkeleton, + GoabSpacer +} from "@abgov/react-components"; +import { Sandbox } from "@components/sandbox"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const FormStepperControlledNavigationExample = () => { + const {version} = useContext(LanguageVersionContext); + + const [controlledStep, setControlledStep] = useState(1); + + function setControlledPage(page: number) { + if (page < 1 || page > 4) return; + setControlledStep(page); + } + + return ( + <> +

+ The user needs to partially or completely finish a step to be able to move forward to + the next step. In this case:

+
    +
  • A step that is “Not started” will not be clickable.
  • +
  • A user cannot use the stepper to navigate to another page.
  • +
  • + Clicking the Active step when you are on that step will do nothing. (no page + refresh). +
  • +
+

To use the controlled type you must set a step value ≥ 1

+ + + {/*Must skipRender because we must illustrate the Prev and Next button click logic which cannot be rendered by sandbox*/} + {/*Angular code*/} + {version === "old" && 4) return; + this.step = page + } + } + `} + />} + + {version === "new" && 4) return; + this.step = page + } + } + `} + />} + + {version === "old" && + + + + + + +
+
+
+
+
+
+ Previous + Next +
+ `} + />} + + {version === "new" && + + + + + + +
+
+
+
+
+
+ Previous + Next +
+ `} + />} + + {/*React code*/} + (1); // set to first step + function setPage(page: number) { + if (page < 1 || page > 4) return; + setStep(page); + } + `} + /> + {version === "old" && setStep(step)}> + + + + + + +
+
+
+
+
+
+ setPage(step - 1)}>Previous + setPage(step + 1)}>Next +
+ `} + />} + + {version === "new" && setStep(event.step)}> + + + + + + +
+ {/*Page 1 content*/} +
+
{/* Page 2 content */}
+
{/* Page 3 content */}
+
{/* Page 4 content */}
+
+
+ setPage(step - 1)}>Previous + setPage(step + 1)}>Next +
+ `} + />} + + setControlledStep(event.step)}> + + + + + + +
+ +
+
+ + + + +
+
+ + + +
+
+ + + + +
+
+ +
+ setControlledPage(controlledStep - 1)}> + Previous + + setControlledPage(controlledStep + 1)}> + Next + +
+
+ + ) +} diff --git a/src/examples/form-stepper/FormStepperExamples.tsx b/src/examples/form-stepper/FormStepperExamples.tsx new file mode 100644 index 000000000..c69cef041 --- /dev/null +++ b/src/examples/form-stepper/FormStepperExamples.tsx @@ -0,0 +1,19 @@ +import { + FormStepperControlledNavigationExample +} from "@examples/form-stepper/FormStepperControlledNavigationExample.tsx"; +import { FormStepperStepStatusExample } from "@examples/form-stepper/FormStepperStepStatusExample.tsx"; + +export const FormStepperExamples = () => { + return ( + <> + +

Controlled Navigation

+ + +

Step status

+ + + ) +} diff --git a/src/examples/form-stepper/FormStepperStepStatusExample.tsx b/src/examples/form-stepper/FormStepperStepStatusExample.tsx new file mode 100644 index 000000000..759055c02 --- /dev/null +++ b/src/examples/form-stepper/FormStepperStepStatusExample.tsx @@ -0,0 +1,241 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { + GoabButton, + GoabFormStep, + GoabFormStepper, + GoabPages, + GoabSkeleton, + GoabSpacer +} from "@abgov/react-components"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { GoabFormStepStatus } from "@abgov/ui-components-common"; + +export const FormStepperStepStatusExample = () => { + const {version} = useContext(LanguageVersionContext); + const [statusStep, setStatusStep] = useState(-1); + const status: GoabFormStepStatus[] = ["complete", "complete", "incomplete", "incomplete"]; + + function setStatusPage(page: number) { + if (page < 1 || page > 4) return; + setStatusStep(page); + } + return ( + <> + The status of each step can be configured to either “complete” or “incomplete” using the + status property. + + {/*Angular code*/} + {version === "old" && 4) return; + this.step = page + } + } + `} + />} + {version === "new" && 4) return; + this.step = page + } + } + `} + />} + {version === "old" && + + + + + + +
+
+
+
+
+
+ Previous + Next +
+ `} + />} + {version === "new" && + + + + + + +
+
+
+
+
+
+ Previous + Next +
+ `} + />} + + {version === "old" && (-1); + // controlled by the user based on form completion + const [status, setStatus] = useState([ + "complete", + "complete", + "incomplete", + "incomplete" + ]) + function setPage(page) { + if (page < 1 || page > 4) return; + setStep(page); + } + return ( + <> + setStep(step)}> + + + + + + +
+
+
+
+
+
+ setPage(step - 1)}>Previous + setPage(step + 1)}>Next +
+ + ) + `} + />} + + {version === "new" && (-1); + // controlled by the user based on form completion + const [status, setStatus] = useState([ + "complete", + "complete", + "incomplete", + "incomplete" + ]) + function setPage(page: number) { + if (page < 1 || page > 4) return; + setStep(page); + setStatus((prevStatus) => + prevStatus.map((_, index) => (index < page ? "complete" : "incomplete")) + ); + } + `} + />} + + {version === "new" && setStep(event.step)}> + + + + + + +
{/*Page 1 content*/}
+
{/*Page 2 content*/}
+
{/*Page 3 content*/}
+
{/*Page 4 content*/}
+
+
+ setPage(step - 1)}>Previous + setPage(step + 1)}>Next +
+ `} + />} + + setStatusStep(+event.step)}> + + + + + + +
+ +
+
+ + + + +
+
+ + + +
+
+ + + + +
+
+
+ setStatusPage(statusStep - 1)}> + Previous + + setStatusPage(statusStep + 1)}> + Next + +
+
+ + ) +} diff --git a/src/examples/microsite-header/MicrositeHeaderExamples.tsx b/src/examples/microsite-header/MicrositeHeaderExamples.tsx index 32dc93600..0ea2b2e70 100644 --- a/src/examples/microsite-header/MicrositeHeaderExamples.tsx +++ b/src/examples/microsite-header/MicrositeHeaderExamples.tsx @@ -1,25 +1,30 @@ -import { GoAMicrositeHeader } from "@abgov/react-components"; +import { GoabMicrositeHeader } from "@abgov/react-components"; import { Sandbox } from "@components/sandbox"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; -const onClick = () => { - console.log("Feedback clicked"); - alert("Thank you for your feedback!"); -}; - -export default function MicrositeHeaderExamples () { +export default function MicrositeHeaderExamples() { + const { version } = useContext(LanguageVersionContext); + const onClick = () => { + console.log("Feedback clicked"); + alert("Thank you for your feedback!"); + }; return ( <> - +

Custom click event handler (for feedback)

- - - - + + {/*Angular code*/} + {version === "old" && ( + + /> + )} + {version === "new" && ( + + )} - `} - /> + /> + )} + {version === "new" && ( + + `} + /> + )} - - + /> + )} + {version === "new" && ( + + onClick()} + /> + + ); + } + `} + /> + )} +

Slotted version

{/*Angular*/} -
Slotted version text. @@ -86,24 +148,55 @@ export default function MicrositeHeaderExamples () {
`} - /> + />} + {version === "new" && + + Slotted version text. + v1.23 + + + `} + />} {/*React*/} - Slotted version text.v1.23} > `} - /> - } + {version === "new" && Slotted version text.v1.23} + >
+ `} + />} + Slotted version text.v1.23} + version={ + <> + + Slotted version text. + + v1.23 + + } /> - ) -} \ No newline at end of file + ); +} diff --git a/src/examples/modal/ModalAddAnotherItemExample.tsx b/src/examples/modal/ModalAddAnotherItemExample.tsx new file mode 100644 index 000000000..9acdfccc3 --- /dev/null +++ b/src/examples/modal/ModalAddAnotherItemExample.tsx @@ -0,0 +1,331 @@ +import { + GoabButton, + GoabButtonGroup, + GoabContainer, + GoabDropdown, GoabDropdownItem, + GoabFormItem, GoabInput, + GoabModal, GoabTextarea +} from "@abgov/react-components"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { GoabDropdownOnChangeDetail, GoabTextAreaOnChangeDetail } from "@abgov/ui-components-common"; + +export const ModalAddAnotherItemExample = () => { + const {version} = useContext(LanguageVersionContext); + const [addItemModalOpen, setAddItemModalOpen] = useState(); + const [type, setType] = useState(); + const [name, setName] = useState(); + const [description, setDescription] = useState(); + + const onChangeName = (value: string) => { + setName(value); + }; + + const onChangeDescription = (event: GoabTextAreaOnChangeDetail) => { + setDescription(event.value); + }; + const onChangeType = (event: GoabDropdownOnChangeDetail) => { + setType(event.value); + }; + + return ( + <> + {/*Don't use a Sandbox because the Dropdown inside a modal will make the modal shifts everytime we tab from the dropdown*/} + + + setAddItemModalOpen(true)}> + Add another item + + + + + setAddItemModalOpen(false)}> + Cancel + + setAddItemModalOpen(false)}> + Save new item + + + }> +

Fill in the information to create a new item

+ + + + + + + + onChangeName(event.value)} + value={name} + name="name"> + + + + +
+
+ {/*Angular code*/} + {version === "old" && } + + {version === "new" && } + + {version === "old" && Add another item + +

Fill in the information to create a new item

+ + + + + + + + + + + + +
+ + Cancel + Save new item + +
+
+ `} + />} + + {version === "new" && Add another item + +

Fill in the information to create a new item

+ + + + + + + + + + + + + + + Cancel + Save new item + + +
+ `} + />} + + {/*React code*/} + {version === "old" && (); + const [name, setName] = useState(); + const [description, setDescription] = useState(); + + function onChangeName(name: string, value: string) { + setName(value); + } + + function onChangeDescription(name: string, value: string) { + setDescription(value); + } + + function onChangeType(name: string, value: string[] | string) { + setType(value as string); + }; + + `} + />} + + {version === "new" && (); + const [name, setName] = useState(); + const [description, setDescription] = useState(); + + function onChangeName(value: string) { + setName(value); + } + + function onChangeDescription(event: GoabTextAreaOnChangeDetail) { + setDescription(event.value); + } + + function onChangeType(event: GoabDropdownOnChangeDetail) { + setType(event.value); + }; + + `} + />} + {version === "old" && setOpen(true)}> + Add another item + + + setOpen(false)}> + Cancel + + setOpen(false)}> + Save new item + + + }> +

Fill in the information to create a new item

+ + + + + + + + + + + + +
+ `} + />} + {version === "new" && setOpen(true)}> + Add another item + + + setOpen(false)}> + Cancel + + setOpen(false)}> + Save new item + + + }> +

Fill in the information to create a new item

+ + + + + + + + onChangeName(event.value)} value={name} name="name"> + + + + +
+ `} + />} + + + ) +} diff --git a/src/examples/modal/ModalBasicExample.tsx b/src/examples/modal/ModalBasicExample.tsx new file mode 100644 index 000000000..0ae259c33 --- /dev/null +++ b/src/examples/modal/ModalBasicExample.tsx @@ -0,0 +1,154 @@ +import { Sandbox } from "@components/sandbox"; +import { GoabButton, GoabButtonGroup, GoabModal } from "@abgov/react-components"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const ModalBasicExample = () => { + const {version} = useContext(LanguageVersionContext); + const [basicModalOpen, setBasicModalOpen] = useState(); + return ( + + setBasicModalOpen(true)}>Open Basic Modal + setBasicModalOpen(false)} + actions={ + + setBasicModalOpen(false)}> + Secondary + + setBasicModalOpen(false)}> + Primary + + + }> +

Content

+
+ {/*Angular*/} + + + {version === "old" && ( + Open Basic Modal + +

Content

+
+ + Secondary + Primary + +
+
+ `} + /> + )} + + {version === "new" && ( + Open Basic Modal + +

Content

+ + + Secondary + Primary + + +
+ `} + /> + )} + + {/*React code*/} + + + {version === "old" && ( + setOpen(true)}>Open Basic Modal + setOpen(false)} + actions={ + + setOpen(false)}> + Secondary + + setOpen(false)}> + Primary + + + } + > +

Content

+
+ `} + /> + )} + + {version === "new" && ( + setOpen(true)}>Open Basic Modal + setOpen(false)} + actions={ + + setOpen(false)}> + Secondary + + setOpen(false)}> + Primary + + + } + > +

Content

+
+ `} + /> + )} +
+ ) +} diff --git a/src/examples/modal/ModalConfirmDestructiveActionExample.tsx b/src/examples/modal/ModalConfirmDestructiveActionExample.tsx new file mode 100644 index 000000000..bf0fce3a0 --- /dev/null +++ b/src/examples/modal/ModalConfirmDestructiveActionExample.tsx @@ -0,0 +1,161 @@ +import { GoabButton, GoabButtonGroup, GoabModal } from "@abgov/react-components"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { Sandbox } from "@components/sandbox"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const ModalConfirmDestructiveActionExample = () => { + const {version} = useContext(LanguageVersionContext); + const [destructiveModalOpen, setDestructiveModalOpen] = useState(); + return ( + + setDestructiveModalOpen(true)}> + Delete my application + + + setDestructiveModalOpen(false)}> + Cancel + + setDestructiveModalOpen(false)}> + Delete application + + + }> +

This action cannot be undone.

+
+ + {/*Angular code*/} + + + {version === "old" && ( + Delete my application + +

This action cannot be undone.

+
+ + Cancel + Delete application + +
+
+ `} + /> + )} + {version === "new" && ( + Delete my application + +

This action cannot be undone.

+ + + Cancel + Delete application + + +
+ `} + /> + )} + + {/*React code*/} + + + {version === "old" && ( + setOpen(true)}>Delete my application + setOpen(false)} + actions={ + + setOpen(false)}> + Cancel + + setOpen(false)}> + Delete application + + + } + > +

This action cannot be undone.

+
+ `} + /> + )} + + {version === "new" && ( + setOpen(true)}>Delete my application + setOpen(false)} + actions={ + + setOpen(false)}> + Cancel + + setOpen(false)}> + Delete application + + + } + > +

This action cannot be undone.

+
+ `} + /> + )} +
+ ) +} diff --git a/src/examples/modal/ModalConfirmRecordChangeExample.tsx b/src/examples/modal/ModalConfirmRecordChangeExample.tsx new file mode 100644 index 000000000..d8c039f51 --- /dev/null +++ b/src/examples/modal/ModalConfirmRecordChangeExample.tsx @@ -0,0 +1,300 @@ +import { + GoabButton, + GoabButtonGroup, + GoabContainer, + GoabDatePicker, + GoabFormItem, + GoabModal +} from "@abgov/react-components"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { GoabDatePickerOnChangeDetail } from "@abgov/ui-components-common"; + +export const ModalConfirmRecordChangeExample = () => { + const {version} = useContext(LanguageVersionContext); + const [inputModalOpen, setInputModalOpen] = useState(); + const [effectiveDate, setEffectiveDate] = useState(new Date()); + + const onChangeEffectiveDate = (detail: GoabDatePickerOnChangeDetail) => { + setEffectiveDate(detail.value as Date); + }; + return ( + <> + {/*Don't use a Sandbox because Datepicker inside a modal will make the modal shifts everytime we click on datepicker*/} + + + setInputModalOpen(true)}>Save and continue + + + + setInputModalOpen(false)}> + Undo address change + + setInputModalOpen(false)}> + Confirm + + + }> + +
+
Before
+
123456 78 Ave NW, Edmonton, Alberta
+
+
+
After
+
881 12 Ave NW, Edmonton, Alberta
+
+
+ + + +
+
+ + + {/*Angular code*/} + {version === "old" && } + + {version === "new" && } + + {version === "old" && Save and continue + + +
+
Before
+
123456 78 Ave NW, Edmonton, Alberta
+
+
+
After
+
881 12 Ave NW, Edmonton, Alberta
+
+
+ + + + +
+ + + Undo address change + + + Confirm + + +
+
+ `} + />} + + {version === "new" && Save and continue + + +
+
Before
+
123456 78 Ave NW, Edmonton, Alberta
+
+
+
After
+
881 12 Ave NW, Edmonton, Alberta
+
+
+ + + + + + + Undo address change + + + Confirm + + + +
+ `} + />} + + {/*React code*/} + {version === "old" && (new Date()); + + const onChangeEffectiveDate = (name: string, value: Date) => { + setEffectiveDate(value); + } + `} + />} + {version === "new" && (new Date()); + + const onChangeEffectiveDate = (detail: GoabDatePickerOnChangeDetail) => { + setEffectiveDate(detail.value as Date); + } + `} + />} + + {version === "old" && setOpen(true)}>Save and continue + setOpen(false)} + actions={ + + setOpen(false)}> + Undo address change + + setOpen(false)}> + Confirm + + + } + > + +
+
Before
+
123456 78 Ave NW, Edmonton, Alberta
+
+
+
After
+
881 12 Ave NW, Edmonton, Alberta
+
+
+ + + +
+ `} + />} + {version === "new" && setOpen(true)}>Save and continue + setOpen(false)} + actions={ + + setOpen(false)}> + Undo address change + + setOpen(false)}> + Confirm + + + } + > + +
+
Before
+
123456 78 Ave NW, Edmonton, Alberta
+
+
+
After
+
881 12 Ave NW, Edmonton, Alberta
+
+
+ + + +
+ `} + />} + + ) +} diff --git a/src/examples/modal/ModalExamples.tsx b/src/examples/modal/ModalExamples.tsx index e2b2bf7e0..38822fc4b 100644 --- a/src/examples/modal/ModalExamples.tsx +++ b/src/examples/modal/ModalExamples.tsx @@ -1,788 +1,34 @@ -import { LanguageContext, Sandbox } from "@components/sandbox"; -import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; -import { - GoAButton, - GoAButtonGroup, - GoAContainer, - GoADatePicker, - GoADropdown, - GoADropdownItem, - GoAFormItem, - GoAInput, - GoAModal, - GoATextArea, -} from "@abgov/react-components"; -import { useContext, useState } from "react"; -import { useNavigate } from "react-router-dom"; import "./modal-examples.css"; +import { ModalBasicExample } from "@examples/modal/ModalBasicExample.tsx"; +import { ModalConfirmDestructiveActionExample } from "@examples/modal/ModalConfirmDestructiveActionExample.tsx"; +import { ModalWarnUserDeadlineExample } from "@examples/modal/ModalWarnUserDeadlineExample.tsx"; +import { ModalConfirmRecordChangeExample } from "@examples/modal/ModalConfirmRecordChangeExample.tsx"; +import { ModalAddAnotherItemExample } from "@examples/modal/ModalAddAnotherItemExample.tsx"; +import { ModalRouteChangeExample } from "@examples/modal/ModalRouteChangeExample.tsx"; export default function ModalExamples() { - // hooks - const [basicModalOpen, setBasicModalOpen] = useState(); - const [destructiveModalOpen, setDestructiveModalOpen] = useState(); - const [warnCalloutModalOpen, setWarnCalloutModalOpen] = useState(); - const [inputModalOpen, setInputModalOpen] = useState(); - const [effectiveDate, setEffectiveDate] = useState(new Date()); - const [onRouteChangeModalOpen, setOnRouteChangeModalOpen] = useState(); - const [addItemModalOpen, setAddItemModalOpen] = useState(); - const [type, setType] = useState(); - const [name, setName] = useState(); - const [description, setDescription] = useState(); - - const navigate = useNavigate(); - const language = useContext(LanguageContext); - // @ts-ignore - const onChangeEffectiveDate = (name: string, value: Date | undefined) => { - setEffectiveDate(value); - }; - - // @ts-ignore - const onChangeType = (name: string, value: string[] | string) => { - setType(value as string); - }; - - // @ts-ignore - const onChangeName = (name: string, value: string) => { - setName(value); - } - - // @ts-ignore - const onChangeDescription = (name: string, value: string) => { - setDescription(value); - } - return ( <>

Basic Modal

- - setBasicModalOpen(true)}>Open Basic Modal - setBasicModalOpen(false)} - actions={ - - setBasicModalOpen(false)}> - Secondary - - setBasicModalOpen(false)}> - Primary - - - }> -

Content

-
- - Open Basic Modal - -

Content

-
- - Secondary - Primary - -
-
- `} - /> - - - setOpen(true)}>Open Basic Modal - setOpen(false)} - actions={ - - setOpen(false)}> - Secondary - - setOpen(false)}> - Primary - - - } - > -

Content

-
- `} - /> -
+

Confirm a destructive action

- - setDestructiveModalOpen(true)}> - Delete my application - - - setDestructiveModalOpen(false)}> - Cancel - - setDestructiveModalOpen(false)}> - Delete application - - - }> -

This action cannot be undone.

-
- - - Delete my application - -

This action cannot be undone.

-
- - Cancel - Delete application - -
-
- `} - /> - - - setOpen(true)}>Delete my application - setOpen(false)} - actions={ - - setOpen(false)}> - Cancel - - setOpen(false)}> - Delete application - - - } - > -

This action cannot be undone.

-
- `} - /> -
+

Warn a user of a deadline

- - setWarnCalloutModalOpen(true)}> - Save for later - - setWarnCalloutModalOpen(false)} - actions={ - - setWarnCalloutModalOpen(false)}> - I understand - - - }> -

- You’ve selected to adjourn a matter that is required to appear today. This Calgary court - location does not accept adjournment requests past 1PM MST. Please submit your - adjournment request as soon as possible. -

-
- - Save for later - -

You’ve selected to adjourn a matter that is required to appear today. This Calgary court location does not accept adjournment requests past 1PM MST. Please submit your adjournment request as soon as possible.

-
- - - I understand - - -
-
- `} - /> - - setOpen(true)}>Save for later - setOpen(false)} - actions={ - - setOpen(false)}>I understand - - } - > -

You’ve selected to adjourn a matter that is required to appear today. This Calgary court location does not accept adjournment requests past 1PM MST. Please submit your adjournment request as soon as possible.

-
- `} - /> -
+

Confirm record change

- {/*Don't use a Sandbox because Datepicker inside a modal will make the modal shifts everytime we click on datepicker*/} - - - setInputModalOpen(true)}>Save and continue - - - - setInputModalOpen(false)}> - Undo address change - - setInputModalOpen(false)}> - Confirm - - - }> - -
-
Before
-
123456 78 Ave NW, Edmonton, Alberta
-
-
-
After
-
881 12 Ave NW, Edmonton, Alberta
-
-
- - - -
-
- - - {language === "angular" && ( - <> - - - Save and continue - - -
-
Before
-
123456 78 Ave NW, Edmonton, Alberta
-
-
-
After
-
881 12 Ave NW, Edmonton, Alberta
-
-
- - - - -
- - - Undo address change - - - Confirm - - -
-
- `} - /> - - )} - - {language === "react" && ( - <> - (new Date()); - - const onChangeEffectiveDate = (name: string, value: Date) => { - setEffectiveDate(value); - } - `} - /> - - setOpen(true)}>Save and continue - setOpen(false)} - actions={ - - setOpen(false)}> - Undo address change - - setOpen(false)}> - Confirm - - - } - > - -
-
Before
-
123456 78 Ave NW, Edmonton, Alberta
-
-
-
After
-
881 12 Ave NW, Edmonton, Alberta
-
-
- - - -
- `} - /> - - )} +

Add another item

- {/*Don't use a Sandbox because the Dropdown inside a modal will make the modal shifts everytime we tab from the dropdown*/} - - - setAddItemModalOpen(true)}> - Add another item - - - - - setAddItemModalOpen(false)}> - Cancel - - setAddItemModalOpen(false)}> - Save new item - - - }> -

Fill in the information to create a new item

- - - - - - - - - - - - -
-
- - {language === "angular" && ( - <> - - Add another item - -

Fill in the information to create a new item

- - - - - - - - - - - - -
- - Cancel - Save new item - -
-
- `} - /> - - )} - - {language === "react" && ( - <> - (); - const [name, setName] = useState(); - const [description, setDescription] = useState(); - - function onChangeName(name: string, value: string) { - setName(value); - } - - function onChangeDescription(name: string, value: string) { - setDescription(value); - } - - function onChangeType(name: string, value: string[] | string) { - setType(value as string); - }; - - `} - /> - setOpen(true)}> - Add another item - - - setOpen(false)}> - Cancel - - setOpen(false)}> - Save new item - - - }> -

Fill in the information to create a new item

- - - - - - - - - - - - -
- `} - /> - - )} +

Route changes

- - this.router.navigate(["/components"]), 0) - } - } - `} - /> - - Open - -
- - Cancel - Change route - -
-
- `} - /> - - - - - setOpen(true)}>Open - setOpen(false)} - actions={ - - setOpen(false)}> - Cancel - - { - setOpen(false); - // setTimeout will allow any modal transitions to be run - // setTimeout(() => navigate("/some-path"), 300) } - navigate("/components") - }}>Change route - - } - > - `} - /> - setOnRouteChangeModalOpen(true)}>Open - setOnRouteChangeModalOpen(false)} - actions={ - - setOnRouteChangeModalOpen(false)}> - Cancel - - { - setOnRouteChangeModalOpen(false); - navigate("/components"); - }}> - Change route - - - }> -
+ ); } diff --git a/src/examples/modal/ModalRouteChangeExample.tsx b/src/examples/modal/ModalRouteChangeExample.tsx new file mode 100644 index 000000000..9296863be --- /dev/null +++ b/src/examples/modal/ModalRouteChangeExample.tsx @@ -0,0 +1,172 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabButton, GoabButtonGroup, GoabModal } from "@abgov/react-components"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { useNavigate } from "react-router-dom"; + +export const ModalRouteChangeExample = () => { + const {version} = useContext(LanguageVersionContext); + const [onRouteChangeModalOpen, setOnRouteChangeModalOpen] = useState(); + const navigate = useNavigate(); + + return ( + + + {/*Angular code*/} + this.router.navigate(["/components"]), 0) + } + } + `} + /> + + {version === "old" && Open + +
+ + Cancel + Change route + +
+
+ `} + />} + + {version === "new" && Open + + + + Cancel + Change route + + + + `} + />} + + + + + {version === "old" && setOpen(true)}>Open + setOpen(false)} + actions={ + + setOpen(false)}> + Cancel + + { + setOpen(false); + // setTimeout will allow any modal transitions to be run + // setTimeout(() => navigate("/some-path"), 300) } + navigate("/components") + }}>Change route + + } + > + `} + />} + + {version === "new" && setOpen(true)}>Open + setOpen(false)} + actions={ + + setOpen(false)}> + Cancel + + { + setOpen(false); + // setTimeout will allow any modal transitions to be run + // setTimeout(() => navigate("/some-path"), 300) } + navigate("/components") + }}>Change route + + } + > + `} + />} + + setOnRouteChangeModalOpen(true)}>Open + setOnRouteChangeModalOpen(false)} + actions={ + + setOnRouteChangeModalOpen(false)}> + Cancel + + { + setOnRouteChangeModalOpen(false); + navigate("/components"); + }}> + Change route + + + }> +
+ ) +} diff --git a/src/examples/modal/ModalWarnUserDeadlineExample.tsx b/src/examples/modal/ModalWarnUserDeadlineExample.tsx new file mode 100644 index 000000000..a911b3966 --- /dev/null +++ b/src/examples/modal/ModalWarnUserDeadlineExample.tsx @@ -0,0 +1,153 @@ +import { Sandbox } from "@components/sandbox"; +import { GoabButton, GoabButtonGroup, GoabModal } from "@abgov/react-components"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const ModalWarnUserDeadlineExample = () => { + const {version} = useContext(LanguageVersionContext); + const [warnCalloutModalOpen, setWarnCalloutModalOpen] = useState(); + return ( + + setWarnCalloutModalOpen(true)}> + Save for later + + setWarnCalloutModalOpen(false)} + actions={ + + setWarnCalloutModalOpen(false)}> + I understand + + + }> +

+ You’ve selected to adjourn a matter that is required to appear today. This Calgary court + location does not accept adjournment requests past 1PM MST. Please submit your + adjournment request as soon as possible. +

+
+ + {/*Angular code*/} + + {version === "old" && ( + Save for later + +

You’ve selected to adjourn a matter that is required to appear today. This Calgary court location does not accept adjournment requests past 1PM MST. Please submit your adjournment request as soon as possible.

+
+ + + I understand + + +
+
+ `} + /> + )} + {version === "new" && ( + Save for later + +

You’ve selected to adjourn a matter that is required to appear today. This Calgary court location does not accept adjournment requests past 1PM MST. Please submit your adjournment request as soon as possible.

+ + + + I understand + + + +
+ `} + /> + )} + + {/*React code*/} + + + {version === "old" && ( + setOpen(true)}>Save for later + setOpen(false)} + actions={ + + setOpen(false)}>I understand + + } + > +

You’ve selected to adjourn a matter that is required to appear today. This Calgary court location does not accept adjournment requests past 1PM MST. Please submit your adjournment request as soon as possible.

+
+ `} + /> + )} + + {version === "new" && ( + setOpen(true)}>Save for later + setOpen(false)} + actions={ + + setOpen(false)}>I understand + + } + > +

You’ve selected to adjourn a matter that is required to appear today. This Calgary court location does not accept adjournment requests past 1PM MST. Please submit your adjournment request as soon as possible.

+
+ `} + /> + )} +
+ ) +} diff --git a/src/examples/pagination/PaginationExamples.tsx b/src/examples/pagination/PaginationExamples.tsx new file mode 100644 index 000000000..8a98352bc --- /dev/null +++ b/src/examples/pagination/PaginationExamples.tsx @@ -0,0 +1,580 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { + GoabBlock, + GoabDropdown, + GoabDropdownItem, + GoabPagination, + GoabSpacer, + GoabTable, +} from "@abgov/react-components"; +import { useContext, useEffect, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { GoabDropdownOnChangeDetail } from "@abgov/ui-components-common"; +import { faker } from "@faker-js/faker"; + +interface User { + id: string; + firstName: string; + lastName: string; + age: number; +} + +export const PaginationExamples = () => { + const { version } = useContext(LanguageVersionContext); + const [users, setUsers] = useState([]); + const [pageUsers, setPageUsers] = useState([]); + const [page, setPage] = useState(1); + const [perPage, setPerPage] = useState(10); + + useEffect(() => { + const _users = []; + for (let i = 1; i <= 100; i++) { + _users.push({ + id: faker.datatype.uuid(), + firstName: faker.name.firstName(), + lastName: faker.name.lastName(), + age: faker.datatype.number({ min: 18, max: 60 }), + }); + } + setUsers(_users); + setPageUsers(_users.slice(0, perPage)); + }, [perPage]); + + function changePage(newPage: number) { + const offset = (newPage - 1) * 10; + const _users = users.slice(offset, offset + perPage); + setPage(newPage); + setPageUsers(_users); + } + + function handlePerPageCountChangeEvent(event: GoabDropdownOnChangeDetail) { + const perPageValue = parseInt(event.value || "1"); + setPage(1); + setPerPage(perPageValue); + const _users = users.slice(0, perPageValue); + setPageUsers(_users); + } + + return ( + <> + + +

Show X per page

+ + {/*============= React code ==============*/} + {version === "old" && ( + ([]); + const [pageUsers, setPageUsers] = useState([]); + const [page, setPage] = useState(1); + const [perPage, setPerPage] = useState(10); + + useEffect(() => { + const _users = []; + for (let i = 1; i <= 100; i++) { + _users.push({ + id: faker.datatype.uuid(), + firstName: faker.name.firstName(), + lastName: faker.name.lastName(), + age: faker.datatype.number({ min: 18, max: 60 }), + }); + } + setUsers(_users); + setPageUsers(_users.slice(0, perPage)); + }, [perPage]); + + function changePage(newPage: number) { + const offset = (newPage - 1) * 10; + const _users = users.slice(offset, offset + perPage); + setPage(newPage); + setPageUsers(_users); + } + + function handlePerPageCountChangeEvent(name: string, value: string | string[]) { + const perPageValue = Array.isArray(value) ? parseInt(value[0]) : parseInt(value); + setPage(1); + setPerPage(perPageValue); + const _users = users.slice(0, perPageValue); + setPageUsers(_users); + } + `} + /> + )} + + {version === "new" && ( + ([]); + const [pageUsers, setPageUsers] = useState([]); + const [page, setPage] = useState(1); + const [perPage, setPerPage] = useState(10); + + useEffect(() => { + const _users = []; + for (let i = 1; i <= 100; i++) { + _users.push({ + id: faker.string.uuid(), + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), + age: faker.number.int({ min: 18, max: 60 }), + }); + } + setUsers(_users); + setPageUsers(_users.slice(0, perPage)); + }, [perPage]); + + function changePage(newPage: number) { + const offset = (newPage - 1) * 10; + const _users = users.slice(offset, offset + perPage); + setPage(newPage); + setPageUsers(_users); + } + + function handlePerPageCountChangeEvent(event: GoabDropdownOnChangeDetail) { + const perPageValue = parseInt(event.value || '1'); + setPage(1); + setPerPage(perPageValue); + const _users = users.slice(0, perPageValue); + setPageUsers(_users); + } + `} + /> + )} + + {version === "old" && ( + + + + First name + Last name + Age + + + + {pageUsers.map((u) => ( + + {u.firstName} + {u.lastName} + {u.age} + + ))} + + + + + + Show + + + + + + of {users.length} + + + + + + + `} + /> + )} + + {version === "new" && ( + + + + First name + Last name + Age + + + + {pageUsers.map((u) => ( + + {u.firstName} + {u.lastName} + {u.age} + + ))} + + + + + + Show + + + + + + of {users.length} + + + + + changePage(event.page)} + /> + + `} + /> + )} + + {/*================ Angular code ==================*/} + {version === "old" && ( + + )} + + {version === "new" && ( + + )} + + {version === "old" && ( + + + + First name + Last name + Age + + + + + {{ user.firstName }} + {{ user.lastName }} + {{ user.age }} + + + + + + + Show + + + + + + + + + + + + + + of {{ this.users.length }} + + + + + + + + + `} + /> + )} + + {version === "new" && ( + + + + First name + Last name + Age + + + + + {{ user.firstName }} + {{ user.lastName }} + {{ user.age }} + + + + + + + Show + + + + + + + + + + + + + of {{ this.users.length }} + + + + + + + + `} + /> + )} + + + + + First name + Last name + Age + + + + {pageUsers.map(u => ( + + {u.firstName} + {u.lastName} + {u.age} + + ))} + + + + + + Show + + {[10, 20, 30].map(value => ( + + ))} + + per page + + + + changePage(event.page)} + /> + + + + ); +}; diff --git a/src/examples/question-page/QuestionPageExamples.tsx b/src/examples/question-page/QuestionPageExamples.tsx index 6b0ae5415..5d3a7e920 100644 --- a/src/examples/question-page/QuestionPageExamples.tsx +++ b/src/examples/question-page/QuestionPageExamples.tsx @@ -1,16 +1,19 @@ import { Sandbox } from "@components/sandbox"; -import { - GoAButton, - GoADetails, GoADropdown, GoADropdownItem, - GoAFormItem, GoAInput, - GoARadioGroup, - GoARadioItem -} from "@abgov/react-components"; import "./question-page-example.css"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { + GoabButton, + GoabDetails, GoabDropdown, GoabDropdownItem, + GoabFormItem, + GoabInput, + GoabRadioGroup, + GoabRadioItem +} from "@abgov/react-components"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { useContext } from "react"; export default function QuestionPageExamples() { - + const {version} = useContext(LanguageVersionContext); return (
@@ -51,21 +54,21 @@ export default function QuestionPageExamples() { Back - - {}}> - - + {}}> + + No - - - - + + + + Save and continue - +
@@ -126,15 +129,15 @@ export default function QuestionPageExamples() { categorized under 'school'.

Contact your provider if you’re concerned about your school status.

- - {}}> - - - - - + + {}}> + + + + + Save and continue - +
@@ -176,26 +179,26 @@ export default function QuestionPageExamples() { Back - - {}}> - - - - + + + + - +

We ask this question to determine if you are eligible for child care benefits.

-
- + + Save and continue - +
@@ -246,18 +249,18 @@ export default function QuestionPageExamples() { Back

Personal information

- - + {}}> - - - - - + + + + + Save and continue - +
@@ -307,18 +310,18 @@ export default function QuestionPageExamples() { Back

Question 3 of 9

- - + {}}> - - - - - + + + + + Save and continue - +
@@ -373,53 +376,53 @@ export default function QuestionPageExamples() {

Your address

This is the home address of the person applying

- - + {}} name="address-line-1" ariaLabel="Address line 1" width="100%" /> - - - + + {}} name="address-line-2" ariaLabel="Address line 2" width="100%" /> - - - + + {}} name="town-city" ariaLabel="Town or city name" width={"460px"} /> - - - {}} name="province-territory" ariaLabelledBy="provinceLabel"> - - - - - - - - - - - - - - - - - {}} name="postal-code" width={"105px"} /> - - + + + {}} name="province-territory" ariaLabelledBy="provinceLabel"> + + + + + + + + + + + + + + + + + {}} name="postal-code" width={"105px"} /> + + Save and continue - +
@@ -471,7 +474,8 @@ export default function QuestionPageExamples() { /> {/*Angular Code Snippet - need for leadingContent slot*/} - `} - /> + />} + + {version === "new" && + Back + +

+ Step 1 of 5 +

+

+ Personal information +

+ + + + + +
+1
+
+
+ + + + + Save and continue + + `} + />} {/*React Code Snippet - need for leadingContent slot*/} - `} - /> + />} + + {version === "new" && + Back + +

Step 1 of 5

+

Personal information

+ + {}} name="name" ariaLabel="what is your name?" width="50ch" /> + + + {}} + name="phone-number" + ariaLabel="what is your phone number?" + leadingContent="+1" + /> + + + {}} + name="postal-code" + width="14ch" + ariaLabel="what is your home postal code"> + + + Save and continue + + `} + />} Back @@ -543,27 +612,27 @@ export default function QuestionPageExamples() {

Step 1 of 5

Personal information

- - {}} name="name" ariaLabel="what is your name?" width="50ch" /> - - - + {}} name="name" ariaLabel="what is your name?" width="50ch" /> + + + {}} name="phone-number" ariaLabel="what is your phone number?" leadingContent="+1" /> - - - + + {}} name="postal-code" width="14ch" - ariaLabel="what is your home postal code"> - - + ariaLabel="what is your home postal code"> + + Save and continue - +
); diff --git a/src/examples/radio/RadioExamples.tsx b/src/examples/radio/RadioExamples.tsx index 8cab85aea..c9fa0b997 100644 --- a/src/examples/radio/RadioExamples.tsx +++ b/src/examples/radio/RadioExamples.tsx @@ -1,115 +1,17 @@ -import { GoARadioGroup, GoARadioItem, GoAFormItem } from "@abgov/react-components"; -import { Sandbox } from "@components/sandbox"; -import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; - -const noop = () => { }; +import { RadioSlottedDescriptionExample } from "@examples/radio/RadioSlottedDescriptionExample.tsx"; +import { RadioMaxWidthExample } from "@examples/radio/RadioMaxWidthExample.tsx"; export default function RadioExamples () { + return ( - <> - + <> +

Use tags in the description

- - {/*Angular*/} - - - - Help text with a
link. - - - - - - `} - /> - {/*React*/} - - - Help text with a link.} - /> - - - - - `} - /> - - - Help text with a link.} - /> - - - - - +

Radio item with max width

- - {/*Angular*/} - - - - - - - - `} - /> - {/*React*/} - - - - - - - - `} - /> - - - - - - - - + ); -} \ No newline at end of file +} diff --git a/src/examples/radio/RadioMaxWidthExample.tsx b/src/examples/radio/RadioMaxWidthExample.tsx new file mode 100644 index 000000000..fe9041fea --- /dev/null +++ b/src/examples/radio/RadioMaxWidthExample.tsx @@ -0,0 +1,62 @@ +import { Sandbox } from "@components/sandbox"; +import { GoabFormItem, GoabRadioGroup, GoabRadioItem } from "@abgov/react-components"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; + +export const RadioMaxWidthExample = () => { + const {version} = useContext(LanguageVersionContext); + const [selectOne, setSelectOne] = useState("1"); + return ( + + {/*We skipRenderOnly React because it is quite complex to remove value (2 els have value: radio-item and radio-group which radio-group is the one should remove value*/} + {version === "old" && ( + + setValue(value)}> + + + + + + `} + /> + )} + + {version === "new" && ( + + setValue(e.value)}> + + + + + + `} + /> + )} + +
+ + setSelectOne(e.value)}> + + + + + +
+
+ ); +}; diff --git a/src/examples/radio/RadioSlottedDescriptionExample.tsx b/src/examples/radio/RadioSlottedDescriptionExample.tsx new file mode 100644 index 000000000..eb03ab42e --- /dev/null +++ b/src/examples/radio/RadioSlottedDescriptionExample.tsx @@ -0,0 +1,131 @@ +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabFormItem, GoabRadioGroup, GoabRadioItem } from "@abgov/react-components"; +import { Sandbox } from "@components/sandbox"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const RadioSlottedDescriptionExample = () => { + const {version} = useContext(LanguageVersionContext); + const noop = () => {} + return ( + + {/* =========== Angular =============== */} + {version === "old" && ( + + + + Help text with a link. + + + + + + `} + /> + )} + {version === "new" && ( + + )} + + {version === "new" && ( + + + + + Help text with a link. + + + + + + + `} + /> + )} + + {/* ============== React ================== */} + {version === "old" && ( + + + Help text with a link.} + /> + + + + + `} + /> + )} + + {version === "new" && ( + + + Help text with a link.} + /> + + + + + `} + /> + )} + + + + + Help text with a link. + + } + /> + + + + + + ) +} diff --git a/src/examples/result-page/ResultPageExamples.tsx b/src/examples/result-page/ResultPageExamples.tsx index ec1f8e575..572249381 100644 --- a/src/examples/result-page/ResultPageExamples.tsx +++ b/src/examples/result-page/ResultPageExamples.tsx @@ -1,13 +1,12 @@ import { Sandbox } from "@components/sandbox"; -import { - GoABlock, - GoACallout, -} from "@abgov/react-components"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; import "./result-page-example.css"; +import { GoabBlock, GoabCallout } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; export function ResultPageExamples() { - + const {version} = useContext(LanguageVersionContext); return (
@@ -32,7 +31,8 @@ export function ResultPageExamples() { `} /> - Phone: 780 123 4567

`} - /> + />} + {version === "new" && + +

We’ve sent your application to service name. They will contact you to confirm your registration.

+

You can now close this window.

+

What did you think of this service? Give feedback

+

If you have questions about your application

+

Contact the [ministry area].

+

Email: information@gov.ab.ca

+

Phone: 780 123 4567

+ + `} + />} - Phone: 780 123 4567

`} - /> + />} + + {version === "new" && +
+

You have completed the application

+ +

You will receive a copy of the confirmation to the email name@email.com

+

Your reference number is: 1234ABC

+
+

What happens next

+
+

We’ve sent your application to service name. They will contact you to confirm your registration.

+

You can now close this window.

+

What did you think of this service? Give feedback

+

If you have questions about your application

+

Contact the [ministry area].

+

Email: information@gov.ab.ca

+

Phone: 780 123 4567

+ + `} + />} - +

You have completed the application

- +

You will receive a copy of the confirmation to the email name@email.com

Your reference number is: 1234ABC

-
+

What happens next

@@ -112,7 +165,7 @@ export function ResultPageExamples() {

Phone: 780 123 4567

-
+
); diff --git a/src/examples/review-page/ReviewPageExamples.tsx b/src/examples/review-page/ReviewPageExamples.tsx index 4dd0032f3..dd5b5c827 100644 --- a/src/examples/review-page/ReviewPageExamples.tsx +++ b/src/examples/review-page/ReviewPageExamples.tsx @@ -1,11 +1,7 @@ import { Sandbox } from "@components/sandbox"; -import { - GoAButton, - GoAButtonGroup, - GoATable -} from "@abgov/react-components"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; import "./review-page-example.css"; +import { GoabButton, GoabButtonGroup, GoabTable } from "@abgov/react-components"; export function ReviewPageExamples() { @@ -38,7 +34,7 @@ export function ReviewPageExamples() { />

Review your answers

Your situation

- + @@ -46,7 +42,7 @@ export function ReviewPageExamples() { Other - Change + Change @@ -55,7 +51,7 @@ export function ReviewPageExamples() { Manager - Change + Change @@ -67,7 +63,7 @@ export function ReviewPageExamples() { No - Change + Change @@ -76,7 +72,7 @@ export function ReviewPageExamples() { No - Change + Change @@ -85,7 +81,7 @@ export function ReviewPageExamples() { Married - Change + Change @@ -94,7 +90,7 @@ export function ReviewPageExamples() { No - Change + Change @@ -103,15 +99,15 @@ export function ReviewPageExamples() { Yes - Change + Change - - - Confirm and continue - Back to application overview - + + + Confirm and continue + Back to application overview +
); diff --git a/src/examples/start-page/StartPageExamples.tsx b/src/examples/start-page/StartPageExamples.tsx index ef46c9a06..681524ed6 100644 --- a/src/examples/start-page/StartPageExamples.tsx +++ b/src/examples/start-page/StartPageExamples.tsx @@ -1,10 +1,14 @@ import { Sandbox } from "@components/sandbox"; import { - GoAButton, + GoabButton, } from "@abgov/react-components"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; import "./start-page-example.css"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + export function StartPageExamples() { + const {version} = useContext(LanguageVersionContext); return (
@@ -35,7 +39,9 @@ export function StartPageExamples() { `} /> - Support

For assistance, email us at  help@gov.ab.ca

`} - /> + />} + {version === "new" && + Name of service + +

+ A short overview of the service. This is a couple sentences that helps the user understand what the service is. +

+

+ Use this service to apply for [service]. You can use this service to: +

+
    +
  • see of you or a family member is eligible for [service]
  • +
  • create and submit an application for [service]
  • +
  • continue an application for [service] that you already started
  • +
+

Before you begin

+

The application form should take about 20 minutes to complete.

+

In order to complete the application you will need:

+
    +
  • government issued ID for the person applying
  • +
+ + Get started + +

Other information about the service

+

This section contains supplementary details about the service, including descriptions of less common scenarios, exceptions, and additional resources available. It provides context and additional insights that may be relevant to your specific circumstances or interests, helping you understand the full scope and utility of the service offered.

+

Support

+

For assistance, email us at  help@gov.ab.ca

+ `} + />} - Support

For assistance, email us at  help@gov.ab.ca

`} - /> + />} + {version === "new" && + Name of service + +

+ A short overview of the service. This is a couple sentences that helps the user understand what the service is. +

+

Use this service to apply for [service]. You can use this service to:

+
    +
  • see of you or a family member is eligible for [service]
  • +
  • create and submit an application for [service]
  • +
  • continue an application for [service] that you already started
  • +
+

Before you begin

+

The application form should take about 20 minutes to complete.

+

In order to complete the application you will need:

+
    +
  • government issued ID for the person applying
  • +
+ + Get started + +

+ Other information about the service +

+

+ This section contains supplementary details about the service, including descriptions of less common scenarios, exceptions, and additional resources available. It provides context and additional insights that may be relevant to your specific circumstances or interests, helping you understand the full scope and utility of the service offered. +

+

Support

+

For assistance, email us at  help@gov.ab.ca

+ `} + />}

Name of service

@@ -129,9 +207,9 @@ export function StartPageExamples() {
  • government issued ID for the person applying
- {}}> + {}}> Get started - +

Other information about the service

diff --git a/src/examples/tabs/TabsDifferentViewsTableExample.tsx b/src/examples/tabs/TabsDifferentViewsTableExample.tsx new file mode 100644 index 000000000..c12f15530 --- /dev/null +++ b/src/examples/tabs/TabsDifferentViewsTableExample.tsx @@ -0,0 +1,499 @@ +import { GoabBadge, GoabButton, GoabContainer, GoabTab, GoabTable, GoabTabs } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; + +export const TabsDifferentViewsTableExample = () => { + const review = [0, 1, 2, 3]; + const complete = [0, 1]; + const {version} = useContext(LanguageVersionContext); + + return ( + <> + +

+ + + + + + Status + Text + Number + Action + + + + {review.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + {complete.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + Review pending}> + + + + Status + Text + Number + Action + + + + {review.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + Complete}> + + + + Status + Text + Number + Action + + + + {complete.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + +
+ + + {/*Angular code*/} + {version === "old" && + +
All
+ + + + Status + Text + Number + Action + + + + + + + + Lorem ipsum + 1234567890 + + Action + + + + + + + Lorem Ipsum + 1234567890 + + Action + + + + +
+ +
Review pending
+ + + + Status + Text + Number + Action + + + + + + + + Lorem ipsum + 1234567890 + + Action + + + + +
+ +
Complete
+ + + + Status + Text + Number + Action + + + + + + + + Lorem Ipsum + 1234567890 + + Action + + + + +
+ + `} + />} + {version === "new" && + + + + + Status + Text + Number + Action + + + + + + Lorem ipsum + 1234567890 + Action + + + + Lorem Ipsum + 1234567890 + Action + + + + + + Review pending + + + + Status + Text + Number + Action + + + + + + + + Lorem ipsum + 1234567890 + Action + + + + + + Complete + + + + Status + Text + Number + Action + + + + + + Lorem Ipsum + 1234567890 + Action + + + + + + `} + />} + + {/*React code*/} + + + {version === "old" && + + + + + Status + Text + Number + Action + + + + {review.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + {complete.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + Review pending}> + + + + Status + Text + Number + Action + + + + {review.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + Complete}> + + + + Status + Text + Number + Action + + + + {complete.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + + `} + />} + + {version === "new" && + + + + + Status + Text + Number + Action + + + + {review.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + {complete.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + Review pending}> + + + + Status + Text + Number + Action + + + + {review.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + Complete}> + + + + Status + Text + Number + Action + + + + {complete.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + + `} + />} + + + +) +} diff --git a/src/examples/tabs/TabsExamples.tsx b/src/examples/tabs/TabsExamples.tsx new file mode 100644 index 000000000..2671a3864 --- /dev/null +++ b/src/examples/tabs/TabsExamples.tsx @@ -0,0 +1,19 @@ +import { TabsDifferentViewsTableExample } from "@examples/tabs/TabsDifferentViewsTableExample.tsx"; +import { TabsSetSpecificTabActiveExample } from "@examples/tabs/TabsSetSpecificTabActiveExample.tsx"; + +export const TabsExamples = () => { + return ( + <> + +

+ Show different views of data in a table +

+ +

Set a specific tab to be active

+ + + + ) +} diff --git a/src/examples/tabs/TabsSetSpecificTabActiveExample.tsx b/src/examples/tabs/TabsSetSpecificTabActiveExample.tsx new file mode 100644 index 000000000..4bfe8bbd2 --- /dev/null +++ b/src/examples/tabs/TabsSetSpecificTabActiveExample.tsx @@ -0,0 +1,510 @@ +import { GoabBadge, GoabButton, GoabContainer, GoabTab, GoabTable, GoabTabs } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; + +export const TabsSetSpecificTabActiveExample = () => { + const review = [0, 1, 2, 3]; + const complete = [0, 1]; + const {version} = useContext(LanguageVersionContext); + + return ( + <> + +
+ + + + + + Status + Text + Number + Action + + + + {review.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + {complete.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + Review pending}> + + + + Status + Text + Number + Action + + + + {review.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + Complete}> + + + + Status + Text + Number + Action + + + + {complete.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + +
+
+ + {/*Angular code*/} + {version === "old" && + +
All
+ + + + Status + Text + Number + Action + + + + + + + + Lorem ipsum + 1234567890 + + Action + + + + + + + Lorem Ipsum + 1234567890 + + Action + + + + +
+ +
Review pending
+ + + + Status + Text + Number + Action + + + + + + + + Lorem ipsum + 1234567890 + + Action + + + + +
+ +
Complete
+ + + + Status + Text + Number + Action + + + + + + + + Lorem Ipsum + 1234567890 + + Action + + + + +
+ + `} + />} + + {version === "new" && + + + + + Status + Text + Number + Action + + + + + + + + Lorem ipsum + 1234567890 + + Action + + + + + + + Lorem Ipsum + 1234567890 + + Action + + + + + + + Review pending + + + + Status + Text + Number + Action + + + + + + + + Lorem ipsum + 1234567890 + + Action + + + + + + + Complete + + + + Status + Text + Number + Action + + + + + + + + Lorem Ipsum + 1234567890 + + Action + + + + + + + `} + />} + {/*React code*/} + + + {version === "old" && + + + + + Status + Text + Number + Action + + + + {review.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + {complete.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + Review pending}> + + + + Status + Text + Number + Action + + + + {review.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + Complete}> + + + + Status + Text + Number + Action + + + + {complete.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + + `} + />} + {version === "new" && + + + + + Status + Text + Number + Action + + + + {review.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + {complete.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + Review pending}> + + + + Status + Text + Number + Action + + + + {review.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + Complete}> + + + + Status + Text + Number + Action + + + + {complete.map((i) => ( + + + + + Lorem Ipsum + 1234567890 + + Action + + + ))} + + + + + `} + />} + + ) +} diff --git a/src/examples/task-list-page/TaskListPageExamples.tsx b/src/examples/task-list-page/TaskListPageExamples.tsx index 0a5e2c77b..b0cc6b96a 100644 --- a/src/examples/task-list-page/TaskListPageExamples.tsx +++ b/src/examples/task-list-page/TaskListPageExamples.tsx @@ -1,5 +1,5 @@ import { Sandbox } from "@components/sandbox"; -import { GoABadge, GoACallout, GoATable } from "@abgov/react-components"; +import { GoabBadge, GoabCallout, GoabTable } from "@abgov/react-components"; import "./task-list-page-example.css"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; @@ -32,42 +32,42 @@ export function TaskListPageExamples() { />

Apply for a service

- You have completed 1 of 3 sections. - +

1. Before you start

- + Reads terms of use - + - +

2. Prepare application

- + Your contact details - + ariaLabel="not started"> @@ -75,10 +75,10 @@ export function TaskListPageExamples() { Your family - + ariaLabel="not started"> @@ -86,41 +86,41 @@ export function TaskListPageExamples() { Verify your identity - + ariaLabel="not started"> - +

3. Schedule service

You need to complete the previous section before you can start this task.

- + Receive email confirmation - + ariaLabel="cannot start yet"> Pay service fee - + ariaLabel="cannot start yet"> - +
); diff --git a/src/examples/text-field/TextFieldAskBirthdayExample.tsx b/src/examples/text-field/TextFieldAskBirthdayExample.tsx new file mode 100644 index 000000000..45b81c2d1 --- /dev/null +++ b/src/examples/text-field/TextFieldAskBirthdayExample.tsx @@ -0,0 +1,121 @@ +import { Sandbox } from "@components/sandbox"; +import { GoabBlock, GoabDropdown, GoabDropdownItem, GoabFormItem, GoabInput } from "@abgov/react-components"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + + +export const TextFieldAskBirthdayExample = () => { + const {version} = useContext(LanguageVersionContext); + + const noop = () => {} + return ( + + {/*React code*/} + {version === "new" && (''); + const [month, setMonth] = useState(''); + const [year, setYear] = useState(''); + `} + />} + + {version === "new" && For example, 27 November 2004}> + + + setDay(event.value)} value={day} name="day" width="6ch"> + + + setMonth(event.value)} name="month" value={month}> + + + + + + + + + + + + + + + + setYear(event.value)} value={year} name="year" width="10ch"> + + + + `} + />} + + {/*Angular code*/} + {version === "new" && } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} diff --git a/src/examples/text-field/TextFieldAskUserAddressExample.tsx b/src/examples/text-field/TextFieldAskUserAddressExample.tsx new file mode 100644 index 000000000..1acc36cd9 --- /dev/null +++ b/src/examples/text-field/TextFieldAskUserAddressExample.tsx @@ -0,0 +1,152 @@ +import { Sandbox } from "@components/sandbox"; +import { GoabBlock, GoabDropdown, GoabDropdownItem, GoabFormItem, GoabInput } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; + +export const TextFieldAskUserAddressExample = () => { + const {version} = useContext(LanguageVersionContext); + const noop = () => {} + return ( + + {/*React code*/} + {version === "new" && (''); + const [suite, setSuite] = useState(''); + const [city, setCity] = useState(''); + const [province, setProvince] = useState('alberta'); + const [postalCode, setPostalCode] = useState(''); + `} + />} + + {version === "new" && + setStreet(event.value)} width="100%"> + + + setSuite(event.value)} width="100%"> + + + setCity(event.value)} width="100%"> + + + + setProvince(event.value)}> + + + + + + + + + + + + + + setPostalCode(event.value)}> + + + `} + />} + + {version === "old" && + + + + + + + + + + + + + + + + + + + + + + + + + + + + `} + />} + + {/*Angular code*/} + {version === "new" && } + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ) +} diff --git a/src/examples/text-field/TextFieldAskUserAmountExample.tsx b/src/examples/text-field/TextFieldAskUserAmountExample.tsx new file mode 100644 index 000000000..75708251f --- /dev/null +++ b/src/examples/text-field/TextFieldAskUserAmountExample.tsx @@ -0,0 +1,212 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabFormItem, GoabInput } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const TextFieldAskUserAmountExample = () => { + const {version} = useContext(LanguageVersionContext); + + const noop = () => {} + return ( + + {/*Angular Code Snippet - need for leadingContent slot*/} + {version === "old" && } + {version === "old" && + +
$
+
+ + + +
$
+
+
+ + +
$
+
+
+ `} + />} + + {/*Reactive FormControl Angular Code Snippet*/} + + + {version === "old" && + + +
$
+
+
+ + +
$
+
+
+ + +
$
+
+
+ + `} + />} + + {version === "new" && + + +
$
+
+
+ + +
$
+
+
+ + +
$
+
+
+ + `} + />} + + {/*React Code Snippet - need for leadingContent slot*/} + {version === "old" && (""); + const [suppliesAmount, setSuppliesAmount] = useState(""); + const [othersAmount, setOthersAmount] = useState(""); + function onChangeTuitionAmount(_name: string, value: string) { + setTuitionAmount(value); + } + function onChangeSuppliesAmount(_name: string, value: string) { + setSuppliesAmount(value); + } + function onChangeOthersAmount(_name: string, value: string) { + setOthersAmount(value); + } + `} + />} + + {version === "new" && (""); + const [suppliesAmount, setSuppliesAmount] = useState(""); + const [othersAmount, setOthersAmount] = useState(""); + function onChangeTuitionAmount(event: GoabInputOnChangeDetail) { + setTuitionAmount(event.value); + } + function onChangeSuppliesAmount(event: GoabInputOnChangeDetail) { + setSuppliesAmount(event.value); + } + function onChangeOthersAmount(event: GoabInputOnChangeDetail) { + setOthersAmount(event.value); + } + `} + />} + + {version === "old" && + + + + + + + + + `} + />} + + {version === "new" && + + + + + + + + + `} + />} + + + + + + + + + + +
+ + ) +} diff --git a/src/examples/text-field/TextFieldAskUserIndianRegistrationExample.tsx b/src/examples/text-field/TextFieldAskUserIndianRegistrationExample.tsx new file mode 100644 index 000000000..74292c1b0 --- /dev/null +++ b/src/examples/text-field/TextFieldAskUserIndianRegistrationExample.tsx @@ -0,0 +1,142 @@ +import { Sandbox } from "@components/sandbox"; +import { GoabBlock, GoabFormItem, GoabInput } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; + +export const TextFieldAskUserIndianRegistrationExample = () => { + const {version} = useContext(LanguageVersionContext); + const noop = () => {} + + return ( + + {/*React code*/} + {version === "old" && + + + + + + + + + + + + + `} + />} + + {version === "new" && (''); + const [family, setFamily] = useState(''); + const [position, setPosition] = useState(''); + `} + />} + {version === "new" && + + + + setBandNo(event.value) + } + value={bandNo} + name="bandNo" + width="88px" + maxLength={3} + > + + + + setFamily(event.value) + } + value={family} + name="family" + width="105px" + maxLength={5} + > + + + + setPosition(event.value) + } + value={position} + name="position" + width="71px" + maxLength={2} + > + + + + `} + />} + + {/*Angular code*/} + {version === "new" && } + + + + + + + + + + + + + + + + ) +} diff --git a/src/examples/text-field/TextFieldExamples.tsx b/src/examples/text-field/TextFieldExamples.tsx index 8ad9e5b6b..9963f7fb7 100644 --- a/src/examples/text-field/TextFieldExamples.tsx +++ b/src/examples/text-field/TextFieldExamples.tsx @@ -1,16 +1,12 @@ -import { Sandbox } from "@components/sandbox"; +import { TextFieldAskUserAddressExample } from "@examples/text-field/TextFieldAskUserAddressExample.tsx"; +import { TextFieldAskBirthdayExample } from "@examples/text-field/TextFieldAskBirthdayExample.tsx"; +import { TextFieldSearchExample } from "@examples/text-field/TextFieldSearchExample.tsx"; +import { TextFieldAskUserAmountExample } from "@examples/text-field/TextFieldAskUserAmountExample.tsx"; import { - GoABlock, - GoAButton, - GoADropdown, - GoADropdownItem, - GoAFormItem, - GoAInput, -} from "@abgov/react-components"; -import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; + TextFieldAskUserIndianRegistrationExample +} from "@examples/text-field/TextFieldAskUserIndianRegistrationExample.tsx"; export default function TextFieldExamples() { - const noop = () => {}; return ( <> {/*Examples*/} @@ -19,261 +15,21 @@ export default function TextFieldExamples() {

Ask a user for an address

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +

Ask a user for their birthday

- - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - Search - - - +

Ask a user for dollar amounts or costs

- - {/*Angular Code Snippet - need for leadingContent slot*/} - - - -
$
-
- - - -
$
-
-
- - -
$
-
-
- `} - /> - - {/*Reactive FormControl Angular Code Snippet*/} - - - - -
$
-
-
- - -
$
-
-
- - -
$
-
-
- - `} - /> - - {/*React Code Snippet - need for leadingContent slot*/} - (""); - const [suppliesAmount, setSuppliesAmount] = useState(""); - const [othersAmount, setOthersAmount] = useState(""); - function onChangeTuitionAmount(_name: string, value: string) { - setTuitionAmount(value); - } - function onChangeSuppliesAmount(_name: string, value: string) { - setSuppliesAmount(value); - } - function onChangeOthersAmount(_name: string, value: string) { - setOthersAmount(value); - } - `} - /> - - - - - - - - - - `} - /> - - - - - - - - - - -
+

Ask a user for their indian registration number

- - - - - - - - - - - - - - - + ); } diff --git a/src/examples/text-field/TextFieldSearchExample.tsx b/src/examples/text-field/TextFieldSearchExample.tsx new file mode 100644 index 000000000..af41377aa --- /dev/null +++ b/src/examples/text-field/TextFieldSearchExample.tsx @@ -0,0 +1,91 @@ +import { GoabBlock, GoabButton, GoabFormItem, GoabInput } from "@abgov/react-components"; +import { Sandbox } from "@components/sandbox"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; + +export const TextFieldSearchExample = () => { + const {version} = useContext(LanguageVersionContext); + const noop = () => {} + return ( + + {/*Angular code*/} + {version === "new" && ( + + )} + + {/*React code*/} + {version === "old" && ( + + + + Search + + + `} + /> + )} + + {version === "new" && ( + (''); + const onClick = () => console.log('search: ', search); + `} + /> + )} + + {version === "new" && ( + + + setSearch(event.value)} leadingIcon="search"> + Search + + + `} + /> + )} + +
+ + + + + Search + + + +
+
+ ); +} diff --git a/src/examples/textarea/TextAreaAskQuestionMoreInformationExample.tsx b/src/examples/textarea/TextAreaAskQuestionMoreInformationExample.tsx new file mode 100644 index 000000000..1012fac7d --- /dev/null +++ b/src/examples/textarea/TextAreaAskQuestionMoreInformationExample.tsx @@ -0,0 +1,69 @@ +import { Sandbox } from "@components/sandbox"; +import { + GoabButton, + GoabButtonGroup, + GoabContainer, + GoabDetails, + GoabFormItem, + GoabTextarea +} from "@abgov/react-components"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const TextAreaAskQuestionMoreInformationExample = () => { + const {version} = useContext(LanguageVersionContext); + const noop = () => {} + return ( + + {version === "new" && } + + + Back + + +

Description

+

+ List all components and include a description, including the number of hours for + each. +

+
+ + + +
+ +

+ Break down your outline into easily digestible sections. This can help to ensure + that the document is well-organized and easy to navigate. +

+
+ + + + Continue + + +
+ + +
+ ) +} diff --git a/src/examples/textarea/TextAreaExamples.tsx b/src/examples/textarea/TextAreaExamples.tsx new file mode 100644 index 000000000..6453d9590 --- /dev/null +++ b/src/examples/textarea/TextAreaExamples.tsx @@ -0,0 +1,15 @@ +import { + TextAreaAskQuestionMoreInformationExample +} from "@examples/textarea/TextAreaAskQuestionMoreInformationExample.tsx"; + +export const TextAreaExamples = () => { + return ( + <> + +

Ask a question and give more information

+ + + ) +} diff --git a/src/examples/tooltip/TooltipClickCopyToClipboardExample.tsx b/src/examples/tooltip/TooltipClickCopyToClipboardExample.tsx new file mode 100644 index 000000000..6357f3cf9 --- /dev/null +++ b/src/examples/tooltip/TooltipClickCopyToClipboardExample.tsx @@ -0,0 +1,152 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabBlock, GoabIconButton, GoabTooltip } from "@abgov/react-components"; +import { getCssVarValue } from "src/utils/styling.ts"; +import { useContext, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const TooltipClickCopyToClipboardExample = () => { + const {version} = useContext(LanguageVersionContext); + const [isCopied, setIsCopied] = useState(false); + + function copyCode() { + const codeToCopy = "$goa-color-interactive-default"; + navigator.clipboard.writeText(codeToCopy).then(() => { + setIsCopied(true); + setTimeout(() => setIsCopied(false), 1000); + }); + } + + return ( + + + {/*Angular code*/} + { + this.isCopied = true; + setTimeout(() => this.isCopied = false, 1000); + }); + } + `} + /> + {version === "old" && +
+ + $goa-color-interactive-default + + + + + + `} + />} + {version === "new" && +
+ + $goa-color-interactive-default + + + + + + `} + />} + + {/*React code*/} + { + setIsCopied(true); + setTimeout(() => setIsCopied(false), 1000); + }); + } + `} + /> + {version === "old" && +
+ + $goa-color-interactive-default + + + + + + `} + />} + {version === "new" && +
+ + $goa-color-interactive-default + + + + + + `} + />} + +
+ + $goa-color-interactive-default + + + + + + + ) +} diff --git a/src/examples/tooltip/TooltipExamples.tsx b/src/examples/tooltip/TooltipExamples.tsx new file mode 100644 index 000000000..87384f962 --- /dev/null +++ b/src/examples/tooltip/TooltipExamples.tsx @@ -0,0 +1,22 @@ +import { TooltipShowFullDateExample } from "@examples/tooltip/TooltipShowFullDateExample.tsx"; +import { + TooltipShowLabelForIconOnlyButtonExample +} from "@examples/tooltip/TooltipShowLabelForIconOnlyButtonExample.tsx"; + +export const TooltipExamples = () => { + return ( + <> + +

Use a tooltip to show a full date when shortened

+ + +

Show a label on an icon only button

+ + +

Click to copy something to your clipboard

+ + + ) +} diff --git a/src/examples/tooltip/TooltipShowFullDateExample.tsx b/src/examples/tooltip/TooltipShowFullDateExample.tsx new file mode 100644 index 000000000..49dfd035f --- /dev/null +++ b/src/examples/tooltip/TooltipShowFullDateExample.tsx @@ -0,0 +1,111 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabContainer, GoabTooltip } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const TooltipShowFullDateExample = () => { + const {version} = useContext(LanguageVersionContext); + return ( + + {/*SkipRender because we need to display a slot that sandbox doesn't support*/} + + {/*Angular code*/} + {version === "old" && +
+ Joan Smith + + 4 hours ago + +
+

Hover on the time it was added to see the full date and time.

+ + `} + />} + {version === "new" && + + Joan Smith + + 4 hours ago + + +

Hover on the time it was added to see the full date and time.

+ + `} + />} + + {/*React code*/} + {version === "old" && + Joan Smith + + + 4 hours ago + + + + }> +

Hover on the time it was added to see the full date and time.

+ + `} + />} + {version === "new" && + Joan Smith + + + 4 hours ago + + + + }> +

Hover on the time it was added to see the full date and time.

+ + `} + />} + + + Joan Smith + + 4 hours ago + + }> +

Hover on the time it was added to see the full date and time.

+
+
+ ) +} diff --git a/src/examples/tooltip/TooltipShowLabelForIconOnlyButtonExample.tsx b/src/examples/tooltip/TooltipShowLabelForIconOnlyButtonExample.tsx new file mode 100644 index 000000000..07f9444fa --- /dev/null +++ b/src/examples/tooltip/TooltipShowLabelForIconOnlyButtonExample.tsx @@ -0,0 +1,20 @@ +import { Sandbox } from "@components/sandbox"; +import { GoabButtonGroup, GoabIconButton, GoabTooltip } from "@abgov/react-components"; + +export const TooltipShowLabelForIconOnlyButtonExample = () => { + return ( + + + + + + + + + + + + + + ) +} diff --git a/src/global-constants.ts b/src/global-constants.ts new file mode 100644 index 000000000..449ee6cab --- /dev/null +++ b/src/global-constants.ts @@ -0,0 +1,3 @@ +export const MAX_CONTENT_WIDTH = "1360px"; +export const DEFAULT_VERSION = "old"; +export const DEFAULT_LANGUAGE = "react"; diff --git a/src/hooks/useSandboxFormItem.tsx b/src/hooks/useSandboxFormItem.tsx index 126710f8f..8c5c96dff 100644 --- a/src/hooks/useSandboxFormItem.tsx +++ b/src/hooks/useSandboxFormItem.tsx @@ -1,8 +1,8 @@ import { useState } from "react"; import { ComponentBinding } from "@components/sandbox"; -import { GoAFormItemProps } from "@abgov/react-components"; +import { GoabFormItemProps } from "@abgov/react-components"; -export const useSandboxFormItem = (initialProps: GoAFormItemProps) => { +export const useSandboxFormItem = (initialProps: GoabFormItemProps) => { const [formItemBindings, setFormItemBindings] = useState( [ { diff --git a/src/routes/components/Accordion.tsx b/src/routes/components/Accordion.tsx index 12bf9036d..0d004b60b 100644 --- a/src/routes/components/Accordion.tsx +++ b/src/routes/components/Accordion.tsx @@ -1,9 +1,9 @@ import { - GoAAccordion, - GoAAccordionProps, - GoABadge, - GoATab, - GoATabs + GoabAccordion, + GoabAccordionProps, + GoabBadge, + GoabTab, + GoabTabs, } from "@abgov/react-components"; import { ComponentProperties, @@ -13,8 +13,13 @@ import { ComponentBinding, Sandbox } from "@components/sandbox"; import { Category, ComponentHeader } from "@components/component-header/ComponentHeader.tsx"; import { useState } from "react"; import AccordionExamples from "@examples/accordion/AccordionExamples.tsx"; -import { GoAHeadingSize } from "@abgov/react-components"; import { ComponentContent } from "@components/component-content/ComponentContent"; +import { GoabAccordionHeadingSize } from "@abgov/ui-components-common"; +import { + LegacyMarginProperty, + LegacyTestIdProperties, + MarginProperty, TestIdProperty +} from "@components/component-properties/common-properties.ts"; // == Page props == const componentName = "Accordion"; @@ -25,15 +30,16 @@ const relatedComponents = [ { link: "/components/tabs", name: "Tabs" }, ]; -type ComponentPropsType = GoAAccordionProps; +type ComponentPropsType = GoabAccordionProps; type CastingType = { heading: string; - headingSize: GoAHeadingSize; + headingSize: GoabAccordionHeadingSize; children: React.ReactNode; [key: string]: unknown; }; -export default function AccordionPage() { +export default function AccordionPage() { + const [accordionProps, setAccordionProps] = useState({ heading: "Heading", headingSize: "medium", @@ -64,8 +70,8 @@ export default function AccordionPage() { { label: "Open", type: "boolean", - name: "open", - value: false + name: "open", + value: false, }, { label: "Max Width", @@ -76,7 +82,7 @@ export default function AccordionPage() { }, ]); - const componentProperties: ComponentProperty[] = [ + const oldComponentProperties: ComponentProperty[] = [ { name: "heading", type: "string", @@ -140,34 +146,69 @@ export default function AccordionPage() { lang: "angular", }, { - name: "testId", - type: "string", + name: "_change", + lang: "angular", + type: "CustomEvent", + description: "Callback function when accordion heading is clicked.", + }, + { + name: "onChange", lang: "react", - description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", + type: "(open: boolean) => void", + description: "Callback function when accordion heading is clicked.", }, + ...LegacyTestIdProperties, + LegacyMarginProperty + ]; + + const componentProperties: ComponentProperty[] = [ { - name: "testid", + name: "heading", type: "string", - lang: "angular", - description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", + required: true, + description: "Sets the heading text.", }, { - name: "mt,mr,mb,ml", - type: "none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl", - description: "Apply margin to the top, right, bottom, and/or left of the component.", + name: "secondaryText", + type: "string", + description: "Sets secondary text.", }, { - name: "_change", + name: "open", + type: "boolean", + defaultValue: "false", + description: "Sets the state of the accordion container open or closed.", + }, + { + name: "headingSize", + type: "GoabAccordionHeadingSize (small | medium)", + defaultValue: "small", + description: "Sets the heading size of the accordion container heading.", + }, + { + name: "headingContent", + type: "ReactNode", + lang: "react", + description: "Add components to the accordion container heading such as badges.", + }, + { + name: "headingContent", + type: "TemplateRef", lang: "angular", - type: "CustomEvent", - description: "Callback function when accordion heading is clicked.", + description: "Add components to the accordion container heading such as badges.", + }, + { + name: "maxWidth", + type: "string", + description: "Sets the maximum width of the accordion.", }, { name: "onChange", - lang: "react", type: "(open: boolean) => void", description: "Callback function when accordion heading is clicked.", - } + }, + TestIdProperty, + MarginProperty, ]; function onSandboxChange(bindings: ComponentBinding[], props: Record) { @@ -177,31 +218,41 @@ export default function AccordionPage() { return (
- + - - -

Component

+ + +

+ Component +

- + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi - + - + -
+ - - Design guidelines - - } - > - -
+ + Design guidelines + + + }> +
); diff --git a/src/routes/components/AllComponents.tsx b/src/routes/components/AllComponents.tsx index 51a19967b..2ba71dcae 100644 --- a/src/routes/components/AllComponents.tsx +++ b/src/routes/components/AllComponents.tsx @@ -1,8 +1,9 @@ -import { GoAGrid, GoAInput, GoAFormItem } from "@abgov/react-components"; +import { GoabGrid, GoabInput, GoabFormItem } from "@abgov/react-components"; import { ComponentCard, Props as ComponentProps } from "@components/component-card/ComponentCard"; import { ReactNode, useState } from "react"; import "./AllComponents.css"; import { ComponentContent } from "@components/component-content/ComponentContent"; +import { GoabInputOnChangeDetail } from "@abgov/ui-components-common"; export default function AllComponentsPage() { const cards: ComponentProps[] = [ @@ -314,6 +315,12 @@ export default function AllComponentsPage() { tags: ["gap", "margin", "padding", "space", "utilities"], description: "Negative area between the components and the interface.", }, + { + name: "text", + groups: ["utilities"], + tags: ["heading", "font", "typography", "utilities"], + description: "Provides consistent sizing, spacing, and colour to written content." + } ]; function getComponentsByGroup(group: string): ReactNode[] { @@ -368,57 +375,57 @@ export default function AllComponentsPage() {
- - + filterComponents(value)} + onChange={(event: GoabInputOnChangeDetail) => filterComponents(event.value)} /> - + - {mode === "search" && {getComponentsByFilter()}} + {mode === "search" && {getComponentsByFilter()}} {mode === "list" && (

Content layout

- + {getComponentsByGroup("content")} - +

Feedback and alerts

- + {getComponentsByGroup("feedback")} - +

Inputs and actions

- + {getComponentsByGroup("inputs")} - +

Structure and navigation

- + {getComponentsByGroup("structure")} - +

Utilities

- + {getComponentsByGroup("utilities")} - + diff --git a/src/routes/components/AppFooter.tsx b/src/routes/components/AppFooter.tsx index 4c16baa6d..b9d76ed6c 100644 --- a/src/routes/components/AppFooter.tsx +++ b/src/routes/components/AppFooter.tsx @@ -1,12 +1,9 @@ import { - GoAAppFooter, - GoAAppFooterMetaSection, - GoAFooterNavSectionProps, - GoAAppFooterNavSection, - GoAAppFooterProps, - GoABadge, - GoATab, - GoATabs, + GoabAppFooter, + GoabAppFooterProps, + GoabBadge, + GoabTab, + GoabTabs, } from "@abgov/react-components"; import { Category, ComponentHeader } from "@components/component-header/ComponentHeader.tsx"; import { @@ -16,8 +13,8 @@ import { import { ComponentBinding, Sandbox } from "@components/sandbox"; import { ComponentContent } from "@components/component-content/ComponentContent"; import { useState, useContext } from "react"; -import { CodeSnippet } from "@components/code-snippet/CodeSnippet"; -import { LanguageContext } from "@components/sandbox"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { AppFooterExamples } from "@examples/app-footer/AppFooterExamples.tsx"; // == Page props == @@ -26,25 +23,21 @@ const description = "Provides information related your service at the bottom of const componentCategory = Category.STRUCTURE_AND_NAVIGATION; const relatedComponents = [ { link: "/components/header", name: "Header" }, - { link: "/patterns", name: "Layout" }, + { link: "/patterns/layout", name: "Layout" }, ]; -type ComponentPropsType = GoAAppFooterProps; -type FooterNavPropsType = GoAFooterNavSectionProps; +type ComponentPropsType = GoabAppFooterProps; + type CastingType = { // add any required props here [key: string]: unknown; }; export default function AppFooterPage() { - const language = useContext(LanguageContext); + const {language} = useContext(LanguageVersionContext); - const [appFooterProps, setAppFooterProps] = useState({ + const [sandbox1Props, setSandbox1Props] = useState({ maxContentWidth: "100%", }); - const [appFooterNavProps, setAppFooterNavProps] = useState({ - maxColumnCount: 1, - heading: "", - }); const [appFooterBindings, setAppFooterBindings] = useState([ { label: "Max content width", @@ -54,27 +47,6 @@ export default function AppFooterPage() { }, ]); - const [appFooterNavBindings, setAppFooterNavBindings] = useState([ - { - label: "Max content width", - type: "string", - name: "maxContentWidth", - value: "100%", - }, - { - label: "Max footer nav columns", - type: "number", - name: "maxColumnCount", - value: 1, - }, - { - label: "Heading", - type: "string", - name: "heading", - value: "", - }, - ]); - const componentProperties: ComponentProperty[] = [ { name: "maxContentWidth", @@ -107,21 +79,17 @@ export default function AppFooterPage() { { name: "slot", lang: "angular", + required: true, type: "nav", description: "Links to nav information to display in the footer", }, ]; function onSandbox1Change(bindings: ComponentBinding[], props: Record) { - setAppFooterProps(props as CastingType); + setSandbox1Props(props as CastingType); setAppFooterBindings(bindings); } - function onSandbox2Change(bindings: ComponentBinding[], props: Record) { - setAppFooterNavProps(props as CastingType); - setAppFooterNavBindings(bindings); - } - return ( <> - - + +

Component

Basic Footer

- + {/*Component properties table*/} @@ -156,223 +124,20 @@ export default function AppFooterPage() { )} {/* Examples*/} - - - - - - - - Privacy - - - Disclaimer - - - Accessibility - - - Using Alberta.ca - - - - `} - /> - - - - - Privacy - - - Disclaimer - - - Accessibility - - - Using Alberta.ca - - - - `} - /> - - - - Privacy - Disclaimer - Accessibility - Using Alberta.ca - - - - - - - - - - Arts and culture - - - Education and training - - - Family and social supports - - - Housing and community - - - Life events - - - Business and economy - - - Emergencies and public safety - - - Government - - - Jobs and employment - - - Moving to Alberta - - - - - Privacy - - - Disclaimer - - - Accessibility - - - Using Alberta.ca - - - - `} - /> - - - - - Arts and culture - - - Education and training - - - Family and social supports - - - Housing and community - - - Life events - - - Business and economy - - - Emergencies and public safety - - - Government - - - Jobs and employment - - - Moving to Alberta - - - - - Privacy - - - Disclaimer - - - Accessibility - - - Using Alberta.ca - - - - `} - /> + - - - Arts and culture - Education and training - Family and social supports - Housing and community - Life events - Business and economy - Emergencies and public safety - Government - Jobs and employment - Moving to Alberta - - - Privacy - Disclaimer - Accessibility - Using Alberta.ca - - - -
+ - Design guidelines - + }>

Coming Soon

-
-
+ +
); diff --git a/src/routes/components/AppHeader.tsx b/src/routes/components/AppHeader.tsx index 6457bb7e2..1f274907a 100644 --- a/src/routes/components/AppHeader.tsx +++ b/src/routes/components/AppHeader.tsx @@ -1,20 +1,20 @@ import { - GoAAppHeader, - GoAAppHeaderMenu, - GoAAppHeaderProps, - GoABadge, GoARadioGroup, GoARadioItem, - GoATab, - GoATabs + GoabAppHeader, + GoabAppHeaderProps, + GoabBadge, + GoabTab, + GoabTabs } from "@abgov/react-components"; import { Category, ComponentHeader } from "@components/component-header/ComponentHeader.tsx"; import { ComponentProperties, ComponentProperty, } from "@components/component-properties/ComponentProperties.tsx"; -import { CodeSnippet } from "@components/code-snippet/CodeSnippet"; import { ComponentBinding, Sandbox } from "@components/sandbox"; import { useState } from "react"; import { ComponentContent } from "@components/component-content/ComponentContent"; +import { LegacyTestIdProperties, TestIdProperty } from "@components/component-properties/common-properties.ts"; +import { AppHeaderExamples } from "@examples/app-header/AppHeaderExamples.tsx"; const componentName = "Header"; const description = @@ -22,10 +22,10 @@ const description = const componentCategory = Category.STRUCTURE_AND_NAVIGATION; const relatedComponents = [ { link: "/components/footer", name: "Footer" }, - { link: "/patterns", name: "Layout" }, + { link: "/patterns/layout", name: "Layout" }, { link: "/components/microsite-header", name: "Microsite header" } ]; -type ComponentPropsType = GoAAppHeaderProps; +type ComponentPropsType = GoabAppHeaderProps; type CastingType = { // add any required props here [key: string]: unknown; @@ -56,7 +56,7 @@ export default function AppHeaderPage() { }, ]); - const componentProperties: ComponentProperty[] = [ + const oldComponentProperties: ComponentProperty[] = [ { name: "url", type: "string", @@ -93,18 +93,7 @@ export default function AppHeaderPage() { description: "Sets the breakpoint in px for the full menu to display.", lang: "react" }, - { - name: "testId", - type: "string", - lang: "react", - description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", - }, - { - name: "testid", - type: "string", - lang: "angular", - description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", - }, + ...LegacyTestIdProperties, { name: "hasmenuclickhandler", type: "boolean", @@ -124,16 +113,42 @@ export default function AppHeaderPage() { description: "Function invoked when the menu hamburger button (on mobile/tablet device) is clicked." } ]; + const componentProperties: ComponentProperty[] = [ + { + name: "url", + type: "string", + description: "Set the URL to link from the alberta.ca logo. A full url is required.", + }, + { + name: "heading", + type: "string", + description: "Set the service name to display in the app header.", + }, + { + name: "maxContentWidth", + type: "string", + description: "Maximum width of the content area.", + defaultValue: "100%", + }, + { + name: "fullMenuBreakpoint", + type: "number", + description: "Sets the breakpoint in px for the full menu to display.", + }, + TestIdProperty, + { + name: "onMenuClick", + type: "() => void", + description: "Function invoked when the menu hamburger button (on mobile/tablet device) is clicked." + } + ]; + function onSandboxChange(bindings: ComponentBinding[], props: Record) { setAppHeaderProps(props as CastingType); setAppHeaderBindings(bindings); } - const [deviceWidth, setDeviceWidth] = useState("5000"); - function handleMenuClick() { - alert("Menu not being displayed and you can do anything"); - } return ( <> - - + +

Component

- + {/*Component properties*/} - - - {/*Examples*/} - - -

Header with navigation

- - - - Support - - Cases - Payments - Outstanding - - Sign in - - `} - /> - - - Support - - Cases - Payments - Outstanding - - Sign in - - `} - /> - - Support - - Cases - Payments - Outstanding - - Sign in - - - -

Header with menu click event

- - setDeviceWidth(value)}> - - - - - Support - - Cases - Payments - Outstanding - - - Sign in - - - - + - - - - - - - Support - - Cases - Payments - Outstanding - - Sign in - - `} - /> - - - - setDeviceWidth(value)}> - - - - - - Support - - Cases - Payments - Outstanding - - Sign in - - `} - /> - -
+ + - Design guidelines - + }>

Coming Soon

-
-
+ +
); diff --git a/src/routes/components/Badge.tsx b/src/routes/components/Badge.tsx index c4ed25af6..5e5ccbaa4 100644 --- a/src/routes/components/Badge.tsx +++ b/src/routes/components/Badge.tsx @@ -1,6 +1,6 @@ import { Category, ComponentHeader } from "@components/component-header/ComponentHeader.tsx"; -import { GoABadge, GoATab, GoATabs, GoABadgeType, GoABadgeProps } from "@abgov/react-components"; -import { Sandbox, ComponentBinding } from "@components/sandbox"; +import { GoabBadge, GoabTab, GoabTabs, GoabBadgeProps } from "@abgov/react-components"; +import { ComponentBinding, Sandbox } from "@components/sandbox"; import { useState } from "react"; import { ComponentProperties, @@ -8,6 +8,7 @@ import { } from "@components/component-properties/ComponentProperties.tsx"; import { ComponentContent } from "@components/component-content/ComponentContent"; import BadgeExamples from "@examples/badge/BadgeExamples.tsx"; +import { GoabBadgeType } from "@abgov/ui-components-common"; // == Page props == @@ -17,20 +18,20 @@ const description = const category = Category.FEEDBACK_AND_ALERTS; const relatedComponents = [ { - link: "/components/chip", name: "Chip" + link: "/components/filter-chip", name: "Filter Chip" }, { - link: "/components/Icons", name: "Icons" + link: "/components/icons", name: "Icons" }, { - link: "/components/Table", name: "Table" + link: "/components/table", name: "Table" } ]; -type ComponentPropsType = GoABadgeProps; +type ComponentPropsType = GoabBadgeProps; type CastingType = { // add any required props here - type: GoABadgeType; + type: GoabBadgeType; content: string; [key: string]: unknown; }; @@ -69,7 +70,7 @@ export default function BadgePage() { }, ]); - const componentProperties: ComponentProperty[] = [ + const oldComponentProperties: ComponentProperty[] = [ { name: "type", type: "success | important | information | emergency | dark | midtone | light", @@ -118,6 +119,41 @@ export default function BadgePage() { }, ]; + const componentProperties: ComponentProperty[] = [ + { + name: "type", + type: "GoabBadgeType(success | important | information | emergency | dark | midtone | light)", + description: "Define the context and colour of the badge", + required: true, + }, + { + name: "icon", + type: "boolean", + description: "Includes an icon in the badge.", + defaultValue: "false", + }, + { + name: "content", + type: "string", + description: "Text label of the badge.", + }, + { + name: "ariaLabel", + type: "string", + description: "Accessible label.", + }, + { + name: "testId", + type: "string", + description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", + }, + { + name: "mt,mr,mb,ml", + type: "Spacing(none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl)", + description: "Apply margin to the top, right, bottom, and/or left of the component.", + }, + ] + function onSandboxChange(badgeBindings: ComponentBinding[], props: Record) { setBadgeBindings(badgeBindings); setBadgeProps(props as CastingType); @@ -128,26 +164,25 @@ export default function BadgePage() { - - + +

Component

- + - + +
-
- - Design guidelines - + } - > -
+ > +
); diff --git a/src/routes/components/Block.tsx b/src/routes/components/Block.tsx index 8c8418228..dc1f70f43 100644 --- a/src/routes/components/Block.tsx +++ b/src/routes/components/Block.tsx @@ -5,7 +5,7 @@ import { ComponentProperty, } from "@components/component-properties/ComponentProperties.tsx"; import { Category, ComponentHeader } from "@components/component-header/ComponentHeader.tsx"; -import { GoABadge, GoABlock, GoATab, GoATabs } from "@abgov/react-components"; +import { GoabBadge, GoabBlock, GoabTab, GoabTabs } from "@abgov/react-components"; import { ComponentContent } from "@components/component-content/ComponentContent"; export default function BlockPage() { @@ -37,7 +37,7 @@ export default function BlockPage() { }, ]); const [sandboxFullWidth, setSandboxFullWidth] = useState(false); - const componentProperties: ComponentProperty[] = [ + const oldComponentProperties: ComponentProperty[] = [ { name: "gap", type: "none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl", @@ -63,6 +63,33 @@ export default function BlockPage() { }, ]; + const componentProperties: ComponentProperty[] = [ + { + name: "gap", + type: "Spacing (none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl)", + description: "Spacing between items", + defaultValue: "m", + }, + { + name: "direction", + type: "GoabBlockDirection (row | column)", + description: "Stacking direction of child components", + defaultValue: "row", + }, + { + name: "alignment", + type: "GoabBlockAlignment (center | start | end | normal) is", + description: "Primary axis alignment", + defaultValue: "normal", + }, + { + name: "mt,mr,mb,ml", + type: "Spacing (none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl)", + description: "Apply margin to the top, right, bottom, and/or left of the component.", + }, + ]; + + useEffect(() => { const direction = blockBindings.find(binding => binding.name === "direction"); setSandboxFullWidth(direction?.value === "column"); @@ -81,19 +108,19 @@ export default function BlockPage() { description="Used when grouping components into a block with consistent space between." relatedComponents={[ { link: "/components/divider", name: "Divider" }, - { link: "/components/Grid", name: "Grid" }, - { link: "/patterns", name: "Layout" }, - { link: "/component/spacer", name: "Spacer" }, + { link: "/components/grid", name: "Grid" }, + { link: "/patterns/layout", name: "Layout" }, + { link: "/components/spacer", name: "Spacer" }, ]} /> - - + +

Component

- +
Item 3
-
+
{/*Block table properties*/} - - + + - Design guidelines - + } - > - + > + ); diff --git a/src/routes/components/Button.tsx b/src/routes/components/Button.tsx index 2fce5c8d6..8ee72232c 100644 --- a/src/routes/components/Button.tsx +++ b/src/routes/components/Button.tsx @@ -1,19 +1,12 @@ import { useState } from "react"; import { - GoABadge, - GoABlock, - GoAButton, - GoAButtonGroup, - GoADropdown, - GoADropdownItem, - GoAFormItem, - GoAInput, - GoATab, - GoATabs, + GoabBadge, + GoabButton, + GoabTab, + GoabTabs, } from "@abgov/react-components"; import { Sandbox, ComponentBinding } from "@components/sandbox"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet"; -import { GoAModal } from "@components/mock-modal/Modal"; import { Category, ComponentHeader } from "@components/component-header/ComponentHeader"; import { ComponentProperties, @@ -21,6 +14,13 @@ import { } from "@components/component-properties/ComponentProperties"; import ICONS from "@routes/components/icons.json"; import { ComponentContent } from "@components/component-content/ComponentContent"; +import { ButtonExamples } from "@examples/button/ButtonExamples.tsx"; +import { + LegacyMarginProperty, + LegacyTestIdProperties, + MarginProperty, + TestIdProperty +} from "@components/component-properties/common-properties.ts"; export default function ButtonPage() { const [buttonProps, setButtonProps] = useState({}); @@ -64,7 +64,7 @@ export default function ButtonPage() { {label: "Width", type: "string", name: "width", value: ""}, { label: "Disabled", type: "boolean", name: "disabled", value: false }, ]); - const componentProperties: ComponentProperty[] = [ + const oldComponentProperties: ComponentProperty[] = [ { name: "type", type: "primary | submit | secondary | tertiary | start", @@ -130,30 +130,65 @@ export default function ButtonPage() { type: "(e: any) => void", description: "Callback function when button is clicked.", }, + ...LegacyTestIdProperties, + LegacyMarginProperty + ]; + const componentProperties: ComponentProperty[] = [ { - name: "testId", - type: "string", - lang: "react", - description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", + name: "type", + type: "GoabButtonType (primary | submit | secondary | tertiary | start)", + description: "Sets the type of button.", + defaultValue: "primary", + }, + { + name: "size", + type: "GoabButtonSize (normal | compact)", + defaultValue: "normal", + description: "Sets the size of button.", + }, + { + name: "variant", + type: "GoabButtonVariant (normal | destructive)", + defaultValue: "normal", + description: "Styles the button to show a destructive action.", + }, + { + name: "disabled", + type: "boolean", + defaultValue: "false", + description: "Disables the button.", + }, + { + name: "leadingIcon", + type: "GoabIconType", + description: "Shows an icon to the left of the text.", + }, + { + name: "trailingIcon", + type: "GoabIconType", + description: "Shows an icon to the right of the text.", }, { - name: "testid", + name: "width", type: "string", - lang: "angular", - description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", + description: "Sets the width of the button.", }, { - name: "mt,mr,mb,ml", - type: "none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl", - description: "Apply margin to the top, right, bottom, and/or left of the component.", + name: "onClick", + type: "() => void", + description: "Callback function when button is clicked.", }, + TestIdProperty, + MarginProperty, ]; - const noop = () => { }; + + const noop = () => {}; function SandboxOnChange(bindings: ComponentBinding[], props: Record) { setButtonBindings(bindings); setButtonProps(props); } + return ( <> - - + + {/*Button Sandbox*/} -

Component

+

+ Component +

- - Primary Button - - - - {/*Button Table Properties*/} - - - {/*Button Examples*/} - + - {/*Button Example 1*/} -

Ask a user for an address

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Submit and continue - - - Cancel - - - - - {/*Button example 2*/} -

Confirm a destructive action

- - -

You cannot undo this action.

- - - - Cancel - - - Delete record - - -
+ + Primary Button +
- {/*Button example 3*/} -

Disabled button with a required field

- - - - + {/*Button Table Properties*/} + - - - Confirm - - - Cancel - - - -
+ + - Design guidelines - + }>

Coming Soon

-
-
+ +
); diff --git a/src/routes/components/ButtonGroup.tsx b/src/routes/components/ButtonGroup.tsx index a3db59cd0..dd9463118 100644 --- a/src/routes/components/ButtonGroup.tsx +++ b/src/routes/components/ButtonGroup.tsx @@ -5,13 +5,14 @@ import { ComponentProperty, } from "@components/component-properties/ComponentProperties.tsx"; import { Category, ComponentHeader } from "@components/component-header/ComponentHeader.tsx"; -import { GoABadge, GoAButton, GoAButtonGroup, GoATab, GoATabs } from "@abgov/react-components"; -import { GoAButtonGroupAlignment } from "@abgov/react-components"; +import { GoabBadge, GoabButton, GoabButtonGroup, GoabTab, GoabTabs } from "@abgov/react-components"; import { ComponentContent } from "@components/component-content/ComponentContent"; +import { GoabButtonGroupAlignment } from "@abgov/ui-components-common"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; export default function ButtonGroupPage() { const [buttonGroupProps, setButtonGroupProps] = useState({ - alignment: "center" as GoAButtonGroupAlignment, + alignment: "center" as GoabButtonGroupAlignment, }); const [buttonGroupBindings, setButtonGroupBindings] = useState([ @@ -32,7 +33,7 @@ export default function ButtonGroupPage() { }, ]); - const componentProperties: ComponentProperty[] = [ + const oldComponentProperties: ComponentProperty[] = [ { name: "alignment", type: "start | end | center", @@ -62,13 +63,38 @@ export default function ButtonGroupPage() { type: "none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl", description: "Apply margin to the top, right, bottom, and/or left of the component.", }, - ]; + ]; + + const componentProperties: ComponentProperty[] = [ + { + name: "alignment", + type: "GoabButtonGroupAlignment (start | end | center)", + description: "Positions the button group in the page layout.", + required: true, + }, + { + name: "gap", + type: "GoabButtonGroupGap (relaxed | compact)", + description: "Sets the spacing between buttons in the button group.", + defaultValue: "relaxed", + }, + { + name: "testId", + type: "string", + description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", + }, + { + name: "mt,mr,mb,ml", + type: "Spacing (none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl)", + description: "Apply margin to the top, right, bottom, and/or left of the component.", + }, + ]; const noop = () => { }; function onSandboxChange(bindings: ComponentBinding[], props: Record) { setButtonGroupBindings(bindings); - setButtonGroupProps(props as { alignment: GoAButtonGroupAlignment;[key: string]: unknown }); + setButtonGroupProps(props as { alignment: GoabButtonGroupAlignment;[key: string]: unknown }); } return ( @@ -90,35 +116,58 @@ export default function ButtonGroupPage() { - - + + {/*Button Group Sandbox*/}

Component

- - + + + + + Button - - + + Button - - + + Button - - + + - -
- + + Design guidelines - + } - > -
+ > +
); diff --git a/src/routes/components/Callout.tsx b/src/routes/components/Callout.tsx index 2ab6a6930..fae50771a 100644 --- a/src/routes/components/Callout.tsx +++ b/src/routes/components/Callout.tsx @@ -1,14 +1,10 @@ import { Category, ComponentHeader } from "@components/component-header/ComponentHeader.tsx"; import { - GoABadge, - GoAButton, - GoAButtonGroup, - GoACallout, - GoACalloutProps, - GoACalloutType, - GoASpacer, - GoATab, - GoATabs, + GoabBadge, + GoabTab, + GoabTabs, + GoabCallout, + GoabCalloutProps } from "@abgov/react-components"; import { ComponentBinding, Sandbox } from "@components/sandbox"; import { useState } from "react"; @@ -18,7 +14,13 @@ import { ComponentProperty, } from "@components/component-properties/ComponentProperties.tsx"; import { ComponentContent } from "@components/component-content/ComponentContent"; -import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { GoabCalloutType } from "@abgov/ui-components-common"; +import { + LegacyMarginProperty, + LegacyTestIdProperties, MarginProperty, + TestIdProperty +} from "@components/component-properties/common-properties.ts"; +import { CalloutExamples } from "@examples/callout/CalloutExamples.tsx"; // == Page props == @@ -26,11 +28,11 @@ const componentName = "Callout"; const description = "Communicate important information through a strong visual emphasis."; const category = Category.FEEDBACK_AND_ALERTS; const relatedComponents = [ - { link: "/components/Notification-banner", name: "Notification banner" }, + { link: "/components/notification-banner", name: "Notification banner" }, ]; -type ComponentPropsType = GoACalloutProps; +type ComponentPropsType = GoabCalloutProps; type CastingType = { - type: GoACalloutType; + type: GoabCalloutType; [key: string]: unknown; }; @@ -69,7 +71,7 @@ export default function CalloutPage() { }, ]); - const componentProperties: ComponentProperty[] = [ + const oldComponentProperties: ComponentProperty[] = [ { name: "type", type: ["success", "important", "information", "emergency", "event"], @@ -101,36 +103,61 @@ export default function CalloutPage() { lang: "angular", }, { - name: "testId", - type: "string", + name: "arialive", + lang: "angular", + type: ["off", "polite", "assertive"], + description: "Indicates how assistive technology should handle updates to the live region.", + defaultValue: "off", + }, + { + name: "ariaLive", lang: "react", - description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", + type: ["off", "polite", "assertive"], + description: "Indicates how assistive technology should handle updates to the live region.", + defaultValue: "off", + }, + ...LegacyTestIdProperties, + LegacyMarginProperty, + ]; + + const componentProperties: ComponentProperty[] = [ + { + name: "type", + type: "GoabCalloutType (success | important | information | emergency | event)", + description: "Define the context and colour of the callout", + required: true, }, { - name: "testid", + name: "heading", type: "string", - lang: "angular", - description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", + description: "Callout heading text", }, { - name: "mt,mr,mb,ml", - type: "none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl", - description: "Apply margin to the top, right, bottom, and/or left of the component.", + name: "size", + type: "GoabCalloutSize (medium | large)", + defaultValue: "large", + description: + "The medium callout has reduced padding and type size to adjust for a compact area and smaller viewport width when a smaller size is required.", }, { - name: "arialive", - lang: "angular", - type: ["off", "polite", "assertive"], + name: "maxWidth", + type: "string", + description: "Sets the maximum width of the callout.", + }, + { + name: "ariaLive", + type: "GoabCalloutAriaLive (off | polite | assertive)", description: "Indicates how assistive technology should handle updates to the live region.", defaultValue: "off", }, { - name: "ariaLive", - lang: "react", - type: ["off", "polite", "assertive"], + name: "iconTheme", + type: "GoabCalloutIconTheme (outline | filled)", description: "Indicates how assistive technology should handle updates to the live region.", defaultValue: "off", }, + TestIdProperty, + MarginProperty, ]; function onSandboxChange(bindings: ComponentBinding[], props: Record) { @@ -148,101 +175,31 @@ export default function CalloutPage() { /> - - + +

Component

- + Lorem ipsum dolor sit amet, consectetur adipiscing elit. - + - - - - -

Confirm that an application was submitted

- - - You have completed the application + - - Your application was successful -

You will receive a copy of the confirmation to the email person@email.com

-

Confirmation number: 1234ABC

-
- -

Go back to the dashboard, or direct your user somewhere else useful.

-

- Other information about what was just completed, other tertiary information, and/or contact information. - Phone: 780 123 4567 - Email: information@gov.ab.ca -

- - - Go to application - Back to dashboard - - `} - /> - You have completed the application - - -

You will receive a copy of the confirmation to the email person@email.com

-

Confirmation number: 1234ABC

-
- -

Go back to the dashboard, or direct your user somewhere else useful.

-

- Other information about what was just completed, other tertiary information, and/or contact information. - Phone: 780 123 4567 - Email: information@gov.ab.ca -

+ + - - Go to application - Back to dashboard - - `} - /> -

You have completed the application

- -

You will receive a copy of the confirmation to the email person@email.com

-

Confirmation number: 1234ABC

-
-

Go back to the dashboard, or direct your user somewhere else useful.

-

- Other information about what was just completed, other tertiary information, and/or contact information.
- Phone: 780 123 4567
- Email: information@gov.ab.ca -

- - - Go to application - Back to dashboard - -
-
+ - Design guidelines - + - }> -
+ }> +
); diff --git a/src/routes/components/Checkbox.tsx b/src/routes/components/Checkbox.tsx index 0d758287c..5c0deb2cf 100644 --- a/src/routes/components/Checkbox.tsx +++ b/src/routes/components/Checkbox.tsx @@ -1,5 +1,5 @@ -import { useState } from "react"; -import { GoABadge, GoACheckbox, GoACheckboxProps, GoAFormItem, GoATab, GoATabs } from "@abgov/react-components"; +import { useContext, useState } from "react"; +import { GoabBadge, GoabCheckbox, GoabCheckboxProps, GoabFormItem, GoabTab, GoabTabs } from "@abgov/react-components"; import { Sandbox, ComponentBinding } from "@components/sandbox"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet"; import { @@ -10,6 +10,12 @@ import { Category, ComponentHeader } from "@components/component-header/Componen import { useSandboxFormItem } from "@hooks/useSandboxFormItem.tsx"; import { ComponentContent } from "@components/component-content/ComponentContent"; import CheckboxExamples from "@examples/checkbox/CheckboxExamples.tsx"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { + LegacyTestIdProperties, + MarginProperty, + TestIdProperty +} from "@components/component-properties/common-properties.ts"; // == Page props == const componentName = "Checkbox"; @@ -20,13 +26,14 @@ const relatedComponents = [ { link: "/components/form-item", name: "Form item" }, { link: "/components/radio", name: "Radio" } ]; -type ComponentPropsType = GoACheckboxProps; +type ComponentPropsType = GoabCheckboxProps; type CastingType = { name: string; checked: boolean; [key: string]: unknown; }; export default function CheckboxPage() { + const {version} = useContext(LanguageVersionContext); const [checkboxProps, setCheckboxProps] = useState({ name: "item", checked: false, @@ -50,8 +57,7 @@ export default function CheckboxPage() { const { formItemBindings, formItemProps, onFormItemChange } = useSandboxFormItem({ label: "Basic", }); - - const componentProperties: ComponentProperty[] = [ + const oldComponentProperties: ComponentProperty[] = [ { name: "name", type: "string", @@ -131,24 +137,76 @@ export default function CheckboxPage() { description: "Sets the maximum width of the checkbox.", lang: "angular", }, + ...LegacyTestIdProperties, + MarginProperty + ]; + + const componentProperties: ComponentProperty[] = [ { - name: "testId", + name: "name", type: "string", - lang: "react", - description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", + description: "Unique name to identify the checkbox.", + }, + { + name: "checked", + type: "boolean", + description: "Marks the checkbox item as selected.", + }, + { + name: "disabled", + type: "boolean", + defaultValue: "false", + description: + "Disable this control. It will not receive focus or events.", }, { - name: "testid", + name: "error", + type: "boolean", + defaultValue: "false", + description: "Shows an error on the checkbox item.", + }, + { + name: "text", type: "string", + description: "Label shown beside the checkbox.", + }, + { + name: "value", + type: "string | number | boolean", + description: "The value binding.", + }, + { + name: "description", + type: "string | TemplateRef", + description: "Additional content shown below the label.", lang: "angular", - description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", }, { - name: "mt,mr,mb,ml", - type: "none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl", - description: "Apply margin to the top, right, bottom, and/or left of the component.", + name: "description", + type: "string | ReactNode", + description: "Additional content shown below the label.", + lang: "react", }, + { + name: "ariaLabel", + type: "string", + description: + "Defines how the text will be translated for the screen reader. If not specified it will fall back to the name.", + }, + { + name: "maxWidth", + type: "string", + description: "Sets the maximum width of the checkbox.", + }, + { + name: "onChange", + type: "(event: GoabCheckboxOnChangeDetail) => void", + description: "Callback function when checkbox value is changed.", + }, + TestIdProperty, + MarginProperty, ]; + const noop = () => { }; function onChange(bindings: ComponentBinding[], props: Record) { @@ -168,31 +226,30 @@ export default function CheckboxPage() { - - + +

Component

+ flags={version === "old" ? ["reactive"] : ["reactive", "template-driven"]}> - } + + {version === "new" && } + + {version === "new" && } + + {version === "new" && - - - + } + +
+ + + +
- + -
+ - Design guidelines - + - }> -
+ }> +
); diff --git a/src/routes/components/Components.tsx b/src/routes/components/Components.tsx index 3af4caa30..92e9360ab 100644 --- a/src/routes/components/Components.tsx +++ b/src/routes/components/Components.tsx @@ -1,75 +1,83 @@ -import { GoABlock, GoADropdown, GoADropdownItem, GoASideMenu } from "@abgov/react-components"; -import { useEffect, useState } from "react"; +import { GoabNotification, GoabSideMenu } from "@abgov/react-components"; import { Link, Outlet } from "react-router-dom"; -import { LanguageContext } from "@components/sandbox"; import { SupportInfo } from "@components/support-info/SupportInfo.tsx"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { getVersionedUrlPath } from "@components/version-language-switcher/version-language-constants.ts"; +import { DEFAULT_VERSION } from "../../global-constants"; export function Components() { - const [language, setLanguage] = useState(""); + const { language, version } = useContext(LanguageVersionContext); - useEffect(() => { - const lang = localStorage.getItem("goa-docs-lang") || "react"; - setLanguage(lang); - }, []); + const prefixUrl = getVersionedUrlPath(version, language); - function onLanguageChange(_name: string, value: string[] | string) { - const lang = Array.isArray(value) ? value[0] : value; - setLanguage(lang); - localStorage.setItem("goa-docs-lang", lang); - } + const getUrl = (path: string) => { + return prefixUrl.length > 0 ? `${prefixUrl}/${path}` : path; + }; return ( - + <> + {version !== DEFAULT_VERSION && ( + + {DEFAULT_VERSION === "old" ? ( + <> + Most teams should use the Long-term Support (LTS) version of the design system. If + you're ready to explore the latest features, check out our{" "} + upgrade guide + + ) : ( + <> + You are not on the latest version of the design system.{" "} + Upgrade to latest version + + )} + + )} +
- - - - - - - - + All - Accordion - Badge - Block - Button - Button group - Callout - Checkbox - Container - Date picker - Details - Divider - Dropdown - File uploader - Filter chip - Footer - Form item - Form stepper - Grid - Header - Hero banner - Icons - Icon button - Input - List - Microsite header - Modal - Notification banner - Pagination - Popover - Progress indicator - Radio - Side menu - Skeleton loading - Spacer - Table - Tabs - Text area - Tooltip - + Accordion + Badge + Block + Button + Button group + Callout + Checkbox + Container + Date picker + Details + Divider + Dropdown + File uploader + Filter chip + Footer + Form item + Form stepper + Grid + Header + Hero banner + Icons + Icon button + Input + List + Microsite header + Modal + Notification banner + Pagination + Popover + Progress indicator + Radio + Side menu + Skeleton loading + Spacer + Table + Tabs + Text + Text area + Tooltip +
@@ -77,7 +85,7 @@ export function Components() {
-
+ ); } diff --git a/src/routes/components/Container.tsx b/src/routes/components/Container.tsx index 638304822..c5f67abdb 100644 --- a/src/routes/components/Container.tsx +++ b/src/routes/components/Container.tsx @@ -6,10 +6,10 @@ import { } from "@components/component-properties/ComponentProperties"; import { Category, ComponentHeader } from "@components/component-header/ComponentHeader"; import { - GoABadge, - GoAContainer, GoAContainerProps, - GoATab, - GoATabs + GoabBadge, + GoabContainer, GoabContainerProps, + GoabTab, + GoabTabs } from "@abgov/react-components"; import ContainerExamples from "@examples/container/ContainerExamples.tsx"; import { ComponentContent } from "@components/component-content/ComponentContent"; @@ -23,7 +23,7 @@ const relatedComponents = [ { link: "/components/details", name: "Details" }, { link: "/components/divider", name: "Divider" } ]; -type ComponentPropsType = GoAContainerProps; +type ComponentPropsType = GoabContainerProps; type CastingType = { [key: string]: unknown; }; @@ -73,7 +73,7 @@ export default function ContainerPage() { }, ]); - const componentProperties: ComponentProperty[] = [ + const oldComponentProperties: ComponentProperty[] = [ { name: "type", type: "interactive | info | error | success | important | non-interactive", @@ -140,6 +140,75 @@ export default function ContainerPage() { description: "Apply margin to the top, right, bottom, and/or left of the component.", }, ]; + const componentProperties: ComponentProperty[] = [ + { + name: "type", + type: "GoabContainerType (interactive | info | error | success | important | non-interactive)", + description: "Sets the container and accent bar styling.", + defaultValue: "interactive", + }, + { + name: "accent", + type: "GoabContainerAccent (thick | thin | filled)", + defaultValue: "filled", + description: "Sets the style of accent on the container.", + }, + { + name: "padding", + type: "GoabContainerPadding (relaxed | compact)", + defaultValue: "relaxed", + description: "Sets the amount of white space in the container.", + }, + { + name: "width", + type: "GoabContainerWidth (full | content)", + defaultValue: "full", + description: "Sets the width of the container." + }, + { + name: "maxWidth", + type: "string", + description: "Sets the maximum width of the container.", + }, + { + name: "title", + lang: "angular", + type: "TemplateRef", + description: + "Sets the content in the left of the accent bar. Can only be used with accent=thick.", + }, + { + name: "actions", + type: "TemplateRef", + lang: "angular", + description: + "Sets the content in the right of the accent bar. Can only be used with accent=thick.", + }, + { + name: "title", + lang: "react", + type: "ReactNode", + description: + "Sets the content in the left of the accent bar. Can only be used with accent=thick.", + }, + { + name: "actions", + type: "ReactNode", + lang: "react", + description: + "Sets the content in the right of the accent bar. Can only be used with accent=thick.", + }, + { + name: "testId", + type: "string", + description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", + }, + { + name: "mt,mr,mb,ml", + type: "Spacing (none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl)", + description: "Apply margin to the top, right, bottom, and/or left of the component.", + }, + ]; function onSandboxChange(bindings: ComponentBinding[], props: Record) { setContainerBindings(bindings); @@ -157,32 +226,32 @@ export default function ContainerPage() { - - + +

Component

- +

Detach to use

Add things inside me

-
+
{/*Container Table Properties*/} - + -
+ - Design guidelines - + }>

Coming Soon

-
-
+ +
); diff --git a/src/routes/components/DatePicker.tsx b/src/routes/components/DatePicker.tsx index bdcf45a77..999c82919 100644 --- a/src/routes/components/DatePicker.tsx +++ b/src/routes/components/DatePicker.tsx @@ -1,24 +1,26 @@ import { Category, ComponentHeader } from "@components/component-header/ComponentHeader.tsx"; import { ComponentBinding, Sandbox } from "@components/sandbox"; -import { useState } from "react"; +import { useContext, useState } from "react"; import { ComponentProperties, ComponentProperty, } from "@components/component-properties/ComponentProperties.tsx"; import { - GoABadge, - GoATab, - GoATabs, - GoADatePickerProps, - GoADatePicker, - GoAFormItem, - GoAButton, - GoAButtonGroup, + GoabBadge, + GoabTab, + GoabTabs, + GoabDatePickerProps, + GoabDatePicker, + GoabFormItem, } from "@abgov/react-components"; import { useSandboxFormItem } from "@hooks/useSandboxFormItem.tsx"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; import { ComponentContent } from "@components/component-content/ComponentContent"; +import { GoabDatePickerOnChangeDetail } from "@abgov/ui-components-common"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { LegacyMarginProperty, MarginProperty } from "@components/component-properties/common-properties.ts"; +import { DatePickerExamples } from "@examples/date-picker/DatePickerExamples.tsx"; // == Page props == @@ -30,13 +32,14 @@ const relatedComponents = [ ]; const description = "Lets users select a date through a calendar without the need to manually type it in a field."; -type ComponentPropsType = GoADatePickerProps; +type ComponentPropsType = GoabDatePickerProps; type CastingType = { [key: string]: unknown; - onChange: (name: string, value: Date | undefined) => void; + onChange: (event: GoabDatePickerOnChangeDetail)=> void; }; export default function DatePickerPage() { + const {version} = useContext(LanguageVersionContext); const [componentProps, setComponentProps] = useState({ onChange: () => {}, }); @@ -69,7 +72,7 @@ export default function DatePickerPage() { label: "Item", }); - const componentProperties: ComponentProperty[] = [ + const oldComponentProperties: ComponentProperty[] = [ { name: "name", type: "string", @@ -98,10 +101,49 @@ export default function DatePickerPage() { defaultValue: "5 years forward", description: "Maximum date value allowed.", }, + LegacyMarginProperty, + { + name: "disabled", + type: "boolean", + defaultValue: "false", + description: "Disables the date picker.", + }, + { + name: "relative", + type: "boolean", + description: "Set to true if a parent element has a css position of relative.", + defaultValue: "false", + }, + ]; + + const componentProperties: ComponentProperty[] = [ + { + name: "name", + type: "string", + description: "Name of the date field.", + }, + { + name: "value", + type: "Date | string | null | undefined", + description: "Value of the calendar date.", + }, + { + name: "min", + type: "Date | string", + defaultValue: "5 year previous", + description: "Minimum date value allowed.", + }, + { + name: "max", + type: "Date | string", + defaultValue: "5 years forward", + description: "Maximum date value allowed.", + }, { - name: "mt,mr,mb,ml", - type: "none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl", - description: "Apply margin to the top, right, bottom, and/or left of the component.", + name: "error", + type: "boolean", + defaultValue: "false", + description: "Sets the input to an error state.", }, { name: "disabled", @@ -115,6 +157,12 @@ export default function DatePickerPage() { description: "Set to true if a parent element has a css position of relative.", defaultValue: "false", }, + MarginProperty, + { + name: "onChange", + type: "(event: GoabDatePickerOnChangeDetail) => void", + description: "Function to call when the date changes.", + } ]; function onSandboxChange(bindings: ComponentBinding[], props: Record) { @@ -124,23 +172,6 @@ export default function DatePickerPage() { const noop = () => {}; - const [date, setDate] = useState(); - - const setNewDate = (value: Date | undefined) => { - setDate(value); - }; - - function setValue() { - const d = new Date(); - d.setDate(d.getDate() - 7); - - setDate(d); - } - - function clearValue() { - setDate(undefined); - } - return ( <> - - -

- Component -

+ + + +

Component

- + + {/*Angular*/} + {version === "old" && + />} + + {version === "new" && } - + />} - - - - - - - - + />} -

Reset example

- - (); - - const setNewDate = (value: Date | undefined) => { - setDate(value); - }; - - function setValue() { - const d = new Date(); - d.setDate(d.getDate() - 7); - - setDate(d); - } - - function clearValue() { - setDate(undefined); - } - - return ( - <> - - setNewDate(value)} - mb="xl" - > - - - - Set Value - Clear Value - - - ); + export class MyComponent { + item = new Date(); + dateOnChange(event: GoabDatePickerOnChangeDetail) { + // handle change + console.log(event.value); + this.item = event.value as Date; + } } + } `} - /> + />} - - - - - - - Set Value - Clear Value - - `} - /> + function onChange(name: string, value: Date) { + console.log(name, value); + } + `} + />} - } - setValue() { - const d = new Date(); - d.setDate(d.getDate() - 7); - this.dateCtrl.patchValue(d); - console.log("setValue called: ", this.dateCtrl.value); - } + + + + + - clearValue() { - this.dateCtrl.reset(); - console.log("reset called: ", this.dateCtrl.value); - } - } - `} - /> - - - - - - Set Value - Clear Value - - `} - /> + - - setNewDate(value)} - mb="xl"> - +
- - - Set Value - - Clear Value - - -
- Design guidelines - + - }> -
+ }> +
); diff --git a/src/routes/components/Details.tsx b/src/routes/components/Details.tsx index 2cf7a75e5..0629e764c 100644 --- a/src/routes/components/Details.tsx +++ b/src/routes/components/Details.tsx @@ -6,17 +6,18 @@ import { import { ComponentBinding, Sandbox } from "@components/sandbox"; import { Category, ComponentHeader } from "@components/component-header/ComponentHeader.tsx"; import { - GoABadge, - GoABlock, - GoADetails, - GoAFormItem, - GoAInput, - GoARadioGroup, - GoARadioItem, - GoATab, - GoATabs, + GoabBadge, + GoabDetails, + GoabTab, + GoabTabs, } from "@abgov/react-components"; import { ComponentContent } from "@components/component-content/ComponentContent"; +import { + LegacyMarginProperty, + MarginProperty, + TestIdProperty, +} from "@components/component-properties/common-properties.ts"; +import { DetailsExamples } from "@examples/details/DetailsExamples.tsx"; export default function DetailsPage() { const [detailsProps, setDetailsProps] = useState({ @@ -35,10 +36,10 @@ export default function DetailsPage() { name: "maxWidth", requirement: "optional", value: "", - }, + }, ]); - const componentProperties: ComponentProperty[] = [ + const oldComponentProperties: ComponentProperty[] = [ { name: "heading", type: "string", @@ -63,20 +64,36 @@ export default function DetailsPage() { description: "Sets the maximum width of the details.", lang: "angular", }, + LegacyMarginProperty, + ]; + + const componentProperties: ComponentProperty[] = [ + { + name: "heading", + type: "string", + required: true, + description: "The title heading", + }, + { + name: "open", + type: "boolean", + description: "Controls if details is expanded or not", + defaultValue: "false", + }, { - name: "mt,mr,mb,ml", - type: "none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl", - description: "Apply margin to the top, right, bottom, and/or left of the component.", + name: "maxWidth", + type: "string", + description: "Sets the maximum width of the details.", }, + TestIdProperty, + MarginProperty, ]; function onSandboxChange(bindings: ComponentBinding[], props: Record) { - setDetailsProps(props as { heading: string;[key: string]: unknown }); + setDetailsProps(props as { heading: string; [key: string]: unknown }); setDetailsBindings(bindings); } - const noop = () => { }; - return ( <> - - - -

Component

+ + +

+ Component +

- + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vel lacinia metus, sed sodales lectus. Aliquam sed volutpat velit. Sed in lacus ut dui placerat accumsan malesuada quis erat. Aenean mi diam, rhoncus vitae justo eu, venenatis maximus nunc. @@ -104,143 +122,27 @@ export default function DetailsPage() { cursus velit vel libero sollicitudin tincidunt. Proin tincidunt, enim et ultrices rhoncus, nibh leo imperdiet sapien, sed porttitor ipsum nulla non massa. Nulla facilisi. - - - - {/*Component properties table*/} - - - {/* Examples*/} - - -

- Show more information for a basic question -

- - - { }}> - - - - - - -

- This question helps us better understand your situation and ensure that you receive - the right information and support. -

-
+
-

- Additional information to help a user understand and answer a question -

- - - - - - - + - - -
- Examples of education expenses -
    -
  • Laptop and computer hardware
  • -
  • Computer apps and subscriptions
  • -
  • Home internet
  • -
  • Testing and exam fees
  • -
  • Work or school clothing, like work boots
  • -
-
-
- Do not include -
    -
  • Tuition
  • -
  • Mandatory fees
  • -
  • Books and supplies
  • -
  • School association fees
  • -
-
-
-
-
- -

- Show more information to help a user fill out direct deposit information -

- -

Direct deposit information

-

- Find this information on your bank's website or on your personal cheques. Contact your - bank if you can't find this information. -

- - - - - - - - - - - -

- Below is an example of where you can find the required bank information on a - personal cheque. -

- -
-
-
+ + - Design guidelines - + - } - > + }>

Coming Soon

-
-
+ +
); diff --git a/src/routes/components/Divider.tsx b/src/routes/components/Divider.tsx index 7d25debba..d754bd432 100644 --- a/src/routes/components/Divider.tsx +++ b/src/routes/components/Divider.tsx @@ -5,7 +5,7 @@ import { ComponentProperty, } from "@components/component-properties/ComponentProperties.tsx"; import { Category, ComponentHeader } from "@components/component-header/ComponentHeader.tsx"; -import { GoABadge, GoADivider, GoATab, GoATabs } from "@abgov/react-components"; +import { GoabBadge, GoabDivider, GoabTab, GoabTabs } from "@abgov/react-components"; import { ComponentContent } from "@components/component-content/ComponentContent"; import Sandbox from "@components/sandbox/Sandbox.tsx"; import "./AllComponents.css"; @@ -29,7 +29,7 @@ export default function DividerPage() { }, ]); - const componentProperties: ComponentProperty[] = [ + const oldComponentProperties: ComponentProperty[] = [ { name: "mt,mr,mb,ml", type: "none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl", @@ -49,6 +49,19 @@ export default function DividerPage() { }, ]; + const componentProperties: ComponentProperty[] = [ + { + name: "mt,mr,mb,ml", + type: "Spacing (none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl)", + description: "Apply margin to the top, right, bottom, and/or left of the component.", + }, + { + name: "testId", + type: "string", + description: "Sets the data-testid attribute. Used with ByTestId queries in tests.", + } + ]; + function onSandboxChange(utilityBindings: ComponentBinding[], props: Record) { setDividerBindings(utilityBindings); setDividerProps(props); @@ -67,25 +80,25 @@ export default function DividerPage() { - - + +

Component

- + - -
+ + - Design guidelines - + } - > -
+ > +
); diff --git a/src/routes/components/Dropdown.tsx b/src/routes/components/Dropdown.tsx index fb28770fc..3f13f2083 100644 --- a/src/routes/components/Dropdown.tsx +++ b/src/routes/components/Dropdown.tsx @@ -1,11 +1,11 @@ -import { useState } from "react"; +import { useContext, useState } from "react"; import { - GoABadge, - GoADropdown, - GoADropdownItem, GoADropdownProps, - GoAFormItem, - GoATab, - GoATabs + GoabBadge, + GoabDropdown, + GoabDropdownItem, GoabDropdownProps, + GoabFormItem, + GoabTab, + GoabTabs } from "@abgov/react-components"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet"; import { ComponentBinding, Sandbox } from "@components/sandbox"; @@ -18,6 +18,9 @@ import { import { useSandboxFormItem } from "@hooks/useSandboxFormItem.tsx"; import { ComponentContent } from "@components/component-content/ComponentContent"; import { DropdownExamples } from "@examples/dropdown/DropdownExamples"; +import { GoabDropdownOnChangeDetail } from "@abgov/ui-components-common"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { LegacyMarginProperty, MarginProperty } from "@components/component-properties/common-properties.ts"; // == Page props == const componentName = "Dropdown"; @@ -29,15 +32,16 @@ const relatedComponents = [ { link: "/components/popover", name: "Popover" }, { link: "/components/radio", name: "Radio" }, ]; -type ComponentPropsType = GoADropdownProps; +type ComponentPropsType = GoabDropdownProps; type CastingType = { name: string; value: string; [key: string]: unknown; - onChange: (name: string, values: string[] | string) => void; + onChange: (event: GoabDropdownOnChangeDetail) => void; } export default function DropdownPage() { + const {version} = useContext(LanguageVersionContext); const [dropdownProps, setDropdownProps] = useState({ name: "item", value: "", @@ -77,7 +81,7 @@ export default function DropdownPage() { ]); const { formItemBindings, formItemProps, onFormItemChange } = useSandboxFormItem({ label: "Basic dropdown" }); - const dropdownProperties: ComponentProperty[] = [ + const oldDropdownProperties: ComponentProperty[] = [ { name: "name", type: "string", @@ -197,13 +201,94 @@ export default function DropdownPage() { type: "(name: string, value: string[] | string | null) => void", description: "Callback function when dropdown value is changed.", }, + LegacyMarginProperty, + ]; + const dropdownProperties: ComponentProperty[] = [ + { + name: "name", + type: "string", + description: "Identifier for the Dropdown. Should be unique.", + }, + { + name: "value", + type: "string", + description: "Stores the value of the item selected from the dropdown.", + }, + { + name: "leadingIcon", + type: "GoAIconType", + description: "Show an icon to the left of the dropdown option.", + }, + { + name: "maxHeight", + type: "string", + description: "Maximum height of the dropdown menu items popover. Non-native only.", + defaultValue: "276px", + }, + { + name: "placeholder", + type: "string", + description: + "The text displayed for the dropdown before a selection is made. Non-native only.", + }, + { + name: "width", + type: "string", + description: "Overrides the autosized menu width. Non-native only.", + }, + { + name: "disabled", + type: "boolean", + description: "Disable this control.", + defaultValue: "false", + }, + { + name: "relative", + type: "boolean", + description: "Set to true if a parent element has a css positive of relative.", + defaultValue: "false", + }, + { + name: "error", + type: "boolean", + description: "Show an error state", + defaultValue: "false", + }, + { + name: "ariaLabel", + type: "string", + description: + "Defines how the selected value will be translated for the screen reader. If not specified it will fall back to the name.", + }, + { + name: "ariaLabelledBy", + type: "string", + description: + "The aria-labelledby attribute identifies the element(or elements) that labels the dropdown it is applied to. Normally it is the id of the label.", + }, + { + name: "native", + type: "boolean", + defaultValue: "false", + description: "When true will render the native