site: refactor responsive related logic

This commit is contained in:
07akioni 2021-06-05 12:05:41 +08:00
parent 54b8b61c02
commit 66ba55e326
8 changed files with 66 additions and 172 deletions

View File

@ -97,25 +97,21 @@ function genScript (demoInfos, components = [], url, forceShowAnchor) {
const script = `<script>
${importStmts}
import { computed } from 'vue'
import { useBreakpoint, useMemo } from 'vooks'
import { useMemo } from 'vooks'
import { useDisplayMode } from '/demo/store'
import { useIsMobile } from '/demo/utils/composables'
export default {
components: {
${componentStmts}
},
setup () {
const breakpointRef = useBreakpoint()
const isMobileRef = useIsMobile()
const showAnchorRef = useMemo(() => {
const { value: breakpoint } = breakpointRef
if (breakpoint === 'xs' || breakpoint === 's') {
return false
}
if (isMobileRef.value) return false
return ${showAnchor}
})
const useSmallPaddingRef = useMemo(() => {
return breakpointRef.value === 'xs'
})
const useSmallPaddingRef = isMobileRef
return {
showAnchor: showAnchorRef,
displayMode: useDisplayMode(),

View File

@ -1,5 +1,5 @@
<template>
<n-layout :position="isXs ? undefined : 'absolute'" class="root-layout">
<n-layout :position="isMobile ? 'static' : 'absolute'" class="root-layout">
<site-header />
<router-view />
</n-layout>
@ -10,7 +10,7 @@ import { onMounted } from 'vue'
import { useLoadingBar } from 'naive-ui'
import SiteHeader from './SiteHeader.vue'
import { loadingBarApiRef } from './routes/router'
import { useIsXs } from './utils/composables'
import { useIsMobile } from './utils/composables'
export default {
name: 'Site',
@ -19,13 +19,13 @@ export default {
},
setup () {
const loadingBar = useLoadingBar()
const isXsRef = useIsXs()
const isMobileRef = useIsMobile()
onMounted(() => {
loadingBarApiRef.value = loadingBar
loadingBar.finish()
})
return {
isXs: isXsRef
isMobile: isMobileRef
}
}
}

View File

@ -2,10 +2,10 @@
<n-layout-header bordered class="nav" :style="style">
<n-text tag="div" class="ui-logo" :depth="1" @click="handleLogoClick">
<img src="./assets/images/naivelogo.svg" />
<span v-if="!isXs">Naive UI</span>
<span v-if="!isMobile">Naive UI</span>
</n-text>
<div :style="!isXs ? 'display: flex; align-items: center;' : ''">
<div class="nav-menu" v-if="!isS">
<div :style="!isMobile ? 'display: flex; align-items: center;' : ''">
<div class="nav-menu" v-if="!(isMobile || isTablet)">
<n-menu
mode="horizontal"
:value="menuValue"
@ -15,7 +15,7 @@
</div>
<n-auto-complete
v-model:value="searchPattern"
:style="!isXs ? 'width: 216px; margin-left: 24px' : undefined"
:style="!isMobile ? 'width: 216px; margin-left: 24px' : undefined"
:placeholder="t('searchPlaceholder')"
:options="searchOptions"
clear-after-select
@ -24,7 +24,7 @@
/>
</div>
<n-popover
v-if="isXs"
v-if="isMobile || isTablet"
style="padding: 0; width: 288px"
placement="bottom-end"
display-directive="show"
@ -35,50 +35,13 @@
</template>
<div style="overflow: auto; max-height: 79vh">
<n-menu
:value="xsMenuValue"
:options="xsMenuOptions"
:value="mobileMenuValue"
:options="mobileMenuOptions"
:indent="18"
@update:value="handleUpdateXsMenu"
@update:value="handleUpdateMobileMenu"
/>
</div>
</n-popover>
<n-popover
v-else-if="isS"
style="padding: 0; width: 288px"
placement="bottom-end"
display-directive="show"
trigger="hover"
>
<template #trigger>
<n-icon size="20" style="margin-left: 12px"><menu-outline /></n-icon>
</template>
<div style="overflow: auto; max-height: 75vh">
<n-menu
:value="sMenuValue"
:options="sMenuOptions"
:indent="18"
@update:value="handleUpdateSMenu"
/>
</div>
</n-popover>
<!-- <div style="display: flex" v-else-if="isM">
<n-popover
style="padding: 0; width: 180px"
placement="bottom-end"
display-directive="show"
trigger="hover"
>
<template #trigger>
<n-icon size="20" style="margin-left: 12px"><menu-outline /></n-icon>
</template>
<n-menu
:value="mMenuValue"
:options="mMenuOptions"
:indent="18"
@update:value="handleUpdateMMenu"
/>
</n-popover>
</div> -->
<div class="nav-end" v-else>
<n-button text class="nav-picker" @click="handleLocaleUpdate">
{{ localeLabelMap[locale] }}
@ -118,7 +81,7 @@ import { useRouter, useRoute } from 'vue-router'
import { useMessage, version } from 'naive-ui'
import { MenuOutline } from '@vicons/ionicons5'
import { repoUrl } from './utils/github-url'
import { i18n, useIsXs, useIsM, useIsS } from './utils/composables'
import { i18n, useIsMobile, useIsTablet } from './utils/composables'
import { findMenuValue } from './utils/route'
import {
useThemeName,
@ -225,75 +188,10 @@ export default {
return null
})
// m options
// const mMenuOptionsRef = computed(() => [
// {
// key: 'theme',
// title: themeLabelMapRef.value[themeNameRef.value]
// },
// {
// key: 'locale',
// title: localeNameRef.value === 'zh-CN' ? 'English' : ''
// }
// ])
// function handleUpdateMMenu (value, { path }) {
// if (value === 'theme') {
// handleThemeUpdate()
// } else if (value === 'locale') {
// if (localeNameRef.value === 'zh-CN') {
// localeNameRef.value = 'en-US'
// } else {
// localeNameRef.value = 'zh-CN'
// }
// }
// }
// s opitions
const sMenuOptionsRef = computed(() => {
return [
{
key: 'theme',
title: themeLabelMapRef.value[themeNameRef.value]
},
{
key: 'locale',
title: localeNameRef.value === 'zh-CN' ? 'English' : '中文'
},
{
key: 'home',
title: t('home')
},
{
key: 'doc',
title: t('doc')
},
{
key: 'component',
title: t('component')
},
{
key: 'github',
title: 'Github'
}
]
})
function handleUpdateSMenu (value) {
if (value === 'theme') {
handleThemeUpdate()
} else if (value === 'locale') {
if (localeNameRef.value === 'zh-CN') {
localeNameRef.value = 'en-US'
} else {
localeNameRef.value = 'zh-CN'
}
} else {
handleMenuUpdateValue(value)
}
}
// xs options
// mobile options
const docOptionsRef = useDocOptions()
const componentOptionsRef = useComponentOptions()
const xsMenuOptionsRef = computed(() => {
const mobileMenuOptionsRef = computed(() => {
return [
{
key: 'theme',
@ -323,11 +221,11 @@ export default {
}
]
})
const xsMenuValueRef = computed(() => {
const mobileMenuValueRef = computed(() => {
if (route.name === 'home') return 'home'
return findMenuValue(xsMenuOptionsRef.value, route.path)
return findMenuValue(mobileMenuOptionsRef.value, route.path)
})
function handleUpdateXsMenu (value, { path }) {
function handleUpdateMobileMenu (value, { path }) {
if (value === 'theme') {
handleThemeUpdate()
} else if (value === 'locale') {
@ -430,7 +328,8 @@ export default {
}
// common
const isXsRef = useIsXs()
const isMobileRef = useIsMobile()
const isTabletRef = useIsTablet()
function handleLogoClick () {
if (/^(\/[^/]+){2}$/.test(route.path)) {
message.info(t('alreadyHome'))
@ -440,15 +339,14 @@ export default {
}
return {
// xsMenuOptions,
// mobileMenuOptions,
tusimple: process.env.TUSIMPLE,
dev: __DEV__,
message,
t,
version,
isXs: isXsRef,
isM: useIsM(),
isS: useIsS(),
isMobile: isMobileRef,
isTablet: isTabletRef,
repoUrl,
// theme
theme: themeNameRef,
@ -474,22 +372,14 @@ export default {
menuOptions: menuOptionsRef,
menuValue: menuValueRef,
handleMenuUpdateValue,
// m menu
// mMenuOptions: mMenuOptionsRef,
// handleUpdateMMenu,
// mMenuValue: null,
// s menu
sMenuOptions: sMenuOptionsRef,
handleUpdateSMenu,
sMenuValue: menuValueRef,
// xs menu
xsMenuOptions: xsMenuOptionsRef,
handleUpdateXsMenu,
xsMenuValue: xsMenuValueRef,
// mobile & tablet menu
mobileMenuOptions: mobileMenuOptionsRef,
handleUpdateMobileMenu,
mobileMenuValue: mobileMenuValueRef,
// common
handleLogoClick,
style: computed(() => {
return isXsRef.value
return isMobileRef.value
? {
'--side-padding': '16px',
'grid-template-columns': 'auto 1fr auto'

View File

@ -2,8 +2,10 @@
<n-layout
id="doc-layout"
:has-sider="showSider"
:position="isXs ? undefined : 'absolute'"
:style="isXs ? undefined : 'top: var(--header-height)'"
:position="isMobile ? 'static' : 'absolute'"
:style="{
top: isMobile ? '' : 'var(--header-height)'
}"
>
<n-layout-sider
:native-scrollbar="false"
@ -23,6 +25,7 @@
<n-layout
ref="layoutInstRef"
:native-scrollbar="false"
:position="isMobile || showSider ? 'static' : 'absolute'"
content-style="min-height: calc(100vh - var(--header-height)); display: flex; flex-direction: column;"
>
<router-view />
@ -36,7 +39,7 @@
import { computed, watch, toRef, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { findMenuValue } from '../utils/route'
import { useIsXs } from '../utils/composables'
import { useIsMobile, useIsTablet } from '../utils/composables'
import SiteFooter from './home/Footer.vue'
import { useDocOptions, useComponentOptions } from '../store'
import { useMemo } from 'vooks'
@ -70,15 +73,16 @@ export default {
layoutInstRef.value.scrollTo(0, 0)
}
})
const isXsRef = useIsXs()
const isMobileRef = useIsMobile()
const isTabletRef = useIsTablet()
return {
showSider: useMemo(() => {
return !isXsRef.value
return !isMobileRef.value && !isTabletRef.value
}),
layoutInstRef,
options: optionsRef,
menuValue: menuValueRef,
isXs: isXsRef,
isMobile: isMobileRef,
handleMenuUpdateValue: (_, option) => {
router.push(option.path)
}

View File

@ -1,11 +1,11 @@
<template>
<n-layout
:native-scrollbar="false"
:position="isXs ? 'static' : 'absolute'"
:style="isXs ? undefined : 'top: var(--header-height);'"
:position="isMobile ? 'static' : 'absolute'"
:style="isMobile ? undefined : 'top: var(--header-height);'"
>
<div class="banner" style="overflow: hidden">
<right-image class="right-image" v-if="!isS" />
<right-image class="right-image" v-if="!(isMobile || isTablet)" />
<n-h1 :style="titleStyle" class="naive-title">
<span
@mouseenter="handleTitleMouseEnter"
@ -60,7 +60,7 @@ import { computed } from 'vue'
import LandingFooter from './Footer.vue'
import leftImage from './Left.vue'
import rightImage from './Right.vue'
import { i18n, useIsXs, useIsS } from '../../utils/composables'
import { i18n, useIsMobile, useIsTablet } from '../../utils/composables'
import { useThemeName } from '../../store'
export default {
@ -70,13 +70,13 @@ export default {
rightImage
},
setup () {
const isXsRef = useIsXs()
const isMobileRef = useIsMobile()
return {
isXs: isXsRef,
isS: useIsS(),
isMobile: isMobileRef,
isTablet: useIsTablet(),
theme: useThemeName(),
titleStyle: computed(() => {
if (isXsRef.value) {
if (isMobileRef.value) {
return 'margin-top: 0; font-size: 64px !important'
} else {
return 'margin-top: 0; font-size: 80px !important'

View File

@ -10,7 +10,7 @@ import {
useOsTheme
} from 'naive-ui'
import { TsConfigProvider } from '../../themes/tusimple/src'
import { i18n, useIsXs } from '../utils/composables'
import { i18n, useIsMobile } from '../utils/composables'
import {
createDocumentationMenuOptions,
createComponentMenuOptions
@ -125,10 +125,10 @@ const flattenedDocOptionsRef = computed(() => {
export function siteSetup () {
i18n.provide(computed(() => localeNameRef.value))
const isXsRef = useIsXs()
const isMobileRef = useIsMobile()
return {
themeEditorStyle: computed(() => {
return isXsRef.value ? 'right: 18px; bottom: 24px;' : undefined
return isMobileRef.value ? 'right: 18px; bottom: 24px;' : undefined
}),
configProvider: configProviderRef,
hljs,

View File

@ -1,5 +1,5 @@
import { defineComponent, Fragment, h, computed } from 'vue'
import { useIsM } from './composables'
import { useIsMobile, useIsTablet, useIsSmallDesktop } from './composables'
export default defineComponent({
name: 'ComponentDemos',
@ -10,9 +10,13 @@ export default defineComponent({
}
},
setup (props) {
const isMRef = useIsM()
const isMobileRef = useIsMobile()
const isTabletRef = useIsTablet()
const isSmallDesktop = useIsSmallDesktop()
const mergedColsRef = computed(() => {
return isMRef.value ? 1 : props.span
return isMobileRef.value || isTabletRef.value || isSmallDesktop.value
? 1
: props.span
})
return {
mergedCols: mergedColsRef

View File

@ -1,24 +1,24 @@
import { toRef, inject, provide, reactive, watchEffect } from 'vue'
import { useBreakpoint, useMemo } from 'vooks'
export function useIsXs () {
export function useIsMobile () {
const breakpointRef = useBreakpoint()
return useMemo(() => {
return breakpointRef.value === 'xs'
})
}
export function useIsS () {
export function useIsTablet () {
const breakpointRef = useBreakpoint()
return useMemo(() => {
return ['xs', 's'].includes(breakpointRef.value)
return breakpointRef.value === 's'
})
}
export function useIsM () {
export function useIsSmallDesktop () {
const breakpointRef = useBreakpoint()
return useMemo(() => {
return ['xs', 's', 'm'].includes(breakpointRef.value)
return breakpointRef.value === 'm'
})
}