From 15a2fe7e668d3ce3cc114654705b11abe5cac4cb Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Mon, 29 Sep 2025 20:42:37 -0700 Subject: [PATCH 01/40] Algolia AskAI (Beta) --- docusaurus.config.js | 6 ++++ package.json | 1 + yarn.lock | 66 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/docusaurus.config.js b/docusaurus.config.js index 010cbcce38..bb24519e38 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -274,6 +274,12 @@ module.exports = { indexName: 'crawler_sumodocs', contextualSearch: false, insights: true, + askAi: { + assistantId: 'dFgp1Fa5XLla', + indexName: 'crawler_sumodocs', + apiKey: 'fb2f4e1fb40f962900631121cb365549', + appId: '2SJPGMLW1Q', + }, insightsConfig: { useCookie: true, // alt to useCookie: true, }, diff --git a/package.json b/package.json index 007d6e437d..d473be9ffb 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "@braintree/sanitize-url": "^6.0.1", "@csstools/selector-resolve-nested": "3.1.0", "@docsearch/css": "3.8.2", + "@docsearch/react": "^4.0.0-beta.8", "@docusaurus/bundler": "3.9.1", "@docusaurus/core": "3.9.1", "@docusaurus/cssnano-preset": "3.9.1", diff --git a/yarn.lock b/yarn.lock index bf58ee9cdf..7f43f83866 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,6 +10,15 @@ "@ai-sdk/provider" "2.0.0" "@ai-sdk/provider-utils" "3.0.10" +"@ai-sdk/provider-utils@2.2.8": + version "2.2.8" + resolved "https://registry.yarnpkg.com/@ai-sdk/provider-utils/-/provider-utils-2.2.8.tgz#ad11b92d5a1763ab34ba7b5fc42494bfe08b76d1" + integrity sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA== + dependencies: + "@ai-sdk/provider" "1.1.3" + nanoid "^3.3.8" + secure-json-parse "^2.7.0" + "@ai-sdk/provider-utils@3.0.10": version "3.0.10" resolved "https://registry.yarnpkg.com/@ai-sdk/provider-utils/-/provider-utils-3.0.10.tgz#f76010c78445bb25cfc102bcd7e162103e6e7d96" @@ -19,6 +28,13 @@ "@standard-schema/spec" "^1.0.0" eventsource-parser "^3.0.5" +"@ai-sdk/provider@1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@ai-sdk/provider/-/provider-1.1.3.tgz#ebdda8077b8d2b3f290dcba32c45ad19b2704681" + integrity sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg== + dependencies: + json-schema "^0.4.0" + "@ai-sdk/provider@2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@ai-sdk/provider/-/provider-2.0.0.tgz#b853c739d523b33675bc74b6c506b2c690bc602b" @@ -36,6 +52,25 @@ swr "^2.2.5" throttleit "2.1.0" +"@ai-sdk/react@^1.2.12": + version "1.2.12" + resolved "https://registry.yarnpkg.com/@ai-sdk/react/-/react-1.2.12.tgz#f4250b6df566b170af98a71d5708b52108dd0ce1" + integrity sha512-jK1IZZ22evPZoQW3vlkZ7wvjYGYF+tRBKXtrcolduIkQ/m/sOAVcVeVDUDvh1T91xCnWCdUGCPZg2avZ90mv3g== + dependencies: + "@ai-sdk/provider-utils" "2.2.8" + "@ai-sdk/ui-utils" "1.2.11" + swr "^2.2.5" + throttleit "2.1.0" + +"@ai-sdk/ui-utils@1.2.11": + version "1.2.11" + resolved "https://registry.yarnpkg.com/@ai-sdk/ui-utils/-/ui-utils-1.2.11.tgz#4f815589d08d8fef7292ade54ee5db5d09652603" + integrity sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w== + dependencies: + "@ai-sdk/provider" "1.1.3" + "@ai-sdk/provider-utils" "2.2.8" + zod-to-json-schema "^3.24.1" + "@algolia/abtesting@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@algolia/abtesting/-/abtesting-1.5.0.tgz#3faf3770c7fcb4afcf86d9ac29d29c3cfca33441" @@ -1779,6 +1814,11 @@ resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.8.2.tgz#7973ceb6892c30f154ba254cd05c562257a44977" integrity sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ== +"@docsearch/css@4.0.0-beta.8": + version "4.0.0-beta.8" + resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-4.0.0-beta.8.tgz#836ac7c3eeecf87cfc9c518210f4dfd27e49b05f" + integrity sha512-/ZlyvZCjIJM4aaOYoJpVNHPJckX7J5KIbt6IWjnZXvo0QAUI1aH976vKEJUC9olgUbE3LWafB8yuX4qoqahIQg== + "@docsearch/css@4.1.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-4.1.0.tgz#e156e011539d73624b2354dc8be8e96ac9be9ddc" @@ -1797,6 +1837,17 @@ marked "^16.3.0" zod "^4.1.8" +"@docsearch/react@^4.0.0-beta.8": + version "4.0.0-beta.8" + resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-4.0.0-beta.8.tgz#b3d75b42cf2b1b696317930d7b255c098df266ca" + integrity sha512-2gbk3SHUOKXDw0SfnblIpV3Z5pp4nANFg0oUB3kuheOfv5Wau0ZssIOAjEBTKmEzP5tO0Gljh5NL6t4SrXIhBg== + dependencies: + "@ai-sdk/react" "^1.2.12" + "@algolia/autocomplete-core" "1.19.2" + "@docsearch/css" "4.0.0-beta.8" + algoliasearch "^5.28.0" + marked "^15.0.12" + "@docusaurus/babel@3.9.1": version "3.9.1" resolved "https://registry.yarnpkg.com/@docusaurus/babel/-/babel-3.9.1.tgz#5297195ab34df9e184e3e2fe20de1a2e1b2a22e8" @@ -9441,6 +9492,11 @@ markdown-table@^3.0.0: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.4.tgz#fe44d6d410ff9d6f2ea1797a3f60aa4d2b631c2a" integrity sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw== +marked@^15.0.12: + version "15.0.12" + resolved "https://registry.yarnpkg.com/marked/-/marked-15.0.12.tgz#30722c7346e12d0a2d0207ab9b0c4f0102d86c4e" + integrity sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA== + marked@^16.0.0: version "16.2.0" resolved "https://registry.yarnpkg.com/marked/-/marked-16.2.0.tgz#c407a4f7ed3acc1110812525cfd1b0ed8502792c" @@ -12846,6 +12902,11 @@ section-matter@^1.0.0: extend-shallow "^2.0.1" kind-of "^6.0.0" +secure-json-parse@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" + integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -14842,6 +14903,11 @@ yocto-queue@^1.0.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.2.1.tgz#36d7c4739f775b3cbc28e6136e21aa057adec418" integrity sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg== +zod-to-json-schema@^3.24.1: + version "3.24.6" + resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz#5920f020c4d2647edfbb954fa036082b92c9e12d" + integrity sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg== + zod@3.23.8: version "3.23.8" resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d" From 8a353c40a64eacb4929be0a30ad2ca8d61001fc2 Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Mon, 29 Sep 2025 21:22:43 -0700 Subject: [PATCH 02/40] add staging --- .github/workflows/pr.yml | 11 ++++++ .github/workflows/rebuild-lockfile-linux.yml | 41 -------------------- .github/workflows/review.yml | 19 +++++++++ 3 files changed, 30 insertions(+), 41 deletions(-) delete mode 100644 .github/workflows/rebuild-lockfile-linux.yml create mode 100644 .github/workflows/review.yml diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 13fd112067..dffc181961 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -36,6 +36,17 @@ jobs: run: yarn install --frozen-lockfile - name: Build the Docusaurus site run: yarn build + deploy-to-review: + uses: SumoLogic/sumologic-documentation/.github/workflows/build_and_deploy.yml@main + with: + hostname: https://d2t1s0ah22jxsa.cloudfront.net + base_url: /${{ github.ref_name }}/ + environment: review/${{ github.ref_name }} + secrets: + S3_BUCKET_NAME: ${{ secrets.REVIEW_S3_BUCKET_NAME }} + CLOUDFRONT_DISTRIBUTION_ID: ${{ secrets.REVIEW_CLOUDFRONT_DISTRIBUTION_ID }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} spellcheck: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/rebuild-lockfile-linux.yml b/.github/workflows/rebuild-lockfile-linux.yml deleted file mode 100644 index 8d4e2d10a3..0000000000 --- a/.github/workflows/rebuild-lockfile-linux.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Rebuild yarn.lock on Linux - -on: - workflow_dispatch: {} # run it manually from the Actions tab - -permissions: - contents: write # needed to push a branch/PR - -jobs: - rebuild: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Use Node 20 - uses: actions/setup-node@v4 - with: - node-version: 20 - - - name: Install Yarn 1.x - run: npm i -g yarn@1.22.22 - - - name: Clean lock & modules - run: rm -rf node_modules yarn.lock - - - name: Install (generate Linux lockfile) - run: yarn install - - - name: Create PR - uses: peter-evans/create-pull-request@v6 - with: - branch: fix/linux-lockfile - commit-message: "chore: regenerate yarn.lock on Linux for CI compatibility" - title: "chore: regenerate yarn.lock on Linux" - body: | - Regenerated lockfile on Linux to avoid platform-specific @swc/* entries. - CI can keep using `yarn install --frozen-lockfile`. - delete-branch: true diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml new file mode 100644 index 0000000000..ca2a045584 --- /dev/null +++ b/.github/workflows/review.yml @@ -0,0 +1,19 @@ +name: deploy-to-review + +on: workflow_dispatch + +permissions: + contents: write + +jobs: + deploy-to-review: + uses: SumoLogic/sumologic-documentation/.github/workflows/build_and_deploy.yml@main + with: + hostname: https://d2t1s0ah22jxsa.cloudfront.net + base_url: /${{ github.ref_name }}/ + environment: review/${{ github.ref_name }} + secrets: + S3_BUCKET_NAME: ${{ secrets.REVIEW_S3_BUCKET_NAME }} + CLOUDFRONT_DISTRIBUTION_ID: ${{ secrets.REVIEW_CLOUDFRONT_DISTRIBUTION_ID }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} From fb17a8fbe0fe879ed30ce9ff42a282e457a8f697 Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Tue, 30 Sep 2025 00:52:41 -0700 Subject: [PATCH 03/40] Ask AI - assistantId --- docusaurus.config.js | 2 +- package.json | 2 +- yarn.lock | 68 +------------------------------------------- 3 files changed, 3 insertions(+), 69 deletions(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index bb24519e38..c259f99cd3 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -275,7 +275,7 @@ module.exports = { contextualSearch: false, insights: true, askAi: { - assistantId: 'dFgp1Fa5XLla', + assistantId: 'Gj8Bh1qOc2XJ', indexName: 'crawler_sumodocs', apiKey: 'fb2f4e1fb40f962900631121cb365549', appId: '2SJPGMLW1Q', diff --git a/package.json b/package.json index d473be9ffb..8bce1806e1 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@braintree/sanitize-url": "^6.0.1", "@csstools/selector-resolve-nested": "3.1.0", "@docsearch/css": "3.8.2", - "@docsearch/react": "^4.0.0-beta.8", + "@docsearch/react": "^4.1.0", "@docusaurus/bundler": "3.9.1", "@docusaurus/core": "3.9.1", "@docusaurus/cssnano-preset": "3.9.1", diff --git a/yarn.lock b/yarn.lock index 7f43f83866..502f988ff1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,15 +10,6 @@ "@ai-sdk/provider" "2.0.0" "@ai-sdk/provider-utils" "3.0.10" -"@ai-sdk/provider-utils@2.2.8": - version "2.2.8" - resolved "https://registry.yarnpkg.com/@ai-sdk/provider-utils/-/provider-utils-2.2.8.tgz#ad11b92d5a1763ab34ba7b5fc42494bfe08b76d1" - integrity sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA== - dependencies: - "@ai-sdk/provider" "1.1.3" - nanoid "^3.3.8" - secure-json-parse "^2.7.0" - "@ai-sdk/provider-utils@3.0.10": version "3.0.10" resolved "https://registry.yarnpkg.com/@ai-sdk/provider-utils/-/provider-utils-3.0.10.tgz#f76010c78445bb25cfc102bcd7e162103e6e7d96" @@ -28,13 +19,6 @@ "@standard-schema/spec" "^1.0.0" eventsource-parser "^3.0.5" -"@ai-sdk/provider@1.1.3": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@ai-sdk/provider/-/provider-1.1.3.tgz#ebdda8077b8d2b3f290dcba32c45ad19b2704681" - integrity sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg== - dependencies: - json-schema "^0.4.0" - "@ai-sdk/provider@2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@ai-sdk/provider/-/provider-2.0.0.tgz#b853c739d523b33675bc74b6c506b2c690bc602b" @@ -52,25 +36,6 @@ swr "^2.2.5" throttleit "2.1.0" -"@ai-sdk/react@^1.2.12": - version "1.2.12" - resolved "https://registry.yarnpkg.com/@ai-sdk/react/-/react-1.2.12.tgz#f4250b6df566b170af98a71d5708b52108dd0ce1" - integrity sha512-jK1IZZ22evPZoQW3vlkZ7wvjYGYF+tRBKXtrcolduIkQ/m/sOAVcVeVDUDvh1T91xCnWCdUGCPZg2avZ90mv3g== - dependencies: - "@ai-sdk/provider-utils" "2.2.8" - "@ai-sdk/ui-utils" "1.2.11" - swr "^2.2.5" - throttleit "2.1.0" - -"@ai-sdk/ui-utils@1.2.11": - version "1.2.11" - resolved "https://registry.yarnpkg.com/@ai-sdk/ui-utils/-/ui-utils-1.2.11.tgz#4f815589d08d8fef7292ade54ee5db5d09652603" - integrity sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w== - dependencies: - "@ai-sdk/provider" "1.1.3" - "@ai-sdk/provider-utils" "2.2.8" - zod-to-json-schema "^3.24.1" - "@algolia/abtesting@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@algolia/abtesting/-/abtesting-1.5.0.tgz#3faf3770c7fcb4afcf86d9ac29d29c3cfca33441" @@ -1814,17 +1779,12 @@ resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.8.2.tgz#7973ceb6892c30f154ba254cd05c562257a44977" integrity sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ== -"@docsearch/css@4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-4.0.0-beta.8.tgz#836ac7c3eeecf87cfc9c518210f4dfd27e49b05f" - integrity sha512-/ZlyvZCjIJM4aaOYoJpVNHPJckX7J5KIbt6IWjnZXvo0QAUI1aH976vKEJUC9olgUbE3LWafB8yuX4qoqahIQg== - "@docsearch/css@4.1.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-4.1.0.tgz#e156e011539d73624b2354dc8be8e96ac9be9ddc" integrity sha512-nuNKGjHj/FQeWgE9t+i83QD/V67QiaAmGY7xS9TVCRUiCqSljOgIKlsLoQZKKVwEG8f+OWKdznzZkJxGZ7d06A== -"@docsearch/react@^3.9.0 || ^4.1.0": +"@docsearch/react@^3.9.0 || ^4.1.0", "@docsearch/react@^4.1.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-4.1.0.tgz#a04f22324067f2e39dbe12f0e1247e7e0341d26d" integrity sha512-4GHI7TT3sJZ2Vs4Kjadv7vAkMrTsJqHvzvxO3JA7UT8iPRKaDottG5o5uNshPWhVVaBYPC35Ukf8bfCotGpjSg== @@ -1837,17 +1797,6 @@ marked "^16.3.0" zod "^4.1.8" -"@docsearch/react@^4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-4.0.0-beta.8.tgz#b3d75b42cf2b1b696317930d7b255c098df266ca" - integrity sha512-2gbk3SHUOKXDw0SfnblIpV3Z5pp4nANFg0oUB3kuheOfv5Wau0ZssIOAjEBTKmEzP5tO0Gljh5NL6t4SrXIhBg== - dependencies: - "@ai-sdk/react" "^1.2.12" - "@algolia/autocomplete-core" "1.19.2" - "@docsearch/css" "4.0.0-beta.8" - algoliasearch "^5.28.0" - marked "^15.0.12" - "@docusaurus/babel@3.9.1": version "3.9.1" resolved "https://registry.yarnpkg.com/@docusaurus/babel/-/babel-3.9.1.tgz#5297195ab34df9e184e3e2fe20de1a2e1b2a22e8" @@ -9492,11 +9441,6 @@ markdown-table@^3.0.0: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.4.tgz#fe44d6d410ff9d6f2ea1797a3f60aa4d2b631c2a" integrity sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw== -marked@^15.0.12: - version "15.0.12" - resolved "https://registry.yarnpkg.com/marked/-/marked-15.0.12.tgz#30722c7346e12d0a2d0207ab9b0c4f0102d86c4e" - integrity sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA== - marked@^16.0.0: version "16.2.0" resolved "https://registry.yarnpkg.com/marked/-/marked-16.2.0.tgz#c407a4f7ed3acc1110812525cfd1b0ed8502792c" @@ -12902,11 +12846,6 @@ section-matter@^1.0.0: extend-shallow "^2.0.1" kind-of "^6.0.0" -secure-json-parse@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" - integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== - select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -14903,11 +14842,6 @@ yocto-queue@^1.0.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.2.1.tgz#36d7c4739f775b3cbc28e6136e21aa057adec418" integrity sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg== -zod-to-json-schema@^3.24.1: - version "3.24.6" - resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz#5920f020c4d2647edfbb954fa036082b92c9e12d" - integrity sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg== - zod@3.23.8: version "3.23.8" resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d" From 88d63aa7d28fde68255e46c0fc4800a6bd39443b Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Tue, 30 Sep 2025 00:58:26 -0700 Subject: [PATCH 04/40] docsearch css --- package.json | 2 +- yarn.lock | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 8bce1806e1..924db4dbe9 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@babel/runtime-corejs3": "7.26.10", "@braintree/sanitize-url": "^6.0.1", "@csstools/selector-resolve-nested": "3.1.0", - "@docsearch/css": "3.8.2", + "@docsearch/css": "^4.1.0", "@docsearch/react": "^4.1.0", "@docusaurus/bundler": "3.9.1", "@docusaurus/core": "3.9.1", diff --git a/yarn.lock b/yarn.lock index 502f988ff1..3ede609b8a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1774,12 +1774,7 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@docsearch/css@3.8.2": - version "3.8.2" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.8.2.tgz#7973ceb6892c30f154ba254cd05c562257a44977" - integrity sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ== - -"@docsearch/css@4.1.0": +"@docsearch/css@4.1.0", "@docsearch/css@^4.1.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-4.1.0.tgz#e156e011539d73624b2354dc8be8e96ac9be9ddc" integrity sha512-nuNKGjHj/FQeWgE9t+i83QD/V67QiaAmGY7xS9TVCRUiCqSljOgIKlsLoQZKKVwEG8f+OWKdznzZkJxGZ7d06A== From 34870c05b7ea42943ed3670490e9d35f12b16cd8 Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Tue, 30 Sep 2025 02:05:27 -0700 Subject: [PATCH 05/40] rm staging --- .github/workflows/pr.yml | 11 ----------- .github/workflows/review.yml | 19 ------------------- 2 files changed, 30 deletions(-) delete mode 100644 .github/workflows/review.yml diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index dffc181961..13fd112067 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -36,17 +36,6 @@ jobs: run: yarn install --frozen-lockfile - name: Build the Docusaurus site run: yarn build - deploy-to-review: - uses: SumoLogic/sumologic-documentation/.github/workflows/build_and_deploy.yml@main - with: - hostname: https://d2t1s0ah22jxsa.cloudfront.net - base_url: /${{ github.ref_name }}/ - environment: review/${{ github.ref_name }} - secrets: - S3_BUCKET_NAME: ${{ secrets.REVIEW_S3_BUCKET_NAME }} - CLOUDFRONT_DISTRIBUTION_ID: ${{ secrets.REVIEW_CLOUDFRONT_DISTRIBUTION_ID }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} spellcheck: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml deleted file mode 100644 index ca2a045584..0000000000 --- a/.github/workflows/review.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: deploy-to-review - -on: workflow_dispatch - -permissions: - contents: write - -jobs: - deploy-to-review: - uses: SumoLogic/sumologic-documentation/.github/workflows/build_and_deploy.yml@main - with: - hostname: https://d2t1s0ah22jxsa.cloudfront.net - base_url: /${{ github.ref_name }}/ - environment: review/${{ github.ref_name }} - secrets: - S3_BUCKET_NAME: ${{ secrets.REVIEW_S3_BUCKET_NAME }} - CLOUDFRONT_DISTRIBUTION_ID: ${{ secrets.REVIEW_CLOUDFRONT_DISTRIBUTION_ID }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} From d9771d90d9dee45a858370bc26a687d88181b9ff Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Tue, 30 Sep 2025 02:37:15 -0700 Subject: [PATCH 06/40] rm staging --- .github/workflows/pr.yml | 11 ----------- .github/workflows/review.yml | 19 ------------------- 2 files changed, 30 deletions(-) delete mode 100644 .github/workflows/review.yml diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index dffc181961..13fd112067 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -36,17 +36,6 @@ jobs: run: yarn install --frozen-lockfile - name: Build the Docusaurus site run: yarn build - deploy-to-review: - uses: SumoLogic/sumologic-documentation/.github/workflows/build_and_deploy.yml@main - with: - hostname: https://d2t1s0ah22jxsa.cloudfront.net - base_url: /${{ github.ref_name }}/ - environment: review/${{ github.ref_name }} - secrets: - S3_BUCKET_NAME: ${{ secrets.REVIEW_S3_BUCKET_NAME }} - CLOUDFRONT_DISTRIBUTION_ID: ${{ secrets.REVIEW_CLOUDFRONT_DISTRIBUTION_ID }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} spellcheck: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml deleted file mode 100644 index ca2a045584..0000000000 --- a/.github/workflows/review.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: deploy-to-review - -on: workflow_dispatch - -permissions: - contents: write - -jobs: - deploy-to-review: - uses: SumoLogic/sumologic-documentation/.github/workflows/build_and_deploy.yml@main - with: - hostname: https://d2t1s0ah22jxsa.cloudfront.net - base_url: /${{ github.ref_name }}/ - environment: review/${{ github.ref_name }} - secrets: - S3_BUCKET_NAME: ${{ secrets.REVIEW_S3_BUCKET_NAME }} - CLOUDFRONT_DISTRIBUTION_ID: ${{ secrets.REVIEW_CLOUDFRONT_DISTRIBUTION_ID }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} From a99274f2c55d093e4071b5992d39484ede8fb833 Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Thu, 18 Dec 2025 20:25:51 -0800 Subject: [PATCH 07/40] restore Algolia Ask AI credentials --- docusaurus.config.js | 14 +++++++------- static/abc655ef33c7411c86d05452602d6c02.txt | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 static/abc655ef33c7411c86d05452602d6c02.txt diff --git a/docusaurus.config.js b/docusaurus.config.js index ce7730993c..418bc44098 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -291,15 +291,15 @@ module.exports = { apiKey: 'fb2f4e1fb40f962900631121cb365549', indexName: 'crawler_sumodocs', contextualSearch: false, - searchPagePath: 'docs-search', // Default value is 'search'; renamed to 'docs-search' so it doesn't conflict with '/Search' redirect + searchPagePath: 'docs-search', // Default value is 'search'; renamed to 'docs-search' so it doesn't conflict with '/Search' cid-redirect insights: true, // Testing AskAI in Algolia portal -// askAi: { -// assistantId: 'Gj8Bh1qOc2XJ', -// indexName: 'crawler_sumodocs', -// apiKey: 'fb2f4e1fb40f962900631121cb365549', -// appId: '2SJPGMLW1Q', -// }, + askAi: { + assistantId: 'T7pp7iENesuU', + indexName: 'crawler_sumodocs', + apiKey: 'fb2f4e1fb40f962900631121cb365549', + appId: '2SJPGMLW1Q', + }, insightsConfig: { useCookie: true, // alt to useCookie: true, }, diff --git a/static/abc655ef33c7411c86d05452602d6c02.txt b/static/abc655ef33c7411c86d05452602d6c02.txt new file mode 100644 index 0000000000..deae657e07 --- /dev/null +++ b/static/abc655ef33c7411c86d05452602d6c02.txt @@ -0,0 +1 @@ +abc655ef33c7411c86d05452602d6c02 From 0c78a7d70816faec9141e6de0aebbd5ab6b5072b Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Mon, 13 Apr 2026 16:29:06 -0700 Subject: [PATCH 08/40] merge w main --- docusaurus.config.js | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index 87ef95dabb..bd047bba0f 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -120,19 +120,10 @@ module.exports = { ], clientModules: [ require.resolve('./src/client-modules/trackTrialClick.js'), - require.resolve('./src/client-modules/fixAnchorScroll.js'), ], - storage: { - type: 'localStorage', - namespace: true, - }, future: { - faster: true, - v4: { - siteStorageNamespacing: true, - fasterByDefault: true, - removeLegacyPostBuildHeadAttribute: true, - }, + v4: true, + experimental_faster: true, }, staticDirectories: ['static'], presets: [ @@ -354,7 +345,7 @@ module.exports = { ], announcementBar: { id: 'domain', - content: 'Check out Mobot, your conversational interface for Sumo Logic. Search logs using natural language, troubleshoot faster, and get how-to guidance.', + content: 'Come see us at RSA Conference 2026! Visit booth 6465 — March 23–26 in San Francisco. Book a meeting.', backgroundColor: '#000', textColor: '#000', }, @@ -375,14 +366,14 @@ module.exports = { apiKey: 'fb2f4e1fb40f962900631121cb365549', indexName: 'crawler_sumodocs', contextualSearch: false, - searchPagePath: 'docs-search', // Default value is 'search'; renamed to 'docs-search' so it doesn't conflict with '/Search' cid-redirect + searchPagePath: 'docs-search', // Default value is 'search'; renamed to 'docs-search' so it doesn't conflict with '/Search' redirect insights: true, - // Testing AskAI in Algolia portal askAi: { assistantId: 'T7pp7iENesuU', indexName: 'crawler_sumodocs', apiKey: 'fb2f4e1fb40f962900631121cb365549', appId: '2SJPGMLW1Q', + suggestedQuestions: true, }, insightsConfig: { useCookie: true, // alt to useCookie: true, @@ -392,7 +383,7 @@ module.exports = { prism: { theme: lightCodeTheme, darkTheme: darkCodeTheme, - additionalLanguages: ['csharp', 'powershell', 'java', 'markdown', 'scala', 'bash', 'diff', 'json', `sql`, `sumo`], + additionalLanguages: ['csharp', 'powershell', 'java', 'markdown', 'scala', 'bash', 'diff', 'json'], }, navbar: { logo: { From 3be01a4dcebfc39f737d01b7bf273e974b9212e6 Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Mon, 13 Apr 2026 16:32:39 -0700 Subject: [PATCH 09/40] merge w main --- docusaurus.config.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index bd047bba0f..4811d58f22 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -120,10 +120,19 @@ module.exports = { ], clientModules: [ require.resolve('./src/client-modules/trackTrialClick.js'), + require.resolve('./src/client-modules/fixAnchorScroll.js'), ], + storage: { + type: 'localStorage', + namespace: true, + }, future: { - v4: true, - experimental_faster: true, + faster: true, + v4: { + siteStorageNamespacing: true, + fasterByDefault: true, + removeLegacyPostBuildHeadAttribute: true, + }, }, staticDirectories: ['static'], presets: [ @@ -345,7 +354,7 @@ module.exports = { ], announcementBar: { id: 'domain', - content: 'Come see us at RSA Conference 2026! Visit booth 6465 — March 23–26 in San Francisco. Book a meeting.', + content: 'Check out Mobot, your conversational interface for Sumo Logic. Search logs using natural language, troubleshoot faster, and get how-to guidance.', backgroundColor: '#000', textColor: '#000', }, @@ -383,7 +392,7 @@ module.exports = { prism: { theme: lightCodeTheme, darkTheme: darkCodeTheme, - additionalLanguages: ['csharp', 'powershell', 'java', 'markdown', 'scala', 'bash', 'diff', 'json'], + additionalLanguages: ['csharp', 'powershell', 'java', 'markdown', 'scala', 'bash', 'diff', 'json', `sql`, `sumo`], }, navbar: { logo: { From acf099493b1e664b253b55c63a5a10dd11690dfa Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Mon, 13 Apr 2026 19:40:43 -0700 Subject: [PATCH 10/40] Implement Algolia Ask AI integration with navbar button - Add Root component to mount Ask AI button within Docusaurus context - Create AskAiButton component with SVG sparkles icon and Cmd/Ctrl+I shortcut - Add AskAiSidepanel component with lazy-loaded Algolia AI interface - Style button to match search box design (transparent bg, matching border) - Add navbar placeholder div in docusaurus.config.js - Handle window resize events to keep button visible - Support light/dark mode with proper color inheritance Co-Authored-By: Claude Opus 4.6 --- docusaurus.config.js | 6 ++ src/components/AskAiButton/index.tsx | 52 ++++++++++++ src/components/AskAiButton/styles.module.css | 42 ++++++++++ src/components/AskAiSidepanel/index.tsx | 85 ++++++++++++++++++++ src/components/AskAiSidepanel/styles.css | 84 +++++++++++++++++++ src/theme/Root.tsx | 51 ++++++++++++ 6 files changed, 320 insertions(+) create mode 100644 src/components/AskAiButton/index.tsx create mode 100644 src/components/AskAiButton/styles.module.css create mode 100644 src/components/AskAiSidepanel/index.tsx create mode 100644 src/components/AskAiSidepanel/styles.css create mode 100644 src/theme/Root.tsx diff --git a/docusaurus.config.js b/docusaurus.config.js index 4811d58f22..972e75ff5a 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -545,6 +545,12 @@ module.exports = { type: 'search', position: 'left', }, + { + type: 'html', + position: 'left', + className: 'navbar-ask-ai-item', + value: '', + }, ], }, footer: { diff --git a/src/components/AskAiButton/index.tsx b/src/components/AskAiButton/index.tsx new file mode 100644 index 0000000000..831198babb --- /dev/null +++ b/src/components/AskAiButton/index.tsx @@ -0,0 +1,52 @@ +/** + * Ask AI Button Component + * + * Renders a button in the navbar that opens the Algolia Ask AI sidepanel. + * Includes keyboard shortcut support (Cmd/Ctrl + I). + */ + +import React, { useState, useEffect } from 'react'; +import styles from './styles.module.css'; + +// Lazy load the sidepanel component +const AskAiSidepanel = React.lazy(() => import('@site/src/components/AskAiSidepanel')); + +export default function AskAiButton() { + const [isOpen, setIsOpen] = useState(false); + + // Keyboard shortcut: Cmd/Ctrl + I + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if ((event.metaKey || event.ctrlKey) && event.key === 'i') { + event.preventDefault(); + setIsOpen((prev) => !prev); + } + }; + + document.addEventListener('keydown', handleKeyDown); + return () => document.removeEventListener('keydown', handleKeyDown); + }, []); + + return ( + <> + + + {isOpen && ( + Loading...}> + setIsOpen(false)} /> + + )} + + ); +} diff --git a/src/components/AskAiButton/styles.module.css b/src/components/AskAiButton/styles.module.css new file mode 100644 index 0000000000..f8bfab3d75 --- /dev/null +++ b/src/components/AskAiButton/styles.module.css @@ -0,0 +1,42 @@ +.askAiButton { + display: flex; + align-items: center; + gap: 0.25rem; + padding: 0 0.75rem; + height: 36px; + background: transparent; + border: 1px solid var(--ifm-color-border-pale); + border-radius: 0.5rem; + color: var(--ifm-navbar-link-color); + font-size: 0.85rem; + cursor: pointer; + transition: all 0.2s ease; + margin-left: -1rem; +} + +.askAiButton:hover { + background: rgba(0, 0, 0, 0.05); +} + +[data-theme='dark'] .askAiButton { + border-color: #6b6f78; +} + +[data-theme='dark'] .askAiButton:hover { + background: rgba(255, 255, 255, 0.05); +} + +.buttonText { + display: inline; +} + +.buttonIcon { + display: inline-block; + flex-shrink: 0; +} + +@media (max-width: 768px) { + .buttonText { + display: none; + } +} diff --git a/src/components/AskAiSidepanel/index.tsx b/src/components/AskAiSidepanel/index.tsx new file mode 100644 index 0000000000..d06f8f6ad5 --- /dev/null +++ b/src/components/AskAiSidepanel/index.tsx @@ -0,0 +1,85 @@ +/** + * Ask AI Sidepanel Component + * + * Renders the Algolia Ask AI sidepanel modal using Algolia's official component. + * Integrates with Docusaurus theme and configuration. + */ + +import React, { useEffect, useState } from 'react'; +import { createPortal } from 'react-dom'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import './styles.css'; + +interface AskAiSidepanelProps { + isOpen: boolean; + onClose: () => void; +} + +export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) { + const { siteConfig } = useDocusaurusContext(); + const [SidepanelComponent, setSidepanelComponent] = useState(null); + + // Lazy load the Algolia Sidepanel component + useEffect(() => { + if (isOpen && !SidepanelComponent) { + import('@docsearch/react/sidepanel').then((module) => { + setSidepanelComponent(() => module.Sidepanel); + }); + } + }, [isOpen, SidepanelComponent]); + + // Close on Escape key + useEffect(() => { + if (!isOpen) return; + + const handleEscape = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + onClose(); + } + }; + + document.addEventListener('keydown', handleEscape); + return () => document.removeEventListener('keydown', handleEscape); + }, [isOpen, onClose]); + + if (!isOpen || !SidepanelComponent) { + return null; + } + + // Get Algolia config from Docusaurus config + const algoliaConfig = (siteConfig.themeConfig as any)?.algolia; + + if (!algoliaConfig?.askAi) { + console.error('Ask AI configuration not found in docusaurus.config.js'); + return null; + } + + const { assistantId, indexName, appId, apiKey } = algoliaConfig.askAi; + + // Create the sidepanel element + const sidepanel = ( + <> + {/* Backdrop */} +
+ + {/* Sidepanel */} +
+ +
+ + ); + + // Render as portal to avoid z-index issues + return createPortal(sidepanel, document.body); +} diff --git a/src/components/AskAiSidepanel/styles.css b/src/components/AskAiSidepanel/styles.css new file mode 100644 index 0000000000..babbaa545d --- /dev/null +++ b/src/components/AskAiSidepanel/styles.css @@ -0,0 +1,84 @@ +/** + * Ask AI Sidepanel Styles + * + * Styles for the Algolia Ask AI sidepanel modal. + * Includes backdrop, positioning, and dark mode support. + */ + +/* Backdrop */ +.ask-ai-backdrop { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + z-index: 9998; + backdrop-filter: blur(4px); +} + +/* Sidepanel Container */ +.ask-ai-sidepanel { + position: fixed; + top: 0; + right: 0; + bottom: 0; + width: 100%; + max-width: 480px; + background: var(--ifm-background-color); + box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1); + z-index: 9999; + overflow: hidden; + animation: slideIn 0.3s ease-out; +} + +@keyframes slideIn { + from { + transform: translateX(100%); + } + to { + transform: translateX(0); + } +} + +/* Mobile: full width */ +@media (max-width: 768px) { + .ask-ai-sidepanel { + max-width: 100%; + } +} + +/* Dark mode support */ +[data-theme='dark'] .ask-ai-backdrop { + background: rgba(0, 0, 0, 0.7); +} + +[data-theme='dark'] .ask-ai-sidepanel { + box-shadow: -2px 0 16px rgba(0, 0, 0, 0.3); +} + +/* Algolia Sidepanel overrides for theme integration */ +.ask-ai-sidepanel :global(.DocSearch-Sidepanel) { + background: var(--ifm-background-color); + color: var(--ifm-font-color-base); + height: 100%; +} + +.ask-ai-sidepanel :global(.DocSearch-Input) { + background: var(--ifm-color-emphasis-100); + color: var(--ifm-font-color-base); + border: 1px solid var(--ifm-color-emphasis-300); +} + +.ask-ai-sidepanel :global(.DocSearch-Input:focus) { + border-color: var(--ifm-color-primary); +} + +.ask-ai-sidepanel :global(.DocSearch-Button) { + background: var(--ifm-color-primary); + color: white; +} + +.ask-ai-sidepanel :global(.DocSearch-Button:hover) { + background: var(--ifm-color-primary-dark); +} diff --git a/src/theme/Root.tsx b/src/theme/Root.tsx new file mode 100644 index 0000000000..c1da7da83e --- /dev/null +++ b/src/theme/Root.tsx @@ -0,0 +1,51 @@ +/** + * Root component wrapper for Docusaurus + * + * This component wraps the entire app and is rendered WITHIN Docusaurus's + * context providers, so we can safely use hooks like useColorMode here. + * + * We use this to mount the Ask AI button to the navbar placeholder. + */ + +import React, { useEffect, useState } from 'react'; +import { createPortal } from 'react-dom'; +import AskAiButton from '@site/src/components/AskAiButton'; + +interface RootProps { + children: React.ReactNode; +} + +export default function Root({ children }: RootProps) { + const [placeholder, setPlaceholder] = useState(null); + + useEffect(() => { + // Find and monitor the navbar placeholder + const findPlaceholder = () => { + const el = document.getElementById('navbar-ask-ai-button'); + if (el && el !== placeholder) { + setPlaceholder(el); + } + }; + + // Initial check + findPlaceholder(); + + // Set up interval to check if placeholder exists (handles navbar re-renders) + const interval = setInterval(findPlaceholder, 500); + + // Also check on window resize + window.addEventListener('resize', findPlaceholder); + + return () => { + clearInterval(interval); + window.removeEventListener('resize', findPlaceholder); + }; + }, [placeholder]); + + return ( + <> + {children} + {placeholder && createPortal(, placeholder)} + + ); +} From 8924c4d5605c432da865d3cf229854a3c2456fac Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Mon, 13 Apr 2026 20:36:11 -0700 Subject: [PATCH 11/40] Enhance Ask AI sidepanel with premium styling and bug fixes - Import Algolia base CSS and add comprehensive style overrides - Apply modern design patterns inspired by Algolia and Stripe docs - Enhance button styling with hover effects, shadows, and animations - Customize intro text to be Sumo Logic-specific - Fix panel disappearing on window resize by lifting state to Root - Wire up onClose handler to close button and backdrop - Align header icon and title side-by-side - Improve dark mode support with refined colors and shadows - Add smooth cubic-bezier animations for panel and button - Style input fields, buttons, and suggested questions - Add custom scrollbar styling Co-Authored-By: Claude Opus 4.6 --- src/components/AskAiButton/index.tsx | 13 +- src/components/AskAiButton/styles.module.css | 65 +++- src/components/AskAiSidepanel/index.tsx | 22 +- src/components/AskAiSidepanel/styles.css | 329 ++++++++++++++++--- src/theme/Root.tsx | 9 +- 5 files changed, 372 insertions(+), 66 deletions(-) diff --git a/src/components/AskAiButton/index.tsx b/src/components/AskAiButton/index.tsx index 831198babb..6b082c2e01 100644 --- a/src/components/AskAiButton/index.tsx +++ b/src/components/AskAiButton/index.tsx @@ -5,27 +5,30 @@ * Includes keyboard shortcut support (Cmd/Ctrl + I). */ -import React, { useState, useEffect } from 'react'; +import React, { useEffect } from 'react'; import styles from './styles.module.css'; // Lazy load the sidepanel component const AskAiSidepanel = React.lazy(() => import('@site/src/components/AskAiSidepanel')); -export default function AskAiButton() { - const [isOpen, setIsOpen] = useState(false); +interface AskAiButtonProps { + isOpen: boolean; + setIsOpen: (open: boolean) => void; +} +export default function AskAiButton({ isOpen, setIsOpen }: AskAiButtonProps) { // Keyboard shortcut: Cmd/Ctrl + I useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if ((event.metaKey || event.ctrlKey) && event.key === 'i') { event.preventDefault(); - setIsOpen((prev) => !prev); + setIsOpen(!isOpen); } }; document.addEventListener('keydown', handleKeyDown); return () => document.removeEventListener('keydown', handleKeyDown); - }, []); + }, [isOpen, setIsOpen]); return ( <> diff --git a/src/components/AskAiButton/styles.module.css b/src/components/AskAiButton/styles.module.css index f8bfab3d75..a6b228db86 100644 --- a/src/components/AskAiButton/styles.module.css +++ b/src/components/AskAiButton/styles.module.css @@ -1,42 +1,87 @@ +/** + * Ask AI Button - Premium navbar button styling + * Matches Algolia and Stripe documentation design patterns + */ + .askAiButton { display: flex; align-items: center; - gap: 0.25rem; - padding: 0 0.75rem; + gap: 0.375rem; + padding: 0 0.875rem; height: 36px; background: transparent; - border: 1px solid var(--ifm-color-border-pale); - border-radius: 0.5rem; + border: 1.5px solid var(--ifm-color-emphasis-300); + border-radius: 8px; color: var(--ifm-navbar-link-color); - font-size: 0.85rem; + font-size: 0.875rem; + font-weight: 500; cursor: pointer; - transition: all 0.2s ease; + transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1); margin-left: -1rem; + position: relative; + overflow: hidden; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); } +/* Hover effect with subtle background and shadow */ .askAiButton:hover { - background: rgba(0, 0, 0, 0.05); + background: var(--ifm-color-emphasis-100); + border-color: var(--ifm-color-emphasis-400); + transform: translateY(-1px); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08); +} + +/* Active/pressed state */ +.askAiButton:active { + transform: translateY(0); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); +} + +/* Focus state for accessibility */ +.askAiButton:focus-visible { + outline: 2px solid var(--ifm-color-primary); + outline-offset: 2px; } +/* Dark mode styling */ [data-theme='dark'] .askAiButton { - border-color: #6b6f78; + border-color: var(--ifm-color-emphasis-400); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); } [data-theme='dark'] .askAiButton:hover { - background: rgba(255, 255, 255, 0.05); + background: var(--ifm-color-emphasis-200); + border-color: var(--ifm-color-emphasis-500); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); } +/* Button text and icon */ .buttonText { display: inline; + letter-spacing: -0.01em; } .buttonIcon { - display: inline-block; + display: inline-flex; + align-items: center; flex-shrink: 0; + transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1); +} + +/* Subtle icon animation on hover */ +.askAiButton:hover .buttonIcon { + transform: scale(1.1); } +/* Responsive: Hide text on mobile, show icon only */ @media (max-width: 768px) { .buttonText { display: none; } + + .askAiButton { + padding: 0 0.625rem; + min-width: 36px; + justify-content: center; + } } diff --git a/src/components/AskAiSidepanel/index.tsx b/src/components/AskAiSidepanel/index.tsx index d06f8f6ad5..6d3db7652f 100644 --- a/src/components/AskAiSidepanel/index.tsx +++ b/src/components/AskAiSidepanel/index.tsx @@ -8,6 +8,7 @@ import React, { useEffect, useState } from 'react'; import { createPortal } from 'react-dom'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import '@docsearch/css/dist/sidepanel.css'; import './styles.css'; interface AskAiSidepanelProps { @@ -42,6 +43,22 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) return () => document.removeEventListener('keydown', handleEscape); }, [isOpen, onClose]); + // Prevent panel from disappearing on window resize + useEffect(() => { + if (!isOpen) return; + + const handleResize = () => { + // Force the panel to stay visible by ensuring container classes are maintained + const container = document.querySelector('.DocSearch-Sidepanel-Container'); + if (container && !container.classList.contains('is-open')) { + container.classList.add('is-open'); + } + }; + + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, [isOpen]); + if (!isOpen || !SidepanelComponent) { return null; } @@ -69,9 +86,12 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) apiKey={apiKey} indexName={indexName} assistantId={assistantId} + onClose={onClose} translations={{ title: 'Ask AI about Sumo Logic', - placeholder: 'Ask a question...', + placeholder: 'Ask a question about Sumo Logic...', + greeting: 'How can I help you with Sumo Logic today?', + introduction: 'I can help you find information about Sumo Logic features, integrations, troubleshooting guides, APIs, and best practices across our documentation.', poweredBy: 'Powered by Algolia', }} insights diff --git a/src/components/AskAiSidepanel/styles.css b/src/components/AskAiSidepanel/styles.css index babbaa545d..f6a31b0168 100644 --- a/src/components/AskAiSidepanel/styles.css +++ b/src/components/AskAiSidepanel/styles.css @@ -1,35 +1,92 @@ /** * Ask AI Sidepanel Styles * - * Styles for the Algolia Ask AI sidepanel modal. - * Includes backdrop, positioning, and dark mode support. + * Custom overrides for Algolia Ask AI sidepanel. + * Modern design inspired by Algolia and Stripe documentation. */ -/* Backdrop */ +/* =================================================================== + Backdrop - Enhanced with smooth fade-in + =================================================================== */ .ask-ai-backdrop { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: rgba(0, 0, 0, 0.5); - z-index: 9998; - backdrop-filter: blur(4px); + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + bottom: 0 !important; + background: rgba(0, 0, 0, 0.48) !important; + z-index: 998 !important; + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + animation: fadeIn 0.25s cubic-bezier(0.16, 1, 0.3, 1); } -/* Sidepanel Container */ +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +[data-theme='dark'] .ask-ai-backdrop { + background: rgba(0, 0, 0, 0.64) !important; +} + +/* =================================================================== + Sidepanel Container Wrapper + =================================================================== */ .ask-ai-sidepanel { - position: fixed; - top: 0; - right: 0; - bottom: 0; - width: 100%; - max-width: 480px; - background: var(--ifm-background-color); - box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1); - z-index: 9999; - overflow: hidden; - animation: slideIn 0.3s ease-out; + position: fixed !important; + top: 0 !important; + right: 0 !important; + bottom: 0 !important; + left: auto !important; + width: 100% !important; + max-width: 540px !important; + z-index: 999 !important; +} + +@media (max-width: 768px) { + .ask-ai-sidepanel { + max-width: 100% !important; + left: 0 !important; + } +} + +/* =================================================================== + Algolia Component Overrides - Container & Panel + =================================================================== */ + +/* Override the container positioning */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Container { + position: relative !important; + top: 0 !important; + right: 0 !important; + bottom: 0 !important; + left: 0 !important; + width: 100% !important; + height: 100% !important; + max-width: none !important; + transform: none !important; + opacity: 1 !important; + border-radius: 0 !important; + box-shadow: + -1px 0 0 0 rgba(0, 0, 0, 0.05), + -8px 0 32px -4px rgba(0, 0, 0, 0.12), + -16px 0 64px -8px rgba(0, 0, 0, 0.08) !important; + animation: slideIn 0.35s cubic-bezier(0.16, 1, 0.3, 1); + display: flex !important; + visibility: visible !important; +} + +/* Ensure panel stays visible during resize */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Container.is-open { + transform: none !important; + opacity: 1 !important; + display: flex !important; + visibility: visible !important; } @keyframes slideIn { @@ -41,44 +98,218 @@ } } -/* Mobile: full width */ -@media (max-width: 768px) { - .ask-ai-sidepanel { - max-width: 100%; - } +[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-Container { + box-shadow: + -1px 0 0 0 rgba(255, 255, 255, 0.08), + -8px 0 32px -4px rgba(0, 0, 0, 0.4), + -16px 0 64px -8px rgba(0, 0, 0, 0.32) !important; } -/* Dark mode support */ -[data-theme='dark'] .ask-ai-backdrop { - background: rgba(0, 0, 0, 0.7); +/* Main sidepanel - integrate with Docusaurus theme */ +.ask-ai-sidepanel .DocSearch-Sidepanel { + background-color: var(--ifm-background-color) !important; + border-left: 1px solid var(--ifm-color-emphasis-200) !important; +} + +[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel { + border-left-color: var(--ifm-color-emphasis-300) !important; +} + +/* =================================================================== + Header Styling + =================================================================== */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Header { + background-color: var(--ifm-navbar-background-color) !important; + border-bottom: 1px solid var(--ifm-color-emphasis-200) !important; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Header--center { + display: flex !important; + flex-direction: row !important; + align-items: center !important; + gap: 0.5rem !important; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Header-TitleIcon { + display: block !important; + margin: 0 !important; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Title { + color: var(--ifm-font-color-base) !important; + font-weight: 600 !important; + margin: 0 !important; +} + +/* =================================================================== + Content Area + =================================================================== */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Content { + background-color: var(--ifm-background-color) !important; +} + +/* Scrollbar styling */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Content::-webkit-scrollbar { + width: 8px; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Content::-webkit-scrollbar-track { + background: transparent; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Content::-webkit-scrollbar-thumb { + background: var(--ifm-color-emphasis-300); + border-radius: 4px; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Content::-webkit-scrollbar-thumb:hover { + background: var(--ifm-color-emphasis-400); +} + +/* =================================================================== + Prompt Input Area + =================================================================== */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt { + background-color: var(--ifm-navbar-background-color) !important; + border-top: 1px solid var(--ifm-color-emphasis-200) !important; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--form { + border-color: var(--ifm-color-emphasis-300) !important; + border-radius: 8px !important; + transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1); +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--form:focus-within { + border-color: var(--ifm-color-primary) !important; + box-shadow: 0 0 0 3px var(--ifm-color-primary-lightest) !important; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--textarea { + color: var(--ifm-font-color-base) !important; + font-size: 0.95rem !important; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--textarea::placeholder { + color: var(--ifm-color-emphasis-600) !important; +} + +/* Submit button styling */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--submit { + background-color: var(--ifm-color-primary) !important; + border-radius: 6px !important; + transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1) !important; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--submit:hover { + background-color: var(--ifm-color-primary-dark) !important; + transform: scale(1.05); +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--submit:disabled { + opacity: 0.5; + transform: none; +} + +/* =================================================================== + Footer + =================================================================== */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Footer { + background-color: var(--ifm-navbar-background-color) !important; +} + +/* =================================================================== + Message Bubbles & Content + =================================================================== */ +.ask-ai-sidepanel .DocSearch-AskAiScreen-Response { + background-color: var(--ifm-color-emphasis-100) !important; + border-radius: 12px !important; + border: 1px solid var(--ifm-color-emphasis-200) !important; +} + +[data-theme='dark'] .ask-ai-sidepanel .DocSearch-AskAiScreen-Response { + background-color: var(--ifm-color-emphasis-200) !important; + border-color: var(--ifm-color-emphasis-300) !important; +} + +/* Text colors */ +.ask-ai-sidepanel .DocSearch-Markdown-Content { + color: var(--ifm-font-color-base) !important; +} + +/* =================================================================== + Button Overrides + =================================================================== */ +.ask-ai-sidepanel button { + transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1) !important; +} + +.ask-ai-sidepanel button[aria-label] { + color: var(--ifm-font-color-base) !important; + border-radius: 6px !important; +} + +.ask-ai-sidepanel button[aria-label]:hover { + background-color: var(--ifm-color-emphasis-100) !important; +} + +/* =================================================================== + Suggested Questions + =================================================================== */ +.ask-ai-sidepanel .DocSearch-Sidepanel-SuggestedQuestion { + background-color: var(--ifm-color-emphasis-0) !important; + border-color: var(--ifm-color-emphasis-300) !important; + color: var(--ifm-font-color-base) !important; + border-radius: 8px !important; + transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1); +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-SuggestedQuestion:hover { + border-color: var(--ifm-color-primary) !important; + background-color: var(--ifm-color-emphasis-100) !important; + transform: translateY(-1px); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08); +} + +[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-SuggestedQuestion { + background-color: var(--ifm-color-emphasis-100) !important; + border-color: var(--ifm-color-emphasis-400) !important; } -[data-theme='dark'] .ask-ai-sidepanel { - box-shadow: -2px 0 16px rgba(0, 0, 0, 0.3); +/* =================================================================== + Intro Screen - Custom Text Override + =================================================================== */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Screen--title { + color: var(--ifm-font-color-base) !important; + font-size: 1.5rem !important; } -/* Algolia Sidepanel overrides for theme integration */ -.ask-ai-sidepanel :global(.DocSearch-Sidepanel) { - background: var(--ifm-background-color); - color: var(--ifm-font-color-base); - height: 100%; +/* Hide original title and show custom text */ +.ask-ai-sidepanel .DocSearch-Sidepanel-NewConversationScreen .DocSearch-Sidepanel-Screen--title { + font-size: 0 !important; + line-height: 0 !important; } -.ask-ai-sidepanel :global(.DocSearch-Input) { - background: var(--ifm-color-emphasis-100); - color: var(--ifm-font-color-base); - border: 1px solid var(--ifm-color-emphasis-300); +.ask-ai-sidepanel .DocSearch-Sidepanel-NewConversationScreen .DocSearch-Sidepanel-Screen--title::before { + font-size: 1.625rem !important; + line-height: 2rem !important; + content: 'How can I help you with Sumo Logic today?'; + display: block; } -.ask-ai-sidepanel :global(.DocSearch-Input:focus) { - border-color: var(--ifm-color-primary); +.ask-ai-sidepanel .DocSearch-Sidepanel-Screen--introduction { + color: var(--ifm-color-emphasis-700) !important; } -.ask-ai-sidepanel :global(.DocSearch-Button) { - background: var(--ifm-color-primary); - color: white; +/* Hide original introduction and show custom text */ +.ask-ai-sidepanel .DocSearch-Sidepanel-NewConversationScreen .DocSearch-Sidepanel-Screen--introduction { + font-size: 0 !important; + line-height: 0 !important; } -.ask-ai-sidepanel :global(.DocSearch-Button:hover) { - background: var(--ifm-color-primary-dark); +.ask-ai-sidepanel .DocSearch-Sidepanel-NewConversationScreen .DocSearch-Sidepanel-Screen--introduction::before { + font-size: 0.875rem !important; + line-height: 1.25rem !important; + content: 'I can help you find information about Sumo Logic features, integrations, troubleshooting guides, APIs, and best practices across our documentation.'; + display: block; } diff --git a/src/theme/Root.tsx b/src/theme/Root.tsx index c1da7da83e..d6dcd2c93a 100644 --- a/src/theme/Root.tsx +++ b/src/theme/Root.tsx @@ -17,6 +17,7 @@ interface RootProps { export default function Root({ children }: RootProps) { const [placeholder, setPlaceholder] = useState(null); + const [isAskAiOpen, setIsAskAiOpen] = useState(false); useEffect(() => { // Find and monitor the navbar placeholder @@ -45,7 +46,13 @@ export default function Root({ children }: RootProps) { return ( <> {children} - {placeholder && createPortal(, placeholder)} + {placeholder && createPortal( + , + placeholder + )} ); } From 703bb255d3188bbddd26a1bd6f6446db659e41cd Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Mon, 13 Apr 2026 20:48:01 -0700 Subject: [PATCH 12/40] Match Ask AI button styling to DocSearch and enable suggested questions - Match button border, text, and icon colors to DocSearch-Button - Light mode: #5f6368 text, border-pale border - Dark mode: #bdc1c6 text, #6b6f78 border and icon - Reduce gap between text and icon from 0.375rem to 0.25rem - Pass suggestedQuestions prop to Algolia Sidepanel component - Extract suggestedQuestions from config and enable in UI Co-Authored-By: Claude Opus 4.6 --- src/components/AskAiButton/styles.module.css | 19 +++++++++++++------ src/components/AskAiSidepanel/index.tsx | 3 ++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/components/AskAiButton/styles.module.css b/src/components/AskAiButton/styles.module.css index a6b228db86..4ea403b1de 100644 --- a/src/components/AskAiButton/styles.module.css +++ b/src/components/AskAiButton/styles.module.css @@ -6,13 +6,13 @@ .askAiButton { display: flex; align-items: center; - gap: 0.375rem; + gap: 0.25rem; padding: 0 0.875rem; height: 36px; background: transparent; - border: 1.5px solid var(--ifm-color-emphasis-300); + border: 1px solid var(--ifm-color-border-pale); border-radius: 8px; - color: var(--ifm-navbar-link-color); + color: #5f6368; font-size: 0.875rem; font-weight: 500; cursor: pointer; @@ -26,7 +26,7 @@ /* Hover effect with subtle background and shadow */ .askAiButton:hover { background: var(--ifm-color-emphasis-100); - border-color: var(--ifm-color-emphasis-400); + border-color: var(--ifm-color-emphasis-300); transform: translateY(-1px); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08); } @@ -45,13 +45,14 @@ /* Dark mode styling */ [data-theme='dark'] .askAiButton { - border-color: var(--ifm-color-emphasis-400); + border-color: #6b6f78; + color: #bdc1c6; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); } [data-theme='dark'] .askAiButton:hover { background: var(--ifm-color-emphasis-200); - border-color: var(--ifm-color-emphasis-500); + border-color: #6b6f78; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); } @@ -66,6 +67,12 @@ align-items: center; flex-shrink: 0; transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1); + color: #5f6368; +} + +/* Dark mode icon color to match DocSearch-Search-Icon */ +[data-theme='dark'] .buttonIcon { + color: #6b6f78; } /* Subtle icon animation on hover */ diff --git a/src/components/AskAiSidepanel/index.tsx b/src/components/AskAiSidepanel/index.tsx index 6d3db7652f..be482b5f60 100644 --- a/src/components/AskAiSidepanel/index.tsx +++ b/src/components/AskAiSidepanel/index.tsx @@ -71,7 +71,7 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) return null; } - const { assistantId, indexName, appId, apiKey } = algoliaConfig.askAi; + const { assistantId, indexName, appId, apiKey, suggestedQuestions } = algoliaConfig.askAi; // Create the sidepanel element const sidepanel = ( @@ -87,6 +87,7 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) indexName={indexName} assistantId={assistantId} onClose={onClose} + suggestedQuestions={suggestedQuestions} translations={{ title: 'Ask AI about Sumo Logic', placeholder: 'Ask a question about Sumo Logic...', From b119dc9b6d2ec7e71c86fb8566c41426fe3c83b8 Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Mon, 13 Apr 2026 20:49:38 -0700 Subject: [PATCH 13/40] Reduce Ask AI button animation intensity and hide loading text - Remove translateY hover lift effect for subtler interaction - Change active state to gentle scale(0.98) with faster transition - Replace icon scale animation with opacity fade on hover - Hide "Loading..." fallback text by setting Suspense fallback to null Co-Authored-By: Claude Opus 4.6 --- src/components/AskAiButton/index.tsx | 2 +- src/components/AskAiButton/styles.module.css | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/AskAiButton/index.tsx b/src/components/AskAiButton/index.tsx index 6b082c2e01..74799d298d 100644 --- a/src/components/AskAiButton/index.tsx +++ b/src/components/AskAiButton/index.tsx @@ -46,7 +46,7 @@ export default function AskAiButton({ isOpen, setIsOpen }: AskAiButtonProps) { {isOpen && ( - Loading...
}> + setIsOpen(false)} /> )} diff --git a/src/components/AskAiButton/styles.module.css b/src/components/AskAiButton/styles.module.css index 4ea403b1de..7cc297fcc1 100644 --- a/src/components/AskAiButton/styles.module.css +++ b/src/components/AskAiButton/styles.module.css @@ -27,14 +27,14 @@ .askAiButton:hover { background: var(--ifm-color-emphasis-100); border-color: var(--ifm-color-emphasis-300); - transform: translateY(-1px); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08); } -/* Active/pressed state */ +/* Active/pressed state - minimal animation */ .askAiButton:active { - transform: translateY(0); + transform: scale(0.98); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); + transition: transform 0.1s ease; } /* Focus state for accessibility */ @@ -77,7 +77,7 @@ /* Subtle icon animation on hover */ .askAiButton:hover .buttonIcon { - transform: scale(1.1); + opacity: 0.8; } /* Responsive: Hide text on mobile, show icon only */ From c81fe79a9082f0572956e728a296a8dabccb17c9 Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Mon, 13 Apr 2026 22:57:45 -0700 Subject: [PATCH 14/40] Fix Ask AI sidepanel input alignment and width stability - Fix submit button vertical alignment by changing form to row flex layout and overriding absolute positioning - Prevent sidepanel from temporarily narrowing during query processing by setting fixed width - Add state-based submit button styling (grey when empty, blue when user types) - Minor font size adjustment for Ask AI button Co-Authored-By: Claude Opus 4.6 --- src/components/AskAiButton/styles.module.css | 2 +- src/components/AskAiSidepanel/index.tsx | 37 ++++ src/components/AskAiSidepanel/styles.css | 190 +++++++++++++++++-- 3 files changed, 212 insertions(+), 17 deletions(-) diff --git a/src/components/AskAiButton/styles.module.css b/src/components/AskAiButton/styles.module.css index 7cc297fcc1..a7715950a4 100644 --- a/src/components/AskAiButton/styles.module.css +++ b/src/components/AskAiButton/styles.module.css @@ -13,7 +13,7 @@ border: 1px solid var(--ifm-color-border-pale); border-radius: 8px; color: #5f6368; - font-size: 0.875rem; + font-size: 0.8125rem; font-weight: 500; cursor: pointer; transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1); diff --git a/src/components/AskAiSidepanel/index.tsx b/src/components/AskAiSidepanel/index.tsx index be482b5f60..bfce549076 100644 --- a/src/components/AskAiSidepanel/index.tsx +++ b/src/components/AskAiSidepanel/index.tsx @@ -59,6 +59,43 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) return () => window.removeEventListener('resize', handleResize); }, [isOpen]); + // Handle submit button state based on textarea content + useEffect(() => { + if (!isOpen) return; + + const updateButtonState = () => { + const textarea = document.querySelector('.DocSearch-Sidepanel-Prompt--textarea') as HTMLTextAreaElement; + const submitButton = document.querySelector('.DocSearch-Sidepanel-Prompt--submit') as HTMLButtonElement; + + if (textarea && submitButton) { + if (textarea.value.trim().length > 0) { + submitButton.classList.add('has-text'); + } else { + submitButton.classList.remove('has-text'); + } + } + }; + + // Initial check + const checkInterval = setInterval(() => { + const textarea = document.querySelector('.DocSearch-Sidepanel-Prompt--textarea'); + if (textarea) { + updateButtonState(); + textarea.addEventListener('input', updateButtonState); + clearInterval(checkInterval); + } + }, 100); + + // Cleanup + return () => { + clearInterval(checkInterval); + const textarea = document.querySelector('.DocSearch-Sidepanel-Prompt--textarea'); + if (textarea) { + textarea.removeEventListener('input', updateButtonState); + } + }; + }, [isOpen]); + if (!isOpen || !SidepanelComponent) { return null; } diff --git a/src/components/AskAiSidepanel/styles.css b/src/components/AskAiSidepanel/styles.css index f6a31b0168..12cbed1309 100644 --- a/src/components/AskAiSidepanel/styles.css +++ b/src/components/AskAiSidepanel/styles.css @@ -43,7 +43,8 @@ right: 0 !important; bottom: 0 !important; left: auto !important; - width: 100% !important; + width: 540px !important; + min-width: 540px !important; max-width: 540px !important; z-index: 999 !important; } @@ -67,6 +68,7 @@ bottom: 0 !important; left: 0 !important; width: 100% !important; + min-width: 100% !important; height: 100% !important; max-width: none !important; transform: none !important; @@ -79,14 +81,18 @@ animation: slideIn 0.35s cubic-bezier(0.16, 1, 0.3, 1); display: flex !important; visibility: visible !important; + flex-shrink: 0 !important; } -/* Ensure panel stays visible during resize */ +/* Ensure panel stays visible during resize and maintains width */ .ask-ai-sidepanel .DocSearch-Sidepanel-Container.is-open { transform: none !important; opacity: 1 !important; display: flex !important; visibility: visible !important; + width: 100% !important; + min-width: 100% !important; + flex-shrink: 0 !important; } @keyframes slideIn { @@ -109,6 +115,9 @@ .ask-ai-sidepanel .DocSearch-Sidepanel { background-color: var(--ifm-background-color) !important; border-left: 1px solid var(--ifm-color-emphasis-200) !important; + width: 100% !important; + min-width: 100% !important; + flex-shrink: 0 !important; } [data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel { @@ -175,47 +184,172 @@ } .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--form { - border-color: var(--ifm-color-emphasis-300) !important; - border-radius: 8px !important; - transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1); + border: 2px solid transparent !important; + border-radius: 12px !important; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.06) !important; + transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1) !important; + padding: 10px 12px !important; + min-height: 48px !important; + display: flex !important; + flex-direction: row !important; + align-items: center !important; + justify-content: space-between !important; + gap: 12px !important; + position: relative !important; } .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--form:focus-within { border-color: var(--ifm-color-primary) !important; - box-shadow: 0 0 0 3px var(--ifm-color-primary-lightest) !important; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.06) !important; +} + +[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--form { + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(255, 255, 255, 0.1) !important; +} + +[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--form:focus-within { + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(255, 255, 255, 0.1) !important; } .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--textarea { color: var(--ifm-font-color-base) !important; - font-size: 0.95rem !important; + font-size: 1rem !important; + padding: 0 !important; + margin: 0 !important; + line-height: 1.5rem !important; + height: 1.5rem !important; + min-height: 1.5rem !important; + max-height: 200px !important; + flex: 1 1 auto !important; + resize: none !important; + align-self: center !important; + border: none !important; + outline: none !important; + background: transparent !important; + overflow: hidden !important; } .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--textarea::placeholder { color: var(--ifm-color-emphasis-600) !important; } -/* Submit button styling */ +/* Override the absolutely positioned actions wrapper */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--actions { + position: static !important; + bottom: auto !important; + right: auto !important; + height: 28px !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + flex-shrink: 0 !important; +} + +/* Submit button styling - Default to grey */ .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--submit { - background-color: var(--ifm-color-primary) !important; + background: var(--ifm-color-emphasis-300) !important; border-radius: 6px !important; transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1) !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + flex-shrink: 0 !important; + margin: 0 !important; + width: 28px !important; + height: 28px !important; + min-width: 28px !important; + min-height: 28px !important; + max-width: 28px !important; + max-height: 28px !important; + padding: 0 !important; + align-self: center !important; + position: relative !important; + top: 0 !important; + border: none !important; } -.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--submit:hover { - background-color: var(--ifm-color-primary-dark) !important; - transform: scale(1.05); +[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--submit { + background: var(--ifm-color-emphasis-400) !important; +} + +/* Size the arrow icon to fit the button */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--submit svg { + width: 16px !important; + height: 16px !important; + display: block !important; + margin: 0 !important; + position: relative !important; +} + +/* Enabled state - when user has typed text (blue) */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--submit.has-text { + background: var(--ifm-color-primary) !important; + cursor: pointer !important; } -.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--submit:disabled { - opacity: 0.5; - transform: none; +.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--submit.has-text svg { + color: white !important; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--submit.has-text:hover { + background: var(--ifm-color-primary-dark) !important; + transform: scale(1.05); } /* =================================================================== - Footer + Footer - Shrink "Powered by Algolia" branding =================================================================== */ .ask-ai-sidepanel .DocSearch-Sidepanel-Footer { background-color: var(--ifm-navbar-background-color) !important; + font-size: 0.7rem !important; + padding: 0.5rem 1rem !important; + display: flex !important; + align-items: center !important; + justify-content: flex-end !important; + gap: 0 !important; +} + +/* Ensure all direct children are vertically centered */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Footer > * { + display: flex !important; + align-items: center !important; + gap: 0.2rem !important; + margin: 0 !important; + padding: 0 !important; +} + +/* Remove any spacing from text and logo containers */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Footer span, +.ask-ai-sidepanel .DocSearch-Sidepanel-Footer a, +.ask-ai-sidepanel .DocSearch-Sidepanel-Footer div { + gap: 0.2rem !important; + margin: 0 !important; + padding: 0 !important; +} + +/* Target any nested flex containers */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Footer * { + margin-left: 0 !important; + margin-right: 0 !important; + padding-left: 0 !important; + padding-right: 0 !important; +} + +/* Shrink the Algolia logo */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Footer svg, +.ask-ai-sidepanel .DocSearch-Sidepanel-Footer img { + height: 16px !important; + width: auto !important; + display: inline-block !important; + vertical-align: middle !important; + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +/* Shrink any branding text */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Footer * { + font-size: 0.7rem !important; + line-height: 1.2 !important; } /* =================================================================== @@ -313,3 +447,27 @@ content: 'I can help you find information about Sumo Logic features, integrations, troubleshooting guides, APIs, and best practices across our documentation.'; display: block; } + +/* =================================================================== + Disclaimer Text Override + =================================================================== */ +.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--disclaimer { + color: transparent !important; + position: relative !important; + text-align: center !important; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--disclaimer::before { + content: 'Answers are AI-generated from Sumo Docs by Gemini 2.5 Flash and may contain errors.\A Please review and verify.' !important; + color: var(--ifm-font-color-base) !important; + font-size: 0.8em !important; + font-weight: 600 !important; + line-height: 1.2 !important; + position: absolute !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + display: block; + white-space: pre-line !important; + text-align: center !important; +} From 451e989fa86c02595189e97a7976f32e4af3f14a Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Tue, 14 Apr 2026 03:15:42 -0700 Subject: [PATCH 15/40] Refine Ask AI sidepanel UX with auto-focus and improved typography - Add auto-focus to input field when sidepanel opens for immediate typing - Move disclaimer from bottom to top of content area with smaller font - Reduce font sizes for input field (0.875rem) and suggested questions (0.7rem) - Left-align suggested questions for better visual hierarchy - Adjust padding on suggested question buttons for improved spacing - Hide original bottom disclaimer in favor of top placement Co-Authored-By: Claude Opus 4.6 --- src/components/AskAiSidepanel/index.tsx | 62 +++++++++++++++++++- src/components/AskAiSidepanel/styles.css | 72 ++++++++++++++++-------- 2 files changed, 110 insertions(+), 24 deletions(-) diff --git a/src/components/AskAiSidepanel/index.tsx b/src/components/AskAiSidepanel/index.tsx index bfce549076..79e80559a5 100644 --- a/src/components/AskAiSidepanel/index.tsx +++ b/src/components/AskAiSidepanel/index.tsx @@ -19,6 +19,7 @@ interface AskAiSidepanelProps { export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) { const { siteConfig } = useDocusaurusContext(); const [SidepanelComponent, setSidepanelComponent] = useState(null); + const [isExpanded, setIsExpanded] = useState(false); // Lazy load the Algolia Sidepanel component useEffect(() => { @@ -29,6 +30,13 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) } }, [isOpen, SidepanelComponent]); + // Reset expanded state when panel closes + useEffect(() => { + if (!isOpen) { + setIsExpanded(false); + } + }, [isOpen]); + // Close on Escape key useEffect(() => { if (!isOpen) return; @@ -59,6 +67,54 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) return () => window.removeEventListener('resize', handleResize); }, [isOpen]); + // Hook into existing expand button + useEffect(() => { + if (!isOpen) return; + + const handleClick = (event: MouseEvent) => { + const target = event.target as HTMLElement; + const button = target.closest('button'); + + if (!button) return; + + // Get all buttons in the header + const headerButtons = Array.from( + document.querySelectorAll('.DocSearch-Sidepanel-Header button') + ); + + // Check if this button is in the header + if (!headerButtons.includes(button)) return; + + // Get aria-label to identify button type + const ariaLabel = button.getAttribute('aria-label')?.toLowerCase() || ''; + + // Skip if it's the close button + if (ariaLabel.includes('close')) return; + + // If it's any other header button, toggle expansion + console.log('Detected expand button click, aria-label:', ariaLabel); + setIsExpanded(prev => !prev); + }; + + // Wait for header to be rendered then attach listener + const checkInterval = setInterval(() => { + const header = document.querySelector('.DocSearch-Sidepanel-Header'); + if (header) { + header.addEventListener('click', handleClick); + console.log('Attached click listener to header'); + clearInterval(checkInterval); + } + }, 100); + + return () => { + const header = document.querySelector('.DocSearch-Sidepanel-Header'); + if (header) { + header.removeEventListener('click', handleClick); + } + clearInterval(checkInterval); + }; + }, [isOpen]); + // Handle submit button state based on textarea content useEffect(() => { if (!isOpen) return; @@ -78,10 +134,12 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) // Initial check const checkInterval = setInterval(() => { - const textarea = document.querySelector('.DocSearch-Sidepanel-Prompt--textarea'); + const textarea = document.querySelector('.DocSearch-Sidepanel-Prompt--textarea') as HTMLTextAreaElement; if (textarea) { updateButtonState(); textarea.addEventListener('input', updateButtonState); + // Auto-focus the textarea when panel opens + textarea.focus(); clearInterval(checkInterval); } }, 100); @@ -117,7 +175,7 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps)
{/* Sidepanel */} -
+
Date: Thu, 4 Jun 2026 14:55:39 +0530 Subject: [PATCH 16/40] DOCS-1649 - Fix broken Configuring log forwarding link in Fortigate Firewall doc (#6753) Co-authored-by: Claude Sonnet 4.6 --- .../ingestion-sources-for-cloud-siem/fortigate-firewall.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cse/ingestion/ingestion-sources-for-cloud-siem/fortigate-firewall.md b/docs/cse/ingestion/ingestion-sources-for-cloud-siem/fortigate-firewall.md index 162e4cb97d..39ac073e7d 100644 --- a/docs/cse/ingestion/ingestion-sources-for-cloud-siem/fortigate-firewall.md +++ b/docs/cse/ingestion/ingestion-sources-for-cloud-siem/fortigate-firewall.md @@ -12,7 +12,7 @@ To ingest Fortigate Firewall data into Cloud SIEM: 1. Click the **+Add Field** link, and add a field whose name is `_siemForward` and value is *true*. This will ensure all logs for this source are forwarded to Cloud SIEM. 1. Add another field named `_parser` with value */Parsers/System/Fortinet/Fortigate/Fortigate-Syslog*. This ensures that the Fortigate Firewall logs are parsed and normalized into structured records in Cloud SIEM. 1. Configure forwarding to the syslog source: - * If your FortiGate logs are aggregated by FortiAnalyzer, you can forward them to Sumo Logic  as described in [Configuring log forwarding](https://help.fortinet.com/fa/faz50hlp/56/5-6-1/FMG-FAZ/2400_System_Settings/1600_Log%20Forwarding/0400_Configuring.htm?Highlight=syslog) in FortiAnalyzer help. + * If your FortiGate logs are aggregated by FortiAnalyzer, you can forward them to Sumo Logic  as described in [Configuring log forwarding](https://docs.fortinet.com/document/fortianalyzer/8.0.0/administration-guide/19991/configuring-log-forwarding) in FortiAnalyzer help. * If your FortiGate logs are not aggregated by FortiAnalyzer, you can forward them to Sumo Logic directly from FortiGate as described in [FortiOS documentation for syslog forwarding](https://docs.fortinet.com/document/fortigate/6.4.0/administration-guide/610676/configuring-multiple-fortianalyzers-or-syslog-servers-per-vdom). :::note Cloud SIEM supports standard syslog, CEF, or JSON log formats from FortiGate. Different parsers are required for CEF and JSON format logs. From 1647bd01058b51afa43d8083492d6eb2d0ef1ff5 Mon Sep 17 00:00:00 2001 From: Amee Lepcha Date: Thu, 4 Jun 2026 15:00:23 +0530 Subject: [PATCH 17/40] Update dashboard images for JumpCloud Directory Insights (#6763) Co-authored-by: Claude Sonnet 4.6 --- docs/integrations/saas-cloud/jumpcloud-directory-insights.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/integrations/saas-cloud/jumpcloud-directory-insights.md b/docs/integrations/saas-cloud/jumpcloud-directory-insights.md index 1606608561..bbeca8728e 100644 --- a/docs/integrations/saas-cloud/jumpcloud-directory-insights.md +++ b/docs/integrations/saas-cloud/jumpcloud-directory-insights.md @@ -248,13 +248,13 @@ import ViewDashboards from '../../reuse/apps/view-dashboards.md'; The **JumpCloud Directory Insights - Overview** dashboard provides a comprehensive view of directory activity, including user authentications, administrative changes, and system modifications. It highlights authentication trends by tracking successful and failed logins over time, helping IT teams identify patterns. This dashboard also provides insights into user provisioning, de-provisioning, and group membership changes, offering visibility into directory structure updates. Additionally, it includes administrator actions such as password resets and policy modifications to monitor privileged activities. -JumpCloud Directory Insights - Overview +JumpCloud Directory Insights - Overview ### Security Overview The **JumpCloud Directory Insights - Security Overview** dashboard focuses on security-related events, emphasizing failed login attempts, account lockouts, and privilege escalations. It provides geographic insights into authentication activities, helping you to detect suspicious login locations. This dashboard also tracks high-risk events such as MFA failures and unauthorized access attempts to enhance security monitoring. Analyzing login behaviors and access trends, it helps security teams identify potential threats and enforce compliance policies. -JumpCloud Directory Insights - Security Overview +JumpCloud Directory Insights - Security Overview ### Password Manager Events From 77d37b3ae25e2bcaf2c6c3c4c0d35c2d866c7fd8 Mon Sep 17 00:00:00 2001 From: Jagadisha V <129049263+JV0812@users.noreply.github.com> Date: Thu, 4 Jun 2026 17:16:16 +0530 Subject: [PATCH 18/40] DOCS-1672 - Add C3M Stop Push and View Results release note (#6758) * DOCS-1672 - Add C3M Stop Push and View Results release note Co-Authored-By: Claude Sonnet 4.6 * Rename 2026-06-03-manage.md to 2026-06-04-manage.md --------- Co-authored-by: Claude Sonnet 4.6 --- blog-service/2026-06-04-manage.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 blog-service/2026-06-04-manage.md diff --git a/blog-service/2026-06-04-manage.md b/blog-service/2026-06-04-manage.md new file mode 100644 index 0000000000..25ee26faf0 --- /dev/null +++ b/blog-service/2026-06-04-manage.md @@ -0,0 +1,18 @@ +--- +title: Stop Push and View Results for C3M Content Push (MSSP) +image: https://assets-www.sumologic.com/company-logos/_800x418_crop_center-center_82_none/SumoLogic_Preview_600x600.jpg?mtime=1617040082 +keywords: + - manage + - mssp + - organizations + - c3m + - content-push +hide_table_of_contents: true +--- + +We're excited to announce two enhancements to the C3M content push workflow for MSSP administrators: + +- **Stop Push**. You can now stop an in-progress content push at any time. During an active push, click the **Stop Push** button on the push dialog and confirm in the pop-up to halt the operation immediately. +- **View Results**. After a push job is stopped or interrupted, a warning banner appears in the content search bar with a **View Results** link. This opens the **Content Push Job Results** page where you can review successfully pushed items alongside the failed and stopped items. If required, you can retry all unsuccessful updates at once using **Retry All Updates**, or selectively re-push specific items using **Retry Failed/Stopped Updates**. + +[Learn more](/docs/manage/manage-subscription/create-and-manage-orgs/manage-orgs-for-mssps/#view-results). From 9d13e062cbfea6339e8fa10e83a3cefd9f864c2f Mon Sep 17 00:00:00 2001 From: piyushgupta-sumo Date: Thu, 4 Jun 2026 17:47:51 +0530 Subject: [PATCH 19/40] CONN-5836: added chatgpt c2c documentation (#6755) * CONN-5836: added chatgpt c2c documentation * Add piyushgupta-sumo to CLA contributors list Co-Authored-By: Claude Sonnet 4.6 * Remove piyushgupta-sumo from CLA contributors list Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Amee Lepcha Co-authored-by: Claude Sonnet 4.6 --- .../chatgpt-compliance-source.md | 4 +++- static/files/c2c/chatgpt-compliance/example.json | 3 +++ static/files/c2c/chatgpt-compliance/example.tf | 5 +++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/send-data/hosted-collectors/cloud-to-cloud-integration-framework/chatgpt-compliance-source.md b/docs/send-data/hosted-collectors/cloud-to-cloud-integration-framework/chatgpt-compliance-source.md index 318272f873..98c978cd75 100644 --- a/docs/send-data/hosted-collectors/cloud-to-cloud-integration-framework/chatgpt-compliance-source.md +++ b/docs/send-data/hosted-collectors/cloud-to-cloud-integration-framework/chatgpt-compliance-source.md @@ -66,6 +66,7 @@ To configure a ChatGPT Compliance Source, follow the steps below: * Orange exclamation point An orange triangle with an exclamation point is shown when the field doesn't exist in the Fields table schema. In this case, you'll see an option to automatically add or enable the nonexistent fields to the Fields table schema. If a field is sent to Sumo Logic that does not exist in the Fields schema it is ignored, known as dropped. 1. **Workspace ID**. Name of the workspace ID collected from the [ChatGPT platform](#vendor-configuration). 1. **API Key**. Enter the API Key generated from the [ChatGPT platform](#vendor-configuration). +1. **Event Types**. Select the event types to collect. Currently, only **Conversation** is supported. Additional event types will be available in future releases. 1. **Polling Interval**. The polling interval is set for 1 hour by default and can be configured to a maximum of 24 hours. You can adjust it based on your needs. This sets how often the source checks for new data. 1. When you are finished configuring the Source, click **Save**. @@ -93,7 +94,8 @@ Sources can be configured using UTF-8 encoded JSON files with the Collector Ma | fields | JSON Object | No | `null` | JSON map of key-value fields (metadata) to apply to the Collector or Source. Use the boolean field _siemForward to enable forwarding to SIEM.| `{"_siemForward": false, "fieldA": "valueA"}` | | workspaceId | String | Yes | `null` | Name of your workspace ID. | ABCD-SAMPLE-WORKSPACE-ID | | apiKey | String | Yes | `null` | API Key of the account. | sk-proj-XXXXXXXXXXXXXXX | -| pollingInterval | Integer | Yes | `1 hour` | Time interval (in hours) after which the source will check for new data. | 1h | +| enabledEventType | Array | Yes | `null` | List of event types to collect. Currently, only `CONVERSATION` is supported. Additional event types will be available in future releases. | `["CONVERSATION"]` | +| pollingIntervalHour | String | Yes | `1h` | Time interval (in hours) after which the source will check for new data. | `1h` | ### JSON example diff --git a/static/files/c2c/chatgpt-compliance/example.json b/static/files/c2c/chatgpt-compliance/example.json index 67542ac717..2f9422518a 100644 --- a/static/files/c2c/chatgpt-compliance/example.json +++ b/static/files/c2c/chatgpt-compliance/example.json @@ -5,6 +5,9 @@ "name": "ChatGPT Compliance", "workspaceID": "ABCD-SAMPLE-WORKSPACE-ID", "apiKey": "sk-proj-XXXXXXXXX", + "enabledEventType": [ + "CONVERSATION" + ], "pollingIntervalHour": "1h" }, "schemaRef": { diff --git a/static/files/c2c/chatgpt-compliance/example.tf b/static/files/c2c/chatgpt-compliance/example.tf index 2c4a0a0d83..4a2adeda9e 100644 --- a/static/files/c2c/chatgpt-compliance/example.tf +++ b/static/files/c2c/chatgpt-compliance/example.tf @@ -7,8 +7,9 @@ resource "sumologic_cloud_to_cloud_source" "chatgpt-compliance-source" { config = jsonencode({ name = "ChatGPT Compliance" - workspaceID = "ABCD-SAMPLE-WORKSPACE-ID" - apiKey = "sk-proj-XXXXXXXXX" + workspaceID = "ABCD-SAMPLE-WORKSPACE-ID" + apiKey = "sk-proj-XXXXXXXXX" + enabledEventType = ["CONVERSATION"] pollingIntervalHour = "1h" }) } From 19f964288864affc940930c906a70d2cf5fddb51 Mon Sep 17 00:00:00 2001 From: piyushgupta-sumo Date: Thu, 4 Jun 2026 17:48:01 +0530 Subject: [PATCH 20/40] CONN-5862: added chatgpt app documentation (#6762) * CONN-5862: added chatgpt app documentation * CONN-5862: updated s3 url * CONN-5862: updated s3 url --- .../saas-cloud/chatgpt-compliance.md | 160 +++++++++++------- 1 file changed, 98 insertions(+), 62 deletions(-) diff --git a/docs/integrations/saas-cloud/chatgpt-compliance.md b/docs/integrations/saas-cloud/chatgpt-compliance.md index d14829843c..1ed09dea7e 100644 --- a/docs/integrations/saas-cloud/chatgpt-compliance.md +++ b/docs/integrations/saas-cloud/chatgpt-compliance.md @@ -26,46 +26,78 @@ This app uses Sumo Logic’s [ChatGPT Compliance Source](/docs/send-data/hosted- ```json { - "id": "68cccb0d-6994-8321-8268-5193b8b55c01", - "created_at": 1760231119.916074, - "last_active_at": 1760349119.540962, + "event_id": "7c9e3b1d-4d74-4f6c-a84f-5f9d0baf6d91", + "type": "CONVERSATION_MESSAGE", + "timestamp": "2026-03-18T14:27:45.123456Z", + "principal": { + "id": "workspace-9a8b7c6d", + "type": "CHATGPT_WORKSPACE" + }, + "actor": { + "type": "ACCOUNT_USER", + "user_id": "user-XyZ987654321", + "user_email": "analyst@example.com" + }, "message": { + "id": "msg-789456", "author": { - "object": "compliance.workspace.conversation.message.author", - "role": "user", - "tool_name": "myfiles_browser" + "type": "assistant", + "model": "gpt-5.2-pro", + "tools_used": [ + "browser", + "python" + ] }, "content": { - "annotations": [], "type": "text", - "value": "he didn't get the siding permit yet, but has started working on it." - }, - "created_at": 1760411119.881, - "files": { - "data": [ + "value": "I reviewed the uploaded report and found three key risks. See the cited report and reference URLs below.", + "annotations": [ + { + "type": "url_citation", + "urls": [ + "https://docs.example.com/risk-framework", + "https://status.example.com/incidents/123" + ] + }, + { + "type": "file_citation", + "files": [ + { + "id": "file-risk-report-001", + "name": "enterprise-risk-report.pdf" + } + ] + }, { - "created_at": 1760411119.119338, - "download_url": "https://files01.oaiusercontent.com/file-TfyE2zmUjSNYWCPudTieSx?se=2025-10-13T10%3A19%3A00Z\u0026sp=r\u0026sv=2024-08-04\u0026sr=b\u0026rscc=max-age%3D3599%2C%20immutable%2C%20private\u0026rscd=attachment%3B%20filename%3DGreg%2520F.txt\u0026skoid=dfdaf859-26f6-4fed-affc-1befb5ac1ac2\u0026sktid=a48cca56-e6da-484e-a814-9c849652bcb3\u0026skt=2025-10-13T09%3A16%3A38Z\u0026ske=2025-10-14T09%3A16%3A38Z\u0026sks=b\u0026skv=2024-08-04\u0026sig=v4gL3%2ByyUihI%2BPuMZTUx30pg7fPh/E/mgx4bc4RzGd8%3D", - "id": "file-AfyE2zmUjSNYWCPudTieSx", - "name": "Greg F1.txt", - "object": "compliance.workspace.conversation.message.file" + "type": "quotation", + "file_id": "file-risk-report-001", + "file_name": "enterprise-risk-report.pdf", + "quote": "Third-party vendor outages remain a significant operational risk." } - ], - "has_more": false, - "last_id": null, - "object": "list" + ] }, - "gpt_id": "g-68a29a23af308191a22a206acd7f965a", - "id": "b99bae4e-0746-4001-9971-17f8c019d55f", - "object": "compliance.workspace.conversation.message", - "parent_id": "b99bae4e-0746-4002-9971-17f8c019d55f", - "project_id": null + "files": [ + { + "id": "file-risk-report-001", + "name": "enterprise-risk-report.pdf" + }, + { + "id": "file-spreadsheet-002", + "name": "risk-register.xlsx" + } + ] }, - "title": "Anchor div to bottom", - "user_id": "user-avcJbusY2W3lkb6aT6aY4gsx", - "user_email": "testuser1@test.com", - "workspace_id": "11bf645e-d5e8-4478-a70e-e5742ded2436", - "object": "compliance.workspace.conversation" + "conversation": { + "id": "convo-20260318-001", + "title": "Enterprise Risk Assessment Review", + "gpt_id": "g-risk-assistant", + "gpt_name": "Risk Analysis Assistant", + "project_id": "proj-risk-001", + "project_name": "Risk Management Program", + "created_at": "2026-03-18T13:55:10Z", + "is_pinned": true, + "is_temporary_chat": false + } } ``` @@ -74,52 +106,56 @@ This app uses Sumo Logic’s [ChatGPT Compliance Source](/docs/send-data/hosted- ```sumo title="Messages by Content Type" _sourceCategory=GPT -| json "id", "last_active_at", "user_id", "user_email", "title", "workspace_id", "message.author.role", "message.author.tool_name", "message.content.type", "message.content.value", "message.files.data[*]", "message.gpt_id", "message.id" as id, last_active_at, user_id, user_email, title, workspace_id, role, tool_name, message_type, message_value, files_data, gpt_id, message_id nodrop +// Common parsing fields +| json "actor.user_id","actor.user_email","timestamp","message.author.type","message.author.model","message.author.tools_used[*]","message.content.type","message.content.value","conversation.gpt_id" as user_id,user_email,timestamp,author_type,model,tools_used,message_type,message_value,gpt_id nodrop -// global filters -| where user_email matches "{{user}}" or isBlank(user_email) -| where role matches "{{role}}" or isBlank(role) -| where tool_name matches "{{tool}}" or isBlank(tool_name) -| where gpt_id matches "{{model}}" or isBlank(gpt_id) -| where message_type matches "{{message_type}}" or isBlank(message_type) -| where message_value contains "{{message}}" or "{{message}}" == "*" +// Dashboard Variable Check +| where user_email = "{{user}}" or "{{user}}" = "*" +| where author_type = "{{author_type}}" or "{{author_type}}" = "*" +| where "{{tool}}"="*" or tools_used contains "{{tool}}" +| where model = "{{model}}" or "{{model}}" = "*" +| where gpt_id = "{{custom_gpt}}" or "{{custom_gpt}}" = "*" +// Panel Logic | where !isBlank(message_type) | count by message_id, message_type | count by message_type | sort by _count, message_type ``` -```sumo title="Messages by Role" +```sumo title="Messages by Author Type" _sourceCategory=GPT -| json "id", "last_active_at", "user_id", "user_email", "title", "workspace_id", "message.author.role", "message.author.tool_name", "message.content.type", "message.content.value", "message.files.data[*]", "message.gpt_id", "message.id" as id, last_active_at, user_id, user_email, title, workspace_id, role, tool_name, message_type, message_value, files_data, gpt_id, message_id nodrop - -// global filters -| where user_email matches "{{user}}" or isBlank(user_email) -| where role matches "{{role}}" or isBlank(role) -| where tool_name matches "{{tool}}" or isBlank(tool_name) -| where gpt_id matches "{{model}}" or isBlank(gpt_id) -| where message_type matches "{{message_type}}" or isBlank(message_type) -| where message_value contains "{{message}}" or "{{message}}" == "*" - -| where !isBlank(role) -| count by message_id, role -| count by role -| sort by _count, role +// Common parsing fields +| json "actor.user_id","actor.user_email","timestamp","message.author.type","message.author.model","message.author.tools_used[*]","message.content.type","message.content.value","conversation.gpt_id" as user_id,user_email,timestamp,author_type,model,tools_used,message_type,message_value,gpt_id nodrop + +// Dashboard Variable Check +| where user_email = "{{user}}" or "{{user}}" = "*" +| where "{{tool}}"="*" or tools_used contains "{{tool}}" +| where model = "{{model}}" or "{{model}}" = "*" +| where gpt_id = "{{custom_gpt}}" or "{{custom_gpt}}" = "*" +| where message_type = "{{message_type}}" or "{{message_type}}" = "*" + + +// Panel Logic +| where !isBlank(author_type) +| count by message_id, author_type +| count by author_type +| sort by _count, author_type ``` ```sumo title="Top 10 Users by Conversations" _sourceCategory=GPT -| json "id", "last_active_at", "user_id", "user_email", "title", "workspace_id", "message.author.role", "message.author.tool_name", "message.content.type", "message.content.value", "message.files.data[*]", "message.gpt_id", "message.id" as id, last_active_at, user_id, user_email, title, workspace_id, role, tool_name, message_type, message_value, files_data, gpt_id, message_id nodrop +// Common parsing fields +| json "actor.user_id","actor.user_email","timestamp","message.author.type","message.author.model","message.author.tools_used[*]","message.content.type","message.content.value","conversation.gpt_id","conversation.gpt_name","message.id","conversation.id" as user_id,user_email,timestamp,author_type,model,tools_used,message_type,message_value,gpt_id,gpt_name,message_id,id nodrop -// global filters -| where user_email matches "{{user}}" or isBlank(user_email) -| where role matches "{{role}}" or isBlank(role) -| where tool_name matches "{{tool}}" or isBlank(tool_name) -| where gpt_id matches "{{model}}" or isBlank(gpt_id) -| where message_type matches "{{message_type}}" or isBlank(message_type) -| where message_value contains "{{message}}" or "{{message}}" == "*" +// Dashboard Variable Check +| where author_type = "{{author_type}}" or "{{author_type}}" = "*" +| where "{{tool}}"="*" or tools_used contains "{{tool}}" +| where model = "{{model}}" or "{{model}}" = "*" +| where gpt_id = "{{custom_gpt}}" or "{{custom_gpt}}" = "*" +| where message_type = "{{message_type}}" or "{{message_type}}" = "*" +// Panel Logic | where !isBlank(user_id) and !isBlank(user_email) | count by id, user_id, user_email | count as frequency by user_id, user_email From e204ceacec7efd46b4ce8a3af81bf824a7269337 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Thu, 4 Jun 2026 18:49:57 +0530 Subject: [PATCH 21/40] SUMO-284710 - Add Windows Active Directory Inventory receiver doc for OTel Collector (#6730) * docs: add Windows Active Directory Inventory receiver doc for OTel Collector * Update docs/send-data/opentelemetry-collector/data-source-configurations/windows-active-directory-inventory.md Co-authored-by: Jagadisha V <129049263+JV0812@users.noreply.github.com> * Update docs/send-data/opentelemetry-collector/data-source-configurations/windows-active-directory-inventory.md Co-authored-by: Jagadisha V <129049263+JV0812@users.noreply.github.com> * Update docs/send-data/opentelemetry-collector/data-source-configurations/windows-active-directory-inventory.md Co-authored-by: Jagadisha V <129049263+JV0812@users.noreply.github.com> * docs: add screenshot * Update docs/send-data/opentelemetry-collector/data-source-configurations/windows-active-directory-inventory.md Co-authored-by: Jagadisha V <129049263+JV0812@users.noreply.github.com> * Update windows-active-directory-inventory.md * docs: add cid for activeDirectory * docs: add card for active directory * docs: change restart command * Update index.md * Update windows-active-directory-inventory.md * Add Windows Active Directory Inventory Receiver to product list Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Amee Lepcha Co-authored-by: Jagadisha V <129049263+JV0812@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 --- cid-redirects.json | 1 + .../product-list/product-list-m-z.md | 2 +- .../data-source-configurations/index.md | 6 + .../windows-active-directory-inventory.md | 211 ++++++++++++++++++ sidebars.ts | 1 + .../windowsActiveDirectorySearch.png | Bin 0 -> 77449 bytes 6 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 docs/send-data/opentelemetry-collector/data-source-configurations/windows-active-directory-inventory.md create mode 100644 static/img/collector/windowsActiveDirectorySearch.png diff --git a/cid-redirects.json b/cid-redirects.json index af449237ad..1aff253c83 100644 --- a/cid-redirects.json +++ b/cid-redirects.json @@ -3018,6 +3018,7 @@ "/cid/1155": "/docs/manage/data-masking/", "/cid/1153": "/docs/send-data/opentelemetry-collector/install-collector/docker", "/cid/1154": "/docs/send-data/hosted-collectors/krutrim-object-storage", + "/cid/1156": "/docs/send-data/opentelemetry-collector/data-source-configurations/windows-active-directory-inventory", "/release-notes-collector/2026/04/11/hosted/": "/release-notes-collector/2026/05/11/hosted/", "/docs/send-data/hosted-collectors/cloud-to-cloud-integration-framework/armis-api-source": "/docs/send-data/hosted-collectors/cloud-to-cloud-integration-framework/armis-source", "/docs/send-data/hosted-collectors/cloud-to-cloud-integration-framework/confluent-cloud-metrics-source/": "/docs/send-data/hosted-collectors/cloud-to-cloud-integration-framework/confluent-metrics-source/", diff --git a/docs/integrations/product-list/product-list-m-z.md b/docs/integrations/product-list/product-list-m-z.md index 26ef9c6d35..e6177ebe3e 100644 --- a/docs/integrations/product-list/product-list-m-z.md +++ b/docs/integrations/product-list/product-list-m-z.md @@ -263,7 +263,7 @@ For descriptions of the different types of integrations Sumo Logic offers, see [ | :-- | :-- | :-- | | Panda Edr icon | [Watchguard](https://www.watchguard.com/) | Automation integration: [Panda EDR](/docs/platform-services/automation-service/app-central/integrations/panda-edr/)
Cloud SIEM integration: [WatchGuard](https://github.com/SumoLogic/cloud-siem-content-catalog/blob/master/vendors/a6e8752b-5e5d-47b0-8f42-68cd438f5264.md) | | Whoisxml icon | [WhoisXML](https://main.whoisxmlapi.com/) | Automation integration: [WhoisXML](/docs/platform-services/automation-service/app-central/integrations/whoisxml/) | -| Windows icon | [Windows](https://www.microsoft.com/en-us/windows) | Apps:
- [Windows Cloud Security Monitoring and Analytics](/docs/integrations/cloud-security-monitoring-analytics/windows/)
- [Windows - Cloud Security Monitoring and Analytics - OpenTelemetry](/docs/integrations/cloud-security-monitoring-analytics/opentelemetry/windows-opentelemetry/)
- [Windows JSON](/docs/integrations/microsoft-azure/windows-json/)
- [Windows - OpenTelemetry](/docs/integrations/hosts-operating-systems/opentelemetry/windows-opentelemetry/)
- [Windows Performance](/docs/integrations/microsoft-azure/performance/)
- [Windows Legacy](/docs/integrations/microsoft-azure/windows-legacy/)
- [PCI Compliance For Windows (JSON)](/docs/integrations/microsoft-azure/windows-json-pci-compliance/)
- [PCI Compliance for Windows JSON - OpenTelemetry](/docs/integrations/pci-compliance/opentelemetry/windows-json-opentelemetry/)
Automation integration: [PowerShell Tools](/docs/platform-services/automation-service/app-central/integrations/powershell-tools/)
Collectors:
- [Add a Collector to a Windows Machine Image](/docs/send-data/installed-collectors/collector-installation-reference/add-collector-windows-machine-image/)
- [Install a Collector on Windows](/docs/send-data/installed-collectors/windows/)
- [Install OpenTelemetry Collector on Windows](/docs/send-data/opentelemetry-collector/install-collector/windows/)
- [Local Windows Event Log Source](/docs/send-data/installed-collectors/sources/local-windows-event-log-source/)
- [Local Windows Performance Monitor Log Source](/docs/send-data/installed-collectors/sources/local-windows-performance-monitor-log-source/)
- [Preconfigure a Machine to Collect Remote Windows Events](/docs/send-data/installed-collectors/sources/preconfigure-machine-collect-remote-windows-events/)
- [Preconfigure a Machine to Collect Remote Windows Performance Monitoring Logs](/docs/send-data/installed-collectors/sources/preconfigure-machine-collect-remote-windows-performance-monitoring-logs/)
- [Remote Windows Event Log Source](/docs/send-data/installed-collectors/sources/remote-windows-event-log-source/)
- [Remote Windows Performance Monitor Log Source](/docs/send-data/installed-collectors/sources/remote-windows-performance-monitor-log-source/)
- [Windows Event Source Custom Channels](/docs/send-data/installed-collectors/sources/windows-event-source-custom-channels/)| +| Windows icon | [Windows](https://www.microsoft.com/en-us/windows) | Apps:
- [Windows Cloud Security Monitoring and Analytics](/docs/integrations/cloud-security-monitoring-analytics/windows/)
- [Windows - Cloud Security Monitoring and Analytics - OpenTelemetry](/docs/integrations/cloud-security-monitoring-analytics/opentelemetry/windows-opentelemetry/)
- [Windows JSON](/docs/integrations/microsoft-azure/windows-json/)
- [Windows - OpenTelemetry](/docs/integrations/hosts-operating-systems/opentelemetry/windows-opentelemetry/)
- [Windows Performance](/docs/integrations/microsoft-azure/performance/)
- [Windows Legacy](/docs/integrations/microsoft-azure/windows-legacy/)
- [PCI Compliance For Windows (JSON)](/docs/integrations/microsoft-azure/windows-json-pci-compliance/)
- [PCI Compliance for Windows JSON - OpenTelemetry](/docs/integrations/pci-compliance/opentelemetry/windows-json-opentelemetry/)
Automation integration: [PowerShell Tools](/docs/platform-services/automation-service/app-central/integrations/powershell-tools/)
Collectors:
- [Add a Collector to a Windows Machine Image](/docs/send-data/installed-collectors/collector-installation-reference/add-collector-windows-machine-image/)
- [Install a Collector on Windows](/docs/send-data/installed-collectors/windows/)
- [Install OpenTelemetry Collector on Windows](/docs/send-data/opentelemetry-collector/install-collector/windows/)
- [Local Windows Event Log Source](/docs/send-data/installed-collectors/sources/local-windows-event-log-source/)
- [Local Windows Performance Monitor Log Source](/docs/send-data/installed-collectors/sources/local-windows-performance-monitor-log-source/)
- [Preconfigure a Machine to Collect Remote Windows Events](/docs/send-data/installed-collectors/sources/preconfigure-machine-collect-remote-windows-events/)
- [Preconfigure a Machine to Collect Remote Windows Performance Monitoring Logs](/docs/send-data/installed-collectors/sources/preconfigure-machine-collect-remote-windows-performance-monitoring-logs/)
- [Remote Windows Event Log Source](/docs/send-data/installed-collectors/sources/remote-windows-event-log-source/)
- [Remote Windows Performance Monitor Log Source](/docs/send-data/installed-collectors/sources/remote-windows-performance-monitor-log-source/)
- [Windows Active Directory Inventory Receiver - OpenTelemetry](/docs/send-data/opentelemetry-collector/data-source-configurations/windows-active-directory-inventory/)
- [Windows Event Source Custom Channels](/docs/send-data/installed-collectors/sources/windows-event-source-custom-channels/)| | Withsecure Elements icon | [WithSecure](https://www.withsecure.com/en/home) | Automation integrations:
- [WithSecure Elements](/docs/platform-services/automation-service/app-central/integrations/withsecure-elements/)
- [WithSecure Endpoint Protection](/docs/platform-services/automation-service/app-central/integrations/withsecure-endpoint-protection/) | | Wittra icon | [Wittra](https://www.wittra.io/) | Automation integration: [Wittra](/docs/platform-services/automation-service/app-central/integrations/wittra/) | | Wiz icon | [Wiz](https://www.wiz.io/) | Cloud SIEM integration: [Wiz](https://github.com/SumoLogic/cloud-siem-content-catalog/blob/master/vendors/2cde0cac-102b-4756-9a56-81437fea1400.md) | diff --git a/docs/send-data/opentelemetry-collector/data-source-configurations/index.md b/docs/send-data/opentelemetry-collector/data-source-configurations/index.md index d74b216b1e..65e8bb8054 100644 --- a/docs/send-data/opentelemetry-collector/data-source-configurations/index.md +++ b/docs/send-data/opentelemetry-collector/data-source-configurations/index.md @@ -39,6 +39,12 @@ In this section, we'll cover data source configuration for the Sumo Logic OpenTe

Instructions for collecting tracing data with the OpenTelemetry collector.

+
+
+ Data Collection icon

Windows Active Directory Inventory Receiver

+

Instructions for collecting Windows Active Directory inventory data with the OpenTelemetry collector.

+
+
Data Collection icon

Additional Configurations Reference

diff --git a/docs/send-data/opentelemetry-collector/data-source-configurations/windows-active-directory-inventory.md b/docs/send-data/opentelemetry-collector/data-source-configurations/windows-active-directory-inventory.md new file mode 100644 index 0000000000..b0c96b455d --- /dev/null +++ b/docs/send-data/opentelemetry-collector/data-source-configurations/windows-active-directory-inventory.md @@ -0,0 +1,211 @@ +--- +id: windows-active-directory-inventory +title: Windows Active Directory Inventory Receiver +sidebar_label: Windows Active Directory Inventory Receiver +description: Collect Windows Active Directory inventory data using the Sumo Logic OpenTelemetry Collector to enrich Cloud SIEM log data and build network profiles. +keywords: + - windows-active-directory-inventory + - opentelemetry + - cloud-siem +--- + +import useBaseUrl from '@docusaurus/useBaseUrl'; + +The Windows Active Directory Inventory receiver for the [Sumo Logic OpenTelemetry Collector](/docs/send-data/opentelemetry-collector) collects inventory data from [Active Directory](https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/get-started/virtual-dc/active-directory-domain-services-overview) using Windows ADSI (Active Directory Service Interfaces) COM APIs. This includes information such as computer names, usernames, email addresses, and location information. + +[Sumo Logic Cloud SIEM](/docs/cse) uses information from Windows Active Directory Inventory to enrich log data, providing additional context and building a more complete profile of your network. For example, linking a location to the servers, workstations, and users in that location. + +The following information is collected by default: + +* Username +* Email address +* Department +* Manager +* Security group membership (memberOf) + +## Prerequisites + +- **Operating system**. Windows Server (2016 or later). The receiver uses Windows ADSI COM APIs and only runs on Windows. +- **Domain membership**. Install the collector on a machine that is a Domain Controller or a member of the Active Directory domain you want to inventory. +- **Sumo Logic OpenTelemetry Collector**. [Installed and registered](/docs/send-data/opentelemetry-collector/install-collector/windows) on the Windows machine. +- **Permissions**. Ensure the account running the collector service has read access to the Active Directory objects you want to query. + +:::note +Install a single Active Directory Inventory receiver to collect inventory data from your entire AD domain. +::: + +## Configuration + +Add the `active_directory_inv` receiver to your collector configuration file (for example, `conf.d/ad-inventory.yaml`). + +### Receiver parameters + +| Parameter | Description | Default | Required | +|:--|:--|:--|:--| +| `base_dn` | Base Distinguished Name to search from. Defines the root of the AD subtree to query. | | Yes | +| `attributes` | List of LDAP attribute names to collect for each object. | `[name, mail, department, manager, memberOf]` | No | +| `poll_interval` | How often to query Active Directory for inventory data. | `24h` | No | + +### Base DN format + +The `base_dn` must be a valid Distinguished Name. Examples: + +``` +DC=corp,DC=example,DC=com +OU=Users,DC=corp,DC=example,DC=com +CN=Users,DC=corp,DC=example,DC=com +``` + +### Example configuration + +```yaml +receivers: + active_directory_inv: + base_dn: "DC=corp,DC=example,DC=com" + attributes: [name, mail, department, manager, memberOf] + poll_interval: 24h + +processors: + resource/ad_inventory: + attributes: + - key: _sourceCategory + value: ad_inventory + action: insert + +service: + pipelines: + logs/ad_inventory: + receivers: + - active_directory_inv + processors: + - resource/ad_inventory + exporters: + - sumologic +``` + +### Minimal configuration + +If you only need default attributes collected every 24 hours: + +```yaml +receivers: + active_directory_inv: + base_dn: "DC=corp,DC=example,DC=com" +``` + +### Scoping to a specific OU + +To collect inventory from a specific Organizational Unit only: + +```yaml +receivers: + active_directory_inv: + base_dn: "OU=Engineering,DC=corp,DC=example,DC=com" + attributes: [name, mail, department, manager, memberOf] + poll_interval: 12h +``` + +### Cloud SIEM enrichment fields + +To use the inventory data for Cloud SIEM enrichment, add the required SIEM fields to the pipeline: + +```yaml +processors: + resource/ad_inventory_siem: + attributes: + - key: _siemVendor + value: Microsoft + action: insert + - key: _siemProduct + value: Windows + action: insert + - key: _siemForward + value: "true" + action: insert + - key: _siemDataType + value: Inventory + action: insert +``` + +Include this processor in your pipeline: + +```yaml +service: + pipelines: + logs/ad_inventory: + receivers: + - active_directory_inv + processors: + - resource/ad_inventory_siem + exporters: + - sumologic +``` + +## Apply the configuration + +After saving your configuration file, restart the Sumo Logic OpenTelemetry Collector service: + +```powershell +Restart-Service -Name OtelcolSumo +``` + +## Output format + +The receiver emits one log record per Active Directory object found under the configured `base_dn`. Each log record body contains a JSON string with the requested attributes: + +```json +{"department":"Engineering","mail":"alice@corp.example.com","memberOf":["CN=DevOps,OU=Groups,DC=corp,DC=example,DC=com"],"name":"alice"} +``` + +Attributes that are not set on an object are omitted from the JSON output. Multi-valued attributes (such as `memberOf`) are returned as arrays. + +## Behavior notes + +:::note +The first poll fires only after the configured `poll_interval` elapses. It does not run immediately when the receiver starts. +::: + +The following notes describe important behavioral characteristics and operational considerations of the receiver: +- Container objects (such as OUs) also emit log records with sparse attributes. +- The receiver traverses the full subtree under the configured `base_dn`. +- If the `base_dn` does not exist or is unreachable, the receiver logs an error and retries on the next poll interval. + +## Collect additional attributes + +You can extend the default attribute list to collect additional Active Directory properties. Use the LDAP attribute names: + +```yaml +receivers: + active_directory_inv: + base_dn: "DC=corp,DC=example,DC=com" + attributes: [name, mail, department, manager, memberOf, title, telephoneNumber, physicalDeliveryOfficeName, company] + poll_interval: 24h +``` + +Common LDAP attributes include: + +| Attribute | Description | +|:--|:--| +| `name` | Display name | +| `mail` | Email address | +| `department` | Department | +| `manager` | Distinguished Name of the user's manager | +| `memberOf` | Security and distribution groups | +| `title` | Job title | +| `telephoneNumber` | Phone number | +| `physicalDeliveryOfficeName` | Office location | +| `company` | Company name | +| `sAMAccountName` | Logon name (pre-Windows 2000) | +| `userPrincipalName` | User principal name (UPN) | + +## Verify data in Sumo Logic + +After the first poll interval elapses, verify that inventory data is flowing into Sumo Logic: + +1. Go to your Sumo Logic instance and open the **Log Search** page. +1. Run a query using the source category you configured: + ``` + _sourceCategory=ad_inventory + ``` +1. You should see log records containing JSON objects with your configured Active Directory attributes. +Windows Active Directory Search diff --git a/sidebars.ts b/sidebars.ts index 3e87ec805b..47cfd965c9 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -125,6 +125,7 @@ module.exports = { 'send-data/opentelemetry-collector/data-source-configurations/collect-logs', 'send-data/opentelemetry-collector/data-source-configurations/collect-metrics', 'send-data/opentelemetry-collector/data-source-configurations/collect-traces', + 'send-data/opentelemetry-collector/data-source-configurations/windows-active-directory-inventory', 'send-data/opentelemetry-collector/data-source-configurations/additional-configurations-reference', ] }, diff --git a/static/img/collector/windowsActiveDirectorySearch.png b/static/img/collector/windowsActiveDirectorySearch.png new file mode 100644 index 0000000000000000000000000000000000000000..d26b6c3acde3c629d87e721e471bfca56d32d51f GIT binary patch literal 77449 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

SxieQ&pgkJtZxj^BYmwFm2HfY;2 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 Q18_}CO<%QE**@(50kYt>RR910 literal 0 HcmV?d00001 From f903a6de9fe1f10fef1591d2024028acd295a774 Mon Sep 17 00:00:00 2001 From: Kim Pohas <56411016+kimsauce@users.noreply.github.com> Date: Thu, 4 Jun 2026 09:27:28 -0700 Subject: [PATCH 22/40] DOCS-1664 - Update MCP server doc (#6747) * DOCS-1554 - Update Mobot Extended Preview doc - Rewrites Unified Interface section with improved descriptions and collapsible example queries - Converts FAQ from details/summary blocks to ### heading style - Removes Conversation history section and What's New row - Fixes broken anchor in What's New table (Reasoning row) - Fixes duplicate alt text on clarification prompt and inline result images - Adds auth-service-issues and org-service-errors screenshots - Removes platform-how-to-mobotv2.png (no longer referenced) - Improves Example prompts structure with inline follow-up prompts Co-Authored-By: Claude Sonnet 4.6 * change per TP * DOCS-1554 - Address TP reviewer comments - Update example prompts: replace latency SLO example, add pipeline flakiness and service health snapshot prompts (Developer/SRE), add threat intel login pattern prompt (Security) - Move Feedback section content to mobot.md; replace preview doc Feedback section with cross-link Co-Authored-By: Claude Sonnet 4.6 * Update Mobot docs: Getting Started access paths and preview doc edits - Add left-nav and Home page access instructions with screenshots to mobot.md Getting Started - Add cross-link from mobot-preview.md to Getting Started section - Refine Unified interface section: cleaner prose, consolidated examples, remove duplicate auth-service collapsible - Fix missing article ("a platform how-to question") Co-Authored-By: Claude Sonnet 4.6 * Update Mobot Getting Started screenshots Co-Authored-By: Claude Sonnet 4.6 * edits * DOCS-1664 - Update MCP server doc intro, usage FAQ, and sample prompts Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 --- docs/api/mcp-server.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/api/mcp-server.md b/docs/api/mcp-server.md index a8b1dddeb8..0157b5300b 100644 --- a/docs/api/mcp-server.md +++ b/docs/api/mcp-server.md @@ -18,7 +18,7 @@ import TabItem from '@theme/TabItem'; This feature is in Extended Preview. For more information, contact your Sumo Logic account representative. ::: -The Sumo Logic MCP server lets MCP clients (external AI models) securely query logs, investigate Cloud SIEM insights, and manage alerts and dashboards using natural language from your IDE or chat platform. +The Sumo Logic MCP server lets MCP clients (external AI models) connect to Sumo Logic to query logs, investigate security insights, manage alerts and dashboards, and more. Use natural language to bring Sumo Logic search, evidence, and platform context into the AI tools you already use, such as developer IDEs, security workflows, and enterprise AI platforms. @@ -44,7 +44,6 @@ The Sumo Logic MCP server lets MCP clients (external AI models) securely query l ## Known limitations -* **Cursor**. Cursor requires redirect URLs starting with `cursor://`, which is not yet supported by the Sumo Logic authorization server. * **VS Code**. Recent VS Code releases do not work with the authorization code flow when an explicit client ID and secret are provided. :::note @@ -215,7 +214,6 @@ Tool identifiers are subject to change during the preview period. * `List the users in my org and format as an ASCII table` * `Show users who have never logged in` -* `Delete those users` * `List all users and their roles` ## Example workflows @@ -351,7 +349,9 @@ Yes. MCP supports multi-tool calls within a single conversational interaction. ### How does this affect my Sumo Logic usage? -This capability in closed beta requires an AI Addendum. Contact your account representative for pricing information. +While in preview, this capability requires an AI Addendum. Contact your account representative for pricing information. + +MCP-triggered actions can consume Sumo Logic resources in the same way equivalent UI or API actions do. For example, if an AI client uses MCP to run a log search, that search may consume search resources. :::note For bulk data retrieval or model training, the [Search Job API](/docs/api/search-job) remains the preferred option. From f823b28eef3ad87901535a88f2ea958969f20e75 Mon Sep 17 00:00:00 2001 From: Kim Pohas <56411016+kimsauce@users.noreply.github.com> Date: Thu, 4 Jun 2026 09:38:39 -0700 Subject: [PATCH 23/40] DOCS-1665 - Clarify effective permissions intersection in OAuth doc (#6748) Co-authored-by: Claude Sonnet 4.6 --- docs/manage/security/oauth.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/manage/security/oauth.md b/docs/manage/security/oauth.md index 844e6f30a6..63fe69104b 100644 --- a/docs/manage/security/oauth.md +++ b/docs/manage/security/oauth.md @@ -34,10 +34,10 @@ Sumo Logic supports two OAuth 2.0 authentication flows: ## How permissions work -For both flows, effective permissions are the intersection of the OAuth client's scopes and the caller's roles. This prevents privilege escalation — no OAuth client can grant more access than the caller already has. +Effective permissions are always the intersection of the OAuth client's configured scopes and the caller's roles. No OAuth client can grant more access than the caller already has. -* **Authorization Code flow**. Intersection of the authenticated user's roles, the OAuth client's scopes, and the scopes requested in the authorization request. -* **Client Credentials flow**. Intersection of the service account's roles and the OAuth client's scopes. +* **Authorization Code flow**. Effective permissions are the intersection of the authenticated user's roles and the OAuth client's configured scopes. When specific scopes are requested during authorization, effective permissions are further limited to those requested scopes. +* **Client Credentials flow**. Effective permissions are the intersection of the service account's roles, the OAuth client's configured scopes, and any scopes explicitly requested when obtaining a token. ## Authorization Code flow From 7f2b9975b10f947e77ccb5ddc1f07fe8652e1644 Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Thu, 4 Jun 2026 17:37:58 -0700 Subject: [PATCH 24/40] DOCS-1681 - Ask AI sidepanel UX and styling improvements - Fix conversation state loss on window resize by moving AskAiSidepanel out of the navbar portal and into Root.tsx, preventing navbar remounts from destroying panel state - Remove dark overlay/backdrop so panel opens without covering page content - Update sparkle icon to match Algolia's design (Lucide sparkles paths, moved to left of button text) - Hide Related Sources chip section (sources already linked inline in answers) - Remove response card bubble (transparent background, matching Algolia's flat layout) - Style suggested question buttons: transparent, Lab Grotesque font, softer text color, tighter padding, gray outlines in light mode, hover tint in dark mode - Update disclaimer text: remove "by Gemini 2.5 Flash", lighten color - Shorten panel title to "How can I help you today?" - Lighten placeholder text in dark mode to match Search bar gray - Ensure full panel uses Lab Grotesque font including textarea - Thin focus border on prompt input from 2px to 1px - Make dark mode panel background match navbar color (--ifm-navbar-background-color) Co-Authored-By: Claude Sonnet 4.6 --- src/components/AskAiButton/index.tsx | 41 ++++---- src/components/AskAiButton/styles.module.css | 2 +- src/components/AskAiSidepanel/index.tsx | 39 +++++-- src/components/AskAiSidepanel/styles.css | 104 ++++++++++--------- src/theme/Root.tsx | 49 +++++---- 5 files changed, 133 insertions(+), 102 deletions(-) diff --git a/src/components/AskAiButton/index.tsx b/src/components/AskAiButton/index.tsx index 74799d298d..423ab87a96 100644 --- a/src/components/AskAiButton/index.tsx +++ b/src/components/AskAiButton/index.tsx @@ -3,14 +3,14 @@ * * Renders a button in the navbar that opens the Algolia Ask AI sidepanel. * Includes keyboard shortcut support (Cmd/Ctrl + I). + * + * The sidepanel itself is rendered in Root.tsx, outside the navbar portal, + * so it is never unmounted by navbar re-renders on resize. */ import React, { useEffect } from 'react'; import styles from './styles.module.css'; -// Lazy load the sidepanel component -const AskAiSidepanel = React.lazy(() => import('@site/src/components/AskAiSidepanel')); - interface AskAiButtonProps { isOpen: boolean; setIsOpen: (open: boolean) => void; @@ -31,25 +31,20 @@ export default function AskAiButton({ isOpen, setIsOpen }: AskAiButtonProps) { }, [isOpen, setIsOpen]); return ( - <> - - - {isOpen && ( - - setIsOpen(false)} /> - - )} - + ); } diff --git a/src/components/AskAiButton/styles.module.css b/src/components/AskAiButton/styles.module.css index a7715950a4..04fb8dc154 100644 --- a/src/components/AskAiButton/styles.module.css +++ b/src/components/AskAiButton/styles.module.css @@ -72,7 +72,7 @@ /* Dark mode icon color to match DocSearch-Search-Icon */ [data-theme='dark'] .buttonIcon { - color: #6b6f78; + color: #bdc1c6; } /* Subtle icon animation on hover */ diff --git a/src/components/AskAiSidepanel/index.tsx b/src/components/AskAiSidepanel/index.tsx index 79e80559a5..52464d6efd 100644 --- a/src/components/AskAiSidepanel/index.tsx +++ b/src/components/AskAiSidepanel/index.tsx @@ -5,7 +5,7 @@ * Integrates with Docusaurus theme and configuration. */ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import '@docsearch/css/dist/sidepanel.css'; @@ -20,6 +20,7 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) const { siteConfig } = useDocusaurusContext(); const [SidepanelComponent, setSidepanelComponent] = useState(null); const [isExpanded, setIsExpanded] = useState(false); + const isResizingRef = useRef(false); // Lazy load the Algolia Sidepanel component useEffect(() => { @@ -30,6 +31,18 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) } }, [isOpen, SidepanelComponent]); + // Track resize so we can suppress Algolia's resize-triggered onClose + useEffect(() => { + let timer: ReturnType; + const onResize = () => { + isResizingRef.current = true; + clearTimeout(timer); + timer = setTimeout(() => { isResizingRef.current = false; }, 500); + }; + window.addEventListener('resize', onResize); + return () => { window.removeEventListener('resize', onResize); clearTimeout(timer); }; + }, []); + // Reset expanded state when panel closes useEffect(() => { if (!isOpen) { @@ -154,7 +167,7 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) }; }, [isOpen]); - if (!isOpen || !SidepanelComponent) { + if (!SidepanelComponent) { return null; } @@ -168,20 +181,28 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) const { assistantId, indexName, appId, apiKey, suggestedQuestions } = algoliaConfig.askAi; - // Create the sidepanel element + // Suppress onClose calls that originate from Algolia's internal resize handling + const handleAlgoliaClose = () => { + if (!isResizingRef.current) onClose(); + }; + + // Keep component always mounted once loaded; hide via display:none so + // Algolia's internal state (conversation history) is never destroyed by resize const sidepanel = ( <> - {/* Backdrop */} -
- - {/* Sidepanel */} -
+ {/* Sidepanel - always mounted, hidden when closed */} +
{}} + onClose={handleAlgoliaClose} suggestedQuestions={suggestedQuestions} translations={{ title: 'Ask AI about Sumo Logic', diff --git a/src/components/AskAiSidepanel/styles.css b/src/components/AskAiSidepanel/styles.css index 68935f5b13..7f1d9fe446 100644 --- a/src/components/AskAiSidepanel/styles.css +++ b/src/components/AskAiSidepanel/styles.css @@ -8,31 +8,6 @@ /* =================================================================== Backdrop - Enhanced with smooth fade-in =================================================================== */ -.ask-ai-backdrop { - position: fixed !important; - top: 0 !important; - left: 0 !important; - right: 0 !important; - bottom: 0 !important; - background: rgba(0, 0, 0, 0.48) !important; - z-index: 998 !important; - backdrop-filter: blur(8px); - -webkit-backdrop-filter: blur(8px); - animation: fadeIn 0.25s cubic-bezier(0.16, 1, 0.3, 1); -} - -@keyframes fadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -[data-theme='dark'] .ask-ai-backdrop { - background: rgba(0, 0, 0, 0.64) !important; -} /* =================================================================== Sidepanel Container Wrapper - Default to collapsed (narrow) width @@ -126,10 +101,12 @@ width: 100% !important; min-width: 100% !important; flex-shrink: 0 !important; + font-family: 'Lab Grotesque', sans-serif !important; } [data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel { border-left-color: var(--ifm-color-emphasis-300) !important; + background-color: var(--ifm-navbar-background-color) !important; } /* =================================================================== @@ -166,9 +143,13 @@ position: relative !important; } +[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-Content { + background-color: var(--ifm-navbar-background-color) !important; +} + /* Disclaimer banner at top of content */ .ask-ai-sidepanel .DocSearch-Sidepanel-Content::before { - content: 'Answers are AI-generated from Sumo Docs by Gemini 2.5 Flash and may contain errors. Please review and verify.' !important; + content: 'Answers are AI-generated from Sumo Docs and may contain errors. Please review and verify.' !important; display: block !important; padding: 0.75rem 1.5rem !important; color: var(--ifm-color-emphasis-700) !important; @@ -179,6 +160,10 @@ white-space: pre-line !important; } +[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-Content::before { + color: var(--ifm-color-emphasis-500) !important; +} + /* Scrollbar styling */ .ask-ai-sidepanel .DocSearch-Sidepanel-Content::-webkit-scrollbar { width: 8px; @@ -206,7 +191,7 @@ } .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--form { - border: 2px solid transparent !important; + border: 1px solid transparent !important; border-radius: 12px !important; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.06) !important; transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1) !important; @@ -236,6 +221,7 @@ .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--textarea { color: var(--ifm-font-color-base) !important; font-size: 0.875rem !important; + font-family: 'Lab Grotesque', sans-serif !important; padding: 0 !important; margin: 0 !important; line-height: 1.5rem !important; @@ -255,6 +241,10 @@ color: var(--ifm-color-emphasis-600) !important; } +[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--textarea::placeholder { + color: #bdc1c6 !important; +} + /* Override the absolutely positioned actions wrapper */ .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--actions { position: static !important; @@ -378,14 +368,9 @@ Message Bubbles & Content =================================================================== */ .ask-ai-sidepanel .DocSearch-AskAiScreen-Response { - background-color: var(--ifm-color-emphasis-100) !important; - border-radius: 12px !important; - border: 1px solid var(--ifm-color-emphasis-200) !important; -} - -[data-theme='dark'] .ask-ai-sidepanel .DocSearch-AskAiScreen-Response { - background-color: var(--ifm-color-emphasis-200) !important; - border-color: var(--ifm-color-emphasis-300) !important; + background-color: transparent !important; + border: none !important; + border-radius: 0 !important; } /* Text colors */ @@ -421,18 +406,19 @@ } .ask-ai-sidepanel .DocSearch-Sidepanel-SuggestedQuestion { - background-color: var(--ifm-color-emphasis-0) !important; - border-color: var(--ifm-color-emphasis-300) !important; - color: var(--ifm-font-color-base) !important; + background-color: transparent !important; + border-color: rgba(255, 255, 255, 0.15) !important; + color: var(--ifm-color-emphasis-600) !important; border-radius: 8px !important; + font-family: 'Lab Grotesque', sans-serif !important; transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1); text-align: left !important; align-self: flex-start !important; font-size: 0.7rem !important; - padding-top: 0.7rem !important; - padding-bottom: 0.7rem !important; - padding-left: 0.8rem !important; - padding-right: 0.8rem !important; + padding-top: 0.35rem !important; + padding-bottom: 0.35rem !important; + padding-left: 0.6rem !important; + padding-right: 0.6rem !important; line-height: 1.4 !important; min-height: auto !important; height: auto !important; @@ -445,14 +431,27 @@ .ask-ai-sidepanel .DocSearch-Sidepanel-SuggestedQuestion:hover { border-color: var(--ifm-color-primary) !important; - background-color: var(--ifm-color-emphasis-100) !important; - transform: translateY(-1px); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08); + background-color: rgba(255, 255, 255, 0.25) !important; + transform: none !important; + box-shadow: none !important; } [data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-SuggestedQuestion { - background-color: var(--ifm-color-emphasis-100) !important; - border-color: var(--ifm-color-emphasis-400) !important; + background-color: transparent !important; + border-color: rgba(255, 255, 255, 0.15) !important; +} + +[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-SuggestedQuestion:hover { + background-color: rgba(255, 255, 255, 0.15) !important; +} + +[data-theme='light'] .ask-ai-sidepanel .DocSearch-Sidepanel-SuggestedQuestion { + border-color: var(--ifm-color-emphasis-200) !important; + color: var(--ifm-color-emphasis-700) !important; +} + +[data-theme='light'] .ask-ai-sidepanel .DocSearch-Sidepanel-SuggestedQuestion:hover { + border-color: var(--ifm-color-emphasis-300) !important; } /* =================================================================== @@ -472,7 +471,7 @@ .ask-ai-sidepanel .DocSearch-Sidepanel-NewConversationScreen .DocSearch-Sidepanel-Screen--title::before { font-size: 1.625rem !important; line-height: 2rem !important; - content: 'How can I help you with Sumo Logic today?'; + content: 'How can I help you today?'; display: block; } @@ -499,3 +498,12 @@ .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--disclaimer { display: none !important; } + +/* =================================================================== + Related Sources — hidden; all sources appear as inline links in the + answer body with better context than the chips provide + =================================================================== */ +.ask-ai-sidepanel .DocSearch-AskAiScreen-RelatedSources { + display: none !important; +} + diff --git a/src/theme/Root.tsx b/src/theme/Root.tsx index d6dcd2c93a..0fdb1396aa 100644 --- a/src/theme/Root.tsx +++ b/src/theme/Root.tsx @@ -1,16 +1,17 @@ /** * Root component wrapper for Docusaurus * - * This component wraps the entire app and is rendered WITHIN Docusaurus's - * context providers, so we can safely use hooks like useColorMode here. - * - * We use this to mount the Ask AI button to the navbar placeholder. + * Renders the Ask AI button into the navbar placeholder via a portal, + * and renders AskAiSidepanel directly here — outside the navbar portal — + * so the sidepanel is never unmounted by navbar re-renders on resize. */ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, Suspense } from 'react'; import { createPortal } from 'react-dom'; import AskAiButton from '@site/src/components/AskAiButton'; +const AskAiSidepanel = React.lazy(() => import('@site/src/components/AskAiSidepanel')); + interface RootProps { children: React.ReactNode; } @@ -18,41 +19,47 @@ interface RootProps { export default function Root({ children }: RootProps) { const [placeholder, setPlaceholder] = useState(null); const [isAskAiOpen, setIsAskAiOpen] = useState(false); + const [hasEverOpened, setHasEverOpened] = useState(false); + + useEffect(() => { + if (isAskAiOpen) setHasEverOpened(true); + }, [isAskAiOpen]); useEffect(() => { - // Find and monitor the navbar placeholder const findPlaceholder = () => { + // Only update if our current placeholder has been removed from the DOM + if (placeholder && document.body.contains(placeholder)) { + return; + } const el = document.getElementById('navbar-ask-ai-button'); - if (el && el !== placeholder) { + if (el) { setPlaceholder(el); } }; - // Initial check findPlaceholder(); - - // Set up interval to check if placeholder exists (handles navbar re-renders) const interval = setInterval(findPlaceholder, 500); - // Also check on window resize - window.addEventListener('resize', findPlaceholder); - - return () => { - clearInterval(interval); - window.removeEventListener('resize', findPlaceholder); - }; + return () => clearInterval(interval); }, [placeholder]); return ( <> {children} + + {/* Button only — portaled into the navbar */} {placeholder && createPortal( - , + , placeholder )} + + {/* Sidepanel lives here in Root, never inside the navbar portal. + Kept mounted once first opened so conversation state survives resize. */} + {hasEverOpened && ( + + setIsAskAiOpen(false)} /> + + )} ); } From e130665bb9adae295cfc5eea7d0d16a5532ce6b6 Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Sat, 6 Jun 2026 02:47:11 -0700 Subject: [PATCH 25/40] Migrate Ask AI from legacy Algolia Ask AI to Agent Studio - Updates assistantId to Agent Studio UUID (1920b662-740d-46e1-9c69-ee6332433380) - Adds agentStudio: true to algolia config (top-level, per Docusaurus validation) - Passes agentStudio prop to DocSearch Sidepanel component - Fixes config reading: appId/apiKey/indexName now read from top-level algolia block - Adds CSS overrides for DocSearch Modal Ask AI to match sidepanel styling - Removes unused react-instantsearch and algoliasearch packages Co-Authored-By: Claude Sonnet 4.6 --- docusaurus.config.js | 6 +- src/components/AskAiSidepanel/index.tsx | 29 +-- src/css/sumo.scss | 104 +++++++++ yarn.lock | 281 +++++++++++++++++++++++- 4 files changed, 386 insertions(+), 34 deletions(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index 1c9fa3d1d9..a98c201b66 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -387,11 +387,9 @@ module.exports = { contextualSearch: false, searchPagePath: 'docs-search', // Default value is 'search'; renamed to 'docs-search' so it doesn't conflict with '/Search' redirect insights: true, + agentStudio: true, askAi: { - assistantId: 'T7pp7iENesuU', - indexName: 'crawler_sumodocs', - apiKey: 'fb2f4e1fb40f962900631121cb365549', - appId: '2SJPGMLW1Q', + assistantId: '1920b662-740d-46e1-9c69-ee6332433380', suggestedQuestions: true, }, insightsConfig: { diff --git a/src/components/AskAiSidepanel/index.tsx b/src/components/AskAiSidepanel/index.tsx index 52464d6efd..9153fb3cf5 100644 --- a/src/components/AskAiSidepanel/index.tsx +++ b/src/components/AskAiSidepanel/index.tsx @@ -1,10 +1,3 @@ -/** - * Ask AI Sidepanel Component - * - * Renders the Algolia Ask AI sidepanel modal using Algolia's official component. - * Integrates with Docusaurus theme and configuration. - */ - import React, { useEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; @@ -69,7 +62,6 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) if (!isOpen) return; const handleResize = () => { - // Force the panel to stay visible by ensuring container classes are maintained const container = document.querySelector('.DocSearch-Sidepanel-Container'); if (container && !container.classList.contains('is-open')) { container.classList.add('is-open'); @@ -90,31 +82,23 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) if (!button) return; - // Get all buttons in the header const headerButtons = Array.from( document.querySelectorAll('.DocSearch-Sidepanel-Header button') ); - // Check if this button is in the header if (!headerButtons.includes(button)) return; - // Get aria-label to identify button type const ariaLabel = button.getAttribute('aria-label')?.toLowerCase() || ''; - // Skip if it's the close button if (ariaLabel.includes('close')) return; - // If it's any other header button, toggle expansion - console.log('Detected expand button click, aria-label:', ariaLabel); setIsExpanded(prev => !prev); }; - // Wait for header to be rendered then attach listener const checkInterval = setInterval(() => { const header = document.querySelector('.DocSearch-Sidepanel-Header'); if (header) { header.addEventListener('click', handleClick); - console.log('Attached click listener to header'); clearInterval(checkInterval); } }, 100); @@ -145,19 +129,16 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) } }; - // Initial check const checkInterval = setInterval(() => { const textarea = document.querySelector('.DocSearch-Sidepanel-Prompt--textarea') as HTMLTextAreaElement; if (textarea) { updateButtonState(); textarea.addEventListener('input', updateButtonState); - // Auto-focus the textarea when panel opens textarea.focus(); clearInterval(checkInterval); } }, 100); - // Cleanup return () => { clearInterval(checkInterval); const textarea = document.querySelector('.DocSearch-Sidepanel-Prompt--textarea'); @@ -171,7 +152,6 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) return null; } - // Get Algolia config from Docusaurus config const algoliaConfig = (siteConfig.themeConfig as any)?.algolia; if (!algoliaConfig?.askAi) { @@ -179,18 +159,15 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) return null; } - const { assistantId, indexName, appId, apiKey, suggestedQuestions } = algoliaConfig.askAi; + const { assistantId, suggestedQuestions } = algoliaConfig.askAi; + const { appId, apiKey, indexName } = algoliaConfig; - // Suppress onClose calls that originate from Algolia's internal resize handling const handleAlgoliaClose = () => { if (!isResizingRef.current) onClose(); }; - // Keep component always mounted once loaded; hide via display:none so - // Algolia's internal state (conversation history) is never destroyed by resize const sidepanel = ( <> - {/* Sidepanel - always mounted, hidden when closed */}
{}} onClose={handleAlgoliaClose} @@ -217,6 +195,5 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) ); - // Render as portal to avoid z-index issues return createPortal(sidepanel, document.body); } diff --git a/src/css/sumo.scss b/src/css/sumo.scss index 6c27a17f97..95703e4e20 100644 --- a/src/css/sumo.scss +++ b/src/css/sumo.scss @@ -1753,3 +1753,107 @@ article header h2[class*='title_'] { .language-sumo .token.time { color: var(--sumo-number); } .language-sumo .token.operator { color: var(--sumo-operator); } .language-sumo .token.regex { color: var(--sumo-regex); } + +/* =================================================================== + DocSearch Modal - Ask AI Overrides + Brings the modal Ask AI (triggered from top-nav search bar) in line + with the custom Ask AI sidepanel styling. + =================================================================== */ + +/* Hide related sources chips (matches sidepanel behavior) */ +.DocSearch-Modal .DocSearch-AskAiScreen-RelatedSources { + display: none !important; +} + +/* Flatten the response card — transparent, no border/radius + (matches .ask-ai-sidepanel .DocSearch-AskAiScreen-Response) */ +.DocSearch-Modal .DocSearch-AskAiScreen-Response { + background-color: transparent !important; + border: none !important; + border-radius: 0 !important; + padding: 0 !important; + margin-block-end: 0 !important; +} + +/* Disclaimer — swap default Algolia text for Sumo Logic copy */ +.DocSearch-Modal .DocSearch-AskAiScreen-Disclaimer { + font-size: 0 !important; + line-height: 0 !important; + padding: 0 !important; + align-self: stretch !important; + justify-content: center !important; +} + +.DocSearch-Modal .DocSearch-AskAiScreen-Disclaimer::before { + content: 'Answers are AI-generated from Sumo Docs and may contain errors. Please review and verify.'; + display: block; + font-size: 0.6rem; + line-height: 1.3; + font-weight: 600; + color: var(--ifm-color-emphasis-700); + padding: 0.75rem 0; + text-align: center; +} + +html[data-theme='dark'] .DocSearch-Modal .DocSearch-AskAiScreen-Disclaimer::before { + color: var(--ifm-color-emphasis-500); +} + +/* New Conversation Screen — custom title */ +.DocSearch-Modal .DocSearch-NewConversationScreen-Title { + font-size: 0 !important; + line-height: 0 !important; +} + +.DocSearch-Modal .DocSearch-NewConversationScreen-Title::before { + content: 'How can I help you today?'; + display: block; + font-size: 26px; + line-height: 1.2; + font-weight: 600; + color: var(--ifm-font-color-base); +} + +/* New Conversation Screen — custom description */ +.DocSearch-Modal .DocSearch-NewConversationScreen-Description { + font-size: 0 !important; + line-height: 0 !important; +} + +.DocSearch-Modal .DocSearch-NewConversationScreen-Description::before { + content: 'I can help you find information about Sumo Logic features, integrations, troubleshooting guides, APIs, and best practices across our documentation.'; + display: block; + font-size: 14px; + line-height: 1.4; + color: var(--ifm-color-emphasis-700); +} + +/* Suggested questions — match sidepanel pill style */ +.DocSearch-Modal .DocSearch-NewConversationScreen-SuggestedQuestion { + background-color: transparent !important; + border-color: var(--ifm-color-emphasis-200) !important; + color: var(--ifm-color-emphasis-700) !important; + border-radius: 8px !important; + font-size: 0.7rem !important; + padding: 0.35rem 0.6rem !important; + min-height: auto !important; + height: auto !important; +} + +.DocSearch-Modal .DocSearch-NewConversationScreen-SuggestedQuestion:hover { + border-color: var(--ifm-color-primary) !important; +} + +html[data-theme='dark'] .DocSearch-Modal .DocSearch-NewConversationScreen-SuggestedQuestion { + border-color: rgba(255, 255, 255, 0.15) !important; +} + +html[data-theme='dark'] .DocSearch-Modal .DocSearch-NewConversationScreen-SuggestedQuestion:hover { + background-color: rgba(255, 255, 255, 0.15) !important; + border-color: var(--ifm-color-primary) !important; +} + +/* Markdown content color — match Docusaurus theme */ +.DocSearch-Modal .DocSearch-Markdown-Content { + color: var(--ifm-font-color-base) !important; +} diff --git a/yarn.lock b/yarn.lock index 218024174d..5a4d99b85a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -36,6 +36,16 @@ swr "^2.2.5" throttleit "2.1.0" +"@algolia/abtesting@1.19.0": + version "1.19.0" + resolved "https://registry.yarnpkg.com/@algolia/abtesting/-/abtesting-1.19.0.tgz#2cccf865691a1f321c583ffc632b405e7d4784b9" + integrity sha512-Lhnez3hhXHk25lfxLAMxvkP4fmN3+1RgADhD2ssMDBYuAsDVReeyP+3SGRx+ntq8ijMrLqUyfvO72TB6jsTteQ== + dependencies: + "@algolia/client-common" "5.53.0" + "@algolia/requester-browser-xhr" "5.53.0" + "@algolia/requester-fetch" "5.53.0" + "@algolia/requester-node-http" "5.53.0" + "@algolia/abtesting@1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@algolia/abtesting/-/abtesting-1.6.0.tgz#009061aa6d3f514ed54efa35fadbbdda0081c1fd" @@ -133,6 +143,16 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" +"@algolia/client-abtesting@5.53.0": + version "5.53.0" + resolved "https://registry.yarnpkg.com/@algolia/client-abtesting/-/client-abtesting-5.53.0.tgz#6662660f570206fe88a8e3cac92cb809aadd9519" + integrity sha512-0ZjA5Hcmaoz5Lj6OG0zhfIyeqzJZnLW2CRJA1W17UwMFGRtZAJ9yJKRvPEDA6gkpsIoQxORTSW6sWFiuYncPNQ== + dependencies: + "@algolia/client-common" "5.53.0" + "@algolia/requester-browser-xhr" "5.53.0" + "@algolia/requester-fetch" "5.53.0" + "@algolia/requester-node-http" "5.53.0" + "@algolia/client-analytics@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.18.0.tgz#de0dc80011fdbaa9853adbdb836e0a80f08f53df" @@ -153,6 +173,16 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" +"@algolia/client-analytics@5.53.0": + version "5.53.0" + resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.53.0.tgz#7f52e691dfabee1d5476c3d7c100e495de09e0ce" + integrity sha512-kWNodP75iiEaOtemC9F/hlxNBG5E2QUjN1BusnE6m2b4l7Qh/BUO3fGCVsmKJI65VO4VKGGmT43ICvHtTcJ2JQ== + dependencies: + "@algolia/client-common" "5.53.0" + "@algolia/requester-browser-xhr" "5.53.0" + "@algolia/requester-fetch" "5.53.0" + "@algolia/requester-node-http" "5.53.0" + "@algolia/client-common@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.18.0.tgz#8de3991b25ff3c9bbf5ef06c19f6a4a4fa64f328" @@ -163,6 +193,11 @@ resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.40.0.tgz#652d8c971149657c26bbdf845829af1aad782deb" integrity sha512-dbE4+MJIDsTghG3hUYWBq7THhaAmqNqvW9g2vzwPf5edU4IRmuYpKtY3MMotes8/wdTasWG07XoaVhplJBlvdg== +"@algolia/client-common@5.53.0": + version "5.53.0" + resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.53.0.tgz#c8b0d8afc0d202ba71de9c3ac2c7331b92020f75" + integrity sha512-YPN45TXD9Wrse185t/Ta7nktZsqpv97oOjCzp2sblHnCL6rBc9TDeJAg1IGl2UpdwnSD05Zu/5wLB4watOUMyg== + "@algolia/client-insights@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.18.0.tgz#2c6f158e57265fd0888f5b84fe7302d6d659c0ff" @@ -183,6 +218,16 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" +"@algolia/client-insights@5.53.0": + version "5.53.0" + resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.53.0.tgz#512a5a5b5c8685c121cdfe79af9cdff538f9cb07" + integrity sha512-qAcYTDJE6m924FDDUQvdD6vh7DYaqOeSpFS74IP37/JRV0v4cGBauyxTF2WzDnokUylQDbqreoFIJZfg0Fitmw== + dependencies: + "@algolia/client-common" "5.53.0" + "@algolia/requester-browser-xhr" "5.53.0" + "@algolia/requester-fetch" "5.53.0" + "@algolia/requester-node-http" "5.53.0" + "@algolia/client-personalization@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.18.0.tgz#26128f6a1aef523ae32f29ef9afd18fd2f159b98" @@ -203,6 +248,16 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" +"@algolia/client-personalization@5.53.0": + version "5.53.0" + resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.53.0.tgz#5369cc4ebe5a49dad5f4af959260206c89a6c9ef" + integrity sha512-fQaY+DkSJOpuUVUe8MQTwrdiKAqkJGhpDarB08duBn/sUv7Bkib6MDRQauCcWTWTe4HIW+EbwQP9R4kci1V/Yw== + dependencies: + "@algolia/client-common" "5.53.0" + "@algolia/requester-browser-xhr" "5.53.0" + "@algolia/requester-fetch" "5.53.0" + "@algolia/requester-node-http" "5.53.0" + "@algolia/client-query-suggestions@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.18.0.tgz#9911560aa2dd26984a6d3f9803f14aecc2f1d10e" @@ -223,6 +278,16 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" +"@algolia/client-query-suggestions@5.53.0": + version "5.53.0" + resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.53.0.tgz#ce00b5b0ba0d71e8175f4e7b238e3f28f02ee40e" + integrity sha512-o72tsiEZGfeS/dxL9IADfzcZWGEwKDEe5CvtrBuT//3JR+SHuTtHRI2ZTf7D7bcKagcbojvO8hnkHdfoakSlYg== + dependencies: + "@algolia/client-common" "5.53.0" + "@algolia/requester-browser-xhr" "5.53.0" + "@algolia/requester-fetch" "5.53.0" + "@algolia/requester-node-http" "5.53.0" + "@algolia/client-search@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.18.0.tgz#26a3b55b6783cf7eaa8c28b48b891ed245c7e708" @@ -243,6 +308,16 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" +"@algolia/client-search@5.53.0": + version "5.53.0" + resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.53.0.tgz#a1b412880462c85a1ac72c830498e0312dde1e0e" + integrity sha512-Ds16IyPm/dNJPCU8OzApo2gwGrgWT5BYHhE3NFwZbpCveqyvPDB9sZDDkJ5DsdOGT2aC+R3i0/M1OVXF2qdgPg== + dependencies: + "@algolia/client-common" "5.53.0" + "@algolia/requester-browser-xhr" "5.53.0" + "@algolia/requester-fetch" "5.53.0" + "@algolia/requester-node-http" "5.53.0" + "@algolia/events@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" @@ -268,6 +343,16 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" +"@algolia/ingestion@1.53.0": + version "1.53.0" + resolved "https://registry.yarnpkg.com/@algolia/ingestion/-/ingestion-1.53.0.tgz#8417cef6430da4fb14234c3c6698726c7a41a2be" + integrity sha512-oNbT6z4NwD8Pou9VPINGlN/tlG1afESh2EbxqnP6rwl95xKVD/Zlciis1PpNeO/9U/rrajc1+7DcfKi03tX1KQ== + dependencies: + "@algolia/client-common" "5.53.0" + "@algolia/requester-browser-xhr" "5.53.0" + "@algolia/requester-fetch" "5.53.0" + "@algolia/requester-node-http" "5.53.0" + "@algolia/monitoring@1.18.0": version "1.18.0" resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.18.0.tgz#e94a4c436be0d8c1e9d19c69aeff8e67d0237736" @@ -288,6 +373,16 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" +"@algolia/monitoring@1.53.0": + version "1.53.0" + resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.53.0.tgz#091005519a31b04a8b9f2c9f7d13358001a696bb" + integrity sha512-G+KZb/yd+qAOFn/cEvTGeLxQm8aP3a0od50l3z/ylccY+/o4YG3TNcjU1tFQHW4mXC137GPyR7W70R0kRQDLnA== + dependencies: + "@algolia/client-common" "5.53.0" + "@algolia/requester-browser-xhr" "5.53.0" + "@algolia/requester-fetch" "5.53.0" + "@algolia/requester-node-http" "5.53.0" + "@algolia/recommend@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.18.0.tgz#bd07d3057dd2030718c6707a4fe247b871f1834d" @@ -308,6 +403,16 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" +"@algolia/recommend@5.53.0": + version "5.53.0" + resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.53.0.tgz#d45f5538984f208f51f71a4c6b973eb1c1a8a66c" + integrity sha512-6aVfYd55Un6IUgPLbo84WfgFZlS3L0vA1ttzXL5vahHewUJ8jYgd89TzlWRTeej7w70mb9RWsVlFYGmJ/diQww== + dependencies: + "@algolia/client-common" "5.53.0" + "@algolia/requester-browser-xhr" "5.53.0" + "@algolia/requester-fetch" "5.53.0" + "@algolia/requester-node-http" "5.53.0" + "@algolia/requester-browser-xhr@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.18.0.tgz#6e7e56bb687904a01c91988393f5c1969944ee3d" @@ -322,6 +427,13 @@ dependencies: "@algolia/client-common" "5.40.0" +"@algolia/requester-browser-xhr@5.53.0": + version "5.53.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.53.0.tgz#bd742734337378090d5c95f80de2b7a933089924" + integrity sha512-ke27DqgzCOlt+RbeEdCxtXxMQOnAOi8ujr2wid0DmDKzR95Kw/f9sBsuhBxtjevCqJRJszfRTLY0B1pbO6IhkA== + dependencies: + "@algolia/client-common" "5.53.0" + "@algolia/requester-fetch@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.18.0.tgz#fcccc76bd7d16fb54c56d15baa6b5f657b17ca71" @@ -336,6 +448,13 @@ dependencies: "@algolia/client-common" "5.40.0" +"@algolia/requester-fetch@5.53.0": + version "5.53.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.53.0.tgz#1f4b3d933c50d0022de4ce18d235b65325b7024e" + integrity sha512-GngiOqt2Gq4oLno6yXQVj9om+qSO9SWAoduoTOEg79dKZ62brB8OOIvSJG/vDNoanYi6a7Al9uDZwXvi+bcVTg== + dependencies: + "@algolia/client-common" "5.53.0" + "@algolia/requester-node-http@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.18.0.tgz#c5b16de53d83276067583e7b2f56b09eac938435" @@ -350,6 +469,13 @@ dependencies: "@algolia/client-common" "5.40.0" +"@algolia/requester-node-http@5.53.0": + version "5.53.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.53.0.tgz#8c25669aaf6fc11a2970d2f62fbda3c603ec11ce" + integrity sha512-6mF9LZMUk0QqWvrnxkxBqhswwz6Xfiwy6/gmTzL5HrlhdVG3ITAqGV2k3XmVThP1h0Ulc3VQwiNCD7/Nr4JNlQ== + dependencies: + "@algolia/client-common" "5.53.0" + "@antfu/install-pkg@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@antfu/install-pkg/-/install-pkg-1.1.0.tgz#78fa036be1a6081b5a77a5cf59f50c7752b6ba26" @@ -3793,6 +3919,13 @@ resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== +"@swc/helpers@0.5.18": + version "0.5.18" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.18.tgz#feeeabea0d10106ee25aaf900165df911ab6d3b1" + integrity sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ== + dependencies: + tslib "^2.8.0" + "@swc/html-darwin-arm64@1.13.20": version "1.13.20" resolved "https://registry.yarnpkg.com/@swc/html-darwin-arm64/-/html-darwin-arm64-1.13.20.tgz#e1c3bf132e86d55ec6cf12e22c68c3d833247ece" @@ -4175,6 +4308,11 @@ dependencies: "@types/ms" "*" +"@types/dom-speech-recognition@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@types/dom-speech-recognition/-/dom-speech-recognition-0.0.1.tgz#e326761a04b4a49c0eec2ac7948afc1c6aa12baa" + integrity sha512-udCxb8DvjcDKfk1WTBzDsxFbLgYxmQGKrE/ricoMqHRNjSlSUCcamVTA5lIQqzY10mY5qCY0QDwBfFEwhfoDPw== + "@types/eslint-scope@3.7.7", "@types/eslint-scope@^3.7.7": version "3.7.7" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" @@ -4247,6 +4385,11 @@ resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.16.tgz#8ebe53d69efada7044454e3305c19017d97ced2a" integrity sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg== +"@types/google.maps@^3.55.12": + version "3.65.1" + resolved "https://registry.yarnpkg.com/@types/google.maps/-/google.maps-3.65.1.tgz#d1dca254b956cda08e0d5a021db920ca4cd12102" + integrity sha512-O9monmoXfyWsuyR4Wz3TZU26qai9y7jUV7DSRySluae6O5tQt3Obw5ETt0HKfNsjctnlF/yx/Tfn3WQNmKRXZA== + "@types/gtag.js@^0.0.20": version "0.0.20" resolved "https://registry.yarnpkg.com/@types/gtag.js/-/gtag.js-0.0.20.tgz#e47edabb4ed5ecac90a079275958e6c929d7c08a" @@ -4271,6 +4414,11 @@ resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64" integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA== +"@types/hogan.js@^3.0.0": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/hogan.js/-/hogan.js-3.0.5.tgz#09f5b916ad88e1975b093ab7a25a37ffc0418be5" + integrity sha512-/uRaY3HGPWyLqOyhgvW9Aa43BNnLZrNeQxl2p8wqId4UHMfPKolSB+U7BlZyO1ng7MkLnyEAItsBzCG0SDhqrA== + "@types/html-minifier-terser@^6.0.0": version "6.1.0" resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" @@ -4385,6 +4533,11 @@ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.14.0.tgz#d8b60cecf62f2db0fb68e5e006077b9178b85de5" integrity sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ== +"@types/qs@^6.5.3": + version "6.15.1" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.15.1.tgz#8606884272c63f0db96986bd3548650d8a9388bf" + integrity sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw== + "@types/range-parser@*": version "1.2.7" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" @@ -4792,6 +4945,11 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + accepts@~1.3.4, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -4889,6 +5047,13 @@ ajv@^8.0.0, ajv@^8.9.0: json-schema-traverse "^1.0.0" require-from-string "^2.0.2" +algoliasearch-helper@3.29.1: + version "3.29.1" + resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.29.1.tgz#4e764351493d461aa825d2a1209403a98e9b2477" + integrity sha512-6ck2YFudF2Pje7szQoPBiRFTGfd+1I+0I/WfLPGn0bj1kvrFoOQmNyedNiDxTk3/r4IfSLDYk+RA4G7u8H6+yA== + dependencies: + "@algolia/events" "^4.0.1" + algoliasearch-helper@^3.26.0: version "3.26.0" resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.26.0.tgz#d6e283396a9fc5bf944f365dc3b712570314363f" @@ -4916,6 +5081,26 @@ algoliasearch@^5.37.0: "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" +algoliasearch@^5.53.0: + version "5.53.0" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-5.53.0.tgz#393d1990fc1d3164d2684c09b11c797de0fbb0c9" + integrity sha512-OGW1q6b91CRSSeiOnM8LxuR5NYJ2esvw66jUZ4IIvdv+ItNkx3pwLuyR+jaCdbGee4ov5WgUnyPryyh11xvByQ== + dependencies: + "@algolia/abtesting" "1.19.0" + "@algolia/client-abtesting" "5.53.0" + "@algolia/client-analytics" "5.53.0" + "@algolia/client-common" "5.53.0" + "@algolia/client-insights" "5.53.0" + "@algolia/client-personalization" "5.53.0" + "@algolia/client-query-suggestions" "5.53.0" + "@algolia/client-search" "5.53.0" + "@algolia/ingestion" "1.53.0" + "@algolia/monitoring" "1.53.0" + "@algolia/recommend" "5.53.0" + "@algolia/requester-browser-xhr" "5.53.0" + "@algolia/requester-fetch" "5.53.0" + "@algolia/requester-node-http" "5.53.0" + ansi-align@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" @@ -8456,6 +8641,14 @@ history@^4.9.0: tiny-warning "^1.0.0" value-equal "^1.0.1" +hogan.js@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/hogan.js/-/hogan.js-3.0.2.tgz#4cd9e1abd4294146e7679e41d7898732b02c7bfd" + integrity sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg== + dependencies: + mkdirp "0.3.0" + nopt "1.0.10" + hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" @@ -8473,6 +8666,11 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" +htm@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/htm/-/htm-3.1.1.tgz#49266582be0dc66ed2235d5ea892307cc0c24b78" + integrity sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ== + html-escaper@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -8792,6 +8990,34 @@ inline-style-parser@0.2.4: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.4.tgz#f4af5fe72e612839fcd453d989a586566d695f22" integrity sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q== +instantsearch-ui-components@0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/instantsearch-ui-components/-/instantsearch-ui-components-0.30.0.tgz#cc10b6d12b5289dd817544c7e3e22348159cbdb6" + integrity sha512-4EXowST/yMYnEblKjjUj82Y97nbZvjNRK1se3/c1bVnyGiOe4xO4ETe8is+7oEQu8yVCDA7HEPWTqOGX7xLJKw== + dependencies: + "@swc/helpers" "0.5.18" + markdown-to-jsx "^7.7.15" + +instantsearch.js@4.101.0: + version "4.101.0" + resolved "https://registry.yarnpkg.com/instantsearch.js/-/instantsearch.js-4.101.0.tgz#82fdd5d176046e79044e3b22b75972481ae26d80" + integrity sha512-sdUrQtGBCzrtqbesFcWvbnWbZ5FVhaETFBaoUMHWHMCcJfAQYuQUPtfMo0X3GHlsosdBNQML3yCGHHdVrIhwuw== + dependencies: + "@algolia/events" "^4.0.1" + "@swc/helpers" "0.5.18" + "@types/dom-speech-recognition" "^0.0.1" + "@types/google.maps" "^3.55.12" + "@types/hogan.js" "^3.0.0" + "@types/qs" "^6.5.3" + algoliasearch-helper "3.29.1" + hogan.js "^3.0.2" + htm "^3.0.0" + instantsearch-ui-components "0.30.0" + preact "^10.10.0" + qs "^6.5.1" + react ">= 0.14.0" + search-insights "^2.17.2" + internal-slot@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" @@ -9705,6 +9931,11 @@ markdown-table@^3.0.0: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.4.tgz#fe44d6d410ff9d6f2ea1797a3f60aa4d2b631c2a" integrity sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw== +markdown-to-jsx@^7.7.15: + version "7.7.17" + resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.7.17.tgz#6e997d6aa4dbe2e69c423c65745541846777483c" + integrity sha512-7mG/1feQ0TX5I7YyMZVDgCC/y2I3CiEhIRQIhyov9nGBP5eoVrOXXHuL5ZP8GRfxVZKRiXWJgwXkb9It+nQZfQ== + marked@^16.3.0: version "16.4.2" resolved "https://registry.yarnpkg.com/marked/-/marked-16.4.2.tgz#4959a64be6c486f0db7467ead7ce288de54290a3" @@ -10937,6 +11168,11 @@ mitt@3.0.1: resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1" integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== +mkdirp@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" + integrity sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew== + mri@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" @@ -11054,6 +11290,13 @@ node-releases@^2.0.27: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== +nopt@1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== + dependencies: + abbrev "1" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -12169,6 +12412,11 @@ postcss@^8.4.21, postcss@^8.4.24, postcss@^8.4.33, postcss@^8.5.10, postcss@^8.5 picocolors "^1.1.1" source-map-js "^1.2.1" +preact@^10.10.0: + version "10.29.2" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.29.2.tgz#3e6069c471718b8d124d1cd67565114532e88d70" + integrity sha512-7tNmwg/7mzzAoB/8kSg6Hl37JraAZw3Z3A0JSY7VXlZwo82Xn0G7wKbNNs2qoF4ZEEsQGTwDAroNdqKs1ofJxQ== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -12340,7 +12588,7 @@ pvutils@^1.1.3, pvutils@^1.1.5: resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.5.tgz#84b0dea4a5d670249aa9800511804ee0b7c2809c" integrity sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA== -qs@~6.15.1: +qs@^6.5.1, qs@~6.15.1: version "6.15.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.15.2.tgz#fd55426d710403ddccc45e0f9eab16db7727ece9" integrity sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw== @@ -12424,6 +12672,26 @@ react-iframe@^1.8.0: dependencies: object-assign "^4.1.1" +react-instantsearch-core@7.35.0: + version "7.35.0" + resolved "https://registry.yarnpkg.com/react-instantsearch-core/-/react-instantsearch-core-7.35.0.tgz#841a0d0eb3a2d87b1bbd6821c33f80b0bb4d2e1e" + integrity sha512-oy8JvhCkOYg2kYB2RF8dZfEc5Dn3N2ktR7n8Z1w/NbRxSmq64lEmJ4DMPJItU1uGqohbD0ZgDtT7Ug8bLPIU8g== + dependencies: + "@swc/helpers" "0.5.18" + algoliasearch-helper "3.29.1" + instantsearch.js "4.101.0" + use-sync-external-store "^1.0.0" + +react-instantsearch@^7.35.0: + version "7.35.0" + resolved "https://registry.yarnpkg.com/react-instantsearch/-/react-instantsearch-7.35.0.tgz#26cd47a0b2263afedc649a134422b13b391535fc" + integrity sha512-6jI/TLXDrBj3CoT8dutwq+qsIofMGICb6AvGRp2b6t6R96yAFVhKaXJhKIiEaG+KqssbBtuyBRkrQyakX83piw== + dependencies: + "@swc/helpers" "0.5.18" + instantsearch-ui-components "0.30.0" + instantsearch.js "4.101.0" + react-instantsearch-core "7.35.0" + react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -12512,6 +12780,11 @@ react-transition-group@^4.4.5: loose-envify "^1.4.0" prop-types "^15.6.2" +"react@>= 0.14.0": + version "19.2.7" + resolved "https://registry.yarnpkg.com/react/-/react-19.2.7.tgz#1f47a1bfc06f8ec885752c6f4af14369a9f8260b" + integrity sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ== + react@^19.0.0: version "19.0.0" resolved "https://registry.yarnpkg.com/react/-/react-19.0.0.tgz#6e1969251b9f108870aa4bff37a0ce9ddfaaabdd" @@ -13070,7 +13343,7 @@ schema-utils@^4.0.0, schema-utils@^4.0.1, schema-utils@^4.2.0, schema-utils@^4.3 ajv-formats "^2.1.1" ajv-keywords "^5.1.0" -search-insights@^2.17.3: +search-insights@^2.17.2, search-insights@^2.17.3: version "2.17.3" resolved "https://registry.yarnpkg.com/search-insights/-/search-insights-2.17.3.tgz#8faea5d20507bf348caba0724e5386862847b661" integrity sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ== @@ -14135,7 +14408,7 @@ tslib@^1.8.1, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.4.0, tslib@^2.6.0, tslib@^2.8.1: +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.4.0, tslib@^2.6.0, tslib@^2.8.0, tslib@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -14512,7 +14785,7 @@ use-sync-external-store@1.2.0: resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== -use-sync-external-store@^1.4.0: +use-sync-external-store@^1.0.0, use-sync-external-store@^1.4.0: version "1.6.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz#b174bfa65cb2b526732d9f2ac0a408027876f32d" integrity sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w== From cf33f9d15c9db72482db37125d8bfa48e2a2422b Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Sat, 6 Jun 2026 02:47:38 -0700 Subject: [PATCH 26/40] Remove unused algoliasearch and react-instantsearch from lockfile Co-Authored-By: Claude Sonnet 4.6 --- yarn.lock | 281 +----------------------------------------------------- 1 file changed, 4 insertions(+), 277 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5a4d99b85a..218024174d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -36,16 +36,6 @@ swr "^2.2.5" throttleit "2.1.0" -"@algolia/abtesting@1.19.0": - version "1.19.0" - resolved "https://registry.yarnpkg.com/@algolia/abtesting/-/abtesting-1.19.0.tgz#2cccf865691a1f321c583ffc632b405e7d4784b9" - integrity sha512-Lhnez3hhXHk25lfxLAMxvkP4fmN3+1RgADhD2ssMDBYuAsDVReeyP+3SGRx+ntq8ijMrLqUyfvO72TB6jsTteQ== - dependencies: - "@algolia/client-common" "5.53.0" - "@algolia/requester-browser-xhr" "5.53.0" - "@algolia/requester-fetch" "5.53.0" - "@algolia/requester-node-http" "5.53.0" - "@algolia/abtesting@1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@algolia/abtesting/-/abtesting-1.6.0.tgz#009061aa6d3f514ed54efa35fadbbdda0081c1fd" @@ -143,16 +133,6 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" -"@algolia/client-abtesting@5.53.0": - version "5.53.0" - resolved "https://registry.yarnpkg.com/@algolia/client-abtesting/-/client-abtesting-5.53.0.tgz#6662660f570206fe88a8e3cac92cb809aadd9519" - integrity sha512-0ZjA5Hcmaoz5Lj6OG0zhfIyeqzJZnLW2CRJA1W17UwMFGRtZAJ9yJKRvPEDA6gkpsIoQxORTSW6sWFiuYncPNQ== - dependencies: - "@algolia/client-common" "5.53.0" - "@algolia/requester-browser-xhr" "5.53.0" - "@algolia/requester-fetch" "5.53.0" - "@algolia/requester-node-http" "5.53.0" - "@algolia/client-analytics@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.18.0.tgz#de0dc80011fdbaa9853adbdb836e0a80f08f53df" @@ -173,16 +153,6 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" -"@algolia/client-analytics@5.53.0": - version "5.53.0" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.53.0.tgz#7f52e691dfabee1d5476c3d7c100e495de09e0ce" - integrity sha512-kWNodP75iiEaOtemC9F/hlxNBG5E2QUjN1BusnE6m2b4l7Qh/BUO3fGCVsmKJI65VO4VKGGmT43ICvHtTcJ2JQ== - dependencies: - "@algolia/client-common" "5.53.0" - "@algolia/requester-browser-xhr" "5.53.0" - "@algolia/requester-fetch" "5.53.0" - "@algolia/requester-node-http" "5.53.0" - "@algolia/client-common@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.18.0.tgz#8de3991b25ff3c9bbf5ef06c19f6a4a4fa64f328" @@ -193,11 +163,6 @@ resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.40.0.tgz#652d8c971149657c26bbdf845829af1aad782deb" integrity sha512-dbE4+MJIDsTghG3hUYWBq7THhaAmqNqvW9g2vzwPf5edU4IRmuYpKtY3MMotes8/wdTasWG07XoaVhplJBlvdg== -"@algolia/client-common@5.53.0": - version "5.53.0" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.53.0.tgz#c8b0d8afc0d202ba71de9c3ac2c7331b92020f75" - integrity sha512-YPN45TXD9Wrse185t/Ta7nktZsqpv97oOjCzp2sblHnCL6rBc9TDeJAg1IGl2UpdwnSD05Zu/5wLB4watOUMyg== - "@algolia/client-insights@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.18.0.tgz#2c6f158e57265fd0888f5b84fe7302d6d659c0ff" @@ -218,16 +183,6 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" -"@algolia/client-insights@5.53.0": - version "5.53.0" - resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.53.0.tgz#512a5a5b5c8685c121cdfe79af9cdff538f9cb07" - integrity sha512-qAcYTDJE6m924FDDUQvdD6vh7DYaqOeSpFS74IP37/JRV0v4cGBauyxTF2WzDnokUylQDbqreoFIJZfg0Fitmw== - dependencies: - "@algolia/client-common" "5.53.0" - "@algolia/requester-browser-xhr" "5.53.0" - "@algolia/requester-fetch" "5.53.0" - "@algolia/requester-node-http" "5.53.0" - "@algolia/client-personalization@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.18.0.tgz#26128f6a1aef523ae32f29ef9afd18fd2f159b98" @@ -248,16 +203,6 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" -"@algolia/client-personalization@5.53.0": - version "5.53.0" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.53.0.tgz#5369cc4ebe5a49dad5f4af959260206c89a6c9ef" - integrity sha512-fQaY+DkSJOpuUVUe8MQTwrdiKAqkJGhpDarB08duBn/sUv7Bkib6MDRQauCcWTWTe4HIW+EbwQP9R4kci1V/Yw== - dependencies: - "@algolia/client-common" "5.53.0" - "@algolia/requester-browser-xhr" "5.53.0" - "@algolia/requester-fetch" "5.53.0" - "@algolia/requester-node-http" "5.53.0" - "@algolia/client-query-suggestions@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.18.0.tgz#9911560aa2dd26984a6d3f9803f14aecc2f1d10e" @@ -278,16 +223,6 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" -"@algolia/client-query-suggestions@5.53.0": - version "5.53.0" - resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.53.0.tgz#ce00b5b0ba0d71e8175f4e7b238e3f28f02ee40e" - integrity sha512-o72tsiEZGfeS/dxL9IADfzcZWGEwKDEe5CvtrBuT//3JR+SHuTtHRI2ZTf7D7bcKagcbojvO8hnkHdfoakSlYg== - dependencies: - "@algolia/client-common" "5.53.0" - "@algolia/requester-browser-xhr" "5.53.0" - "@algolia/requester-fetch" "5.53.0" - "@algolia/requester-node-http" "5.53.0" - "@algolia/client-search@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.18.0.tgz#26a3b55b6783cf7eaa8c28b48b891ed245c7e708" @@ -308,16 +243,6 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" -"@algolia/client-search@5.53.0": - version "5.53.0" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.53.0.tgz#a1b412880462c85a1ac72c830498e0312dde1e0e" - integrity sha512-Ds16IyPm/dNJPCU8OzApo2gwGrgWT5BYHhE3NFwZbpCveqyvPDB9sZDDkJ5DsdOGT2aC+R3i0/M1OVXF2qdgPg== - dependencies: - "@algolia/client-common" "5.53.0" - "@algolia/requester-browser-xhr" "5.53.0" - "@algolia/requester-fetch" "5.53.0" - "@algolia/requester-node-http" "5.53.0" - "@algolia/events@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" @@ -343,16 +268,6 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" -"@algolia/ingestion@1.53.0": - version "1.53.0" - resolved "https://registry.yarnpkg.com/@algolia/ingestion/-/ingestion-1.53.0.tgz#8417cef6430da4fb14234c3c6698726c7a41a2be" - integrity sha512-oNbT6z4NwD8Pou9VPINGlN/tlG1afESh2EbxqnP6rwl95xKVD/Zlciis1PpNeO/9U/rrajc1+7DcfKi03tX1KQ== - dependencies: - "@algolia/client-common" "5.53.0" - "@algolia/requester-browser-xhr" "5.53.0" - "@algolia/requester-fetch" "5.53.0" - "@algolia/requester-node-http" "5.53.0" - "@algolia/monitoring@1.18.0": version "1.18.0" resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.18.0.tgz#e94a4c436be0d8c1e9d19c69aeff8e67d0237736" @@ -373,16 +288,6 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" -"@algolia/monitoring@1.53.0": - version "1.53.0" - resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.53.0.tgz#091005519a31b04a8b9f2c9f7d13358001a696bb" - integrity sha512-G+KZb/yd+qAOFn/cEvTGeLxQm8aP3a0od50l3z/ylccY+/o4YG3TNcjU1tFQHW4mXC137GPyR7W70R0kRQDLnA== - dependencies: - "@algolia/client-common" "5.53.0" - "@algolia/requester-browser-xhr" "5.53.0" - "@algolia/requester-fetch" "5.53.0" - "@algolia/requester-node-http" "5.53.0" - "@algolia/recommend@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.18.0.tgz#bd07d3057dd2030718c6707a4fe247b871f1834d" @@ -403,16 +308,6 @@ "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" -"@algolia/recommend@5.53.0": - version "5.53.0" - resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.53.0.tgz#d45f5538984f208f51f71a4c6b973eb1c1a8a66c" - integrity sha512-6aVfYd55Un6IUgPLbo84WfgFZlS3L0vA1ttzXL5vahHewUJ8jYgd89TzlWRTeej7w70mb9RWsVlFYGmJ/diQww== - dependencies: - "@algolia/client-common" "5.53.0" - "@algolia/requester-browser-xhr" "5.53.0" - "@algolia/requester-fetch" "5.53.0" - "@algolia/requester-node-http" "5.53.0" - "@algolia/requester-browser-xhr@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.18.0.tgz#6e7e56bb687904a01c91988393f5c1969944ee3d" @@ -427,13 +322,6 @@ dependencies: "@algolia/client-common" "5.40.0" -"@algolia/requester-browser-xhr@5.53.0": - version "5.53.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.53.0.tgz#bd742734337378090d5c95f80de2b7a933089924" - integrity sha512-ke27DqgzCOlt+RbeEdCxtXxMQOnAOi8ujr2wid0DmDKzR95Kw/f9sBsuhBxtjevCqJRJszfRTLY0B1pbO6IhkA== - dependencies: - "@algolia/client-common" "5.53.0" - "@algolia/requester-fetch@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.18.0.tgz#fcccc76bd7d16fb54c56d15baa6b5f657b17ca71" @@ -448,13 +336,6 @@ dependencies: "@algolia/client-common" "5.40.0" -"@algolia/requester-fetch@5.53.0": - version "5.53.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.53.0.tgz#1f4b3d933c50d0022de4ce18d235b65325b7024e" - integrity sha512-GngiOqt2Gq4oLno6yXQVj9om+qSO9SWAoduoTOEg79dKZ62brB8OOIvSJG/vDNoanYi6a7Al9uDZwXvi+bcVTg== - dependencies: - "@algolia/client-common" "5.53.0" - "@algolia/requester-node-http@5.18.0": version "5.18.0" resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.18.0.tgz#c5b16de53d83276067583e7b2f56b09eac938435" @@ -469,13 +350,6 @@ dependencies: "@algolia/client-common" "5.40.0" -"@algolia/requester-node-http@5.53.0": - version "5.53.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.53.0.tgz#8c25669aaf6fc11a2970d2f62fbda3c603ec11ce" - integrity sha512-6mF9LZMUk0QqWvrnxkxBqhswwz6Xfiwy6/gmTzL5HrlhdVG3ITAqGV2k3XmVThP1h0Ulc3VQwiNCD7/Nr4JNlQ== - dependencies: - "@algolia/client-common" "5.53.0" - "@antfu/install-pkg@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@antfu/install-pkg/-/install-pkg-1.1.0.tgz#78fa036be1a6081b5a77a5cf59f50c7752b6ba26" @@ -3919,13 +3793,6 @@ resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== -"@swc/helpers@0.5.18": - version "0.5.18" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.18.tgz#feeeabea0d10106ee25aaf900165df911ab6d3b1" - integrity sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ== - dependencies: - tslib "^2.8.0" - "@swc/html-darwin-arm64@1.13.20": version "1.13.20" resolved "https://registry.yarnpkg.com/@swc/html-darwin-arm64/-/html-darwin-arm64-1.13.20.tgz#e1c3bf132e86d55ec6cf12e22c68c3d833247ece" @@ -4308,11 +4175,6 @@ dependencies: "@types/ms" "*" -"@types/dom-speech-recognition@^0.0.1": - version "0.0.1" - resolved "https://registry.yarnpkg.com/@types/dom-speech-recognition/-/dom-speech-recognition-0.0.1.tgz#e326761a04b4a49c0eec2ac7948afc1c6aa12baa" - integrity sha512-udCxb8DvjcDKfk1WTBzDsxFbLgYxmQGKrE/ricoMqHRNjSlSUCcamVTA5lIQqzY10mY5qCY0QDwBfFEwhfoDPw== - "@types/eslint-scope@3.7.7", "@types/eslint-scope@^3.7.7": version "3.7.7" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" @@ -4385,11 +4247,6 @@ resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.16.tgz#8ebe53d69efada7044454e3305c19017d97ced2a" integrity sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg== -"@types/google.maps@^3.55.12": - version "3.65.1" - resolved "https://registry.yarnpkg.com/@types/google.maps/-/google.maps-3.65.1.tgz#d1dca254b956cda08e0d5a021db920ca4cd12102" - integrity sha512-O9monmoXfyWsuyR4Wz3TZU26qai9y7jUV7DSRySluae6O5tQt3Obw5ETt0HKfNsjctnlF/yx/Tfn3WQNmKRXZA== - "@types/gtag.js@^0.0.20": version "0.0.20" resolved "https://registry.yarnpkg.com/@types/gtag.js/-/gtag.js-0.0.20.tgz#e47edabb4ed5ecac90a079275958e6c929d7c08a" @@ -4414,11 +4271,6 @@ resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64" integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA== -"@types/hogan.js@^3.0.0": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@types/hogan.js/-/hogan.js-3.0.5.tgz#09f5b916ad88e1975b093ab7a25a37ffc0418be5" - integrity sha512-/uRaY3HGPWyLqOyhgvW9Aa43BNnLZrNeQxl2p8wqId4UHMfPKolSB+U7BlZyO1ng7MkLnyEAItsBzCG0SDhqrA== - "@types/html-minifier-terser@^6.0.0": version "6.1.0" resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" @@ -4533,11 +4385,6 @@ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.14.0.tgz#d8b60cecf62f2db0fb68e5e006077b9178b85de5" integrity sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ== -"@types/qs@^6.5.3": - version "6.15.1" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.15.1.tgz#8606884272c63f0db96986bd3548650d8a9388bf" - integrity sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw== - "@types/range-parser@*": version "1.2.7" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" @@ -4945,11 +4792,6 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - accepts@~1.3.4, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -5047,13 +4889,6 @@ ajv@^8.0.0, ajv@^8.9.0: json-schema-traverse "^1.0.0" require-from-string "^2.0.2" -algoliasearch-helper@3.29.1: - version "3.29.1" - resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.29.1.tgz#4e764351493d461aa825d2a1209403a98e9b2477" - integrity sha512-6ck2YFudF2Pje7szQoPBiRFTGfd+1I+0I/WfLPGn0bj1kvrFoOQmNyedNiDxTk3/r4IfSLDYk+RA4G7u8H6+yA== - dependencies: - "@algolia/events" "^4.0.1" - algoliasearch-helper@^3.26.0: version "3.26.0" resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.26.0.tgz#d6e283396a9fc5bf944f365dc3b712570314363f" @@ -5081,26 +4916,6 @@ algoliasearch@^5.37.0: "@algolia/requester-fetch" "5.40.0" "@algolia/requester-node-http" "5.40.0" -algoliasearch@^5.53.0: - version "5.53.0" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-5.53.0.tgz#393d1990fc1d3164d2684c09b11c797de0fbb0c9" - integrity sha512-OGW1q6b91CRSSeiOnM8LxuR5NYJ2esvw66jUZ4IIvdv+ItNkx3pwLuyR+jaCdbGee4ov5WgUnyPryyh11xvByQ== - dependencies: - "@algolia/abtesting" "1.19.0" - "@algolia/client-abtesting" "5.53.0" - "@algolia/client-analytics" "5.53.0" - "@algolia/client-common" "5.53.0" - "@algolia/client-insights" "5.53.0" - "@algolia/client-personalization" "5.53.0" - "@algolia/client-query-suggestions" "5.53.0" - "@algolia/client-search" "5.53.0" - "@algolia/ingestion" "1.53.0" - "@algolia/monitoring" "1.53.0" - "@algolia/recommend" "5.53.0" - "@algolia/requester-browser-xhr" "5.53.0" - "@algolia/requester-fetch" "5.53.0" - "@algolia/requester-node-http" "5.53.0" - ansi-align@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" @@ -8641,14 +8456,6 @@ history@^4.9.0: tiny-warning "^1.0.0" value-equal "^1.0.1" -hogan.js@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/hogan.js/-/hogan.js-3.0.2.tgz#4cd9e1abd4294146e7679e41d7898732b02c7bfd" - integrity sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg== - dependencies: - mkdirp "0.3.0" - nopt "1.0.10" - hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" @@ -8666,11 +8473,6 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" -htm@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/htm/-/htm-3.1.1.tgz#49266582be0dc66ed2235d5ea892307cc0c24b78" - integrity sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ== - html-escaper@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -8990,34 +8792,6 @@ inline-style-parser@0.2.4: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.4.tgz#f4af5fe72e612839fcd453d989a586566d695f22" integrity sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q== -instantsearch-ui-components@0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/instantsearch-ui-components/-/instantsearch-ui-components-0.30.0.tgz#cc10b6d12b5289dd817544c7e3e22348159cbdb6" - integrity sha512-4EXowST/yMYnEblKjjUj82Y97nbZvjNRK1se3/c1bVnyGiOe4xO4ETe8is+7oEQu8yVCDA7HEPWTqOGX7xLJKw== - dependencies: - "@swc/helpers" "0.5.18" - markdown-to-jsx "^7.7.15" - -instantsearch.js@4.101.0: - version "4.101.0" - resolved "https://registry.yarnpkg.com/instantsearch.js/-/instantsearch.js-4.101.0.tgz#82fdd5d176046e79044e3b22b75972481ae26d80" - integrity sha512-sdUrQtGBCzrtqbesFcWvbnWbZ5FVhaETFBaoUMHWHMCcJfAQYuQUPtfMo0X3GHlsosdBNQML3yCGHHdVrIhwuw== - dependencies: - "@algolia/events" "^4.0.1" - "@swc/helpers" "0.5.18" - "@types/dom-speech-recognition" "^0.0.1" - "@types/google.maps" "^3.55.12" - "@types/hogan.js" "^3.0.0" - "@types/qs" "^6.5.3" - algoliasearch-helper "3.29.1" - hogan.js "^3.0.2" - htm "^3.0.0" - instantsearch-ui-components "0.30.0" - preact "^10.10.0" - qs "^6.5.1" - react ">= 0.14.0" - search-insights "^2.17.2" - internal-slot@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" @@ -9931,11 +9705,6 @@ markdown-table@^3.0.0: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.4.tgz#fe44d6d410ff9d6f2ea1797a3f60aa4d2b631c2a" integrity sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw== -markdown-to-jsx@^7.7.15: - version "7.7.17" - resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.7.17.tgz#6e997d6aa4dbe2e69c423c65745541846777483c" - integrity sha512-7mG/1feQ0TX5I7YyMZVDgCC/y2I3CiEhIRQIhyov9nGBP5eoVrOXXHuL5ZP8GRfxVZKRiXWJgwXkb9It+nQZfQ== - marked@^16.3.0: version "16.4.2" resolved "https://registry.yarnpkg.com/marked/-/marked-16.4.2.tgz#4959a64be6c486f0db7467ead7ce288de54290a3" @@ -11168,11 +10937,6 @@ mitt@3.0.1: resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1" integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== -mkdirp@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" - integrity sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew== - mri@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" @@ -11290,13 +11054,6 @@ node-releases@^2.0.27: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== -nopt@1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== - dependencies: - abbrev "1" - normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -12412,11 +12169,6 @@ postcss@^8.4.21, postcss@^8.4.24, postcss@^8.4.33, postcss@^8.5.10, postcss@^8.5 picocolors "^1.1.1" source-map-js "^1.2.1" -preact@^10.10.0: - version "10.29.2" - resolved "https://registry.yarnpkg.com/preact/-/preact-10.29.2.tgz#3e6069c471718b8d124d1cd67565114532e88d70" - integrity sha512-7tNmwg/7mzzAoB/8kSg6Hl37JraAZw3Z3A0JSY7VXlZwo82Xn0G7wKbNNs2qoF4ZEEsQGTwDAroNdqKs1ofJxQ== - prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -12588,7 +12340,7 @@ pvutils@^1.1.3, pvutils@^1.1.5: resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.5.tgz#84b0dea4a5d670249aa9800511804ee0b7c2809c" integrity sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA== -qs@^6.5.1, qs@~6.15.1: +qs@~6.15.1: version "6.15.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.15.2.tgz#fd55426d710403ddccc45e0f9eab16db7727ece9" integrity sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw== @@ -12672,26 +12424,6 @@ react-iframe@^1.8.0: dependencies: object-assign "^4.1.1" -react-instantsearch-core@7.35.0: - version "7.35.0" - resolved "https://registry.yarnpkg.com/react-instantsearch-core/-/react-instantsearch-core-7.35.0.tgz#841a0d0eb3a2d87b1bbd6821c33f80b0bb4d2e1e" - integrity sha512-oy8JvhCkOYg2kYB2RF8dZfEc5Dn3N2ktR7n8Z1w/NbRxSmq64lEmJ4DMPJItU1uGqohbD0ZgDtT7Ug8bLPIU8g== - dependencies: - "@swc/helpers" "0.5.18" - algoliasearch-helper "3.29.1" - instantsearch.js "4.101.0" - use-sync-external-store "^1.0.0" - -react-instantsearch@^7.35.0: - version "7.35.0" - resolved "https://registry.yarnpkg.com/react-instantsearch/-/react-instantsearch-7.35.0.tgz#26cd47a0b2263afedc649a134422b13b391535fc" - integrity sha512-6jI/TLXDrBj3CoT8dutwq+qsIofMGICb6AvGRp2b6t6R96yAFVhKaXJhKIiEaG+KqssbBtuyBRkrQyakX83piw== - dependencies: - "@swc/helpers" "0.5.18" - instantsearch-ui-components "0.30.0" - instantsearch.js "4.101.0" - react-instantsearch-core "7.35.0" - react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -12780,11 +12512,6 @@ react-transition-group@^4.4.5: loose-envify "^1.4.0" prop-types "^15.6.2" -"react@>= 0.14.0": - version "19.2.7" - resolved "https://registry.yarnpkg.com/react/-/react-19.2.7.tgz#1f47a1bfc06f8ec885752c6f4af14369a9f8260b" - integrity sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ== - react@^19.0.0: version "19.0.0" resolved "https://registry.yarnpkg.com/react/-/react-19.0.0.tgz#6e1969251b9f108870aa4bff37a0ce9ddfaaabdd" @@ -13343,7 +13070,7 @@ schema-utils@^4.0.0, schema-utils@^4.0.1, schema-utils@^4.2.0, schema-utils@^4.3 ajv-formats "^2.1.1" ajv-keywords "^5.1.0" -search-insights@^2.17.2, search-insights@^2.17.3: +search-insights@^2.17.3: version "2.17.3" resolved "https://registry.yarnpkg.com/search-insights/-/search-insights-2.17.3.tgz#8faea5d20507bf348caba0724e5386862847b661" integrity sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ== @@ -14408,7 +14135,7 @@ tslib@^1.8.1, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.4.0, tslib@^2.6.0, tslib@^2.8.0, tslib@^2.8.1: +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.4.0, tslib@^2.6.0, tslib@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -14785,7 +14512,7 @@ use-sync-external-store@1.2.0: resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== -use-sync-external-store@^1.0.0, use-sync-external-store@^1.4.0: +use-sync-external-store@^1.4.0: version "1.6.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz#b174bfa65cb2b526732d9f2ac0a408027876f32d" integrity sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w== From 3127e1c02eaf8dda956267af089d473e684228b2 Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Sat, 6 Jun 2026 20:10:18 -0700 Subject: [PATCH 27/40] Fix Algolia search input text overlap with 'Clear the query' button --- src/css/sumo.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/css/sumo.scss b/src/css/sumo.scss index 95703e4e20..196b66833a 100644 --- a/src/css/sumo.scss +++ b/src/css/sumo.scss @@ -248,6 +248,11 @@ html[data-theme='dark'] .DocSearch-Search-Icon { color: #6b6f78 !important; } +/* Prevent Algolia search input text from overlapping the "Clear the query" button */ +.DocSearch-Input { + padding-right: 65px !important; +} + //GitHub icon .header-github-link:hover { opacity: 0.6; From 7bcd1df18920da8990f7642a1be923fd4e67b9b7 Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Mon, 8 Jun 2026 04:31:28 -0700 Subject: [PATCH 28/40] =?UTF-8?q?Revert=20Agent=20Studio=20migration=20?= =?UTF-8?q?=E2=80=94=20return=20to=20legacy=20Algolia=20Ask=20AI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent Studio integration caused a StepStartPartV5 validation error on every multi-turn conversation. The @docsearch/react Sidepanel uses Vercel AI SDK v5 internally, which appends step-start markers to assistant message parts. On the second turn these markers are sent back to the Agent Studio API as conversation history, and the backend's request schema rejects them. Upgrading to @docsearch/react 4.6.3 made the error surface on first messages as well. The issue is a library bug in the Agent Studio integration that needs to be resolved upstream by Algolia. Changes: - Restore legacy assistantId (T7pp7iENesuU) and move credentials back inside askAi block in docusaurus.config.js - Remove agentStudio={true} prop from AskAiSidepanel component - Revert config reading to pull appId/apiKey/indexName from askAi block - Remove Agent Studio CSS overrides from sumo.scss - Downgrade @docsearch/react from 4.6.3 back to 4.6.2 Co-Authored-By: Claude Sonnet 4.6 --- docusaurus.config.js | 7 +- package.json | 1 + src/components/AskAiSidepanel/index.tsx | 4 +- src/css/sumo.scss | 104 ------------------------ yarn.lock | 2 +- 5 files changed, 7 insertions(+), 111 deletions(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index a98c201b66..08386aba94 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -387,10 +387,11 @@ module.exports = { contextualSearch: false, searchPagePath: 'docs-search', // Default value is 'search'; renamed to 'docs-search' so it doesn't conflict with '/Search' redirect insights: true, - agentStudio: true, askAi: { - assistantId: '1920b662-740d-46e1-9c69-ee6332433380', - suggestedQuestions: true, + assistantId: 'T7pp7iENesuU', + indexName: 'crawler_sumodocs', + apiKey: 'fb2f4e1fb40f962900631121cb365549', + appId: '2SJPGMLW1Q', }, insightsConfig: { useCookie: true, // alt to useCookie: true, diff --git a/package.json b/package.json index ce7ccae7d0..76ec344233 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "@braintree/sanitize-url": "^6.0.1", "@csstools/selector-resolve-nested": "3.1.0", "@docsearch/css": "4", + "@docsearch/react": "4.6.2", "@docusaurus/bundler": "^3.10.1", "@docusaurus/core": "^3.10.1", "@docusaurus/cssnano-preset": "^3.10.1", diff --git a/src/components/AskAiSidepanel/index.tsx b/src/components/AskAiSidepanel/index.tsx index 9153fb3cf5..c0d2102db9 100644 --- a/src/components/AskAiSidepanel/index.tsx +++ b/src/components/AskAiSidepanel/index.tsx @@ -159,8 +159,7 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) return null; } - const { assistantId, suggestedQuestions } = algoliaConfig.askAi; - const { appId, apiKey, indexName } = algoliaConfig; + const { assistantId, indexName, appId, apiKey, suggestedQuestions } = algoliaConfig.askAi; const handleAlgoliaClose = () => { if (!isResizingRef.current) onClose(); @@ -177,7 +176,6 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) apiKey={apiKey} indexName={indexName} assistantId={assistantId} - agentStudio={true} isOpen={isOpen} onOpen={() => {}} onClose={handleAlgoliaClose} diff --git a/src/css/sumo.scss b/src/css/sumo.scss index bbe61d74ee..c1d685b5e0 100644 --- a/src/css/sumo.scss +++ b/src/css/sumo.scss @@ -1758,107 +1758,3 @@ article header h2[class*='title_'] { .language-sumo .token.time { color: var(--sumo-number); } .language-sumo .token.operator { color: var(--sumo-operator); } .language-sumo .token.regex { color: var(--sumo-regex); } - -/* =================================================================== - DocSearch Modal - Ask AI Overrides - Brings the modal Ask AI (triggered from top-nav search bar) in line - with the custom Ask AI sidepanel styling. - =================================================================== */ - -/* Hide related sources chips (matches sidepanel behavior) */ -.DocSearch-Modal .DocSearch-AskAiScreen-RelatedSources { - display: none !important; -} - -/* Flatten the response card — transparent, no border/radius - (matches .ask-ai-sidepanel .DocSearch-AskAiScreen-Response) */ -.DocSearch-Modal .DocSearch-AskAiScreen-Response { - background-color: transparent !important; - border: none !important; - border-radius: 0 !important; - padding: 0 !important; - margin-block-end: 0 !important; -} - -/* Disclaimer — swap default Algolia text for Sumo Logic copy */ -.DocSearch-Modal .DocSearch-AskAiScreen-Disclaimer { - font-size: 0 !important; - line-height: 0 !important; - padding: 0 !important; - align-self: stretch !important; - justify-content: center !important; -} - -.DocSearch-Modal .DocSearch-AskAiScreen-Disclaimer::before { - content: 'Answers are AI-generated from Sumo Docs and may contain errors. Please review and verify.'; - display: block; - font-size: 0.6rem; - line-height: 1.3; - font-weight: 600; - color: var(--ifm-color-emphasis-700); - padding: 0.75rem 0; - text-align: center; -} - -html[data-theme='dark'] .DocSearch-Modal .DocSearch-AskAiScreen-Disclaimer::before { - color: var(--ifm-color-emphasis-500); -} - -/* New Conversation Screen — custom title */ -.DocSearch-Modal .DocSearch-NewConversationScreen-Title { - font-size: 0 !important; - line-height: 0 !important; -} - -.DocSearch-Modal .DocSearch-NewConversationScreen-Title::before { - content: 'How can I help you today?'; - display: block; - font-size: 26px; - line-height: 1.2; - font-weight: 600; - color: var(--ifm-font-color-base); -} - -/* New Conversation Screen — custom description */ -.DocSearch-Modal .DocSearch-NewConversationScreen-Description { - font-size: 0 !important; - line-height: 0 !important; -} - -.DocSearch-Modal .DocSearch-NewConversationScreen-Description::before { - content: 'I can help you find information about Sumo Logic features, integrations, troubleshooting guides, APIs, and best practices across our documentation.'; - display: block; - font-size: 14px; - line-height: 1.4; - color: var(--ifm-color-emphasis-700); -} - -/* Suggested questions — match sidepanel pill style */ -.DocSearch-Modal .DocSearch-NewConversationScreen-SuggestedQuestion { - background-color: transparent !important; - border-color: var(--ifm-color-emphasis-200) !important; - color: var(--ifm-color-emphasis-700) !important; - border-radius: 8px !important; - font-size: 0.7rem !important; - padding: 0.35rem 0.6rem !important; - min-height: auto !important; - height: auto !important; -} - -.DocSearch-Modal .DocSearch-NewConversationScreen-SuggestedQuestion:hover { - border-color: var(--ifm-color-primary) !important; -} - -html[data-theme='dark'] .DocSearch-Modal .DocSearch-NewConversationScreen-SuggestedQuestion { - border-color: rgba(255, 255, 255, 0.15) !important; -} - -html[data-theme='dark'] .DocSearch-Modal .DocSearch-NewConversationScreen-SuggestedQuestion:hover { - background-color: rgba(255, 255, 255, 0.15) !important; - border-color: var(--ifm-color-primary) !important; -} - -/* Markdown content color — match Docusaurus theme */ -.DocSearch-Modal .DocSearch-Markdown-Content { - color: var(--ifm-font-color-base) !important; -} diff --git a/yarn.lock b/yarn.lock index 218024174d..e0c08ba2a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1859,7 +1859,7 @@ resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-4.6.2.tgz#986776619dccbf798176c75e858cc22f5e710bb4" integrity sha512-fH/cn8BjEEdM2nJdjNMHIvOVYupG6AIDtFVDgIZrNzdCSj4KXr9kd+hsehqsNGYjpUjObeKYKvgy/IwCb1jZYQ== -"@docsearch/react@^3.9.0 || ^4.3.2": +"@docsearch/react@4.6.2", "@docsearch/react@^3.9.0 || ^4.3.2": version "4.6.2" resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-4.6.2.tgz#e6c65fb87fb943eefaa936debe6d31bb51b25056" integrity sha512-/BbtGFtqVOGwZx0dw/UfhN/0/DmMQYnulY4iv0tPRhC2JCXv0ka/+izwt3Jzo1ZxXS/2eMvv9zHsBJOK1I9f/w== From 90c6db6d05dd491f7f6943dcef454dbf86d559d0 Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Wed, 10 Jun 2026 23:34:18 -0700 Subject: [PATCH 29/40] DOCS-1162 - Ask AI panel UI polish: auto-resize input, layout fixes, dark mode tweaks Co-Authored-By: Claude Sonnet 4.6 --- src/components/AskAiButton/index.tsx | 2 +- src/components/AskAiSidepanel/index.tsx | 16 +++++++++++-- src/components/AskAiSidepanel/styles.css | 30 ++++++++---------------- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/components/AskAiButton/index.tsx b/src/components/AskAiButton/index.tsx index 423ab87a96..eab4142246 100644 --- a/src/components/AskAiButton/index.tsx +++ b/src/components/AskAiButton/index.tsx @@ -37,7 +37,7 @@ export default function AskAiButton({ isOpen, setIsOpen }: AskAiButtonProps) { aria-label="Ask AI" title="Ask AI (Cmd/Ctrl + I)" > - + diff --git a/src/components/AskAiSidepanel/index.tsx b/src/components/AskAiSidepanel/index.tsx index c0d2102db9..e1e665735f 100644 --- a/src/components/AskAiSidepanel/index.tsx +++ b/src/components/AskAiSidepanel/index.tsx @@ -129,11 +129,23 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) } }; + const autoResize = (el: HTMLTextAreaElement) => { + el.style.height = '0'; + el.style.height = Math.min(el.scrollHeight, 200) + 'px'; + el.style.overflowY = el.scrollHeight > 200 ? 'auto' : 'hidden'; + }; + + const handleInput = (e: Event) => { + updateButtonState(); + autoResize(e.target as HTMLTextAreaElement); + }; + const checkInterval = setInterval(() => { const textarea = document.querySelector('.DocSearch-Sidepanel-Prompt--textarea') as HTMLTextAreaElement; if (textarea) { updateButtonState(); - textarea.addEventListener('input', updateButtonState); + autoResize(textarea); + textarea.addEventListener('input', handleInput); textarea.focus(); clearInterval(checkInterval); } @@ -143,7 +155,7 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) clearInterval(checkInterval); const textarea = document.querySelector('.DocSearch-Sidepanel-Prompt--textarea'); if (textarea) { - textarea.removeEventListener('input', updateButtonState); + textarea.removeEventListener('input', handleInput); } }; }, [isOpen]); diff --git a/src/components/AskAiSidepanel/styles.css b/src/components/AskAiSidepanel/styles.css index 7f1d9fe446..e309c83572 100644 --- a/src/components/AskAiSidepanel/styles.css +++ b/src/components/AskAiSidepanel/styles.css @@ -198,10 +198,7 @@ padding: 10px 12px !important; min-height: 48px !important; display: flex !important; - flex-direction: row !important; - align-items: center !important; - justify-content: space-between !important; - gap: 12px !important; + flex-direction: column !important; position: relative !important; } @@ -222,19 +219,16 @@ color: var(--ifm-font-color-base) !important; font-size: 0.875rem !important; font-family: 'Lab Grotesque', sans-serif !important; - padding: 0 !important; + padding: 0 36px 0 0 !important; margin: 0 !important; line-height: 1.5rem !important; - height: 1.5rem !important; min-height: 1.5rem !important; max-height: 200px !important; - flex: 1 1 auto !important; + width: 100% !important; resize: none !important; - align-self: center !important; border: none !important; outline: none !important; background: transparent !important; - overflow: hidden !important; } .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--textarea::placeholder { @@ -242,19 +236,19 @@ } [data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--textarea::placeholder { - color: #bdc1c6 !important; + color: #7f8497 !important; } -/* Override the absolutely positioned actions wrapper */ +/* Submit button wrapper — absolutely positioned inside the form at bottom-right */ .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--actions { - position: static !important; - bottom: auto !important; - right: auto !important; + position: absolute !important; + bottom: 10px !important; + right: 12px !important; height: 28px !important; + width: 28px !important; display: flex !important; align-items: center !important; justify-content: center !important; - flex-shrink: 0 !important; } /* Submit button styling - Default to grey */ @@ -265,7 +259,6 @@ display: flex !important; align-items: center !important; justify-content: center !important; - flex-shrink: 0 !important; margin: 0 !important; width: 28px !important; height: 28px !important; @@ -274,9 +267,6 @@ max-width: 28px !important; max-height: 28px !important; padding: 0 !important; - align-self: center !important; - position: relative !important; - top: 0 !important; border: none !important; } @@ -486,7 +476,7 @@ } .ask-ai-sidepanel .DocSearch-Sidepanel-NewConversationScreen .DocSearch-Sidepanel-Screen--introduction::before { - font-size: 0.875rem !important; + font-size: 0.85rem !important; line-height: 1.25rem !important; content: 'I can help you find information about Sumo Logic features, integrations, troubleshooting guides, APIs, and best practices across our documentation.'; display: block; From 37d90df153e193c50d18369608f455f45bfdd820 Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Tue, 16 Jun 2026 02:38:43 -0700 Subject: [PATCH 30/40] DOCS-1162 - Ask AI: copy button fix, search-to-sidepanel handoff, UI improvements Co-Authored-By: Claude Sonnet 4.6 --- docusaurus.config.js | 738 ++++++++++++----------- package.json | 3 +- src/components/AskAiSidepanel/index.tsx | 282 ++++++++- src/components/AskAiSidepanel/styles.css | 137 ++++- src/css/sumo.scss | 380 +++++++----- src/theme/Root.tsx | 186 +++++- yarn.lock | 5 - 7 files changed, 1173 insertions(+), 558 deletions(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index 08386aba94..d1389813da 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -4,21 +4,23 @@ // Documentation page id for open source: sumo-logic-open-source-projects -const fs = require('fs') +const fs = require('fs'); -import {themes as prismThemes} from 'prism-react-renderer'; +import { themes as prismThemes } from 'prism-react-renderer'; const lightCodeTheme = prismThemes.github; const darkCodeTheme = prismThemes.dracula; -const cidRedirects = JSON.parse(fs.readFileSync('cid-redirects.json').toString()) +const cidRedirects = JSON.parse( + fs.readFileSync('cid-redirects.json').toString() +); /** @type {import('@docusaurus/types').DocusaurusConfig} */ module.exports = { title: 'Sumo Logic Docs', tagline: 'Documentation, guides, and API references for Sumo Logic', - url: process.env.HOSTNAME || "http://localhost:3000", + url: process.env.HOSTNAME || 'http://localhost:3000', trailingSlash: true, - baseUrl: process.env.BASE_URL || "/", + baseUrl: process.env.BASE_URL || '/', onBrokenLinks: 'throw', onBrokenAnchors: 'throw', onDuplicateRoutes: 'throw', @@ -30,9 +32,7 @@ module.exports = { favicon: 'https://www.sumologic.com/favicon.ico', organizationName: 'sumologic', // Usually your GitHub org/user name. projectName: 'sumologic-documentation', // Usually your repo name. - stylesheets: [ - 'https://fonts.googleapis.com/css?family=Material+Icons', - ], + stylesheets: ['https://fonts.googleapis.com/css?family=Material+Icons'], headTags: [ { tagName: 'link', @@ -75,14 +75,14 @@ module.exports = { attributes: { rel: 'preconnect', href: 'https://api.intellimize.co', - crossorigin: 'anonymous' + crossorigin: 'anonymous', }, }, { tagName: 'link', attributes: { rel: 'preconnect', - href: 'https://117845498.intellimizeio.com' + href: 'https://117845498.intellimizeio.com', }, }, { @@ -90,7 +90,7 @@ module.exports = { attributes: { rel: 'preconnect', href: 'https://log.intellimize.co', - crossorigin: 'anonymous' + crossorigin: 'anonymous', }, }, // Sumo Logic RUM @@ -147,10 +147,11 @@ module.exports = { presets: [ [ '@docusaurus/preset-classic', - ({ + { docs: { sidebarPath: require.resolve('./sidebars.ts'), - editUrl: 'https://github.com/SumoLogic/sumologic-documentation/edit/main/', + editUrl: + 'https://github.com/SumoLogic/sumologic-documentation/edit/main/', //sidebarCollapsible: true, //sidebarCollapsed: false, remarkPlugins: [ @@ -176,10 +177,7 @@ module.exports = { 'training', ], }, - exclude: [ - '**/reuse/**', - '**/ja/**', - ], + exclude: ['**/reuse/**', '**/ja/**'], }, sitemap: { lastmod: 'date', @@ -191,7 +189,7 @@ module.exports = { '/files/**', '/release-notes-*/archive/**', '/release-notes-*/2021/**', - '/tags/**' + '/tags/**', ], filename: 'sitemap.xml', }, @@ -201,7 +199,8 @@ module.exports = { routeBasePath: 'release-notes-service', blogSidebarTitle: 'All posts', blogSidebarCount: 'ALL', - blogDescription: 'Latest features and bug fixes for Sumo Logic log analytics, AI and automation, observability, alerts, sources, and more.', + blogDescription: + 'Latest features and bug fixes for Sumo Logic log analytics, AI and automation, observability, alerts, sources, and more.', postsPerPage: 'ALL', showReadingTime: false, onUntruncatedBlogPosts: 'ignore', @@ -211,152 +210,191 @@ module.exports = { type: 'rss', xslt: true, title: 'Sumo Logic Service Release Notes', - description: 'Latest features and bug fixes for Sumo Logic log analytics, AI and automation, observability, alerts, sources, and more.', + description: + 'Latest features and bug fixes for Sumo Logic log analytics, AI and automation, observability, alerts, sources, and more.', copyright: `Copyright © ${new Date().getFullYear()} Sumo Logic`, }, }, theme: { - customCss: [ - require.resolve('./src/css/sumo.scss'), - ], + customCss: [require.resolve('./src/css/sumo.scss')], }, - }), + }, ], ], plugins: [ 'docusaurus-plugin-sass', //Embed code file from GitHub repo '@saucelabs/theme-github-codeblock', - ['@docusaurus/plugin-google-tag-manager', + [ + '@docusaurus/plugin-google-tag-manager', { containerId: 'GTM-58ZK7D', }, ], - ['@docusaurus/plugin-google-gtag', + [ + '@docusaurus/plugin-google-gtag', { trackingID: ['G-CVH19TBVSL', 'G-9FTQ9KJJBY'], }, ], - ['@docusaurus/plugin-content-blog', + [ + '@docusaurus/plugin-content-blog', { - id: 'blog-cse', - routeBasePath: 'release-notes-cse', - path: './blog-cse', - archiveBasePath: 'archive', - blogTitle: 'Sumo Logic Cloud SIEM Release Notes', - blogSidebarTitle: 'All posts', - blogSidebarCount: 'ALL', - postsPerPage: 'ALL', - blogDescription: 'New and enhanced Cloud SIEM features, bug fixes, updated rules, log mappers, parsers, and more.', - showReadingTime: false, - onUntruncatedBlogPosts: 'ignore', - onInlineTags: 'ignore', - onInlineAuthors: 'ignore', - feedOptions: { - type: 'rss', - xslt: true, - title: 'Sumo Logic Cloud SIEM Release Notes', - description: 'New and enhanced Cloud SIEM features, bug fixes, updated rules, log mappers, parsers, and more.', - copyright: `Copyright © ${new Date().getFullYear()} Sumo Logic`, - }, + id: 'blog-cse', + routeBasePath: 'release-notes-cse', + path: './blog-cse', + archiveBasePath: 'archive', + blogTitle: 'Sumo Logic Cloud SIEM Release Notes', + blogSidebarTitle: 'All posts', + blogSidebarCount: 'ALL', + postsPerPage: 'ALL', + blogDescription: + 'New and enhanced Cloud SIEM features, bug fixes, updated rules, log mappers, parsers, and more.', + showReadingTime: false, + onUntruncatedBlogPosts: 'ignore', + onInlineTags: 'ignore', + onInlineAuthors: 'ignore', + feedOptions: { + type: 'rss', + xslt: true, + title: 'Sumo Logic Cloud SIEM Release Notes', + description: + 'New and enhanced Cloud SIEM features, bug fixes, updated rules, log mappers, parsers, and more.', + copyright: `Copyright © ${new Date().getFullYear()} Sumo Logic`, + }, }, ], - ['@docusaurus/plugin-content-blog', + [ + '@docusaurus/plugin-content-blog', { - id: 'blog-csoar', - routeBasePath: 'release-notes-csoar', - path: './blog-csoar', - archiveBasePath: 'archive', - blogTitle: 'Sumo Logic Cloud SOAR Release Notes', - blogSidebarTitle: 'All posts', - blogSidebarCount: 'ALL', - postsPerPage: 'ALL', - blogDescription: 'New and enhanced Cloud SOAR features, bug fixes, changes to the application, and more.', - showReadingTime: false, - onUntruncatedBlogPosts: 'ignore', - onInlineTags: 'ignore', - onInlineAuthors: 'ignore', - feedOptions: { - type: 'rss', - xslt: true, - title: 'Sumo Logic Cloud SOAR Release Notes', - description: 'New and enhanced Cloud SOAR features, bug fixes, changes to the application, and more.', - copyright: `Copyright © ${new Date().getFullYear()} Sumo Logic`, - }, + id: 'blog-csoar', + routeBasePath: 'release-notes-csoar', + path: './blog-csoar', + archiveBasePath: 'archive', + blogTitle: 'Sumo Logic Cloud SOAR Release Notes', + blogSidebarTitle: 'All posts', + blogSidebarCount: 'ALL', + postsPerPage: 'ALL', + blogDescription: + 'New and enhanced Cloud SOAR features, bug fixes, changes to the application, and more.', + showReadingTime: false, + onUntruncatedBlogPosts: 'ignore', + onInlineTags: 'ignore', + onInlineAuthors: 'ignore', + feedOptions: { + type: 'rss', + xslt: true, + title: 'Sumo Logic Cloud SOAR Release Notes', + description: + 'New and enhanced Cloud SOAR features, bug fixes, changes to the application, and more.', + copyright: `Copyright © ${new Date().getFullYear()} Sumo Logic`, + }, }, ], - ['@docusaurus/plugin-content-blog', - { - id: 'blog-developer', - routeBasePath: 'release-notes-developer', - path: './blog-developer', - archiveBasePath: 'archive', - blogTitle: 'Sumo Logic Developer Release Notes', - blogDescription: 'The latest Sumo Logic developer features and updates to our APIs, Live Tail CLI, and more.', - blogSidebarTitle: 'All posts', - blogSidebarCount: 'ALL', - postsPerPage: 'ALL', - showReadingTime: false, - onUntruncatedBlogPosts: 'ignore', - onInlineTags: 'ignore', - onInlineAuthors: 'ignore', - feedOptions: { - type: 'rss', - xslt: true, - title: 'Sumo Logic Developer Release Notes', - description: 'The latest Sumo Logic developer features and updates to our APIs, Live Tail CLI, and more.', - copyright: `Copyright © ${new Date().getFullYear()} Sumo Logic`, - }, - }, + [ + '@docusaurus/plugin-content-blog', + { + id: 'blog-developer', + routeBasePath: 'release-notes-developer', + path: './blog-developer', + archiveBasePath: 'archive', + blogTitle: 'Sumo Logic Developer Release Notes', + blogDescription: + 'The latest Sumo Logic developer features and updates to our APIs, Live Tail CLI, and more.', + blogSidebarTitle: 'All posts', + blogSidebarCount: 'ALL', + postsPerPage: 'ALL', + showReadingTime: false, + onUntruncatedBlogPosts: 'ignore', + onInlineTags: 'ignore', + onInlineAuthors: 'ignore', + feedOptions: { + type: 'rss', + xslt: true, + title: 'Sumo Logic Developer Release Notes', + description: + 'The latest Sumo Logic developer features and updates to our APIs, Live Tail CLI, and more.', + copyright: `Copyright © ${new Date().getFullYear()} Sumo Logic`, + }, + }, ], - ['@docusaurus/plugin-content-blog', - { - id: 'blog-collector', - routeBasePath: 'release-notes-collector', - path: './blog-collector', - archiveBasePath: 'archive', - blogTitle: 'Sumo Logic Collector Release Notes', - blogSidebarTitle: 'All posts', - blogSidebarCount: 'ALL', - postsPerPage: 'ALL', - blogDescription: 'Latest features, improvements, and fixes for the Sumo Logic Installed Collector and OpenTelemetry Collector.', - showReadingTime: false, - onUntruncatedBlogPosts: 'ignore', - onInlineTags: 'ignore', - onInlineAuthors: 'ignore', - feedOptions: { - type: 'rss', - xslt: true, - title: 'Sumo Logic Collector Release Notes', - description: 'Latest features, improvements, and fixes for the Sumo Logic Installed Collector and OpenTelemetry Collector.', - copyright: `Copyright © ${new Date().getFullYear()} Sumo Logic`, - }, + [ + '@docusaurus/plugin-content-blog', + { + id: 'blog-collector', + routeBasePath: 'release-notes-collector', + path: './blog-collector', + archiveBasePath: 'archive', + blogTitle: 'Sumo Logic Collector Release Notes', + blogSidebarTitle: 'All posts', + blogSidebarCount: 'ALL', + postsPerPage: 'ALL', + blogDescription: + 'Latest features, improvements, and fixes for the Sumo Logic Installed Collector and OpenTelemetry Collector.', + showReadingTime: false, + onUntruncatedBlogPosts: 'ignore', + onInlineTags: 'ignore', + onInlineAuthors: 'ignore', + feedOptions: { + type: 'rss', + xslt: true, + title: 'Sumo Logic Collector Release Notes', + description: + 'Latest features, improvements, and fixes for the Sumo Logic Installed Collector and OpenTelemetry Collector.', + copyright: `Copyright © ${new Date().getFullYear()} Sumo Logic`, }, + }, ], - ['@docusaurus/plugin-client-redirects', + [ + '@docusaurus/plugin-client-redirects', { - redirects: Object.entries(cidRedirects).map( - ([key, value]) => ({ from: key, to: value }) - ) + redirects: Object.entries(cidRedirects).map(([key, value]) => ({ + from: key, + to: value, + })), }, ], ], - themeConfig: - ({ - docs: { - sidebar: { - hideable: true, - autoCollapseCategories: true, - }, + customFields: { + askAi: { + assistantId: 'T7pp7iENesuU', + indexName: 'crawler_sumodocs', + apiKey: 'fb2f4e1fb40f962900631121cb365549', + appId: '2SJPGMLW1Q', + suggestedQuestions: true, + }, + }, + themeConfig: { + docs: { + sidebar: { + hideable: true, + autoCollapseCategories: true, }, + }, // SEO Global Metadata metadata: [ - { name: 'keywords', content: 'sumo logic, documentation, log management, observability, cloud siem, monitoring, API, tutorials' }, + { + name: 'keywords', + content: + 'sumo logic, documentation, log management, observability, cloud siem, monitoring, API, tutorials', + }, { name: 'msvalidate.01', content: 'BA6FBE48309F6E1CFFD055E769857586' }, - { name: 'description', content: 'Sumo Logic documentation for log analytics, cloud monitoring, security, observability, and AI-powered troubleshooting. Get started guides, API references, and release notes.' }, + { + name: 'description', + content: + 'Sumo Logic documentation for log analytics, cloud monitoring, security, observability, and AI-powered troubleshooting. Get started guides, API references, and release notes.', + }, { property: 'og:site_name', content: 'Sumo Logic Docs' }, - { property: 'og:description', content: 'Sumo Logic documentation for log analytics, cloud monitoring, security, observability, and AI-powered troubleshooting. Get started guides, API references, and release notes.' }, - { property: 'og:image', content: 'https://www.sumologic.com/wp-content/uploads/meta-HomePage_1200x628-1.png' }, + { + property: 'og:description', + content: + 'Sumo Logic documentation for log analytics, cloud monitoring, security, observability, and AI-powered troubleshooting. Get started guides, API references, and release notes.', + }, + { + property: 'og:image', + content: + 'https://www.sumologic.com/wp-content/uploads/meta-HomePage_1200x628-1.png', + }, { property: 'og:image:width', content: '1200' }, { property: 'og:image:height', content: '628' }, { property: 'og:image:alt', content: 'Sumo Logic Docs' }, @@ -364,7 +402,8 @@ module.exports = { ], announcementBar: { id: 'domain', - content: 'Check out Mobot, your conversational interface for Sumo Logic. Search logs using natural language, troubleshoot faster, and get how-to guidance.', + content: + 'Check out Mobot, your conversational interface for Sumo Logic. Search logs using natural language, troubleshoot faster, and get how-to guidance.', backgroundColor: '#000', textColor: '#000', }, @@ -392,231 +431,244 @@ module.exports = { indexName: 'crawler_sumodocs', apiKey: 'fb2f4e1fb40f962900631121cb365549', appId: '2SJPGMLW1Q', + suggestedQuestions: true, }, insightsConfig: { useCookie: true, // alt to useCookie: true, }, - useCookie: true, // alt to insightsConfig: {useCookie: true,}, + useCookie: true, // alt to insightsConfig: {useCookie: true,}, }, prism: { theme: lightCodeTheme, darkTheme: darkCodeTheme, - additionalLanguages: ['csharp', 'powershell', 'java', 'markdown', 'scala', 'bash', 'diff', 'json', `sql`, `sumo`], + additionalLanguages: [ + 'csharp', + 'powershell', + 'java', + 'markdown', + 'scala', + 'bash', + 'diff', + 'json', + `sql`, + `sumo`, + ], }, - navbar: { - logo: { - alt: 'Sumo Logic logo', - srcDark: 'img/reuse/sumo-logo.svg', - src: 'img/reuse/sumo-logo-dark.svg', - }, - items: [ + navbar: { + logo: { + alt: 'Sumo Logic logo', + srcDark: 'img/reuse/sumo-logo.svg', + src: 'img/reuse/sumo-logo-dark.svg', + }, + items: [ // activeregex controls the top nav content // icon uses Google Material name code https://fonts.google.com/icons?query=material - { - label: 'Guides', - position: 'left', - to: '#', - type: 'dropdown', - items:[ - { - type: 'docSidebar', - sidebarId: 'getstarted', - label: 'Get Started', - icon: 'rocket', - }, - { - type: 'docSidebar', - sidebarId: 'senddata', - label: 'Collectors, Sources', - icon: 'settings', - }, - { - type: 'docSidebar', - sidebarId: 'searchlogs', - label: 'Log Search', - icon: 'article', - }, - { - type: 'docSidebar', - sidebarId: 'integrations', - label: 'Apps and Integrations', - icon: 'grid_view', - }, - { - type: 'docSidebar', - sidebarId: 'security', - label: 'Security', - icon: 'security', - }, - { - type: 'docSidebar', - sidebarId: 'manage', - label: 'Manage Account', - icon: 'manage_accounts', - }, - { - type: 'docSidebar', - sidebarId: 'dashboards', - label: 'Dashboards', - icon: 'dashboard', - }, - { - type: 'docSidebar', - sidebarId: 'alerts', - label: 'Alerts', - icon: 'notifications', - }, - { - type: 'docSidebar', - sidebarId: 'metricslogs', - label: 'Metrics', - icon: 'stacked_line_chart', - }, - { - type: 'docSidebar', - sidebarId: 'observability', - label: 'Observability', - icon: 'speed', - }, - { - type: 'docSidebar', - sidebarId: 'platformservices', - label: 'Platform Services', - icon: 'settings_suggest', - }, - { - type: 'docSidebar', - sidebarId: 'apm', - label: 'Traces, RUM, APM', - icon: 'account_tree', - }, - ] - }, - { - label: 'API', - position: 'left', - to: '#', - type: 'dropdown', - items:[ - { - type: 'docSidebar', - sidebarId: 'api', - label: 'API Docs', - icon: 'hub', - }, - { - label: 'API Reference', - href: 'https://api.sumologic.com/docs/', - icon: 'code', - }, - ] - }, - { - label: 'Release Notes', - position: 'left', - to: '/docs/release-notes', - }, - { - label: 'Support', - position: 'left', - to: '#', - type: 'dropdown', - items: [ - { - label: 'Contact Support', - to: 'https://support.sumologic.com/support/s', - icon: 'support', - }, - { - label: 'Request a Demo', - href: 'https://www.sumologic.com/demo', - icon: 'co_present', - }, - { - label: 'Submit Feedback', - to: 'https://github.com/SumoLogic/sumologic-documentation/issues/new/choose', - icon: 'thumbs_up_down', - }, - { - label: 'Contribute to Docs', - to: 'docs/contributing', - icon: 'edit_note', - }, - ], - }, + { + label: 'Guides', + position: 'left', + to: '#', + type: 'dropdown', + items: [ + { + type: 'docSidebar', + sidebarId: 'getstarted', + label: 'Get Started', + icon: 'rocket', + }, + { + type: 'docSidebar', + sidebarId: 'senddata', + label: 'Collectors, Sources', + icon: 'settings', + }, + { + type: 'docSidebar', + sidebarId: 'searchlogs', + label: 'Log Search', + icon: 'article', + }, + { + type: 'docSidebar', + sidebarId: 'integrations', + label: 'Apps and Integrations', + icon: 'grid_view', + }, + { + type: 'docSidebar', + sidebarId: 'security', + label: 'Security', + icon: 'security', + }, + { + type: 'docSidebar', + sidebarId: 'manage', + label: 'Manage Account', + icon: 'manage_accounts', + }, + { + type: 'docSidebar', + sidebarId: 'dashboards', + label: 'Dashboards', + icon: 'dashboard', + }, + { + type: 'docSidebar', + sidebarId: 'alerts', + label: 'Alerts', + icon: 'notifications', + }, + { + type: 'docSidebar', + sidebarId: 'metricslogs', + label: 'Metrics', + icon: 'stacked_line_chart', + }, + { + type: 'docSidebar', + sidebarId: 'observability', + label: 'Observability', + icon: 'speed', + }, + { + type: 'docSidebar', + sidebarId: 'platformservices', + label: 'Platform Services', + icon: 'settings_suggest', + }, + { + type: 'docSidebar', + sidebarId: 'apm', + label: 'Traces, RUM, APM', + icon: 'account_tree', + }, + ], + }, + { + label: 'API', + position: 'left', + to: '#', + type: 'dropdown', + items: [ + { + type: 'docSidebar', + sidebarId: 'api', + label: 'API Docs', + icon: 'hub', + }, + { + label: 'API Reference', + href: 'https://api.sumologic.com/docs/', + icon: 'code', + }, + ], + }, + { + label: 'Release Notes', + position: 'left', + to: '/docs/release-notes', + }, + { + label: 'Support', + position: 'left', + to: '#', + type: 'dropdown', + items: [ + { + label: 'Contact Support', + to: 'https://support.sumologic.com/support/s', + icon: 'support', + }, + { + label: 'Request a Demo', + href: 'https://www.sumologic.com/demo', + icon: 'co_present', + }, + { + label: 'Submit Feedback', + to: 'https://github.com/SumoLogic/sumologic-documentation/issues/new/choose', + icon: 'thumbs_up_down', + }, + { + label: 'Contribute to Docs', + to: 'docs/contributing', + icon: 'edit_note', + }, + ], + }, //{ - //className: 'header-github-link', - //to: 'https://github.com/SumoLogic/sumologic-documentation', - //position: 'right', - //alt: 'Link to Sumo Logic Docs GitHub repository', + //className: 'header-github-link', + //to: 'https://github.com/SumoLogic/sumologic-documentation', + //position: 'right', + //alt: 'Link to Sumo Logic Docs GitHub repository', //}, - { - type: 'search', - position: 'left', - }, - { - type: 'html', - position: 'left', - className: 'navbar-ask-ai-item', - value: '', - }, - ], - }, - footer: { - style: 'dark', - links: [ - { - title: 'Help', - items: [ - { - label: 'Contact support', - href: 'https://support.sumologic.com/support/s' - }, - { - label: 'Community forum', - href: 'https://support.sumologic.com/support/s/topiccatalog' }, - { - label: 'Dojo Slack community', - href: 'https://sumodojo.slack.com' - }, - ], - }, - { - title: 'Learn', - items: [ - { - label: 'Training and certifications', - href: 'https://www.sumologic.com/learn/training' - }, - { - label: 'Webinars and events', - href: 'https://www.sumologic.com/events' - }, - { - label: 'Sumo Logic blog', - href: 'https://www.sumologic.com/blog' - }, - ], - }, - { - title: 'More', - items: [ - { - label: 'Start Free Trial', - href: 'https://www.sumologic.com/sign-up/' - }, - { - label: 'Request a demo', - href: 'https://www.sumologic.com/request-demo' - }, - { - label: 'Status page', - href: 'https://status.sumologic.com' - }, - ], - }, - ], - copyright: `Copyright © ${new Date().getFullYear()} by Sumo Logic, Inc.`, - }, - }), + { + type: 'search', + position: 'left', + }, + { + type: 'html', + position: 'left', + className: 'navbar-ask-ai-item', + value: '', + }, + ], + }, + footer: { + style: 'dark', + links: [ + { + title: 'Help', + items: [ + { + label: 'Contact support', + href: 'https://support.sumologic.com/support/s', + }, + { + label: 'Community forum', + href: 'https://support.sumologic.com/support/s/topiccatalog', + }, + { + label: 'Dojo Slack community', + href: 'https://sumodojo.slack.com', + }, + ], + }, + { + title: 'Learn', + items: [ + { + label: 'Training and certifications', + href: 'https://www.sumologic.com/learn/training', + }, + { + label: 'Webinars and events', + href: 'https://www.sumologic.com/events', + }, + { + label: 'Sumo Logic blog', + href: 'https://www.sumologic.com/blog', + }, + ], + }, + { + title: 'More', + items: [ + { + label: 'Start Free Trial', + href: 'https://www.sumologic.com/sign-up/', + }, + { + label: 'Request a demo', + href: 'https://www.sumologic.com/request-demo', + }, + { + label: 'Status page', + href: 'https://status.sumologic.com', + }, + ], + }, + ], + copyright: `Copyright © ${new Date().getFullYear()} by Sumo Logic, Inc.`, + }, + }, }; diff --git a/package.json b/package.json index 76ec344233..52c566792f 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ "@babel/runtime-corejs3": "7.26.10", "@braintree/sanitize-url": "^6.0.1", "@csstools/selector-resolve-nested": "3.1.0", - "@docsearch/css": "4", + "@docsearch/core": "4.6.2", + "@docsearch/css": "4.6.2", "@docsearch/react": "4.6.2", "@docusaurus/bundler": "^3.10.1", "@docusaurus/core": "^3.10.1", diff --git a/src/components/AskAiSidepanel/index.tsx b/src/components/AskAiSidepanel/index.tsx index e1e665735f..8da728ee21 100644 --- a/src/components/AskAiSidepanel/index.tsx +++ b/src/components/AskAiSidepanel/index.tsx @@ -7,12 +7,20 @@ import './styles.css'; interface AskAiSidepanelProps { isOpen: boolean; onClose: () => void; + initialMessage?: { query: string } | null; } -export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) { +export default function AskAiSidepanel({ + isOpen, + onClose, + initialMessage, +}: AskAiSidepanelProps) { const { siteConfig } = useDocusaurusContext(); const [SidepanelComponent, setSidepanelComponent] = useState(null); const [isExpanded, setIsExpanded] = useState(false); + const [headerActionsEl, setHeaderActionsEl] = useState( + null + ); const isResizingRef = useRef(false); // Lazy load the Algolia Sidepanel component @@ -30,10 +38,15 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) const onResize = () => { isResizingRef.current = true; clearTimeout(timer); - timer = setTimeout(() => { isResizingRef.current = false; }, 500); + timer = setTimeout(() => { + isResizingRef.current = false; + }, 500); }; window.addEventListener('resize', onResize); - return () => { window.removeEventListener('resize', onResize); clearTimeout(timer); }; + return () => { + window.removeEventListener('resize', onResize); + clearTimeout(timer); + }; }, []); // Reset expanded state when panel closes @@ -62,7 +75,9 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) if (!isOpen) return; const handleResize = () => { - const container = document.querySelector('.DocSearch-Sidepanel-Container'); + const container = document.querySelector( + '.DocSearch-Sidepanel-Container' + ); if (container && !container.classList.contains('is-open')) { container.classList.add('is-open'); } @@ -91,8 +106,11 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) const ariaLabel = button.getAttribute('aria-label')?.toLowerCase() || ''; if (ariaLabel.includes('close')) return; + if (!button.classList.contains('DocSearch-Sidepanel-Action-expand')) { + return; + } - setIsExpanded(prev => !prev); + setIsExpanded((prev) => !prev); }; const checkInterval = setInterval(() => { @@ -112,13 +130,193 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) }; }, [isOpen]); + // Add visible shortcuts for Algolia actions hidden in the overflow menu. + useEffect(() => { + if (!isOpen) { + setHeaderActionsEl(null); + return; + } + + const checkInterval = setInterval(() => { + const headerRight = document.querySelector( + '.DocSearch-Sidepanel-Header--right' + ) as HTMLElement | null; + if (headerRight) { + setHeaderActionsEl(headerRight); + clearInterval(checkInterval); + } + }, 100); + + return () => { + clearInterval(checkInterval); + setHeaderActionsEl(null); + }; + }, [isOpen]); + + const triggerHeaderAction = React.useCallback((title: string) => { + const buttons = Array.from( + document.querySelectorAll( + '.DocSearch-Sidepanel-Header button' + ) + ); + const button = buttons.find( + (item) => + item.getAttribute('title') === title && + !item.classList.contains('ask-ai-shortcut-button') + ); + button?.click(); + }, []); + + const copyTextWithTextarea = React.useCallback((text: string) => { + const textarea = document.createElement('textarea'); + textarea.value = text; + textarea.setAttribute('readonly', ''); + textarea.style.position = 'fixed'; + textarea.style.opacity = '0'; + textarea.style.pointerEvents = 'none'; + document.body.appendChild(textarea); + textarea.select(); + textarea.setSelectionRange(0, text.length); + + try { + return document.execCommand('copy'); + } finally { + document.body.removeChild(textarea); + } + }, []); + + const copyTextToClipboard = React.useCallback( + (text: string) => { + const copiedWithTextarea = copyTextWithTextarea(text); + + if (navigator.clipboard?.writeText) { + navigator.clipboard.writeText(text).catch(() => { + if (!copiedWithTextarea) { + copyTextWithTextarea(text); + } + }); + } + }, + [copyTextWithTextarea] + ); + + const showCopiedState = React.useCallback((btn: HTMLButtonElement) => { + btn.classList.add('DocSearch-AskAiScreen-CopyButton--copied'); + btn.disabled = true; + setTimeout(() => { + btn.classList.remove('DocSearch-AskAiScreen-CopyButton--copied'); + btn.disabled = false; + }, 1500); + }, []); + + const getAssistantMessageText = React.useCallback((btn: HTMLElement) => { + const response = btn.closest('.DocSearch-AskAiScreen-Response'); + const assistantMessage = + btn.closest('.DocSearch-AskAiScreen-Message--assistant') || + response?.querySelector('.DocSearch-AskAiScreen-Message--assistant'); + const contentEl = assistantMessage?.querySelector( + '.DocSearch-AskAiScreen-MessageContent' + ) as HTMLElement | null; + if (!contentEl) return ''; + + const markdownBlocks = Array.from( + contentEl.querySelectorAll('.DocSearch-Markdown-Content') + ) as HTMLElement[]; + + if (markdownBlocks.length > 0) { + return markdownBlocks + .map((block) => block.innerText.trim()) + .filter(Boolean) + .join('\n\n'); + } + + const clone = contentEl.cloneNode(true) as HTMLElement; + clone + .querySelectorAll( + [ + '.DocSearch-AskAiScreen-Answer-Footer', + '.DocSearch-AskAiScreen-MessageContent-Tool', + '.DocSearch-AskAiScreen-MessageContent-Tool-Query', + '.DocSearch-AskAiScreen-MessageContent-Reasoning', + '.DocSearck-AskAiScreen-MessageContent-Stopped', + ].join(',') + ) + .forEach((el) => el.remove()); + + return clone.innerText.trim(); + }, []); + + const copyAssistantMessage = React.useCallback( + ( + btn: HTMLButtonElement, + event: Pick< + MouseEvent | React.MouseEvent, + 'preventDefault' | 'stopPropagation' + > & { nativeEvent?: MouseEvent } + ) => { + const text = getAssistantMessageText(btn); + if (!text) return false; + + event.preventDefault(); + event.stopPropagation(); + event.nativeEvent?.stopImmediatePropagation(); + if ('stopImmediatePropagation' in event) { + event.stopImmediatePropagation(); + } + + copyTextToClipboard(text); + showCopiedState(btn); + return true; + }, + [copyTextToClipboard, getAssistantMessageText, showCopiedState] + ); + + // Fix Algolia copy button bug: it can copy the first streamed text chunk + // instead of the rendered answer. Native capture catches the click before + // Algolia's own React handler writes stale content to the clipboard. + useEffect(() => { + if (!isOpen) return; + + const handleDocumentCopyClick = (event: MouseEvent) => { + const target = event.target as HTMLElement; + const btn = target.closest( + '.DocSearch-AskAiScreen-CopyButton' + ) as HTMLButtonElement | null; + if (!btn) return; + + copyAssistantMessage(btn, event); + }; + + document.addEventListener('click', handleDocumentCopyClick, true); + return () => { + document.removeEventListener('click', handleDocumentCopyClick, true); + }; + }, [copyAssistantMessage, isOpen]); + + const handleCopyCapture = React.useCallback( + (e: React.MouseEvent) => { + const target = e.target as HTMLElement; + const btn = target.closest( + '.DocSearch-AskAiScreen-CopyButton' + ) as HTMLButtonElement | null; + if (!btn) return; + + copyAssistantMessage(btn, e); + }, + [copyAssistantMessage] + ); + // Handle submit button state based on textarea content useEffect(() => { if (!isOpen) return; const updateButtonState = () => { - const textarea = document.querySelector('.DocSearch-Sidepanel-Prompt--textarea') as HTMLTextAreaElement; - const submitButton = document.querySelector('.DocSearch-Sidepanel-Prompt--submit') as HTMLButtonElement; + const textarea = document.querySelector( + '.DocSearch-Sidepanel-Prompt--textarea' + ) as HTMLTextAreaElement; + const submitButton = document.querySelector( + '.DocSearch-Sidepanel-Prompt--submit' + ) as HTMLButtonElement; if (textarea && submitButton) { if (textarea.value.trim().length > 0) { @@ -141,7 +339,9 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) }; const checkInterval = setInterval(() => { - const textarea = document.querySelector('.DocSearch-Sidepanel-Prompt--textarea') as HTMLTextAreaElement; + const textarea = document.querySelector( + '.DocSearch-Sidepanel-Prompt--textarea' + ) as HTMLTextAreaElement; if (textarea) { updateButtonState(); autoResize(textarea); @@ -153,7 +353,9 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) return () => { clearInterval(checkInterval); - const textarea = document.querySelector('.DocSearch-Sidepanel-Prompt--textarea'); + const textarea = document.querySelector( + '.DocSearch-Sidepanel-Prompt--textarea' + ); if (textarea) { textarea.removeEventListener('input', handleInput); } @@ -165,13 +367,16 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) } const algoliaConfig = (siteConfig.themeConfig as any)?.algolia; + const askAiConfig = + (siteConfig.customFields as any)?.askAi || algoliaConfig?.askAi; - if (!algoliaConfig?.askAi) { + if (!askAiConfig) { console.error('Ask AI configuration not found in docusaurus.config.js'); return null; } - const { assistantId, indexName, appId, apiKey, suggestedQuestions } = algoliaConfig.askAi; + const { assistantId, indexName, appId, apiKey, suggestedQuestions } = + askAiConfig; const handleAlgoliaClose = () => { if (!isResizingRef.current) onClose(); @@ -182,6 +387,7 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps)
{}} onClose={handleAlgoliaClose} + initialMessage={initialMessage || undefined} suggestedQuestions={suggestedQuestions} translations={{ title: 'Ask AI about Sumo Logic', placeholder: 'Ask a question about Sumo Logic...', greeting: 'How can I help you with Sumo Logic today?', - introduction: 'I can help you find information about Sumo Logic features, integrations, troubleshooting guides, APIs, and best practices across our documentation.', + introduction: + 'I can help you find information about Sumo Logic features, integrations, troubleshooting guides, APIs, and best practices across our documentation.', poweredBy: 'Powered by Algolia', }} insights />
+ {headerActionsEl && + createPortal( +
+ + +
, + headerActionsEl + )} ); diff --git a/src/components/AskAiSidepanel/styles.css b/src/components/AskAiSidepanel/styles.css index e309c83572..b481e209d8 100644 --- a/src/components/AskAiSidepanel/styles.css +++ b/src/components/AskAiSidepanel/styles.css @@ -57,10 +57,8 @@ transform: none !important; opacity: 1 !important; border-radius: 0 !important; - box-shadow: - -1px 0 0 0 rgba(0, 0, 0, 0.05), - -8px 0 32px -4px rgba(0, 0, 0, 0.12), - -16px 0 64px -8px rgba(0, 0, 0, 0.08) !important; + box-shadow: -1px 0 0 0 rgba(0, 0, 0, 0.05), + -8px 0 32px -4px rgba(0, 0, 0, 0.12), -16px 0 64px -8px rgba(0, 0, 0, 0.08) !important; animation: slideIn 0.35s cubic-bezier(0.16, 1, 0.3, 1); display: flex !important; visibility: visible !important; @@ -88,10 +86,8 @@ } [data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-Container { - box-shadow: - -1px 0 0 0 rgba(255, 255, 255, 0.08), - -8px 0 32px -4px rgba(0, 0, 0, 0.4), - -16px 0 64px -8px rgba(0, 0, 0, 0.32) !important; + box-shadow: -1px 0 0 0 rgba(255, 255, 255, 0.08), + -8px 0 32px -4px rgba(0, 0, 0, 0.4), -16px 0 64px -8px rgba(0, 0, 0, 0.32) !important; } /* Main sidepanel - integrate with Docusaurus theme */ @@ -115,24 +111,108 @@ .ask-ai-sidepanel .DocSearch-Sidepanel-Header { background-color: var(--ifm-navbar-background-color) !important; border-bottom: 1px solid var(--ifm-color-emphasis-200) !important; + display: flex !important; + justify-content: flex-start !important; + gap: 0.75rem !important; } .ask-ai-sidepanel .DocSearch-Sidepanel-Header--center { display: flex !important; flex-direction: row !important; align-items: center !important; + flex: 1 1 auto !important; gap: 0.5rem !important; + min-width: 0 !important; + position: static !important; } .ask-ai-sidepanel .DocSearch-Sidepanel-Header-TitleIcon { display: block !important; + flex: 0 0 auto !important; margin: 0 !important; } .ask-ai-sidepanel .DocSearch-Sidepanel-Title { color: var(--ifm-font-color-base) !important; + overflow: hidden !important; font-weight: 600 !important; margin: 0 !important; + min-width: 0 !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Header--right { + flex: 0 0 auto !important; + gap: 0.35rem !important; + margin-left: auto !important; + position: static !important; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Action-menu { + display: none !important; +} + +.ask-ai-sidepanel + .DocSearch-Sidepanel-Header--left + button[title='Start a new conversation'], +.ask-ai-sidepanel + .DocSearch-Sidepanel-Header--left + button[title='Conversation history'] { + display: none !important; +} + +.ask-ai-header-shortcuts { + display: flex; + align-items: center; + gap: 0.35rem; + margin-right: 0.15rem; + order: -1; +} + +.ask-ai-shortcut-button { + display: inline-flex; + align-items: center; + justify-content: center; + width: 34px; + height: 34px; + padding: 0; + border: 1px solid transparent; + border-radius: 6px; + background: transparent; + color: var(--ifm-font-color-base); + cursor: pointer; + font-family: 'Lab Grotesque', sans-serif; + font-size: 0.72rem; + font-weight: 700; + line-height: 1; +} + +.ask-ai-shortcut-button svg { + width: 19px; + height: 19px; + flex: 0 0 auto; +} + +.ask-ai-shortcut-button span { + display: none; +} + +.ask-ai-shortcut-button:hover, +.ask-ai-shortcut-button:focus-visible { + border-color: var(--ifm-color-primary); + background: var(--ifm-color-emphasis-100); + color: var(--ifm-color-primary); + outline: none; +} + +[data-theme='dark'] .ask-ai-shortcut-button { + background: transparent; +} + +[data-theme='dark'] .ask-ai-shortcut-button:hover, +[data-theme='dark'] .ask-ai-shortcut-button:focus-visible { + background: rgba(76, 134, 255, 0.14); } /* =================================================================== @@ -211,7 +291,9 @@ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(255, 255, 255, 0.1) !important; } -[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--form:focus-within { +[data-theme='dark'] + .ask-ai-sidepanel + .DocSearch-Sidepanel-Prompt--form:focus-within { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(255, 255, 255, 0.1) !important; } @@ -235,7 +317,9 @@ color: var(--ifm-color-emphasis-600) !important; } -[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--textarea::placeholder { +[data-theme='dark'] + .ask-ai-sidepanel + .DocSearch-Sidepanel-Prompt--textarea::placeholder { color: #7f8497 !important; } @@ -431,7 +515,9 @@ border-color: rgba(255, 255, 255, 0.15) !important; } -[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-SuggestedQuestion:hover { +[data-theme='dark'] + .ask-ai-sidepanel + .DocSearch-Sidepanel-SuggestedQuestion:hover { background-color: rgba(255, 255, 255, 0.15) !important; } @@ -440,7 +526,9 @@ color: var(--ifm-color-emphasis-700) !important; } -[data-theme='light'] .ask-ai-sidepanel .DocSearch-Sidepanel-SuggestedQuestion:hover { +[data-theme='light'] + .ask-ai-sidepanel + .DocSearch-Sidepanel-SuggestedQuestion:hover { border-color: var(--ifm-color-emphasis-300) !important; } @@ -453,12 +541,16 @@ } /* Hide original title and show custom text */ -.ask-ai-sidepanel .DocSearch-Sidepanel-NewConversationScreen .DocSearch-Sidepanel-Screen--title { +.ask-ai-sidepanel + .DocSearch-Sidepanel-NewConversationScreen + .DocSearch-Sidepanel-Screen--title { font-size: 0 !important; line-height: 0 !important; } -.ask-ai-sidepanel .DocSearch-Sidepanel-NewConversationScreen .DocSearch-Sidepanel-Screen--title::before { +.ask-ai-sidepanel + .DocSearch-Sidepanel-NewConversationScreen + .DocSearch-Sidepanel-Screen--title::before { font-size: 1.625rem !important; line-height: 2rem !important; content: 'How can I help you today?'; @@ -470,12 +562,16 @@ } /* Hide original introduction and show custom text */ -.ask-ai-sidepanel .DocSearch-Sidepanel-NewConversationScreen .DocSearch-Sidepanel-Screen--introduction { +.ask-ai-sidepanel + .DocSearch-Sidepanel-NewConversationScreen + .DocSearch-Sidepanel-Screen--introduction { font-size: 0 !important; line-height: 0 !important; } -.ask-ai-sidepanel .DocSearch-Sidepanel-NewConversationScreen .DocSearch-Sidepanel-Screen--introduction::before { +.ask-ai-sidepanel + .DocSearch-Sidepanel-NewConversationScreen + .DocSearch-Sidepanel-Screen--introduction::before { font-size: 0.85rem !important; line-height: 1.25rem !important; content: 'I can help you find information about Sumo Logic features, integrations, troubleshooting guides, APIs, and best practices across our documentation.'; @@ -488,12 +584,3 @@ .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--disclaimer { display: none !important; } - -/* =================================================================== - Related Sources — hidden; all sources appear as inline links in the - answer body with better context than the chips provide - =================================================================== */ -.ask-ai-sidepanel .DocSearch-AskAiScreen-RelatedSources { - display: none !important; -} - diff --git a/src/css/sumo.scss b/src/css/sumo.scss index c1d685b5e0..1223e71349 100644 --- a/src/css/sumo.scss +++ b/src/css/sumo.scss @@ -9,13 +9,14 @@ // Fonts! @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); @import url('https://fonts.googleapis.com/icon?family=Material+Icons'); -@import "api-override.css"; +@import 'api-override.css'; @font-face { font-family: 'Material Icons'; font-style: normal; font-weight: 400; - src: url(https://fonts.gstatic.com/s/materialicons/v118/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2) format('woff2'); + src: url(https://fonts.gstatic.com/s/materialicons/v118/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2) + format('woff2'); } .material-icons { @@ -36,23 +37,28 @@ @font-face { font-family: 'Lab Grotesque'; - src: url("fonts/lab-grotesque/LabGrotesque-Regular.otf") format("opentype"); } + src: url('fonts/lab-grotesque/LabGrotesque-Regular.otf') format('opentype'); +} @font-face { font-family: 'Lab Grotesque'; font-weight: bold; - src: url("fonts/lab-grotesque/LabGrotesque-Bold.otf") format("opentype"); } + src: url('fonts/lab-grotesque/LabGrotesque-Bold.otf') format('opentype'); +} @font-face { font-family: 'Lab Grotesque Light'; font-weight: normal; - src: url("fonts/lab-grotesque/LabGrotesque-Light.otf") format("opentype"); } + src: url('fonts/lab-grotesque/LabGrotesque-Light.otf') format('opentype'); +} @font-face { font-family: 'Lab Grotesque Light'; font-weight: normal; font-style: italic; - src: url("fonts/lab-grotesque/LabGrotesque-LightItalic.otf") format("opentype"); } + src: url('fonts/lab-grotesque/LabGrotesque-LightItalic.otf') + format('opentype'); +} @font-face { font-family: 'Fira Mono'; @@ -67,10 +73,10 @@ --ifm-color-primary-light: #4e89e8; --ifm-color-primary-lighter: #5a91ea; --ifm-color-primary-lightest: #80aaef; - --ifm-color-border-pale: rgba(29, 43, 69, .20); + --ifm-color-border-pale: rgba(29, 43, 69, 0.2); --ifm-code-font-size: 95%; --ifm-font-family-headings: Roboto, 'Segoe UI'; - --ifm-font-family-base: Roboto,sans-serif; + --ifm-font-family-base: Roboto, sans-serif; --ifm-menu-link-padding-horizontal: 1rem; --ifm-menu-link-padding-vertical: 0.2rem; --ifm-footer-link-hover-color: #06bcee; @@ -85,24 +91,23 @@ --ifm-h5-font-size: 0.875rem; --ifm-h6-font-size: 0.85rem; --ifm-navbar-link-hover-color: #06bcee; - --ifm-code-font-size: .85rem; - --ifm-font-family-base: "Lab Grotesque",sans-serif; - --ifm-font-family-headings: "Lab Grotesque", "Segoe UI"; - + --ifm-code-font-size: 0.85rem; + --ifm-font-family-base: 'Lab Grotesque', sans-serif; + --ifm-font-family-headings: 'Lab Grotesque', 'Segoe UI'; } .navbar__item { - font-size: .85rem; + font-size: 0.85rem; } @media (min-width: 1440px) { .container { - max-width: 97%; + max-width: 97%; } } .table-of-contents .table-of-contents__link { - font-size: .75rem !important; + font-size: 0.75rem !important; display: block; } @@ -110,15 +115,15 @@ html[data-theme='dark'] { --ifm-background-color: #101827; --ifm-navbar-background-color: #101827; --collapse-button-bg-color-dark: transparent !important; - --ifm-toc-border-color: rgba(29, 43, 69, .9); + --ifm-toc-border-color: rgba(29, 43, 69, 0.9); --ifm-code-background: #172b42; - --ifm-dropdown-background-color: #1A253B; + --ifm-dropdown-background-color: #1a253b; --ifm-footer-background-color: #1a273f; - --ifm-table-stripe-background: rgba(29, 43, 69, .50); + --ifm-table-stripe-background: rgba(29, 43, 69, 0.5); --ifm-table-head-background: rgba(0, 164, 219, 0.35); --ifm-table-border-color: rgba(59, 91, 110, 0.35); .button--secondary { - --ifm-color-emphasis-200: rgba(53, 120, 229, .25); + --ifm-color-emphasis-200: rgba(53, 120, 229, 0.25); } g { fill: var(--ifm-color-primary); @@ -131,8 +136,8 @@ html[data-theme='dark'] { } /* Index page 'smallbox' cards/tiles */ article .card { - background-color: rgb(53, 120, 229, .10); - border-color: rgba(187, 199, 218, 0.10); + background-color: rgb(53, 120, 229, 0.1); + border-color: rgba(187, 199, 218, 0.1); border-radius: 12px; h2 { font-size: 1.1rem !important; @@ -144,21 +149,20 @@ html[data-theme='dark'] { box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.6); } .docusaurus-highlight-code-line { - background-color: rgb(46, 149, 255,.2); + background-color: rgb(46, 149, 255, 0.2); } pre { background-color: rgba(84, 84, 84, 0.4) !important; - } .markdown::after { - display: none !important; + display: none !important; } .codeBlockTitle { background-color: rgba(41, 98, 155, 0.4) !important; border-bottom: 1px solid #2b5893; } .breadcrumbsItemLink_node_modules-\@docusaurus-theme-classic-lib-next-theme-DocBreadcrumbs-styles-module { - background-color: rgb(53, 120, 229, .00) !important; + background-color: rgb(53, 120, 229, 0) !important; border-radius: 0px !important; } } @@ -166,7 +170,7 @@ html[data-theme='dark'] { html[data-theme='light'] { --ifm-background-color: #fff; --ifm-navbar-background-color: #fff; - --ifm-toc-border-color: rgba(29, 43, 69, .3); + --ifm-toc-border-color: rgba(29, 43, 69, 0.3); --ifm-font-color-base: #2e2e2e; --ifm-footer-background-color: #1a273f; --ifm-menu-color: var(--ifm-font-color-base); @@ -174,7 +178,7 @@ html[data-theme='light'] { --ifm-table-head-background: rgba(0, 139, 178, 0.397); --ifm-table-border-color: rgba(25, 43, 54, 0.35); .button--secondary { - --ifm-button-border-color: rgba(53, 120, 229, .25); + --ifm-button-border-color: rgba(53, 120, 229, 0.25); } g { fill: var(--ifm-color-primary); @@ -197,24 +201,23 @@ html[data-theme='light'] { } } article .card:hover { - border-color: var(--ifm-pagination-nav-color-hover); + border-color: var(--ifm-pagination-nav-color-hover); } .theme-code-block-highlighted-line { background-color: var(--ifm-table-head-background); } .docusaurus-highlight-code-line { - background-color: rgb(0, 139, 178,.1); + background-color: rgb(0, 139, 178, 0.1); } pre { background-color: rgba(242 244 245) !important; - } .codeBlockTitle { background-color: rgba(0, 139, 178, 0.4) !important; border-bottom: 1px solid #0095bd; } .markdown::after { - display: none !important; + display: none !important; } .breadcrumbsItemLink_node_modules-\@docusaurus-theme-classic-lib-next-theme-DocBreadcrumbs-styles-module { background-color: transparent !important; @@ -223,11 +226,11 @@ html[data-theme='light'] { } .medium-zoom-overlay { - background:rgba(0, 0, 0, 0.6) !important; + background: rgba(0, 0, 0, 0.6) !important; } .DocSearch-Button-Placeholder { - font-size: .85rem !important; + font-size: 0.85rem !important; min-width: 100px; } @@ -253,6 +256,58 @@ html[data-theme='dark'] .DocSearch-Search-Icon { padding-right: 65px !important; } +.ask-ai-search-sidepanel-button { + align-items: center; + background: var(--docsearch-hit-background); + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 6px; + color: var(--docsearch-hit-color); + cursor: pointer; + display: grid; + font: inherit; + gap: 0.25rem 0.75rem; + grid-template-columns: auto minmax(0, max-content) minmax(0, 1fr); + line-height: 1.25; + margin: 0 0 0.75rem; + padding: 0.75rem 1rem; + text-align: left; + width: 100%; +} + +.ask-ai-search-sidepanel-button:hover, +.ask-ai-search-sidepanel-button:focus-visible { + background: var(--docsearch-hit-highlight-color); + border-color: var(--ifm-color-primary); + outline: none; +} + +.ask-ai-search-sidepanel-button-icon { + color: var(--ifm-color-primary); + display: inline-flex; + grid-row: 1 / span 2; +} + +.ask-ai-search-sidepanel-button-label { + font-size: 0.9rem; + font-weight: 700; +} + +.ask-ai-search-sidepanel-button-query { + color: var(--ifm-color-emphasis-700); + font-size: 0.8rem; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +html[data-theme='dark'] .ask-ai-search-sidepanel-button { + border-color: var(--ifm-color-emphasis-300); +} + +.ask-ai-native-modal-option-hidden { + display: none !important; +} + //GitHub icon .header-github-link:hover { opacity: 0.6; @@ -269,8 +324,8 @@ html[data-theme='dark'] .DocSearch-Search-Icon { } .header-github-link::after { - display: none !important; - content: none !important; + display: none !important; + content: none !important; } [data-theme='dark'] .header-github-link::before { @@ -366,8 +421,6 @@ html[data-theme='dark'] .DocSearch-Search-Icon { margin-right: 8px; } - - //Free Trial nav button .header-trial:hover { opacity: 0.85; @@ -375,19 +428,19 @@ html[data-theme='dark'] .DocSearch-Search-Icon { .header-trial::before { content: 'Start free trial'; - border: .5px solid #0466FF; - color: #FFF; + border: 0.5px solid #0466ff; + color: #fff; border-radius: 3px; padding: 5px 15px; font-size: 13px; font-weight: 600; display: inline-flex; - background: linear-gradient(35deg,#0466FF 0%,#0800FF 100%); + background: linear-gradient(35deg, #0466ff 0%, #0800ff 100%); margin-left: -10px; margin-right: -10px; } -div[class*="announcementBar_"] { +div[class*='announcementBar_'] { background: linear-gradient( to right, #6e9ffb 0%, @@ -399,14 +452,14 @@ div[class*="announcementBar_"] { } .header-trial::after { - display: none !important; - content: none !important; + display: none !important; + content: none !important; } [data-theme='dark'] .header-trial::before { background: transparent; - border: .5px solid #0466FF; - color: #FFF; + border: 0.5px solid #0466ff; + color: #fff; border-radius: 3px; padding: 5px 15px; font-size: 13px; @@ -414,11 +467,11 @@ div[class*="announcementBar_"] { display: inline-flex; margin-left: -10px; margin-right: -10px; - background: linear-gradient(35deg, #0466FF 0%, #0800FF 30%, #000099 100%); + background: linear-gradient(35deg, #0466ff 0%, #0800ff 30%, #000099 100%); } [data-theme='light'] .header-trial::before { - border: .5px solid #0466FF; + border: 0.5px solid #0466ff; } .markdown { h1 { @@ -434,7 +487,7 @@ div[class*="announcementBar_"] { font-size: 1.1rem !important; } h5 { - font-size: .9rem !important; + font-size: 0.9rem !important; } } @@ -456,7 +509,7 @@ div[class*="announcementBar_"] { padding: 0px 0px; } .menu__link { - font-size: .8rem; + font-size: 0.8rem; line-height: normal; } @@ -465,9 +518,9 @@ div[class*="announcementBar_"] { text-transform: none; } .menu__link { - font-size: .8rem; + font-size: 0.8rem; //justify-content: normal !important; - padding: var(--ifm-menu-link-padding-vertical) .3rem; + padding: var(--ifm-menu-link-padding-vertical) 0.3rem; line-height: normal; } @@ -481,17 +534,17 @@ div[class*="announcementBar_"] { } .menu__caret:before { - content: ''; - background: var(--ifm-menu-link-sublist-icon) 50% / 2rem 2rem; - filter: var(--ifm-menu-link-sublist-icon-filter); - height: 1.25rem; - // Default chevron is already right/left — no extra rotation needed (was: transform: rotate(180deg);) - width: 1.25rem; - transition: transform var(--ifm-transition-fast) linear; + content: ''; + background: var(--ifm-menu-link-sublist-icon) 50% / 2rem 2rem; + filter: var(--ifm-menu-link-sublist-icon-filter); + height: 1.25rem; + // Default chevron is already right/left — no extra rotation needed (was: transform: rotate(180deg);) + width: 1.25rem; + transition: transform var(--ifm-transition-fast) linear; } .menu__link--sublist:after { - height:auto; + height: auto; } // code highlights @@ -532,7 +585,7 @@ html[data-theme='light'] .table-of-contents__left-border { margin-left: -27px; padding-left: 23px; border-left: 4px solid; - } + } } } @@ -603,7 +656,7 @@ html[data-theme='light'] .table-of-contents__left-border { .navbar-grid-menu:after { transition: opacity 0.2s; - content: ""; + content: ''; width: 24px; height: 24px; display: flex; @@ -624,9 +677,9 @@ html[data-theme='light'] .table-of-contents__left-border { // Responsive @media screen and (max-width: 996px) { - - .navbar-grid-menu, .navbar-grid-menu:before { - content: "Community"; + .navbar-grid-menu, + .navbar-grid-menu:before { + content: 'Community'; background-image: none; margin-right: -10px; } @@ -635,56 +688,51 @@ html[data-theme='light'] .table-of-contents__left-border { } } - .docItemCol_node_modules-\@docusaurus-theme-classic-lib-next-theme-DocItem-styles-module { - max-width: 100% !important; - } - + max-width: 100% !important; +} // Horizontal rule .horizontal-rule { - border-top: .5px solid white; + border-top: 0.5px solid white; border-radius: 1px; } - //Get Started button - homepage, 404 not found - - .homepage { background-color: #1976d2; color: white; padding: 8px 10px; font-weight: 300; font-size: 14px; -// filter: drop-shadow(-1px 2px 2px #64696C); + // filter: drop-shadow(-1px 2px 2px #64696C); text-decoration: none; - border: .5px solid #1976d2; + border: 0.5px solid #1976d2; border-radius: 4px; margin-right: 5px; margin-bottom: 10px; transition: 0.5s; cursor: pointer; a { - color: #F1F1F1; + color: #f1f1f1; text-decoration: none; } a:hover { - color: #0046BE; + color: #0046be; } } .homepage:hover { background-color: #094cbf; - color: #F1F1F1; + color: #f1f1f1; padding: 8px 10px; font-weight: 300; font-size: 14px; transition: 0.5s; text-decoration: none; - border: .5px solid #000; + border: 0.5px solid #000; cursor: pointer; a { color: white; @@ -707,7 +755,6 @@ html[data-theme='light'] .table-of-contents__left-border { margin-bottom: 5px; } - @media screen and (max-width: 996px) { .homepage { margin-right: 50px; @@ -720,9 +767,6 @@ html[data-theme='light'] .table-of-contents__left-border { } } - - - // Admonitions .alert { border-radius: 6; @@ -755,7 +799,7 @@ html[data-theme='light'] .alert--secondary { background-color: #fdfdfe; --ifm-alert-color: #474748; --ifm-alert-border-color: #d4d5d8; - border-left: 6px solid #8C9296; + border-left: 6px solid #8c9296; border-right: 1px solid #d4d5d8; border-top: 1px solid #d4d5d8; border-bottom: 1px solid #d4d5d8; @@ -787,7 +831,7 @@ html[data-theme='dark'] .theme-admonition-sumo { padding: 5px 5px 0px 5px; } a { - // font-weight: bold; + // font-weight: bold; color: #2f5fff; text-decoration: none; } @@ -840,7 +884,6 @@ html[data-theme='dark'] .theme-admonition-training { } } - html[data-theme='light'] .theme-admonition-training { background-color: rgba(112, 0, 162, 0.05); --ifm-alert-border-color: #7000a2; @@ -1019,8 +1062,8 @@ html[data-theme='light'] .edgePath .path { } html[data-theme='light'] .node rect { - stroke: #2196F3 !important; - fill: #E1F4FD !important; + stroke: #2196f3 !important; + fill: #e1f4fd !important; } html[data-theme='light'] .label { @@ -1028,34 +1071,34 @@ html[data-theme='light'] .label { } html[data-theme='light'] .node circle { - stroke: #2196F3 !important; - fill: #E1F4FD !important; + stroke: #2196f3 !important; + fill: #e1f4fd !important; } -html[data-theme='light'] .node ellipse{ - stroke: #2196F3 !important; - fill: #E1F4FD !important; +html[data-theme='light'] .node ellipse { + stroke: #2196f3 !important; + fill: #e1f4fd !important; } html[data-theme='light'] .node polygon { - stroke: #2196F3 !important; - fill: #E1F4FD !important; + stroke: #2196f3 !important; + fill: #e1f4fd !important; } html[data-theme='dark'] .node rect { - stroke: #2196F3 !important; + stroke: #2196f3 !important; } html[data-theme='dark'] .node circle { - stroke: #2196F3 !important; + stroke: #2196f3 !important; } -html[data-theme='dark'] .node ellipse{ - stroke: #2196F3 !important; +html[data-theme='dark'] .node ellipse { + stroke: #2196f3 !important; } html[data-theme='dark'] .node polygon { - stroke: #2196F3 !important; + stroke: #2196f3 !important; } // reduce width of wide tables @@ -1125,8 +1168,7 @@ html[data-theme='dark'] .node polygon { .box7 img, .box8 img, .box9 img, -.box10 img -.boxwidetop img { +.box10 img .boxwidetop img { margin-top: 16px; } @@ -1134,70 +1176,70 @@ html[data-theme='dark'] .node polygon { grid-column: 1; grid-row: 1; padding: 4px; - font-size: .9rem; + font-size: 0.9rem; } .box2 { grid-column: 2; grid-row: 1; padding: 4px; - font-size: .9rem; + font-size: 0.9rem; } .box3 { grid-column: 3; grid-row: 1; padding: 4px; - font-size: .9rem; + font-size: 0.9rem; } .box4 { grid-column: 1; grid-row: 2; padding: 4px; - font-size: .9rem; + font-size: 0.9rem; } .box5 { grid-column: 2; grid-row: 2; padding: 4px; - font-size: .9rem; + font-size: 0.9rem; } .box6 { grid-column: 3; grid-row: 2; padding: 4px; - font-size: .9rem; + font-size: 0.9rem; } .box7 { grid-column: 1; grid-row: 3; padding: 4px; - font-size: .9rem; + font-size: 0.9rem; } .box8 { grid-column: 2; grid-row: 3; padding: 4px; - font-size: .9rem; + font-size: 0.9rem; } .box9 { grid-column: 3; grid-row: 3; padding: 4px; - font-size: .9rem; + font-size: 0.9rem; } .box10 { grid-column: 1; grid-row: 4; padding: 4px; - font-size: .9rem; + font-size: 0.9rem; } .boxwidetop { @@ -1223,7 +1265,7 @@ html[data-theme='dark'] .node polygon { grid-row: 1; padding: 1px; width: 225px !important; - font-size: .9rem; + font-size: 0.9rem; } /* Vertical padding */ @@ -1272,7 +1314,8 @@ html[data-theme='dark'] .card:hover { max-width: var(--ifm-container-width); } -.container-landpage, .container-reverse { +.container-landpage, +.container-reverse { padding: 1rem; margin: 3%; display: flex; @@ -1292,9 +1335,6 @@ html[data-theme='dark'] .card:hover { width: 80%; } - - - // ******* MEGA AND MORE ********* .dropdown__label { @@ -1306,7 +1346,7 @@ html[data-theme='dark'] .card:hover { } .dropdown__link { - font-size: .9rem !important; + font-size: 0.9rem !important; margin-top: 0; } @@ -1319,7 +1359,6 @@ html[data-theme='dark'] .card:hover { max-height: 100vh; } - .dropdown__menu--mega { padding: calc(var(--ifm-navbar-padding-vertical) + 1rem) var(--ifm-navbar-padding-horizontal) !important; @@ -1351,9 +1390,8 @@ html[data-theme='dark'] .card:hover { background: var(--ifm-color-emphasis-200); } - .padding-vert--xl { - padding-bottom: .1rem !important; + padding-bottom: 0.1rem !important; padding-top: 5rem !important; } @@ -1396,7 +1434,7 @@ html[data-theme='dark'] .card:hover { .video-container { overflow: hidden; position: relative; - width:100%; + width: 100%; } .video-container::after { @@ -1426,7 +1464,6 @@ html[data-theme='dark'] .card:hover { max-width: 300px; } - .land-feature { display: inline-flex; align-items: center; @@ -1444,7 +1481,7 @@ html[data-theme='dark'] .card:hover { .land-desc { max-height: 100px; - font-size: .95rem; + font-size: 0.95rem; } .land-image { @@ -1459,7 +1496,8 @@ html[data-theme='dark'] .featureImage { .land-link a { color: var(--ifm-font-base-color); text-decoration: none; - transition: color var(--ifm-transition-fast) var(--ifm-transition-timing-default); + transition: color var(--ifm-transition-fast) + var(--ifm-transition-timing-default); :hover { color: var(--ifm-font-base-color); } @@ -1474,17 +1512,16 @@ html[data-theme='dark'] .featureImage { } @media screen and (max-width: 996px) { - .land-box, .highlight-box { + .land-box, + .highlight-box { height: auto; } .nav-break { border-top: 1px solid rgb(156, 156, 156); border-left: 0px; } - } - // Blog Styles .title_node_modules-\@docusaurus-theme-classic-lib-theme-BlogPostItem-Header-Title-styles-module { @@ -1492,17 +1529,17 @@ html[data-theme='dark'] .featureImage { } .sidebarItemLink_node_modules-\@docusaurus-theme-classic-lib-theme-BlogSidebar-Desktop-styles-module { - font-size: .75rem !important; + font-size: 0.75rem !important; } - .sidebarItemTitle_node_modules-\@docusaurus-theme-classic-lib-theme-BlogSidebar-Desktop-styles-module { font-size: 1.2rem !important; padding: 0 !important; } /* Force smaller font size on blog post titles */ -article header h1, article header h2 { +article header h1, +article header h2 { font-size: 1.5rem !important; } @@ -1512,7 +1549,7 @@ article header h2[class*='title_'] { } .sidebarItem__DBe { - font-size: .75rem !important; + font-size: 0.75rem !important; padding: 0 !important; } @@ -1521,10 +1558,9 @@ article header h2[class*='title_'] { // font-size: .75rem !important; //} - //Blog Author .avatar__name { - font-size: .9rem !important; + font-size: 0.9rem !important; } .margin-bottom--blog { @@ -1536,9 +1572,6 @@ article header h2[class*='title_'] { color: var(--subtle); } - - - // Sumo badges - Preview types (muted Secondary Teal palette) .preview-private { @@ -1600,7 +1633,7 @@ article header h2[class*='title_'] { padding-bottom: calc(49.38% + 27px); width: 100%; height: 100%; -//transform: scale(1); + //transform: scale(1); } .sl-demo { @@ -1612,9 +1645,6 @@ article header h2[class*='title_'] { border: none; } - - - /* The container */ .label-container { display: block; @@ -1654,12 +1684,12 @@ article header h2[class*='title_'] { /* When the checkbox is checked, add a blue background */ .label-container input:checked ~ .checkmark { - background-color: #007E33; + background-color: #007e33; } /* Create the checkmark/indicator (hidden when not checked) */ .checkmark:after { - content: ""; + content: ''; position: absolute; display: none; } @@ -1709,52 +1739,70 @@ article header h2[class*='title_'] { /* Light mode */ [data-theme='light'] .language-sumo { /* keywords: pipe operators, reserved words — Sumo Blue */ - --sumo-keyword: #000099; + --sumo-keyword: #000099; /* strings: quoted values — Sumo Teal */ - --sumo-string: #007A99; + --sumo-string: #007a99; /* urls: path://, asn://, https:// — Light Teal (slightly brighter than strings) */ - --sumo-url: #0099AA; + --sumo-url: #0099aa; /* metadata: _sourceCategory, _source etc. — Sumo Purple */ - --sumo-metadata: #6600CC; + --sumo-metadata: #6600cc; /* functions: anything called with () — CTA Blue */ - --sumo-function: #0444FF; + --sumo-function: #0444ff; /* numbers and time units — Dark Teal */ - --sumo-number: #005F73; + --sumo-number: #005f73; /* operators: | = , * — neutral mid-gray */ --sumo-operator: #555555; /* regex patterns — Vivid Teal */ - --sumo-regex: #008080; + --sumo-regex: #008080; } /* Dark mode */ [data-theme='dark'] .language-sumo { /* keywords — Light Blue (readable on dark bg) */ - --sumo-keyword: #4480FF; + --sumo-keyword: #4480ff; /* strings — Light Teal */ - --sumo-string: #00C8D7; + --sumo-string: #00c8d7; /* urls — slightly brighter teal */ - --sumo-url: #00E5E5; + --sumo-url: #00e5e5; /* metadata — Vivid Purple */ - --sumo-metadata: #C440FF; + --sumo-metadata: #c440ff; /* functions — CTA Blue brightened for dark */ - --sumo-function: #4499FF; + --sumo-function: #4499ff; /* numbers and time units — Muted Teal */ - --sumo-number: #66CCCC; + --sumo-number: #66cccc; /* operators — light gray */ - --sumo-operator: #AAAAAA; + --sumo-operator: #aaaaaa; /* regex patterns — Vivid Teal */ - --sumo-regex: #00CCCC; + --sumo-regex: #00cccc; } /* Apply variables to Prism token classes, scoped to sumo language only */ /* Reset Dracula dark theme italic bleed-through */ -.language-sumo .token { font-style: normal !important; } -.language-sumo .token.keyword { color: var(--sumo-keyword); } -.language-sumo .token.string { color: var(--sumo-string); } -.language-sumo .token.url { color: var(--sumo-url); } -.language-sumo .token.metadata { color: var(--sumo-metadata); } -.language-sumo .token.function { color: var(--sumo-function); } +.language-sumo .token { + font-style: normal !important; +} +.language-sumo .token.keyword { + color: var(--sumo-keyword); +} +.language-sumo .token.string { + color: var(--sumo-string); +} +.language-sumo .token.url { + color: var(--sumo-url); +} +.language-sumo .token.metadata { + color: var(--sumo-metadata); +} +.language-sumo .token.function { + color: var(--sumo-function); +} .language-sumo .token.number, -.language-sumo .token.time { color: var(--sumo-number); } -.language-sumo .token.operator { color: var(--sumo-operator); } -.language-sumo .token.regex { color: var(--sumo-regex); } +.language-sumo .token.time { + color: var(--sumo-number); +} +.language-sumo .token.operator { + color: var(--sumo-operator); +} +.language-sumo .token.regex { + color: var(--sumo-regex); +} diff --git a/src/theme/Root.tsx b/src/theme/Root.tsx index 0fdb1396aa..1574a90567 100644 --- a/src/theme/Root.tsx +++ b/src/theme/Root.tsx @@ -10,16 +10,24 @@ import React, { useEffect, useState, Suspense } from 'react'; import { createPortal } from 'react-dom'; import AskAiButton from '@site/src/components/AskAiButton'; -const AskAiSidepanel = React.lazy(() => import('@site/src/components/AskAiSidepanel')); +const AskAiSidepanel = React.lazy( + () => import('@site/src/components/AskAiSidepanel') +); interface RootProps { children: React.ReactNode; } +interface AskAiInitialMessage { + query: string; +} + export default function Root({ children }: RootProps) { const [placeholder, setPlaceholder] = useState(null); const [isAskAiOpen, setIsAskAiOpen] = useState(false); const [hasEverOpened, setHasEverOpened] = useState(false); + const [initialAskAiMessage, setInitialAskAiMessage] = + useState(null); useEffect(() => { if (isAskAiOpen) setHasEverOpened(true); @@ -43,21 +51,187 @@ export default function Root({ children }: RootProps) { return () => clearInterval(interval); }, [placeholder]); + useEffect(() => { + const openAskAiFromSearch = (query: string) => { + const trimmedQuery = query.trim(); + if (!trimmedQuery) return; + + setInitialAskAiMessage({ query: trimmedQuery }); + setIsAskAiOpen(true); + + const closeButton = document.querySelector( + [ + '.DocSearch-Container button[aria-label="Close"]', + '.DocSearch-Container button[title="Close"]', + '.DocSearch-Container .DocSearch-Cancel', + ].join(',') + ); + closeButton?.click(); + }; + + const getDocSearchQuery = () => { + return ( + document + .querySelector( + '.DocSearch-Container .DocSearch-Input' + ) + ?.value.trim() || '' + ); + }; + + const routeModalAskAiClick = (event: MouseEvent) => { + const target = event.target as HTMLElement | null; + const container = target?.closest('.DocSearch-Container'); + if (!target || !container) return; + + if (target.closest('.ask-ai-search-sidepanel-button')) { + const query = getDocSearchQuery(); + if (!query) return; + + event.preventDefault(); + event.stopPropagation(); + event.stopImmediatePropagation(); + openAskAiFromSearch(query); + return; + } + + const clickable = target.closest( + [ + 'button', + 'a', + '[role="button"]', + '.DocSearch-Hit', + '.DocSearch-Menu-item', + ].join(',') + ); + if (!clickable) return; + + const actionText = [ + clickable.textContent, + clickable.getAttribute('aria-label'), + clickable.getAttribute('title'), + clickable.getAttribute('class'), + ] + .filter(Boolean) + .join(' ') + .toLowerCase(); + + if (!actionText.includes('ask ai')) return; + + const query = getDocSearchQuery(); + if (!query) return; + + event.preventDefault(); + event.stopPropagation(); + event.stopImmediatePropagation(); + openAskAiFromSearch(query); + }; + + const updateSearchHandoff = () => { + const container = document.querySelector('.DocSearch-Container'); + const dropdown = container?.querySelector('.DocSearch-Dropdown'); + const input = + container?.querySelector('.DocSearch-Input'); + + if (!container || !dropdown || !input) return; + + const query = input.value.trim(); + const existingButton = dropdown.querySelector( + '.ask-ai-search-sidepanel-button' + ); + const nativeAskAiOptions = dropdown.querySelectorAll( + [ + '.DocSearch-Hit', + '.DocSearch-Menu-item', + 'button', + 'a', + '[role="button"]', + '[role="option"]', + ].join(',') + ); + + nativeAskAiOptions.forEach((option) => { + if (option.closest('.ask-ai-search-sidepanel-button')) return; + + const text = option.textContent?.replace(/\s+/g, ' ').trim() || ''; + if (/^Ask AI\s*:/i.test(text)) { + option.classList.add('ask-ai-native-modal-option-hidden'); + } + }); + + if (!query) { + existingButton?.remove(); + return; + } + + const button = existingButton || document.createElement('button'); + + if (!existingButton) { + button.type = 'button'; + button.className = 'ask-ai-search-sidepanel-button'; + button.innerHTML = ` + + Ask AI in sidepanel + + `; + button.onclick = () => openAskAiFromSearch(input.value); + } + + if (button.dataset.query === query) { + return; + } + + button.dataset.query = query; + button.setAttribute('aria-label', `Ask AI in sidepanel for ${query}`); + + const queryEl = button.querySelector( + '.ask-ai-search-sidepanel-button-query' + ); + if (queryEl) { + queryEl.textContent = query; + } + + if (!existingButton) { + dropdown.prepend(button); + } + }; + + document.addEventListener('input', updateSearchHandoff, true); + document.addEventListener('click', routeModalAskAiClick, true); + const observer = new MutationObserver(updateSearchHandoff); + observer.observe(document.body, { childList: true, subtree: true }); + + return () => { + document.removeEventListener('input', updateSearchHandoff, true); + document.removeEventListener('click', routeModalAskAiClick, true); + observer.disconnect(); + }; + }, []); + return ( <> {children} {/* Button only — portaled into the navbar */} - {placeholder && createPortal( - , - placeholder - )} + {placeholder && + createPortal( + , + placeholder + )} {/* Sidepanel lives here in Root, never inside the navbar portal. Kept mounted once first opened so conversation state survives resize. */} {hasEverOpened && ( - setIsAskAiOpen(false)} /> + setIsAskAiOpen(false)} + initialMessage={initialAskAiMessage} + /> )} diff --git a/yarn.lock b/yarn.lock index a7df744028..3e2b53f7c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1849,11 +1849,6 @@ resolved "https://registry.yarnpkg.com/@docsearch/core/-/core-4.6.2.tgz#0a6fdc13b1eb12153cb19316f911479b67f7bd58" integrity sha512-/S0e6Dj7Zcm8m9Rru49YEX49dhU11be68c+S/BCyN8zQsTTgkKzXlhRbVL5mV6lOLC2+ZRRryaTdcm070Ug2oA== -"@docsearch/css@4": - version "4.5.3" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-4.5.3.tgz#359930bc8435976c574655adc9bb0574d8887a70" - integrity sha512-kUpHaxn0AgI3LQfyzTYkNUuaFY4uEz/Ym9/N/FvyDE+PzSgZsCyDH9jE49B6N6f1eLCm9Yp64J9wENd6vypdxA== - "@docsearch/css@4.6.2": version "4.6.2" resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-4.6.2.tgz#986776619dccbf798176c75e858cc22f5e710bb4" From b48bddeebd3fb9cd0df675bbf6d1fd1a4acbb18b Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Tue, 16 Jun 2026 02:38:43 -0700 Subject: [PATCH 31/40] DOCS-1162 - Ask AI: copy button fix, search-to-sidepanel handoff, UI improvements Co-Authored-By: Claude Sonnet 4.6 --- docusaurus.config.js | 1 + package.json | 3 +- src/components/AskAiSidepanel/index.tsx | 282 ++++++++++++++++++++++- src/components/AskAiSidepanel/styles.css | 137 +++++++++-- src/css/sumo.scss | 52 +++++ src/theme/Root.tsx | 186 ++++++++++++++- yarn.lock | 5 - 7 files changed, 617 insertions(+), 49 deletions(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index 08386aba94..1c9fa3d1d9 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -392,6 +392,7 @@ module.exports = { indexName: 'crawler_sumodocs', apiKey: 'fb2f4e1fb40f962900631121cb365549', appId: '2SJPGMLW1Q', + suggestedQuestions: true, }, insightsConfig: { useCookie: true, // alt to useCookie: true, diff --git a/package.json b/package.json index 76ec344233..52c566792f 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ "@babel/runtime-corejs3": "7.26.10", "@braintree/sanitize-url": "^6.0.1", "@csstools/selector-resolve-nested": "3.1.0", - "@docsearch/css": "4", + "@docsearch/core": "4.6.2", + "@docsearch/css": "4.6.2", "@docsearch/react": "4.6.2", "@docusaurus/bundler": "^3.10.1", "@docusaurus/core": "^3.10.1", diff --git a/src/components/AskAiSidepanel/index.tsx b/src/components/AskAiSidepanel/index.tsx index e1e665735f..8da728ee21 100644 --- a/src/components/AskAiSidepanel/index.tsx +++ b/src/components/AskAiSidepanel/index.tsx @@ -7,12 +7,20 @@ import './styles.css'; interface AskAiSidepanelProps { isOpen: boolean; onClose: () => void; + initialMessage?: { query: string } | null; } -export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) { +export default function AskAiSidepanel({ + isOpen, + onClose, + initialMessage, +}: AskAiSidepanelProps) { const { siteConfig } = useDocusaurusContext(); const [SidepanelComponent, setSidepanelComponent] = useState(null); const [isExpanded, setIsExpanded] = useState(false); + const [headerActionsEl, setHeaderActionsEl] = useState( + null + ); const isResizingRef = useRef(false); // Lazy load the Algolia Sidepanel component @@ -30,10 +38,15 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) const onResize = () => { isResizingRef.current = true; clearTimeout(timer); - timer = setTimeout(() => { isResizingRef.current = false; }, 500); + timer = setTimeout(() => { + isResizingRef.current = false; + }, 500); }; window.addEventListener('resize', onResize); - return () => { window.removeEventListener('resize', onResize); clearTimeout(timer); }; + return () => { + window.removeEventListener('resize', onResize); + clearTimeout(timer); + }; }, []); // Reset expanded state when panel closes @@ -62,7 +75,9 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) if (!isOpen) return; const handleResize = () => { - const container = document.querySelector('.DocSearch-Sidepanel-Container'); + const container = document.querySelector( + '.DocSearch-Sidepanel-Container' + ); if (container && !container.classList.contains('is-open')) { container.classList.add('is-open'); } @@ -91,8 +106,11 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) const ariaLabel = button.getAttribute('aria-label')?.toLowerCase() || ''; if (ariaLabel.includes('close')) return; + if (!button.classList.contains('DocSearch-Sidepanel-Action-expand')) { + return; + } - setIsExpanded(prev => !prev); + setIsExpanded((prev) => !prev); }; const checkInterval = setInterval(() => { @@ -112,13 +130,193 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) }; }, [isOpen]); + // Add visible shortcuts for Algolia actions hidden in the overflow menu. + useEffect(() => { + if (!isOpen) { + setHeaderActionsEl(null); + return; + } + + const checkInterval = setInterval(() => { + const headerRight = document.querySelector( + '.DocSearch-Sidepanel-Header--right' + ) as HTMLElement | null; + if (headerRight) { + setHeaderActionsEl(headerRight); + clearInterval(checkInterval); + } + }, 100); + + return () => { + clearInterval(checkInterval); + setHeaderActionsEl(null); + }; + }, [isOpen]); + + const triggerHeaderAction = React.useCallback((title: string) => { + const buttons = Array.from( + document.querySelectorAll( + '.DocSearch-Sidepanel-Header button' + ) + ); + const button = buttons.find( + (item) => + item.getAttribute('title') === title && + !item.classList.contains('ask-ai-shortcut-button') + ); + button?.click(); + }, []); + + const copyTextWithTextarea = React.useCallback((text: string) => { + const textarea = document.createElement('textarea'); + textarea.value = text; + textarea.setAttribute('readonly', ''); + textarea.style.position = 'fixed'; + textarea.style.opacity = '0'; + textarea.style.pointerEvents = 'none'; + document.body.appendChild(textarea); + textarea.select(); + textarea.setSelectionRange(0, text.length); + + try { + return document.execCommand('copy'); + } finally { + document.body.removeChild(textarea); + } + }, []); + + const copyTextToClipboard = React.useCallback( + (text: string) => { + const copiedWithTextarea = copyTextWithTextarea(text); + + if (navigator.clipboard?.writeText) { + navigator.clipboard.writeText(text).catch(() => { + if (!copiedWithTextarea) { + copyTextWithTextarea(text); + } + }); + } + }, + [copyTextWithTextarea] + ); + + const showCopiedState = React.useCallback((btn: HTMLButtonElement) => { + btn.classList.add('DocSearch-AskAiScreen-CopyButton--copied'); + btn.disabled = true; + setTimeout(() => { + btn.classList.remove('DocSearch-AskAiScreen-CopyButton--copied'); + btn.disabled = false; + }, 1500); + }, []); + + const getAssistantMessageText = React.useCallback((btn: HTMLElement) => { + const response = btn.closest('.DocSearch-AskAiScreen-Response'); + const assistantMessage = + btn.closest('.DocSearch-AskAiScreen-Message--assistant') || + response?.querySelector('.DocSearch-AskAiScreen-Message--assistant'); + const contentEl = assistantMessage?.querySelector( + '.DocSearch-AskAiScreen-MessageContent' + ) as HTMLElement | null; + if (!contentEl) return ''; + + const markdownBlocks = Array.from( + contentEl.querySelectorAll('.DocSearch-Markdown-Content') + ) as HTMLElement[]; + + if (markdownBlocks.length > 0) { + return markdownBlocks + .map((block) => block.innerText.trim()) + .filter(Boolean) + .join('\n\n'); + } + + const clone = contentEl.cloneNode(true) as HTMLElement; + clone + .querySelectorAll( + [ + '.DocSearch-AskAiScreen-Answer-Footer', + '.DocSearch-AskAiScreen-MessageContent-Tool', + '.DocSearch-AskAiScreen-MessageContent-Tool-Query', + '.DocSearch-AskAiScreen-MessageContent-Reasoning', + '.DocSearck-AskAiScreen-MessageContent-Stopped', + ].join(',') + ) + .forEach((el) => el.remove()); + + return clone.innerText.trim(); + }, []); + + const copyAssistantMessage = React.useCallback( + ( + btn: HTMLButtonElement, + event: Pick< + MouseEvent | React.MouseEvent, + 'preventDefault' | 'stopPropagation' + > & { nativeEvent?: MouseEvent } + ) => { + const text = getAssistantMessageText(btn); + if (!text) return false; + + event.preventDefault(); + event.stopPropagation(); + event.nativeEvent?.stopImmediatePropagation(); + if ('stopImmediatePropagation' in event) { + event.stopImmediatePropagation(); + } + + copyTextToClipboard(text); + showCopiedState(btn); + return true; + }, + [copyTextToClipboard, getAssistantMessageText, showCopiedState] + ); + + // Fix Algolia copy button bug: it can copy the first streamed text chunk + // instead of the rendered answer. Native capture catches the click before + // Algolia's own React handler writes stale content to the clipboard. + useEffect(() => { + if (!isOpen) return; + + const handleDocumentCopyClick = (event: MouseEvent) => { + const target = event.target as HTMLElement; + const btn = target.closest( + '.DocSearch-AskAiScreen-CopyButton' + ) as HTMLButtonElement | null; + if (!btn) return; + + copyAssistantMessage(btn, event); + }; + + document.addEventListener('click', handleDocumentCopyClick, true); + return () => { + document.removeEventListener('click', handleDocumentCopyClick, true); + }; + }, [copyAssistantMessage, isOpen]); + + const handleCopyCapture = React.useCallback( + (e: React.MouseEvent) => { + const target = e.target as HTMLElement; + const btn = target.closest( + '.DocSearch-AskAiScreen-CopyButton' + ) as HTMLButtonElement | null; + if (!btn) return; + + copyAssistantMessage(btn, e); + }, + [copyAssistantMessage] + ); + // Handle submit button state based on textarea content useEffect(() => { if (!isOpen) return; const updateButtonState = () => { - const textarea = document.querySelector('.DocSearch-Sidepanel-Prompt--textarea') as HTMLTextAreaElement; - const submitButton = document.querySelector('.DocSearch-Sidepanel-Prompt--submit') as HTMLButtonElement; + const textarea = document.querySelector( + '.DocSearch-Sidepanel-Prompt--textarea' + ) as HTMLTextAreaElement; + const submitButton = document.querySelector( + '.DocSearch-Sidepanel-Prompt--submit' + ) as HTMLButtonElement; if (textarea && submitButton) { if (textarea.value.trim().length > 0) { @@ -141,7 +339,9 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) }; const checkInterval = setInterval(() => { - const textarea = document.querySelector('.DocSearch-Sidepanel-Prompt--textarea') as HTMLTextAreaElement; + const textarea = document.querySelector( + '.DocSearch-Sidepanel-Prompt--textarea' + ) as HTMLTextAreaElement; if (textarea) { updateButtonState(); autoResize(textarea); @@ -153,7 +353,9 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) return () => { clearInterval(checkInterval); - const textarea = document.querySelector('.DocSearch-Sidepanel-Prompt--textarea'); + const textarea = document.querySelector( + '.DocSearch-Sidepanel-Prompt--textarea' + ); if (textarea) { textarea.removeEventListener('input', handleInput); } @@ -165,13 +367,16 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps) } const algoliaConfig = (siteConfig.themeConfig as any)?.algolia; + const askAiConfig = + (siteConfig.customFields as any)?.askAi || algoliaConfig?.askAi; - if (!algoliaConfig?.askAi) { + if (!askAiConfig) { console.error('Ask AI configuration not found in docusaurus.config.js'); return null; } - const { assistantId, indexName, appId, apiKey, suggestedQuestions } = algoliaConfig.askAi; + const { assistantId, indexName, appId, apiKey, suggestedQuestions } = + askAiConfig; const handleAlgoliaClose = () => { if (!isResizingRef.current) onClose(); @@ -182,6 +387,7 @@ export default function AskAiSidepanel({ isOpen, onClose }: AskAiSidepanelProps)
{}} onClose={handleAlgoliaClose} + initialMessage={initialMessage || undefined} suggestedQuestions={suggestedQuestions} translations={{ title: 'Ask AI about Sumo Logic', placeholder: 'Ask a question about Sumo Logic...', greeting: 'How can I help you with Sumo Logic today?', - introduction: 'I can help you find information about Sumo Logic features, integrations, troubleshooting guides, APIs, and best practices across our documentation.', + introduction: + 'I can help you find information about Sumo Logic features, integrations, troubleshooting guides, APIs, and best practices across our documentation.', poweredBy: 'Powered by Algolia', }} insights />
+ {headerActionsEl && + createPortal( +
+ + +
, + headerActionsEl + )} ); diff --git a/src/components/AskAiSidepanel/styles.css b/src/components/AskAiSidepanel/styles.css index e309c83572..b481e209d8 100644 --- a/src/components/AskAiSidepanel/styles.css +++ b/src/components/AskAiSidepanel/styles.css @@ -57,10 +57,8 @@ transform: none !important; opacity: 1 !important; border-radius: 0 !important; - box-shadow: - -1px 0 0 0 rgba(0, 0, 0, 0.05), - -8px 0 32px -4px rgba(0, 0, 0, 0.12), - -16px 0 64px -8px rgba(0, 0, 0, 0.08) !important; + box-shadow: -1px 0 0 0 rgba(0, 0, 0, 0.05), + -8px 0 32px -4px rgba(0, 0, 0, 0.12), -16px 0 64px -8px rgba(0, 0, 0, 0.08) !important; animation: slideIn 0.35s cubic-bezier(0.16, 1, 0.3, 1); display: flex !important; visibility: visible !important; @@ -88,10 +86,8 @@ } [data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-Container { - box-shadow: - -1px 0 0 0 rgba(255, 255, 255, 0.08), - -8px 0 32px -4px rgba(0, 0, 0, 0.4), - -16px 0 64px -8px rgba(0, 0, 0, 0.32) !important; + box-shadow: -1px 0 0 0 rgba(255, 255, 255, 0.08), + -8px 0 32px -4px rgba(0, 0, 0, 0.4), -16px 0 64px -8px rgba(0, 0, 0, 0.32) !important; } /* Main sidepanel - integrate with Docusaurus theme */ @@ -115,24 +111,108 @@ .ask-ai-sidepanel .DocSearch-Sidepanel-Header { background-color: var(--ifm-navbar-background-color) !important; border-bottom: 1px solid var(--ifm-color-emphasis-200) !important; + display: flex !important; + justify-content: flex-start !important; + gap: 0.75rem !important; } .ask-ai-sidepanel .DocSearch-Sidepanel-Header--center { display: flex !important; flex-direction: row !important; align-items: center !important; + flex: 1 1 auto !important; gap: 0.5rem !important; + min-width: 0 !important; + position: static !important; } .ask-ai-sidepanel .DocSearch-Sidepanel-Header-TitleIcon { display: block !important; + flex: 0 0 auto !important; margin: 0 !important; } .ask-ai-sidepanel .DocSearch-Sidepanel-Title { color: var(--ifm-font-color-base) !important; + overflow: hidden !important; font-weight: 600 !important; margin: 0 !important; + min-width: 0 !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Header--right { + flex: 0 0 auto !important; + gap: 0.35rem !important; + margin-left: auto !important; + position: static !important; +} + +.ask-ai-sidepanel .DocSearch-Sidepanel-Action-menu { + display: none !important; +} + +.ask-ai-sidepanel + .DocSearch-Sidepanel-Header--left + button[title='Start a new conversation'], +.ask-ai-sidepanel + .DocSearch-Sidepanel-Header--left + button[title='Conversation history'] { + display: none !important; +} + +.ask-ai-header-shortcuts { + display: flex; + align-items: center; + gap: 0.35rem; + margin-right: 0.15rem; + order: -1; +} + +.ask-ai-shortcut-button { + display: inline-flex; + align-items: center; + justify-content: center; + width: 34px; + height: 34px; + padding: 0; + border: 1px solid transparent; + border-radius: 6px; + background: transparent; + color: var(--ifm-font-color-base); + cursor: pointer; + font-family: 'Lab Grotesque', sans-serif; + font-size: 0.72rem; + font-weight: 700; + line-height: 1; +} + +.ask-ai-shortcut-button svg { + width: 19px; + height: 19px; + flex: 0 0 auto; +} + +.ask-ai-shortcut-button span { + display: none; +} + +.ask-ai-shortcut-button:hover, +.ask-ai-shortcut-button:focus-visible { + border-color: var(--ifm-color-primary); + background: var(--ifm-color-emphasis-100); + color: var(--ifm-color-primary); + outline: none; +} + +[data-theme='dark'] .ask-ai-shortcut-button { + background: transparent; +} + +[data-theme='dark'] .ask-ai-shortcut-button:hover, +[data-theme='dark'] .ask-ai-shortcut-button:focus-visible { + background: rgba(76, 134, 255, 0.14); } /* =================================================================== @@ -211,7 +291,9 @@ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(255, 255, 255, 0.1) !important; } -[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--form:focus-within { +[data-theme='dark'] + .ask-ai-sidepanel + .DocSearch-Sidepanel-Prompt--form:focus-within { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(255, 255, 255, 0.1) !important; } @@ -235,7 +317,9 @@ color: var(--ifm-color-emphasis-600) !important; } -[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--textarea::placeholder { +[data-theme='dark'] + .ask-ai-sidepanel + .DocSearch-Sidepanel-Prompt--textarea::placeholder { color: #7f8497 !important; } @@ -431,7 +515,9 @@ border-color: rgba(255, 255, 255, 0.15) !important; } -[data-theme='dark'] .ask-ai-sidepanel .DocSearch-Sidepanel-SuggestedQuestion:hover { +[data-theme='dark'] + .ask-ai-sidepanel + .DocSearch-Sidepanel-SuggestedQuestion:hover { background-color: rgba(255, 255, 255, 0.15) !important; } @@ -440,7 +526,9 @@ color: var(--ifm-color-emphasis-700) !important; } -[data-theme='light'] .ask-ai-sidepanel .DocSearch-Sidepanel-SuggestedQuestion:hover { +[data-theme='light'] + .ask-ai-sidepanel + .DocSearch-Sidepanel-SuggestedQuestion:hover { border-color: var(--ifm-color-emphasis-300) !important; } @@ -453,12 +541,16 @@ } /* Hide original title and show custom text */ -.ask-ai-sidepanel .DocSearch-Sidepanel-NewConversationScreen .DocSearch-Sidepanel-Screen--title { +.ask-ai-sidepanel + .DocSearch-Sidepanel-NewConversationScreen + .DocSearch-Sidepanel-Screen--title { font-size: 0 !important; line-height: 0 !important; } -.ask-ai-sidepanel .DocSearch-Sidepanel-NewConversationScreen .DocSearch-Sidepanel-Screen--title::before { +.ask-ai-sidepanel + .DocSearch-Sidepanel-NewConversationScreen + .DocSearch-Sidepanel-Screen--title::before { font-size: 1.625rem !important; line-height: 2rem !important; content: 'How can I help you today?'; @@ -470,12 +562,16 @@ } /* Hide original introduction and show custom text */ -.ask-ai-sidepanel .DocSearch-Sidepanel-NewConversationScreen .DocSearch-Sidepanel-Screen--introduction { +.ask-ai-sidepanel + .DocSearch-Sidepanel-NewConversationScreen + .DocSearch-Sidepanel-Screen--introduction { font-size: 0 !important; line-height: 0 !important; } -.ask-ai-sidepanel .DocSearch-Sidepanel-NewConversationScreen .DocSearch-Sidepanel-Screen--introduction::before { +.ask-ai-sidepanel + .DocSearch-Sidepanel-NewConversationScreen + .DocSearch-Sidepanel-Screen--introduction::before { font-size: 0.85rem !important; line-height: 1.25rem !important; content: 'I can help you find information about Sumo Logic features, integrations, troubleshooting guides, APIs, and best practices across our documentation.'; @@ -488,12 +584,3 @@ .ask-ai-sidepanel .DocSearch-Sidepanel-Prompt--disclaimer { display: none !important; } - -/* =================================================================== - Related Sources — hidden; all sources appear as inline links in the - answer body with better context than the chips provide - =================================================================== */ -.ask-ai-sidepanel .DocSearch-AskAiScreen-RelatedSources { - display: none !important; -} - diff --git a/src/css/sumo.scss b/src/css/sumo.scss index c1d685b5e0..15eb596fc2 100644 --- a/src/css/sumo.scss +++ b/src/css/sumo.scss @@ -253,6 +253,58 @@ html[data-theme='dark'] .DocSearch-Search-Icon { padding-right: 65px !important; } +.ask-ai-search-sidepanel-button { + align-items: center; + background: var(--docsearch-hit-background); + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 6px; + color: var(--docsearch-hit-color); + cursor: pointer; + display: grid; + font: inherit; + gap: 0.25rem 0.75rem; + grid-template-columns: auto minmax(0, max-content) minmax(0, 1fr); + line-height: 1.25; + margin: 0 0 0.75rem; + padding: 0.75rem 1rem; + text-align: left; + width: 100%; +} + +.ask-ai-search-sidepanel-button:hover, +.ask-ai-search-sidepanel-button:focus-visible { + background: var(--docsearch-hit-highlight-color); + border-color: var(--ifm-color-primary); + outline: none; +} + +.ask-ai-search-sidepanel-button-icon { + color: var(--ifm-color-primary); + display: inline-flex; + grid-row: 1 / span 2; +} + +.ask-ai-search-sidepanel-button-label { + font-size: 0.9rem; + font-weight: 700; +} + +.ask-ai-search-sidepanel-button-query { + color: var(--ifm-color-emphasis-700); + font-size: 0.8rem; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +html[data-theme='dark'] .ask-ai-search-sidepanel-button { + border-color: var(--ifm-color-emphasis-300); +} + +.ask-ai-native-modal-option-hidden { + display: none !important; +} + //GitHub icon .header-github-link:hover { opacity: 0.6; diff --git a/src/theme/Root.tsx b/src/theme/Root.tsx index 0fdb1396aa..1574a90567 100644 --- a/src/theme/Root.tsx +++ b/src/theme/Root.tsx @@ -10,16 +10,24 @@ import React, { useEffect, useState, Suspense } from 'react'; import { createPortal } from 'react-dom'; import AskAiButton from '@site/src/components/AskAiButton'; -const AskAiSidepanel = React.lazy(() => import('@site/src/components/AskAiSidepanel')); +const AskAiSidepanel = React.lazy( + () => import('@site/src/components/AskAiSidepanel') +); interface RootProps { children: React.ReactNode; } +interface AskAiInitialMessage { + query: string; +} + export default function Root({ children }: RootProps) { const [placeholder, setPlaceholder] = useState(null); const [isAskAiOpen, setIsAskAiOpen] = useState(false); const [hasEverOpened, setHasEverOpened] = useState(false); + const [initialAskAiMessage, setInitialAskAiMessage] = + useState(null); useEffect(() => { if (isAskAiOpen) setHasEverOpened(true); @@ -43,21 +51,187 @@ export default function Root({ children }: RootProps) { return () => clearInterval(interval); }, [placeholder]); + useEffect(() => { + const openAskAiFromSearch = (query: string) => { + const trimmedQuery = query.trim(); + if (!trimmedQuery) return; + + setInitialAskAiMessage({ query: trimmedQuery }); + setIsAskAiOpen(true); + + const closeButton = document.querySelector( + [ + '.DocSearch-Container button[aria-label="Close"]', + '.DocSearch-Container button[title="Close"]', + '.DocSearch-Container .DocSearch-Cancel', + ].join(',') + ); + closeButton?.click(); + }; + + const getDocSearchQuery = () => { + return ( + document + .querySelector( + '.DocSearch-Container .DocSearch-Input' + ) + ?.value.trim() || '' + ); + }; + + const routeModalAskAiClick = (event: MouseEvent) => { + const target = event.target as HTMLElement | null; + const container = target?.closest('.DocSearch-Container'); + if (!target || !container) return; + + if (target.closest('.ask-ai-search-sidepanel-button')) { + const query = getDocSearchQuery(); + if (!query) return; + + event.preventDefault(); + event.stopPropagation(); + event.stopImmediatePropagation(); + openAskAiFromSearch(query); + return; + } + + const clickable = target.closest( + [ + 'button', + 'a', + '[role="button"]', + '.DocSearch-Hit', + '.DocSearch-Menu-item', + ].join(',') + ); + if (!clickable) return; + + const actionText = [ + clickable.textContent, + clickable.getAttribute('aria-label'), + clickable.getAttribute('title'), + clickable.getAttribute('class'), + ] + .filter(Boolean) + .join(' ') + .toLowerCase(); + + if (!actionText.includes('ask ai')) return; + + const query = getDocSearchQuery(); + if (!query) return; + + event.preventDefault(); + event.stopPropagation(); + event.stopImmediatePropagation(); + openAskAiFromSearch(query); + }; + + const updateSearchHandoff = () => { + const container = document.querySelector('.DocSearch-Container'); + const dropdown = container?.querySelector('.DocSearch-Dropdown'); + const input = + container?.querySelector('.DocSearch-Input'); + + if (!container || !dropdown || !input) return; + + const query = input.value.trim(); + const existingButton = dropdown.querySelector( + '.ask-ai-search-sidepanel-button' + ); + const nativeAskAiOptions = dropdown.querySelectorAll( + [ + '.DocSearch-Hit', + '.DocSearch-Menu-item', + 'button', + 'a', + '[role="button"]', + '[role="option"]', + ].join(',') + ); + + nativeAskAiOptions.forEach((option) => { + if (option.closest('.ask-ai-search-sidepanel-button')) return; + + const text = option.textContent?.replace(/\s+/g, ' ').trim() || ''; + if (/^Ask AI\s*:/i.test(text)) { + option.classList.add('ask-ai-native-modal-option-hidden'); + } + }); + + if (!query) { + existingButton?.remove(); + return; + } + + const button = existingButton || document.createElement('button'); + + if (!existingButton) { + button.type = 'button'; + button.className = 'ask-ai-search-sidepanel-button'; + button.innerHTML = ` + + Ask AI in sidepanel + + `; + button.onclick = () => openAskAiFromSearch(input.value); + } + + if (button.dataset.query === query) { + return; + } + + button.dataset.query = query; + button.setAttribute('aria-label', `Ask AI in sidepanel for ${query}`); + + const queryEl = button.querySelector( + '.ask-ai-search-sidepanel-button-query' + ); + if (queryEl) { + queryEl.textContent = query; + } + + if (!existingButton) { + dropdown.prepend(button); + } + }; + + document.addEventListener('input', updateSearchHandoff, true); + document.addEventListener('click', routeModalAskAiClick, true); + const observer = new MutationObserver(updateSearchHandoff); + observer.observe(document.body, { childList: true, subtree: true }); + + return () => { + document.removeEventListener('input', updateSearchHandoff, true); + document.removeEventListener('click', routeModalAskAiClick, true); + observer.disconnect(); + }; + }, []); + return ( <> {children} {/* Button only — portaled into the navbar */} - {placeholder && createPortal( - , - placeholder - )} + {placeholder && + createPortal( + , + placeholder + )} {/* Sidepanel lives here in Root, never inside the navbar portal. Kept mounted once first opened so conversation state survives resize. */} {hasEverOpened && ( - setIsAskAiOpen(false)} /> + setIsAskAiOpen(false)} + initialMessage={initialAskAiMessage} + /> )} diff --git a/yarn.lock b/yarn.lock index a7df744028..3e2b53f7c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1849,11 +1849,6 @@ resolved "https://registry.yarnpkg.com/@docsearch/core/-/core-4.6.2.tgz#0a6fdc13b1eb12153cb19316f911479b67f7bd58" integrity sha512-/S0e6Dj7Zcm8m9Rru49YEX49dhU11be68c+S/BCyN8zQsTTgkKzXlhRbVL5mV6lOLC2+ZRRryaTdcm070Ug2oA== -"@docsearch/css@4": - version "4.5.3" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-4.5.3.tgz#359930bc8435976c574655adc9bb0574d8887a70" - integrity sha512-kUpHaxn0AgI3LQfyzTYkNUuaFY4uEz/Ym9/N/FvyDE+PzSgZsCyDH9jE49B6N6f1eLCm9Yp64J9wENd6vypdxA== - "@docsearch/css@4.6.2": version "4.6.2" resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-4.6.2.tgz#986776619dccbf798176c75e858cc22f5e710bb4" From b8e0095fe348945014d6195705a1694e0b9e7ad1 Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Tue, 16 Jun 2026 03:09:59 -0700 Subject: [PATCH 32/40] DOCS-1162 - Ask AI: route DocSearch Enter key to sidepanel Co-Authored-By: Claude Sonnet 4.6 --- src/theme/Root.tsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/theme/Root.tsx b/src/theme/Root.tsx index 1574a90567..9d4da56756 100644 --- a/src/theme/Root.tsx +++ b/src/theme/Root.tsx @@ -200,14 +200,30 @@ export default function Root({ children }: RootProps) { } }; + const routeSearchEnterToAskAi = (event: KeyboardEvent) => { + if (event.key !== 'Enter') return; + const target = event.target as HTMLElement | null; + if (!target?.closest('.DocSearch-Container .DocSearch-Input')) return; + + const query = getDocSearchQuery(); + if (!query) return; + + event.preventDefault(); + event.stopPropagation(); + event.stopImmediatePropagation(); + openAskAiFromSearch(query); + }; + document.addEventListener('input', updateSearchHandoff, true); document.addEventListener('click', routeModalAskAiClick, true); + document.addEventListener('keydown', routeSearchEnterToAskAi, true); const observer = new MutationObserver(updateSearchHandoff); observer.observe(document.body, { childList: true, subtree: true }); return () => { document.removeEventListener('input', updateSearchHandoff, true); document.removeEventListener('click', routeModalAskAiClick, true); + document.removeEventListener('keydown', routeSearchEnterToAskAi, true); observer.disconnect(); }; }, []); From 005ebbacc5d278b8984d500491dfcd4e59d0fddc Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Tue, 16 Jun 2026 05:58:32 -0700 Subject: [PATCH 33/40] DOCS-1162 - Ask AI: simplify search-to-sidepanel handoff, remove custom button injection Co-Authored-By: Claude Sonnet 4.6 --- src/theme/Root.tsx | 192 +++++++++++++++------------------------------ 1 file changed, 64 insertions(+), 128 deletions(-) diff --git a/src/theme/Root.tsx b/src/theme/Root.tsx index 9d4da56756..dc2b9db8e9 100644 --- a/src/theme/Root.tsx +++ b/src/theme/Root.tsx @@ -52,13 +52,7 @@ export default function Root({ children }: RootProps) { }, [placeholder]); useEffect(() => { - const openAskAiFromSearch = (query: string) => { - const trimmedQuery = query.trim(); - if (!trimmedQuery) return; - - setInitialAskAiMessage({ query: trimmedQuery }); - setIsAskAiOpen(true); - + const closeDocSearchModal = () => { const closeButton = document.querySelector( [ '.DocSearch-Container button[aria-label="Close"]', @@ -67,9 +61,34 @@ export default function Root({ children }: RootProps) { ].join(',') ); closeButton?.click(); + + document.dispatchEvent( + new KeyboardEvent('keydown', { + bubbles: true, + cancelable: true, + code: 'Escape', + key: 'Escape', + }) + ); + + requestAnimationFrame(() => { + document.querySelectorAll('.DocSearch-Container').forEach((modal) => { + modal.remove(); + }); + document.body.classList.remove('DocSearch--active'); + }); + }; + + const openAskAiThread = (query: string) => { + const trimmedQuery = query.trim(); + if (!trimmedQuery) return; + + setInitialAskAiMessage({ query: trimmedQuery }); + setIsAskAiOpen(true); + closeDocSearchModal(); }; - const getDocSearchQuery = () => { + const getModalQuery = () => { return ( document .querySelector( @@ -79,67 +98,16 @@ export default function Root({ children }: RootProps) { ); }; - const routeModalAskAiClick = (event: MouseEvent) => { - const target = event.target as HTMLElement | null; - const container = target?.closest('.DocSearch-Container'); - if (!target || !container) return; - - if (target.closest('.ask-ai-search-sidepanel-button')) { - const query = getDocSearchQuery(); - if (!query) return; - - event.preventDefault(); - event.stopPropagation(); - event.stopImmediatePropagation(); - openAskAiFromSearch(query); - return; - } - - const clickable = target.closest( - [ - 'button', - 'a', - '[role="button"]', - '.DocSearch-Hit', - '.DocSearch-Menu-item', - ].join(',') - ); - if (!clickable) return; - - const actionText = [ - clickable.textContent, - clickable.getAttribute('aria-label'), - clickable.getAttribute('title'), - clickable.getAttribute('class'), - ] - .filter(Boolean) - .join(' ') - .toLowerCase(); - - if (!actionText.includes('ask ai')) return; - - const query = getDocSearchQuery(); - if (!query) return; - - event.preventDefault(); - event.stopPropagation(); - event.stopImmediatePropagation(); - openAskAiFromSearch(query); + const isAskAiAssistantOption = (element: HTMLElement) => { + const text = element.textContent?.replace(/\s+/g, ' ').trim() || ''; + return /^Ask AI(?: Assistant)?\b/i.test(text); }; - const updateSearchHandoff = () => { - const container = document.querySelector('.DocSearch-Container'); - const dropdown = container?.querySelector('.DocSearch-Dropdown'); - const input = - container?.querySelector('.DocSearch-Input'); - - if (!container || !dropdown || !input) return; + const routeAskAiOptionClick = (event: MouseEvent) => { + const target = event.target as HTMLElement | null; + if (!target?.closest('.DocSearch-Container .DocSearch-Dropdown')) return; - const query = input.value.trim(); - const existingButton = dropdown.querySelector( - '.ask-ai-search-sidepanel-button' - ); - const nativeAskAiOptions = dropdown.querySelectorAll( + const option = target.closest( [ '.DocSearch-Hit', '.DocSearch-Menu-item', @@ -149,82 +117,50 @@ export default function Root({ children }: RootProps) { '[role="option"]', ].join(',') ); + if (!option || !isAskAiAssistantOption(option)) return; - nativeAskAiOptions.forEach((option) => { - if (option.closest('.ask-ai-search-sidepanel-button')) return; - - const text = option.textContent?.replace(/\s+/g, ' ').trim() || ''; - if (/^Ask AI\s*:/i.test(text)) { - option.classList.add('ask-ai-native-modal-option-hidden'); - } - }); - - if (!query) { - existingButton?.remove(); - return; - } - - const button = existingButton || document.createElement('button'); - - if (!existingButton) { - button.type = 'button'; - button.className = 'ask-ai-search-sidepanel-button'; - button.innerHTML = ` - - Ask AI in sidepanel - - `; - button.onclick = () => openAskAiFromSearch(input.value); - } - - if (button.dataset.query === query) { - return; - } - - button.dataset.query = query; - button.setAttribute('aria-label', `Ask AI in sidepanel for ${query}`); - - const queryEl = button.querySelector( - '.ask-ai-search-sidepanel-button-query' - ); - if (queryEl) { - queryEl.textContent = query; - } + const query = getModalQuery(); + if (!query) return; - if (!existingButton) { - dropdown.prepend(button); - } + event.preventDefault(); + event.stopPropagation(); + event.stopImmediatePropagation(); + openAskAiThread(query); }; - const routeSearchEnterToAskAi = (event: KeyboardEvent) => { + const routeAskAiOptionEnter = (event: KeyboardEvent) => { if (event.key !== 'Enter') return; - const target = event.target as HTMLElement | null; - if (!target?.closest('.DocSearch-Container .DocSearch-Input')) return; - - const query = getDocSearchQuery(); + const input = event.target as HTMLInputElement | null; + if (!input?.closest('.DocSearch-Container .DocSearch-Input')) return; + + const activeId = input.getAttribute('aria-activedescendant'); + const activeOption = activeId + ? document.getElementById(activeId) + : document.querySelector( + [ + '.DocSearch-Dropdown [aria-selected="true"]', + '.DocSearch-Dropdown [aria-current="true"]', + '.DocSearch-Dropdown .DocSearch-Hit[aria-selected="true"]', + '.DocSearch-Dropdown .DocSearch-Hit[aria-current="true"]', + ].join(',') + ); + if (!activeOption || !isAskAiAssistantOption(activeOption)) return; + + const query = getModalQuery(); if (!query) return; event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); - openAskAiFromSearch(query); + openAskAiThread(query); }; - document.addEventListener('input', updateSearchHandoff, true); - document.addEventListener('click', routeModalAskAiClick, true); - document.addEventListener('keydown', routeSearchEnterToAskAi, true); - const observer = new MutationObserver(updateSearchHandoff); - observer.observe(document.body, { childList: true, subtree: true }); + document.addEventListener('click', routeAskAiOptionClick, true); + document.addEventListener('keydown', routeAskAiOptionEnter, true); return () => { - document.removeEventListener('input', updateSearchHandoff, true); - document.removeEventListener('click', routeModalAskAiClick, true); - document.removeEventListener('keydown', routeSearchEnterToAskAi, true); - observer.disconnect(); + document.removeEventListener('click', routeAskAiOptionClick, true); + document.removeEventListener('keydown', routeAskAiOptionEnter, true); }; }, []); From 7843a8ffa28895243bbaaf18e7e028105996e687 Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Tue, 16 Jun 2026 06:01:32 -0700 Subject: [PATCH 34/40] DOCS-1162 - revert trailing newline in static txt file Co-Authored-By: Claude Sonnet 4.6 --- static/abc655ef33c7411c86d05452602d6c02.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/abc655ef33c7411c86d05452602d6c02.txt b/static/abc655ef33c7411c86d05452602d6c02.txt index deae657e07..3618833d1e 100644 --- a/static/abc655ef33c7411c86d05452602d6c02.txt +++ b/static/abc655ef33c7411c86d05452602d6c02.txt @@ -1 +1 @@ -abc655ef33c7411c86d05452602d6c02 +abc655ef33c7411c86d05452602d6c02 \ No newline at end of file From a570295eabc81967c8132adc6c5f43ea3980c72b Mon Sep 17 00:00:00 2001 From: Kim Pohas Date: Wed, 17 Jun 2026 00:52:47 -0700 Subject: [PATCH 35/40] Refine Ask AI sidepanel header actions --- src/components/AskAiSidepanel/index.tsx | 49 ++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/src/components/AskAiSidepanel/index.tsx b/src/components/AskAiSidepanel/index.tsx index 8da728ee21..24b034a9e1 100644 --- a/src/components/AskAiSidepanel/index.tsx +++ b/src/components/AskAiSidepanel/index.tsx @@ -167,6 +167,51 @@ export default function AskAiSidepanel({ button?.click(); }, []); + const focusPromptTextarea = React.useCallback(() => { + let attempts = 0; + const maxAttempts = 12; + + const focus = () => { + const textarea = document.querySelector( + '.DocSearch-Sidepanel-Prompt--textarea' + ) as HTMLTextAreaElement | null; + + if (textarea) { + textarea.focus(); + const length = textarea.value.length; + textarea.setSelectionRange(length, length); + return; + } + + attempts += 1; + if (attempts < maxAttempts) { + window.setTimeout(focus, 50); + } + }; + + focus(); + }, []); + + const handleNewConversation = React.useCallback(() => { + triggerHeaderAction('Start a new conversation'); + focusPromptTextarea(); + }, [focusPromptTextarea, triggerHeaderAction]); + + const handleConversationHistory = React.useCallback(() => { + const sidepanel = document.querySelector('.DocSearch-Sidepanel'); + const isHistoryOpen = sidepanel?.classList.contains('conversation-history'); + + if (isHistoryOpen) { + const backButton = document.querySelector( + '.DocSearch-Sidepanel-Action-back:not(.mobile)' + ); + backButton?.click(); + return; + } + + triggerHeaderAction('Conversation history'); + }, [triggerHeaderAction]); + const copyTextWithTextarea = React.useCallback((text: string) => { const textarea = document.createElement('textarea'); textarea.value = text; @@ -418,7 +463,7 @@ export default function AskAiSidepanel({ className="ask-ai-shortcut-button" aria-label="Start a new conversation" title="Start a new conversation" - onClick={() => triggerHeaderAction('Start a new conversation')} + onClick={handleNewConversation} > triggerHeaderAction('Conversation history')} + onClick={handleConversationHistory} > Date: Wed, 24 Jun 2026 02:29:21 -0700 Subject: [PATCH 36/40] Refine Ask AI sidepanel UI --- src/components/AskAiSidepanel/index.tsx | 62 ++++++- src/components/AskAiSidepanel/styles.css | 211 ++++++++++++++++------- 2 files changed, 203 insertions(+), 70 deletions(-) diff --git a/src/components/AskAiSidepanel/index.tsx b/src/components/AskAiSidepanel/index.tsx index 24b034a9e1..d94cfe2d96 100644 --- a/src/components/AskAiSidepanel/index.tsx +++ b/src/components/AskAiSidepanel/index.tsx @@ -18,6 +18,8 @@ export default function AskAiSidepanel({ const { siteConfig } = useDocusaurusContext(); const [SidepanelComponent, setSidepanelComponent] = useState(null); const [isExpanded, setIsExpanded] = useState(false); + const [isHistoryOpen, setIsHistoryOpen] = useState(false); + const [shortcutHint, setShortcutHint] = useState('Ctrl + I'); const [headerActionsEl, setHeaderActionsEl] = useState( null ); @@ -32,6 +34,34 @@ export default function AskAiSidepanel({ } }, [isOpen, SidepanelComponent]); + useEffect(() => { + if (typeof navigator === 'undefined') return; + + if (/(Mac|iPhone|iPad|iPod)/i.test(navigator.platform)) { + setShortcutHint('\u2318 + I'); + } else { + setShortcutHint('Ctrl + I'); + } + }, []); + + useEffect(() => { + if (!isOpen) return; + + const tipText = `Tip: Start a new chat with ${shortcutHint}`; + const checkInterval = setInterval(() => { + const intro = document.querySelector( + '.DocSearch-Sidepanel-NewConversationScreen .DocSearch-Sidepanel-Screen--introduction' + ) as HTMLElement | null; + + if (intro) { + intro.setAttribute('data-shortcut-tip', tipText); + clearInterval(checkInterval); + } + }, 100); + + return () => clearInterval(checkInterval); + }, [isOpen, shortcutHint]); + // Track resize so we can suppress Algolia's resize-triggered onClose useEffect(() => { let timer: ReturnType; @@ -53,6 +83,7 @@ export default function AskAiSidepanel({ useEffect(() => { if (!isOpen) { setIsExpanded(false); + setIsHistoryOpen(false); } }, [isOpen]); @@ -87,6 +118,25 @@ export default function AskAiSidepanel({ return () => window.removeEventListener('resize', handleResize); }, [isOpen]); + useEffect(() => { + if (!isOpen) return; + + const syncHistoryState = () => { + const sidepanel = document.querySelector('.DocSearch-Sidepanel'); + const historyOpen = + sidepanel?.classList.contains('conversation-history') ?? false; + + setIsHistoryOpen((prev) => (prev === historyOpen ? prev : historyOpen)); + }; + + syncHistoryState(); + const syncInterval = setInterval(syncHistoryState, 150); + + return () => { + clearInterval(syncInterval); + }; + }, [isOpen]); + // Hook into existing expand button useEffect(() => { if (!isOpen) return; @@ -430,7 +480,9 @@ export default function AskAiSidepanel({ const sidepanel = ( <>
@@ -460,7 +512,9 @@ export default function AskAiSidepanel({
, headerActionsEl )} + {feedbackModal && + createPortal( +
+
e.stopPropagation()} + > +
+

Thanks for the feedback

+ +
+

+ Provide additional feedback (optional) +

+