From 794ef5e4663ebec73c24ca3457782512c13fecd2 Mon Sep 17 00:00:00 2001 From: Ben Ahmady <32935794+subatoi@users.noreply.github.com> Date: Thu, 23 Oct 2025 16:42:14 +0100 Subject: [PATCH 1/4] Adds workflow for automatic comment requesting feedback on contributor experience (#58152) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/docs-feedback-comment.yaml | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/docs-feedback-comment.yaml diff --git a/.github/workflows/docs-feedback-comment.yaml b/.github/workflows/docs-feedback-comment.yaml new file mode 100644 index 000000000000..509d3dbeb1a4 --- /dev/null +++ b/.github/workflows/docs-feedback-comment.yaml @@ -0,0 +1,24 @@ +name: Automatic comment to request feedback on PR experience + +# What it does: When PRs are merged, generate an automatic comment asking for feedback. +# Why we have it: So Hubbers can leave us feedback on the DIY Docs experience. +# Who it impacts: All Hubbers + +on: + pull_request: + types: + - closed + +jobs: + add-comment: + if: github.repository == 'github/docs-internal' && github.event.pull_request.merged == true + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - name: Comment on the PR + run: | + gh pr comment ${{ github.event.pull_request.number }} --body "Please leave feedback on the contributor experience! Leave a 👍 or 👎. You can also reach us in `#docs-contributor-feedback` on Slack." + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From d368d21dd2ddd3a45038aa61fb58859400419966 Mon Sep 17 00:00:00 2001 From: Kevin Heis Date: Thu, 23 Oct 2025 09:48:06 -0700 Subject: [PATCH 2/4] Fix compact toc link style for underlines (#58157) --- .../components/TableOfContents.module.css | 16 ------ src/landings/components/TableOfContents.tsx | 51 +++++++------------ 2 files changed, 17 insertions(+), 50 deletions(-) delete mode 100644 src/landings/components/TableOfContents.module.css diff --git a/src/landings/components/TableOfContents.module.css b/src/landings/components/TableOfContents.module.css deleted file mode 100644 index bdc4cb6f612c..000000000000 --- a/src/landings/components/TableOfContents.module.css +++ /dev/null @@ -1,16 +0,0 @@ -/* TableOfContents CSS Module */ - -.linkItem { - font-size: 1rem !important; - color: var(--fgColor-accent) !important; - display: block !important; - width: 100% !important; - text-decoration: underline !important; - - span { - user-select: text; - color: var(--fgColor-accent, var(--color-accent-fg)) !important; - font-size: inherit !important; - text-decoration: inherit !important; - } -} diff --git a/src/landings/components/TableOfContents.tsx b/src/landings/components/TableOfContents.tsx index f2c16c297e34..274c13d9a1ef 100644 --- a/src/landings/components/TableOfContents.tsx +++ b/src/landings/components/TableOfContents.tsx @@ -1,10 +1,7 @@ -import cx from 'classnames' import React from 'react' import { Link } from '@/frame/components/Link' import type { TocItem } from '@/landings/types' -import { ActionList } from '@primer/react' -import styles from './TableOfContents.module.css' type Props = { items: Array @@ -14,10 +11,7 @@ export const TableOfContents = (props: Props) => { const { items, variant = 'expanded' } = props return ( -
+
{variant === 'expanded' && items.map((item) => { const { fullPath: href, title, intro } = item @@ -41,40 +35,29 @@ export const TableOfContents = (props: Props) => { })} {variant === 'compact' && ( - +
    {items.map((item) => { const { fullPath, title, childTocItems } = item return ( - - +
  • + {title} - - {(childTocItems || []).length > 0 && ( -
  • - - {(childTocItems || []).filter(Boolean).map((childItem) => { - return ( - - {childItem.title} - - ) - })} - -
  • + + {(childTocItems || []).filter(Boolean).length > 0 && ( +
      + {(childTocItems || []).filter(Boolean).map((childItem) => ( +
    • + + {childItem.title} + +
    • + ))} +
    )} -
    + ) })} - +
)}
) From 05bfe3be007249f1fb30b8a783a42e815d6d01d8 Mon Sep 17 00:00:00 2001 From: Ben Ahmady <32935794+subatoi@users.noreply.github.com> Date: Thu, 23 Oct 2025 18:07:53 +0100 Subject: [PATCH 3/4] Revert "Adds workflow for automatic comment requesting feedback on contributor experience (#58152)" (#58162) --- .github/workflows/docs-feedback-comment.yaml | 24 -------------------- 1 file changed, 24 deletions(-) delete mode 100644 .github/workflows/docs-feedback-comment.yaml diff --git a/.github/workflows/docs-feedback-comment.yaml b/.github/workflows/docs-feedback-comment.yaml deleted file mode 100644 index 509d3dbeb1a4..000000000000 --- a/.github/workflows/docs-feedback-comment.yaml +++ /dev/null @@ -1,24 +0,0 @@ -name: Automatic comment to request feedback on PR experience - -# What it does: When PRs are merged, generate an automatic comment asking for feedback. -# Why we have it: So Hubbers can leave us feedback on the DIY Docs experience. -# Who it impacts: All Hubbers - -on: - pull_request: - types: - - closed - -jobs: - add-comment: - if: github.repository == 'github/docs-internal' && github.event.pull_request.merged == true - permissions: - contents: read - pull-requests: write - runs-on: ubuntu-latest - steps: - - name: Comment on the PR - run: | - gh pr comment ${{ github.event.pull_request.number }} --body "Please leave feedback on the contributor experience! Leave a 👍 or 👎. You can also reach us in `#docs-contributor-feedback` on Slack." - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 3e8e7c02307e11cf9d7452a5a60df1c92479cc0e Mon Sep 17 00:00:00 2001 From: Kevin Heis Date: Thu, 23 Oct 2025 11:02:55 -0700 Subject: [PATCH 4/4] Remove Copilot banner from footer (#58164) --- data/ui.yml | 5 - src/fixtures/fixtures/data/ui.yml | 5 - .../page-footer/SupportSection.module.scss | 4 +- .../components/page-footer/SupportSection.tsx | 12 -- .../components/input/AISearchCTAPopup.tsx | 199 ------------------ 5 files changed, 2 insertions(+), 223 deletions(-) delete mode 100644 src/search/components/input/AISearchCTAPopup.tsx diff --git a/data/ui.yml b/data/ui.yml index e77f87975515..1e3986a0f4ec 100644 --- a/data/ui.yml +++ b/data/ui.yml @@ -69,11 +69,6 @@ search: general_title: There was an error loading search results. ai_title: There was an error loading Copilot. description: You can still use this field to search our docs. - cta: - heading: Get quick answers! - description: Ask Copilot your question. - dismiss: Dismiss - ask_copilot: Ask Copilot old_search: description: Enter a search term to find it in the GitHub Docs. placeholder: Search GitHub Docs diff --git a/src/fixtures/fixtures/data/ui.yml b/src/fixtures/fixtures/data/ui.yml index e77f87975515..1e3986a0f4ec 100644 --- a/src/fixtures/fixtures/data/ui.yml +++ b/src/fixtures/fixtures/data/ui.yml @@ -69,11 +69,6 @@ search: general_title: There was an error loading search results. ai_title: There was an error loading Copilot. description: You can still use this field to search our docs. - cta: - heading: Get quick answers! - description: Ask Copilot your question. - dismiss: Dismiss - ask_copilot: Ask Copilot old_search: description: Enter a search term to find it in the GitHub Docs. placeholder: Search GitHub Docs diff --git a/src/frame/components/page-footer/SupportSection.module.scss b/src/frame/components/page-footer/SupportSection.module.scss index 1bb704c2bc40..fb3c73e29441 100644 --- a/src/frame/components/page-footer/SupportSection.module.scss +++ b/src/frame/components/page-footer/SupportSection.module.scss @@ -17,9 +17,9 @@ } } -// Large is 4 columns +// Large is 3 columns @media (min-width: 1280px) { .supportGrid { - grid-template-columns: minmax(18rem, 1fr) repeat(3, 1fr); + grid-template-columns: repeat(3, 1fr); } } diff --git a/src/frame/components/page-footer/SupportSection.tsx b/src/frame/components/page-footer/SupportSection.tsx index b153c5df4658..494745b3fd0a 100644 --- a/src/frame/components/page-footer/SupportSection.tsx +++ b/src/frame/components/page-footer/SupportSection.tsx @@ -7,8 +7,6 @@ import { useMainContext } from '@/frame/components/context/MainContext' import { useVersion } from '@/versions/components/useVersion' import { useRouter } from 'next/router' import { useTranslation } from '@/languages/components/useTranslation' -import { AISearchCTAPopup } from '@/search/components/input/AISearchCTAPopup' -import { useSearchOverlayContext } from '@/search/components/context/SearchOverlayContext' import styles from './SupportSection.module.scss' @@ -17,7 +15,6 @@ export const SupportSection = () => { const { relativePath, enterpriseServerReleases } = useMainContext() const router = useRouter() const { t } = useTranslation('footer') - const { setIsSearchOpen } = useSearchOverlayContext() const isDeprecated = enterpriseServerReleases.isOldestReleaseDeprecated && @@ -29,7 +26,6 @@ export const SupportSection = () => { const showSurvey = !isDeprecated && !isSitePolicyDocs const showContribution = !isDeprecated && !isEarlyAccess && isEnglish const showSupport = true - const showCopilotCTA = !isDeprecated && !isEarlyAccess && isEnglish return (
@@ -42,14 +38,6 @@ export const SupportSection = () => { styles.supportGrid /* ← adds the grid rules */, )} > - {showCopilotCTA && ( - - )} {showSurvey && } {showContribution && } {showSupport && } diff --git a/src/search/components/input/AISearchCTAPopup.tsx b/src/search/components/input/AISearchCTAPopup.tsx deleted file mode 100644 index 7d0909d205f2..000000000000 --- a/src/search/components/input/AISearchCTAPopup.tsx +++ /dev/null @@ -1,199 +0,0 @@ -import { useEffect, useRef } from 'react' -import { Text, Button, Heading, Popover, useOnEscapePress, Box } from '@primer/react' -import { focusTrap } from '@primer/behaviors' - -import { useTranslation } from '@/languages/components/useTranslation' -import { useMaxWidthBreakpoint, useMinWidthBreakpoint } from '../hooks/useBreakpoint' -import { useCTAPopoverContext } from '@/frame/components/context/CTAContext' -import { sendEvent } from '@/events/components/events' -import { EventType } from '@/events/types' - -let previouslyFocused: HTMLElement | null = null - -export function AISearchCTAPopup({ - isOpen, - dismiss, - setIsSearchOpen, - isDismissible = true, - bannerType = 'popover', - instanceId = '', -}: { - isOpen: boolean - dismiss?: () => void - setIsSearchOpen: (value: boolean) => void - isDismissible?: boolean - bannerType?: 'popover' | 'footer' - instanceId?: string -}) { - const { t } = useTranslation('search') - const { permanentDismiss } = useCTAPopoverContext() - const isLargeOrUp = useMinWidthBreakpoint('large') - const isTooSmallForCTA = useMaxWidthBreakpoint('293px') - let overlayRef = useRef(null) - let dismissButtonRef = useRef(null) - - // Analytics helper functions - const sendCTAAnalytics = (variation: 'dismiss' | 'ask_copilot') => { - const experimentName = - bannerType === 'footer' ? 'copilot_footer_banner' : 'copilot_popover_banner' - sendEvent({ - type: EventType.experiment, - experiment_name: experimentName, - experiment_variation: variation, - experiment_success: true, - }) - } - - const openSearch = () => { - // Send analytics before taking action - sendCTAAnalytics('ask_copilot') - setIsSearchOpen(true) - // They engaged with the CTA, so let's not show this popup for them anymore - permanentDismiss() - } - - // For a11y, focus trap the CTA and allow it to be closed with Escape - useEffect(() => { - if (isTooSmallForCTA) { - return - } - if (isOpen && overlayRef.current && dismissButtonRef.current) { - focusTrap(overlayRef.current, dismissButtonRef.current) - previouslyFocused = document.activeElement as HTMLElement | null - } - }, [isOpen, isTooSmallForCTA]) - - const onDismiss = () => { - if (isTooSmallForCTA) { - return - } - // Send analytics before taking action - sendCTAAnalytics('dismiss') - if (previouslyFocused) { - previouslyFocused.focus() - } - if (dismiss) { - dismiss() - } - } - - useOnEscapePress(onDismiss) - - if (isTooSmallForCTA) { - return null - } - - const innerContent = ( - <> - The Copilot Icon in front of an explosion of color. - - {t('search.cta.heading')} - - - {t('search.cta.description')} - - - {isDismissible ? ( - - ) : null} - - - - ) - - // If not dismissible, it's not being used as a popover - if (!isDismissible) { - return ( - - {innerContent} - - ) - } - - return ( - - - {innerContent} - - - ) -}