pull/4739/merge
Artea 4 months ago committed by GitHub
commit 1b5c76061a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -8,15 +8,18 @@ import VPNav from './components/VPNav.vue'
import VPSidebar from './components/VPSidebar.vue'
import VPSkipLink from './components/VPSkipLink.vue'
import { useData } from './composables/data'
import { registerWatchers } from './composables/layout'
import { registerWatchers, useLayout } from './composables/layout'
import { useSidebarControl } from './composables/sidebar'
const {
isOpen: isSidebarOpen,
open: openSidebar,
close: closeSidebar
close: closeSidebar,
isCollapsed
} = useSidebarControl()
const { hasSidebar } = useLayout()
registerWatchers({ closeSidebar })
const { frontmatter } = useData()
@ -25,13 +28,21 @@ const slots = useSlots()
const heroImageSlotExists = computed(() => !!slots['home-hero-image'])
provide('hero-image-slot-exists', heroImageSlotExists)
const layoutClasses = computed(() => {
return {
[String(frontmatter.value.pageClass || '')]: !!frontmatter.value.pageClass,
'has-sidebar': hasSidebar.value,
'sidebar-collapsed': isCollapsed.value && hasSidebar.value
}
})
</script>
<template>
<div
v-if="frontmatter.layout !== false"
class="Layout"
:class="frontmatter.pageClass"
:class="layoutClasses"
>
<slot name="layout-top" />
<VPSkipLink />
@ -92,4 +103,16 @@ provide('hero-image-slot-exists', heroImageSlotExists)
flex-direction: column;
min-height: 100vh;
}
@media (min-width: 1440px) {
.Layout.has-sidebar.sidebar-collapsed .VPContent :deep(.VPDoc .content-container),
.Layout.has-sidebar.sidebar-collapsed .VPContent :deep(.VPDoc .content) {
max-width: 100%;
}
.Layout.has-sidebar.sidebar-collapsed .VPContent :deep(.VPDoc .container) {
max-width: 100%;
justify-content: space-between;
}
}
</style>

@ -1,20 +1,23 @@
<script setup lang="ts">
import NotFound from '../NotFound.vue'
import { useData } from '../composables/data'
import { useLayout } from '../composables/layout'
import { useLayout, } from '../composables/layout'
import {useSidebarControl} from '../composables/sidebar'
import VPDoc from './VPDoc.vue'
import VPHome from './VPHome.vue'
import VPPage from './VPPage.vue'
const { page, frontmatter } = useData()
const { isHome, hasSidebar } = useLayout()
const {isCollapsed} = useSidebarControl()
</script>
<template>
<div
class="VPContent"
id="VPContent"
:class="{ 'has-sidebar': hasSidebar, 'is-home': isHome }"
:class="{ 'has-sidebar': hasSidebar, 'is-home': isHome ,'collapsed':isCollapsed
}"
>
<slot name="not-found" v-if="page.isNotFound"><NotFound /></slot>
@ -91,5 +94,8 @@ const { isHome, hasSidebar } = useLayout()
padding-right: calc((100vw - var(--vp-layout-max-width)) / 2);
padding-left: calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width));
}
.VPContent.has-sidebar.collapsed {
padding-left: calc(100vw - var(--vp-layout-max-width)) / 2 ;
}
}
</style>

@ -1,7 +1,8 @@
<script lang="ts" setup>
import { useWindowScroll } from '@vueuse/core'
import { useMediaQuery, useWindowScroll } from '@vueuse/core'
import { ref, watchPostEffect } from 'vue'
import { useLayout } from '../composables/layout'
import { useSidebarControl } from '../composables/sidebar'
import VPNavBarAppearance from './VPNavBarAppearance.vue'
import VPNavBarExtra from './VPNavBarExtra.vue'
import VPNavBarHamburger from './VPNavBarHamburger.vue'
@ -20,6 +21,7 @@ defineEmits<{
}>()
const { y } = useWindowScroll()
const {isCollapsed, toggleCollapse: toggleSidebarCollapse } = useSidebarControl()
const { isHome, hasSidebar } = useLayout()
const classes = ref<Record<string, boolean>>({})
@ -29,20 +31,31 @@ watchPostEffect(() => {
'has-sidebar': hasSidebar.value,
'home': isHome.value,
'top': y.value === 0,
'collapsed':isCollapsed.value,
'screen-open': props.isScreenOpen
}
})
const is1440 = useMediaQuery('(min-width: 1440px)')
</script>
<template>
<div class="VPNavBar" :class="classes">
<div class="wrapper">
<div class="container">
<div class="title">
<VPNavBarTitle>
<template #nav-bar-title-before><slot name="nav-bar-title-before" /></template>
<template #nav-bar-title-after><slot name="nav-bar-title-after" /></template>
</VPNavBarTitle>
<div class="title">
<VPNavBarTitle >
<template #nav-bar-title-before><slot name="nav-bar-title-before" /></template>
<template #nav-bar-title-after><slot name="nav-bar-title-after" /></template>
</VPNavBarTitle>
<button
v-if="!isHome&&is1440"
class="sidebar-toggle-button"
@click="toggleSidebarCollapse"
aria-label="collapse sidebar"
>
<span class="vpi-collapse icon" />
</button>
</div>
<div class="content">
@ -94,6 +107,9 @@ watchPostEffect(() => {
.VPNavBar:not(.has-sidebar):not(.home.top) {
background-color: var(--vp-nav-bg-color);
}
.VPNavBar.collapsed {
background-color: var(--vp-nav-bg-color);
}
}
.wrapper {
@ -140,6 +156,17 @@ watchPostEffect(() => {
flex-shrink: 0;
height: calc(var(--vp-nav-height) - 1px);
transition: background-color 0.5s;
display: flex;
align-items: center;
justify-content: space-between;
}
.VPNavBar:not(.home):not(.collapsed).has-sidebar .title{
border-bottom: 1px solid var(--vp-c-divider);
width: calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px - 20px)
}
.VPNavBar:not(.home).collapsed .title{
background-color: var(--vp-nav-bg-color);
border-bottom: 1px solid var(--vp-c-divider);
}
@media (min-width: 960px) {
@ -269,4 +296,33 @@ watchPostEffect(() => {
background-color: var(--vp-c-gutter);
}
}
.sidebar-toggle-button {
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
color: var(--vp-c-text-2);
background-color: transparent;
border: none;
border-radius: 6px;
transition: background-color 0.25s, color 0.25s;
pointer-events: auto;
}
.sidebar-toggle-button:hover {
background-color: var(--vp-c-bg-mute);
color: var(--vp-c-text-1);
}
.sidebar-toggle-button .icon {
width: 20px;
height: 20px;
transition: transform 0.25s ease;
}
.sidebar-toggle-button .icon.is-collapsed {
transform: rotate(180deg);
}
</style>

@ -50,7 +50,6 @@ const target = computed(() =>
.title {
display: flex;
align-items: center;
border-bottom: 1px solid transparent;
width: 100%;
height: var(--vp-nav-height);
font-size: 16px;
@ -63,10 +62,6 @@ const target = computed(() =>
.title {
flex-shrink: 0;
}
.VPNavBarTitle.has-sidebar .title {
border-bottom-color: var(--vp-c-divider);
}
}
:deep(.logo) {

@ -1,11 +1,13 @@
<script lang="ts" setup>
import { useScrollLock } from '@vueuse/core'
import { useEventListener, useScrollLock } from '@vueuse/core'
import { inBrowser } from 'vitepress'
import { ref, watch } from 'vue'
import { useLayout } from '../composables/layout'
import VPSidebarGroup from './VPSidebarGroup.vue'
import { useSidebarControl } from '../composables/sidebar'
const { sidebarGroups, hasSidebar } = useLayout()
const { isHome,sidebarGroups } = useLayout()
const { isCollapsed } = useSidebarControl()
const props = defineProps<{
open: boolean
@ -28,6 +30,7 @@ watch(
const key = ref(0)
watch(
sidebarGroups,
() => {
@ -35,15 +38,25 @@ watch(
},
{ deep: true }
)
useEventListener(document,'mousemove',(e)=>{
if(isHome.value) return
if(e.clientX<5){
navEl.value?.classList.add('expanded')
}else if(e.target instanceof Node &&!navEl.value?.contains(e.target)&&e.pageX>272){
navEl.value?.classList.remove('expanded')
}
})
</script>
<template>
<aside
v-if="hasSidebar"
<aside
class="VPSidebar"
:class="{ open }"
:class="{ open ,collapsed:isCollapsed}"
ref="navEl"
@click.stop
v-if="!isHome"
>
<div class="curtain" />
@ -84,12 +97,26 @@ watch(
overscroll-behavior: contain;
}
.collapsed{
transform: translateX(-100%);
opacity: 0 !important;
transition: opacity 0.25s, transform 0.25s ease;
overscroll-behavior: contain;
}
.expanded{
transform: translateX(0);
opacity: 1 !important;
transition: opacity 0.25s, transform 0.25s ease;
overscroll-behavior: contain;
width: calc(100vw - 64px);
max-width: 320px;
z-index: var(--vp-z-index-sidebar) !important;
}
.VPSidebar.open {
opacity: 1;
visibility: visible;
transform: translateX(0);
transition: opacity 0.25s,
transform 0.5s cubic-bezier(0.19, 1, 0.22, 1);
}
.dark .VPSidebar {

@ -14,6 +14,7 @@ import { hasActiveLink as containsActiveLink } from '../support/sidebar'
import { useData } from './data'
const isOpen = ref(false)
const isCollapsed = ref(false)
/**
* a11y: cache the element that opened the Sidebar (the menu button) then
@ -57,11 +58,17 @@ export function useSidebarControl() {
isOpen.value ? close() : open()
}
function toggleCollapse() {
isCollapsed.value = !isCollapsed.value
}
return {
isOpen,
open,
close,
toggle
toggle,
isCollapsed,
toggleCollapse
}
}

@ -85,6 +85,9 @@
.vpi-corner-down-left {
--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M20 4v7a4 4 0 0 1-4 4H4'/%3E%3Cpath d='m9 10l-5 5l5 5'/%3E%3C/g%3E%3C/svg%3E");
}
.vpi-collapse {
--icon: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUiPgogICAgICAgIDxyZWN0IHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgeD0iMyIgeT0iMyIgcng9IjIiLz4KICAgICAgICA8cGF0aCBkPSJNOSAzdjE4Ii8+CiAgICA8L3N2Zz4=');
}
:root {
/* clipboard */
--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3C/g%3E%3C/svg%3E");

Loading…
Cancel
Save