From 8e959bcd984eb20d75f577272fc51c1f1cd1e335 Mon Sep 17 00:00:00 2001 From: pengzhanbo Date: Sat, 23 Dec 2023 09:16:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20copy-code=20UI=20?= =?UTF-8?q?=E5=92=8C=20=E4=BA=A4=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/notes/vuepress-theme-plume/README.md | 6 +- .../src/client/composables/setup.ts | 6 +- .../src/client/styles/button.scss | 121 ++++++++++++------ plugins/plugin-copy-code/src/client/svg.ts | 5 - plugins/tsconfig.build.json | 3 +- 5 files changed, 88 insertions(+), 53 deletions(-) delete mode 100644 plugins/plugin-copy-code/src/client/svg.ts diff --git a/docs/notes/vuepress-theme-plume/README.md b/docs/notes/vuepress-theme-plume/README.md index e1727a2c..3cab3958 100644 --- a/docs/notes/vuepress-theme-plume/README.md +++ b/docs/notes/vuepress-theme-plume/README.md @@ -41,7 +41,6 @@ __基于 `vuepress 2.0` 制作的 `Blog` 主题。__ ``` sh yarn add @vuepress-plume/vuepress-theme-plume ``` -::: @tab npm ``` sh npm i @vuepress-plume/vuepress-theme-plume @@ -56,13 +55,12 @@ npm i @vuepress-plume/vuepress-theme-plume // .vuepress/config.ts import { defineUserConfig } from 'vuepress' import { themePlume } from '@vuepress-plume/vuepress-theme-plume' -export default defineUserConfig({ - theme: themePlume({ +export default defineUserConfig({ // [!code focus] + theme: themePlume({ // more... }) }) ``` - @tab js ``` js // .vuepress/config.js diff --git a/plugins/plugin-copy-code/src/client/composables/setup.ts b/plugins/plugin-copy-code/src/client/composables/setup.ts index 97347780..e105b80c 100644 --- a/plugins/plugin-copy-code/src/client/composables/setup.ts +++ b/plugins/plugin-copy-code/src/client/composables/setup.ts @@ -2,7 +2,6 @@ import { onMounted, watch } from 'vue' import { useRoute } from 'vue-router' import type { CopyCodeOptions } from '../../shared/index.js' -import { copySVG, successSVG } from '../svg.js' import { copyToClipboard } from './copyToClipboard.js' declare const __COPY_CODE_OPTIONS__: CopyCodeOptions // declare const __COPY_CODE_LOCALES_OPTIONS__: CopyCodeLocaleOption @@ -29,14 +28,13 @@ export const setupCopyCode = (): void => { if (codeBlockEl.hasAttribute('has-copy-code')) return const button = document.createElement('button') button.className = 'copy-code-button' - button.innerHTML = copySVG button.addEventListener('click', () => { copyToClipboard(codeBlockEl.innerText) - button.innerHTML = successSVG + button.classList.add('copied') options.duration && setTimeout(() => { - button.innerHTML = copySVG + button.classList.remove('copied') }, options.duration) }) diff --git a/plugins/plugin-copy-code/src/client/styles/button.scss b/plugins/plugin-copy-code/src/client/styles/button.scss index 5f8c1b13..3ea7073b 100644 --- a/plugins/plugin-copy-code/src/client/styles/button.scss +++ b/plugins/plugin-copy-code/src/client/styles/button.scss @@ -1,47 +1,90 @@ +:root { + --icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2'/%3E%3C/svg%3E"); + --icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-6 9 2 2 4-4'/%3E%3C/svg%3E"); +} + +:root { + --code-copy-code-border-color: #e2e2e3; + --code-copy-code-bg: #f6f6f7; + --code-copy-code-hover-border-color: #e2e2e3; + --code-copy-code-hover-bg: #fff; + --code-copy-code-active-text: rgba(60, 60, 67, 0.78); + --code-copy-copied-text-content: 'Copied'; +} + +.dark { + --code-copy-code-border-color: #2e2e32; + --code-copy-code-bg: #202127; + --code-copy-code-hover-bg: #1b1b1f; + --code-copy-code-hover-border-color: #2e2e32; + --code-copy-code-active-text: rgba(235, 235, 245, 0.6); +} + .copy-code-button { - border: none; - background-color: transparent; - outline: 0; + /*rtl:ignore*/ + direction: ltr; + position: absolute; + top: 12px; + /*rtl:ignore*/ + right: 12px; + z-index: 3; + border: 1px solid var(--code-copy-code-border-color); border-radius: 4px; - padding: 5px 10px; - color: #d1d5db; - text-align: center; + width: 40px; + height: 40px; + background-color: var(--code-copy-code-bg); + opacity: 0; cursor: pointer; - - div[class*='language-'] & { - position: absolute; - right: 0; - top: 0.8rem; - z-index: 99; - opacity: 0; - transition: opacity var(--t-color); - } - - .icon-success { - display: inline-block; - width: 1.5rem; - height: 1.5rem; - vertical-align: middle; - } + background-image: var(--icon-copy); + background-position: 50%; + background-size: 20px; + background-repeat: no-repeat; + transition: + border-color 0.25s, + background-color 0.25s, + opacity 0.25s; } -div[class*='language-'] { - &::before { - opacity: 1; - transition: opacity var(--t-color); - } - - &:hover::before { - opacity: 0; - } - - &:hover .copy-code-button { - opacity: 1; - } +[class*='language-']:hover > .copy-code-button, +[class*='language-'] > .copy-code-button:focus { + opacity: 1; } -.icon-copy { - display: inline-block; - width: 1.5rem; - height: 1.5rem; +[class*='language-'] > .copy-code-button:hover, +[class*='language-'] > .copy-code-button.copied { + border-color: var(--code-copy-code-hover-border-color); + background-color: var(--code-copy-code-hover-bg); +} + +[class*='language-'] > .copy-code-button.copied, +[class*='language-'] > .copy-code-button:hover.copied { + /*rtl:ignore*/ + border-radius: 0 4px 4px 0; + background-color: var(--code-copy-code-hover-bg); + background-image: var(--icon-copied); +} + +[class*='language-'] > .copy-code-button.copied::before, +[class*='language-'] > .copy-code-button:hover.copied::before { + position: relative; + top: -1px; + /*rtl:ignore*/ + transform: translateX(calc(-100% - 1px)); + display: flex; + justify-content: center; + align-items: center; + border: 1px solid var(--code-copy-code-hover-border-color); + /*rtl:ignore*/ + border-right: 0; + border-radius: 4px 0 0 4px; + padding: 0 10px; + width: fit-content; + height: 40px; + text-align: center; + font-size: 12px; + font-weight: 500; + color: var(--code-copy-code-active-text); + background-color: var(--code-copy-code-hover-bg); + white-space: nowrap; + content: var(--code-copy-copied-text-content); } diff --git a/plugins/plugin-copy-code/src/client/svg.ts b/plugins/plugin-copy-code/src/client/svg.ts deleted file mode 100644 index 842c2743..00000000 --- a/plugins/plugin-copy-code/src/client/svg.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const successSVG = - '' - -export const copySVG = - '' diff --git a/plugins/tsconfig.build.json b/plugins/tsconfig.build.json index 649e7a3c..e3ae79aa 100644 --- a/plugins/tsconfig.build.json +++ b/plugins/tsconfig.build.json @@ -14,6 +14,7 @@ { "path": "./plugin-netlify-functions/tsconfig.build.json" }, { "path": "./plugin-notes-data/tsconfig.build.json" }, { "path": "./plugin-page-collection/tsconfig.build.json" }, - { "path": "./plugin-windicss/tsconfig.build.json" } + { "path": "./plugin-windicss/tsconfig.build.json" }, + { "path": "./plugin-shikiji/tsconfig.build.json" } ] }