From f94c443b2db1b1e93cf8229d9426b611f7976408 Mon Sep 17 00:00:00 2001 From: pengzhanbo Date: Sun, 12 Feb 2023 01:02:44 +0800 Subject: [PATCH] feat(theme): add nav screen --- packages/theme/package.json | 1 + .../theme/src/client/components/BlogPage.vue | 0 .../src/client/components/Nav/NavScreen.vue | 102 +++- .../components/Nav/NavScreenAppearance.vue | 31 ++ .../client/components/Nav/NavScreenMenu.vue | 20 + .../components/Nav/NavScreenMenuGroup.vue | 112 ++++ .../components/Nav/NavScreenMenuGroupLink.vue | 37 ++ .../Nav/NavScreenMenuGroupSection.vue | 35 ++ .../components/Nav/NavScreenMenuLink.vue | 34 ++ .../components/Nav/NavScreenSocialLinks.vue | 14 + .../theme/src/client/components/Nav/index.vue | 25 +- packages/theme/src/client/components/Page.vue | 11 + packages/theme/src/client/layouts/Layout.vue | 12 +- packages/theme/src/client/styles/content.css | 501 ++++++++++++++++++ pnpm-lock.yaml | 6 + 15 files changed, 937 insertions(+), 4 deletions(-) create mode 100644 packages/theme/src/client/components/BlogPage.vue create mode 100644 packages/theme/src/client/components/Nav/NavScreenAppearance.vue create mode 100644 packages/theme/src/client/components/Nav/NavScreenMenu.vue create mode 100644 packages/theme/src/client/components/Nav/NavScreenMenuGroup.vue create mode 100644 packages/theme/src/client/components/Nav/NavScreenMenuGroupLink.vue create mode 100644 packages/theme/src/client/components/Nav/NavScreenMenuGroupSection.vue create mode 100644 packages/theme/src/client/components/Nav/NavScreenMenuLink.vue create mode 100644 packages/theme/src/client/components/Nav/NavScreenSocialLinks.vue create mode 100644 packages/theme/src/client/components/Page.vue create mode 100644 packages/theme/src/client/styles/content.css diff --git a/packages/theme/package.json b/packages/theme/package.json index eb23060d..521f9aa6 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -57,6 +57,7 @@ "@vuepress/shared": "2.0.0-beta.60", "@vuepress/utils": "2.0.0-beta.60", "@vueuse/core": "^9.10.0", + "body-scroll-lock": "4.0.0-beta.0", "date-fns": "^2.29.3", "nanoid": "^4.0.0", "ts-debounce": "^4.0.0", diff --git a/packages/theme/src/client/components/BlogPage.vue b/packages/theme/src/client/components/BlogPage.vue new file mode 100644 index 00000000..e69de29b diff --git a/packages/theme/src/client/components/Nav/NavScreen.vue b/packages/theme/src/client/components/Nav/NavScreen.vue index 6b4c19a0..e4cb866c 100644 --- a/packages/theme/src/client/components/Nav/NavScreen.vue +++ b/packages/theme/src/client/components/Nav/NavScreen.vue @@ -1 +1,101 @@ - + + + + + diff --git a/packages/theme/src/client/components/Nav/NavScreenAppearance.vue b/packages/theme/src/client/components/Nav/NavScreenAppearance.vue new file mode 100644 index 00000000..2707f14a --- /dev/null +++ b/packages/theme/src/client/components/Nav/NavScreenAppearance.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/packages/theme/src/client/components/Nav/NavScreenMenu.vue b/packages/theme/src/client/components/Nav/NavScreenMenu.vue new file mode 100644 index 00000000..a6a8873b --- /dev/null +++ b/packages/theme/src/client/components/Nav/NavScreenMenu.vue @@ -0,0 +1,20 @@ + + + diff --git a/packages/theme/src/client/components/Nav/NavScreenMenuGroup.vue b/packages/theme/src/client/components/Nav/NavScreenMenuGroup.vue new file mode 100644 index 00000000..65bcd0c1 --- /dev/null +++ b/packages/theme/src/client/components/Nav/NavScreenMenuGroup.vue @@ -0,0 +1,112 @@ + + + + + diff --git a/packages/theme/src/client/components/Nav/NavScreenMenuGroupLink.vue b/packages/theme/src/client/components/Nav/NavScreenMenuGroupLink.vue new file mode 100644 index 00000000..a8c277d2 --- /dev/null +++ b/packages/theme/src/client/components/Nav/NavScreenMenuGroupLink.vue @@ -0,0 +1,37 @@ + + + + + diff --git a/packages/theme/src/client/components/Nav/NavScreenMenuGroupSection.vue b/packages/theme/src/client/components/Nav/NavScreenMenuGroupSection.vue new file mode 100644 index 00000000..1255f75e --- /dev/null +++ b/packages/theme/src/client/components/Nav/NavScreenMenuGroupSection.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/packages/theme/src/client/components/Nav/NavScreenMenuLink.vue b/packages/theme/src/client/components/Nav/NavScreenMenuLink.vue new file mode 100644 index 00000000..96a503d5 --- /dev/null +++ b/packages/theme/src/client/components/Nav/NavScreenMenuLink.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/packages/theme/src/client/components/Nav/NavScreenSocialLinks.vue b/packages/theme/src/client/components/Nav/NavScreenSocialLinks.vue new file mode 100644 index 00000000..10584b92 --- /dev/null +++ b/packages/theme/src/client/components/Nav/NavScreenSocialLinks.vue @@ -0,0 +1,14 @@ + + + diff --git a/packages/theme/src/client/components/Nav/index.vue b/packages/theme/src/client/components/Nav/index.vue index 071199a8..176e26e4 100644 --- a/packages/theme/src/client/components/Nav/index.vue +++ b/packages/theme/src/client/components/Nav/index.vue @@ -1,7 +1,8 @@ + + diff --git a/packages/theme/src/client/components/Page.vue b/packages/theme/src/client/components/Page.vue new file mode 100644 index 00000000..0a35923b --- /dev/null +++ b/packages/theme/src/client/components/Page.vue @@ -0,0 +1,11 @@ + + + diff --git a/packages/theme/src/client/layouts/Layout.vue b/packages/theme/src/client/layouts/Layout.vue index 0c904404..8d3f278e 100644 --- a/packages/theme/src/client/layouts/Layout.vue +++ b/packages/theme/src/client/layouts/Layout.vue @@ -1,5 +1,6 @@ + + diff --git a/packages/theme/src/client/styles/content.css b/packages/theme/src/client/styles/content.css new file mode 100644 index 00000000..7b828e93 --- /dev/null +++ b/packages/theme/src/client/styles/content.css @@ -0,0 +1,501 @@ +/** + * Headings + * -------------------------------------------------------------------------- */ + +.plume-content h1, +.plume-content h2, +.plume-content h3, +.plume-content h4, +.plume-content h5, +.plume-content h6 { + position: relative; + font-weight: 600; + outline: none; +} + +.plume-content h1 { + letter-spacing: -0.02em; + line-height: 40px; + font-size: 28px; +} + +.plume-content h2 { + margin: 48px 0 16px; + border-top: 1px solid var(--vp-c-divider); + padding-top: 24px; + letter-spacing: -0.02em; + line-height: 32px; + font-size: 24px; +} + +.plume-content h3 { + margin: 32px 0 0; + letter-spacing: -0.01em; + line-height: 28px; + font-size: 20px; +} + +.plume-content .header-anchor { + float: left; + margin-left: -0.87em; + padding-right: 0.23em; + font-weight: 500; + user-select: none; + opacity: 0; + transition: color 0.25s, opacity 0.25s; +} + +.plume-content h1:hover .header-anchor, +.plume-content h1 .header-anchor:focus, +.plume-content h2:hover .header-anchor, +.plume-content h2 .header-anchor:focus, +.plume-content h3:hover .header-anchor, +.plume-content h3 .header-anchor:focus, +.plume-content h4:hover .header-anchor, +.plume-content h4 .header-anchor:focus, +.plume-content h5:hover .header-anchor, +.plume-content h5 .header-anchor:focus, +.plume-content h6:hover .header-anchor, +.plume-content h6 .header-anchor:focus { + opacity: 1; +} + +@media (min-width: 768px) { + .plume-content h1 { + letter-spacing: -0.02em; + line-height: 40px; + font-size: 32px; + } +} + +/** + * Paragraph and inline elements + * -------------------------------------------------------------------------- */ + +.plume-content p, +.plume-content summary { + margin: 16px 0; +} + +.plume-content p { + line-height: 28px; +} + +.plume-content blockquote { + margin: 16px 0; + border-left: 2px solid var(--vp-c-divider); + padding-left: 16px; + transition: border-color 0.5s; +} + +.plume-content blockquote > p { + margin: 0; + font-size: 16px; + color: var(--vp-c-text-2); + transition: color 0.5s; +} + +.plume-content a { + font-weight: 500; + color: var(--vp-c-brand); + text-decoration-style: dotted; + transition: color 0.25s; +} + +.plume-content a:hover { + color: var(--vp-c-brand-dark); +} + +.plume-content strong { + font-weight: 600; +} + +/** + * Lists + * -------------------------------------------------------------------------- */ + +.plume-content ul, +.plume-content ol { + padding-left: 1.25rem; + margin: 16px 0; +} + +.plume-content ul { + list-style: disc; +} + +.plume-content ol { + list-style: decimal; +} + +.plume-content li + li { + margin-top: 8px; +} + +.plume-content li > ol, +.plume-content li > ul { + margin: 8px 0 0; +} + +/** + * Table + * -------------------------------------------------------------------------- */ + +.plume-content table { + display: block; + border-collapse: collapse; + margin: 20px 0; + overflow-x: auto; +} + +.plume-content tr { + border-top: 1px solid var(--vp-c-divider); + transition: background-color 0.5s; +} + +.plume-content tr:nth-child(2n) { + background-color: var(--vp-c-bg-soft); +} + +.plume-content th, +.plume-content td { + border: 1px solid var(--vp-c-divider); + padding: 8px 16px; +} + +.plume-content th { + text-align: left; + font-size: 14px; + font-weight: 600; + color: var(--vp-c-text-2); + background-color: var(--vp-c-bg-soft); +} + +.plume-content td { + font-size: 14px; +} + +/** + * Decorational elements + * -------------------------------------------------------------------------- */ + +.plume-content hr { + margin: 16px 0; + border: none; + border-top: 1px solid var(--vp-c-divider); +} + +/** + * Custom Block + * -------------------------------------------------------------------------- */ + +.plume-content .custom-block { + margin: 16px 0; +} + +.plume-content .custom-block p { + margin: 8px 0; + line-height: 24px; +} + +.plume-content .custom-block p:first-child { + margin: 0; +} + +.plume-content .custom-block a { + color: inherit; + font-weight: 600; + text-decoration: underline; + transition: opacity 0.25s; +} + +.plume-content .custom-block a:hover { + opacity: 0.6; +} + +.plume-content .custom-block code { + font-size: var(--vp-custom-block-code-font-size); + font-weight: 700; + color: inherit; +} + +.plume-content .custom-block div[class*='language-'] { + margin: 8px 0; +} + +.plume-content .custom-block div[class*='language-'] code { + font-weight: 400; + background-color: transparent; +} + +/** + * Code + * -------------------------------------------------------------------------- */ + +/* inline code */ +.plume-content :not(pre, h1, h2, h3, h4, h5, h6) > code { + font-size: var(--vp-code-font-size); +} + +.plume-content :not(pre) > code { + border-radius: 4px; + padding: 3px 6px; + color: var(--vp-c-text-code); + background-color: var(--vp-c-mute); + transition: color 0.5s, background-color 0.5s; +} + +.plume-content h1 > code, +.plume-content h2 > code, +.plume-content h3 > code { + font-size: 0.9em; +} + +.plume-content a > code { + color: var(--vp-c-brand); + transition: color 0.25s; +} + +.plume-content a:hover > code { + color: var(--vp-c-brand-dark); +} + +.plume-content div[class*='language-'] { + position: relative; + margin: 16px -24px; + background-color: var(--vp-code-block-bg); + overflow-x: auto; + transition: background-color 0.5s; +} + +@media (min-width: 640px) { + .plume-content div[class*='language-'] { + border-radius: 8px; + margin: 16px 0; + } +} + +@media (max-width: 639px) { + .plume-content li div[class*='language-'] { + border-radius: 8px 0 0 8px; + } +} + +.plume-content div[class*='language-'] + div[class*='language-'], +.plume-content div[class$='-api'] + div[class*='language-'], +.plume-content + div[class*='language-'] + + div[class$='-api'] + > div[class*='language-'] { + margin-top: -8px; +} + +.plume-content [class*='language-'] pre, +.plume-content [class*='language-'] code { + /*rtl:ignore*/ + direction: ltr; + /*rtl:ignore*/ + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +.plume-content [class*='language-'] pre { + position: relative; + z-index: 1; + margin: 0; + padding: 16px 0; + background: transparent; + overflow-x: auto; +} + +.plume-content [class*='language-'] code { + display: block; + padding: 0 24px; + width: fit-content; + min-width: 100%; + line-height: var(--vp-code-line-height); + font-size: var(--vp-code-font-size); + color: var(--vp-code-block-color); + transition: color 0.5s; +} + +.plume-content [class*='language-'] code .highlighted { + background-color: var(--vp-code-line-highlight-color); + transition: background-color 0.5s; + margin: 0 -24px; + padding: 0 24px; + width: calc(100% + 2 * 24px); + display: inline-block; +} + +.plume-content [class*='language-'] code .highlighted.error { + background-color: var(--vp-code-line-error-color); +} + +.plume-content [class*='language-'] code .highlighted.warning { + background-color: var(--vp-code-line-warning-color); +} + +.plume-content [class*='language-'] code .diff { + transition: background-color 0.5s; + margin: 0 -24px; + padding: 0 24px; + width: calc(100% + 2 * 24px); + display: inline-block; +} + +.plume-content [class*='language-'] code .diff::before { + position: absolute; + left: 10px; +} + +.plume-content [class*='language-'] .has-focused-lines .line:not(.has-focus) { + filter: blur(0.095rem); + opacity: 0.4; + transition: filter 0.35s, opacity 0.35s; +} + +.plume-content [class*='language-'] .has-focused-lines .line:not(.has-focus) { + opacity: 0.7; + transition: filter 0.35s, opacity 0.35s; +} + +.plume-content + [class*='language-']:hover + .has-focused-lines + .line:not(.has-focus) { + filter: blur(0); + opacity: 1; +} + +.plume-content [class*='language-'] code .diff.remove { + background-color: var(--vp-code-line-diff-remove-color); + opacity: 0.7; +} + +.plume-content [class*='language-'] code .diff.remove::before { + content: '-'; + color: var(--vp-code-line-diff-remove-symbol-color); +} + +.plume-content [class*='language-'] code .diff.add { + background-color: var(--vp-code-line-diff-add-color); +} + +.plume-content [class*='language-'] code .diff.add::before { + content: '+'; + color: var(--vp-code-line-diff-add-symbol-color); +} + +.plume-content div[class*='language-'].line-numbers-mode { + /*rtl:ignore*/ + padding-left: 32px; +} + +.plume-content .line-numbers-wrapper { + position: absolute; + top: 0; + bottom: 0; + /*rtl:ignore*/ + left: 0; + z-index: 3; + /*rtl:ignore*/ + border-right: 1px solid var(--vp-code-block-divider-color); + padding-top: 16px; + width: 32px; + text-align: center; + font-family: var(--vp-font-family-mono); + line-height: var(--vp-code-line-height); + font-size: var(--vp-code-font-size); + color: var(--vp-code-line-number-color); + transition: border-color 0.5s, color 0.5s; +} + +.plume-content [class*='language-'] > button.copy { + /*rtl:ignore*/ + direction: ltr; + position: absolute; + top: 8px; + /*rtl:ignore*/ + right: 8px; + z-index: 3; + display: block; + justify-content: center; + align-items: center; + border-radius: 4px; + width: 40px; + height: 40px; + background-color: var(--vp-code-block-bg); + opacity: 0; + cursor: pointer; + background-image: var(--vp-icon-copy); + background-position: 50%; + background-size: 20px; + background-repeat: no-repeat; + transition: opacity 0.4s; +} + +.plume-content [class*='language-']:hover > button.copy, +.plume-content [class*='language-'] > button.copy:focus { + opacity: 1; +} + +.plume-content [class*='language-'] > button.copy:hover { + background-color: var(--vp-code-copy-code-hover-bg); +} + +.plume-content [class*='language-'] > button.copy.copied, +.plume-content [class*='language-'] > button.copy:hover.copied { + /*rtl:ignore*/ + border-radius: 0 4px 4px 0; + background-color: var(--vp-code-copy-code-hover-bg); + background-image: var(--vp-icon-copied); +} + +.plume-content [class*='language-'] > button.copy.copied::before, +.plume-content [class*='language-'] > button.copy:hover.copied::before { + position: relative; + /*rtl:ignore*/ + left: -65px; + display: flex; + justify-content: center; + align-items: center; + /*rtl:ignore*/ + border-radius: 4px 0 0 4px; + width: 64px; + height: 40px; + text-align: center; + font-size: 12px; + font-weight: 500; + color: var(--vp-code-copy-code-active-text); + background-color: var(--vp-code-copy-code-hover-bg); + white-space: nowrap; + content: 'Copied'; +} + +.plume-content [class*='language-'] > span.lang { + position: absolute; + top: 6px; + /*rtl:ignore*/ + right: 12px; + z-index: 2; + font-size: 12px; + font-weight: 500; + color: var(--vp-c-text-dark-3); + transition: color 0.4s, opacity 0.4s; +} + +.plume-content [class*='language-']:hover > button.copy + span.lang, +.plume-content [class*='language-'] > button.copy:focus + span.lang { + opacity: 0; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 800d7f5b..520a8ad9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -297,6 +297,7 @@ importers: '@vuepress/shared': 2.0.0-beta.60 '@vuepress/utils': 2.0.0-beta.60 '@vueuse/core': ^9.10.0 + body-scroll-lock: 4.0.0-beta.0 date-fns: ^2.29.3 nanoid: ^4.0.0 ts-debounce: ^4.0.0 @@ -332,6 +333,7 @@ importers: '@vuepress/shared': 2.0.0-beta.60 '@vuepress/utils': 2.0.0-beta.60 '@vueuse/core': 9.10.0_vue@3.2.47 + body-scroll-lock: 4.0.0-beta.0 date-fns: 2.29.3 nanoid: 4.0.0 ts-debounce: 4.0.0 @@ -4522,6 +4524,10 @@ packages: - supports-color dev: false + /body-scroll-lock/4.0.0-beta.0: + resolution: {integrity: sha512-a7tP5+0Mw3YlUJcGAKUqIBkYYGlYxk2fnCasq/FUph1hadxlTRjF+gAcZksxANnaMnALjxEddmSi/H3OR8ugcQ==} + dev: false + /bonjour-service/1.0.13: resolution: {integrity: sha512-LWKRU/7EqDUC9CTAQtuZl5HzBALoCYwtLhffW3et7vZMwv3bWLpJf8bRYlMD5OCcDpTfnPgNCV4yo9ZIaJGMiA==} dependencies: