diff --git a/docusaurus.config.js b/docusaurus.config.js index 3288ffc7371..69c8864bda8 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -371,6 +371,12 @@ module.exports = { versions: VERSIONS_JSON, }, ], + [ + 'docusaurus-plugin-copy-page-button', + { + injectButton: false, + }, + ], ], customFields: {}, themes: [], diff --git a/package-lock.json b/package-lock.json index 1f0faeaf2c9..954dabe144d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "clsx": "^1.1.1", "concurrently": "^6.2.0", "crowdin": "^3.5.0", + "docusaurus-plugin-copy-page-button": "^0.8.2", "docusaurus-plugin-module-alias": "^0.0.2", "docusaurus-plugin-sass": "^0.2.6", "fs-extra": "^9.1.0", @@ -8031,6 +8032,19 @@ "node": ">=6" } }, + "node_modules/docusaurus-plugin-copy-page-button": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/docusaurus-plugin-copy-page-button/-/docusaurus-plugin-copy-page-button-0.8.2.tgz", + "integrity": "sha512-6flPLd6x5stWlsBmNslh1dTIAUl8U8VwUL5m8rLS23rPtSlemomHP2si/YJvs5dqZc+XlLqR5xOmsRpWznlw0Q==", + "license": "MIT", + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/core": "^3.0.0", + "react": "^18.0.0 || ^19.0.0" + } + }, "node_modules/docusaurus-plugin-module-alias": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/docusaurus-plugin-module-alias/-/docusaurus-plugin-module-alias-0.0.2.tgz", diff --git a/package.json b/package.json index 6fd279bd2af..aa56108b5f7 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "clsx": "^1.1.1", "concurrently": "^6.2.0", "crowdin": "^3.5.0", + "docusaurus-plugin-copy-page-button": "^0.8.2", "docusaurus-plugin-module-alias": "^0.0.2", "docusaurus-plugin-sass": "^0.2.6", "fs-extra": "^9.1.0", diff --git a/src/styles/components/_edit-this-page.scss b/src/styles/components/_edit-this-page.scss index 09ff54bd567..68a6c29cb3b 100644 --- a/src/styles/components/_edit-this-page.scss +++ b/src/styles/components/_edit-this-page.scss @@ -1,5 +1,6 @@ :root { --edit-this-page-c: var(--ifm-link-color); + --edit-this-page-opacity: 0.7; } .theme-edit-this-page { @@ -9,8 +10,6 @@ grid-template-columns: 0.875rem 1fr; - margin-block-start: 1.25rem; - color: var(--edit-this-page-c); transition: opacity 0.2s ease-out; @@ -19,6 +18,6 @@ &:active, &:focus { color: var(--edit-this-page-c); - opacity: 0.7; + opacity: var(--edit-this-page-opacity); } } diff --git a/src/styles/components/_toc.scss b/src/styles/components/_toc.scss index 9c464abc045..82e1b39f694 100644 --- a/src/styles/components/_toc.scss +++ b/src/styles/components/_toc.scss @@ -62,6 +62,7 @@ html[data-theme='dark'] { .theme-edit-this-page { --edit-this-page-c: var(--ifm-heading-color); + margin-block-start: 1.25rem; font-weight: 600; font-size: 0.875rem; } diff --git a/src/theme/EditMetaRow/index.tsx b/src/theme/EditMetaRow/index.tsx new file mode 100644 index 00000000000..b04fc5541ba --- /dev/null +++ b/src/theme/EditMetaRow/index.tsx @@ -0,0 +1,52 @@ +/** + * EditMetaRow is a component that renders the edit and last updated + * metadata for a page. This component is displayed at the bottom of + * each page. + * + * Original source: + * @link https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-theme-classic/src/theme/EditMetaRow/index.tsx + * + * Reason for overriding: + * - Add a copy page button next to the edit this page link + * - Wrap the whole last updated section in a conditional, not just + * its contents. Otherwise the empty column still reserves half the + * row. + */ + +import React, { type ReactNode } from 'react'; +import clsx from 'clsx'; +// CUSTOM CODE +import CopyPageButton from 'docusaurus-plugin-copy-page-button/react'; +// CUSTOM CODE END +import EditThisPage from '@theme/EditThisPage'; +import type { Props } from '@theme/EditMetaRow'; + +import LastUpdated from '@theme/LastUpdated'; + +import globalStyles from '@docusaurus/theme-classic/lib/theme/EditMetaRow/styles.module.css'; +import styles from './styles.module.css'; + +export default function EditMetaRow({ className, editUrl, lastUpdatedAt, lastUpdatedBy }: Props): ReactNode { + return ( +