feat: 优化 copy-code UI 和 交互
This commit is contained in:
parent
617c6c9243
commit
8e959bcd98
@ -41,7 +41,6 @@ __基于 `vuepress 2.0` 制作的 `Blog` 主题。__
|
|||||||
``` sh
|
``` sh
|
||||||
yarn add @vuepress-plume/vuepress-theme-plume
|
yarn add @vuepress-plume/vuepress-theme-plume
|
||||||
```
|
```
|
||||||
:::
|
|
||||||
@tab npm
|
@tab npm
|
||||||
``` sh
|
``` sh
|
||||||
npm i @vuepress-plume/vuepress-theme-plume
|
npm i @vuepress-plume/vuepress-theme-plume
|
||||||
@ -56,13 +55,12 @@ npm i @vuepress-plume/vuepress-theme-plume
|
|||||||
// .vuepress/config.ts
|
// .vuepress/config.ts
|
||||||
import { defineUserConfig } from 'vuepress'
|
import { defineUserConfig } from 'vuepress'
|
||||||
import { themePlume } from '@vuepress-plume/vuepress-theme-plume'
|
import { themePlume } from '@vuepress-plume/vuepress-theme-plume'
|
||||||
export default defineUserConfig({
|
export default defineUserConfig({ // [!code focus]
|
||||||
theme: themePlume({
|
theme: themePlume({
|
||||||
// more...
|
// more...
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@tab js
|
@tab js
|
||||||
``` js
|
``` js
|
||||||
// .vuepress/config.js
|
// .vuepress/config.js
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
import { onMounted, watch } from 'vue'
|
import { onMounted, watch } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import type { CopyCodeOptions } from '../../shared/index.js'
|
import type { CopyCodeOptions } from '../../shared/index.js'
|
||||||
import { copySVG, successSVG } from '../svg.js'
|
|
||||||
import { copyToClipboard } from './copyToClipboard.js'
|
import { copyToClipboard } from './copyToClipboard.js'
|
||||||
declare const __COPY_CODE_OPTIONS__: CopyCodeOptions
|
declare const __COPY_CODE_OPTIONS__: CopyCodeOptions
|
||||||
// declare const __COPY_CODE_LOCALES_OPTIONS__: CopyCodeLocaleOption
|
// declare const __COPY_CODE_LOCALES_OPTIONS__: CopyCodeLocaleOption
|
||||||
@ -29,14 +28,13 @@ export const setupCopyCode = (): void => {
|
|||||||
if (codeBlockEl.hasAttribute('has-copy-code')) return
|
if (codeBlockEl.hasAttribute('has-copy-code')) return
|
||||||
const button = document.createElement('button')
|
const button = document.createElement('button')
|
||||||
button.className = 'copy-code-button'
|
button.className = 'copy-code-button'
|
||||||
button.innerHTML = copySVG
|
|
||||||
|
|
||||||
button.addEventListener('click', () => {
|
button.addEventListener('click', () => {
|
||||||
copyToClipboard(codeBlockEl.innerText)
|
copyToClipboard(codeBlockEl.innerText)
|
||||||
button.innerHTML = successSVG
|
button.classList.add('copied')
|
||||||
options.duration &&
|
options.duration &&
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
button.innerHTML = copySVG
|
button.classList.remove('copied')
|
||||||
}, options.duration)
|
}, options.duration)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -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 {
|
.copy-code-button {
|
||||||
border: none;
|
/*rtl:ignore*/
|
||||||
background-color: transparent;
|
direction: ltr;
|
||||||
outline: 0;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 5px 10px;
|
|
||||||
color: #d1d5db;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
div[class*='language-'] & {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
top: 12px;
|
||||||
top: 0.8rem;
|
/*rtl:ignore*/
|
||||||
z-index: 99;
|
right: 12px;
|
||||||
|
z-index: 3;
|
||||||
|
border: 1px solid var(--code-copy-code-border-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background-color: var(--code-copy-code-bg);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity var(--t-color);
|
cursor: pointer;
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-success {
|
[class*='language-']:hover > .copy-code-button,
|
||||||
display: inline-block;
|
[class*='language-'] > .copy-code-button:focus {
|
||||||
width: 1.5rem;
|
|
||||||
height: 1.5rem;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
div[class*='language-'] {
|
|
||||||
&::before {
|
|
||||||
opacity: 1;
|
|
||||||
transition: opacity var(--t-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover::before {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover .copy-code-button {
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[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);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-copy {
|
[class*='language-'] > .copy-code-button.copied,
|
||||||
display: inline-block;
|
[class*='language-'] > .copy-code-button:hover.copied {
|
||||||
width: 1.5rem;
|
/*rtl:ignore*/
|
||||||
height: 1.5rem;
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
export const successSVG =
|
|
||||||
'<svg t="1651745829084" class="icon-success" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2061" width="200" height="200"><path d="M469.333333 640l0.384 0.384L469.333333 640z m-106.282666 0l-0.384 0.384 0.384-0.384z m48.512 106.666667a87.466667 87.466667 0 0 1-61.653334-24.874667l-179.52-173.632a67.797333 67.797333 0 0 1 0-98.24c28.032-27.157333 73.493333-27.157333 101.589334 0l139.584 134.997333 319.168-308.544c28.032-27.157333 73.493333-27.157333 101.589333 0a67.925333 67.925333 0 0 1 0 98.24L472.981333 722.069333A87.530667 87.530667 0 0 1 411.562667 746.666667z" fill="#78C326" p-id="2062"></path></svg>'
|
|
||||||
|
|
||||||
export const copySVG =
|
|
||||||
'<svg xmlns="http://www.w3.org/2000/svg" class="icon-copy" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" fill="currentColor"></path></svg>'
|
|
||||||
@ -14,6 +14,7 @@
|
|||||||
{ "path": "./plugin-netlify-functions/tsconfig.build.json" },
|
{ "path": "./plugin-netlify-functions/tsconfig.build.json" },
|
||||||
{ "path": "./plugin-notes-data/tsconfig.build.json" },
|
{ "path": "./plugin-notes-data/tsconfig.build.json" },
|
||||||
{ "path": "./plugin-page-collection/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" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user