VEGA-4499: адаптация UI главной страницы документации

This commit is contained in:
Дмитрий Захаров
2025-08-04 14:11:34 +03:00
parent 17a06a1ed0
commit 255f2ffe9d
27 changed files with 919 additions and 225 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "docs", "name": "docs",
"version": "0.5.0", "version": "0.6.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "docs", "name": "docs",
"version": "0.5.0", "version": "0.6.1",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@beeline/design-tokens": "^1.31.0", "@beeline/design-tokens": "^1.31.0",
+13 -1
View File
@@ -26,6 +26,12 @@ export const overrideComponents = () => (
new URL('./theme/components/CustomContent.vue', import.meta.url) new URL('./theme/components/CustomContent.vue', import.meta.url)
) )
}, },
{
find: /^.*\/VPHome\.vue$/,
replacement: fileURLToPath(
new URL('./theme/components/CustomHome.vue', import.meta.url)
)
},
{ {
find: /^.*\/VPDocFooter\.vue$/, find: /^.*\/VPDocFooter\.vue$/,
replacement: fileURLToPath( replacement: fileURLToPath(
@@ -41,7 +47,7 @@ export const overrideComponents = () => (
{ {
find: /^.*\/VPFeature\.vue$/, find: /^.*\/VPFeature\.vue$/,
replacement: fileURLToPath( replacement: fileURLToPath(
new URL('./theme/components/CustomFeature.vue', import.meta.url) new URL('./theme/components/CustomHomeFeature.vue', import.meta.url)
) )
}, },
{ {
@@ -62,6 +68,12 @@ export const overrideComponents = () => (
new URL('./theme/components/CustomNavBarSearchButton.vue', import.meta.url) new URL('./theme/components/CustomNavBarSearchButton.vue', import.meta.url)
) )
}, },
{
find: /^.*\/VPHomeHero\.vue$/,
replacement: fileURLToPath(
new URL('./theme/components/CustomHomeHero.vue', import.meta.url)
)
},
{ {
find: /^.*\/VPLocalSearchBox\.vue$/, find: /^.*\/VPLocalSearchBox\.vue$/,
replacement: fileURLToPath( replacement: fileURLToPath(
@@ -11,49 +11,82 @@ const { hasSidebar } = useSidebar()
</script> </script>
<template> <template>
<div <div class="VPContent CustomContent" id="VPContent" :class="{
class="VPContent CustomContent"
id="VPContent"
:class="{
'has-sidebar': hasSidebar, 'has-sidebar': hasSidebar,
'is-home': frontmatter.layout === 'home' 'is-home': frontmatter.layout === 'home'
}" }">
> <slot name="not-found" v-if="page.isNotFound">
<slot name="not-found" v-if="page.isNotFound"><NotFound /></slot> <NotFound />
</slot>
<VPPage v-else-if="frontmatter.layout === 'page'"> <VPPage v-else-if="frontmatter.layout === 'page'">
<template #page-top><slot name="page-top" /></template> <template #page-top>
<template #page-bottom><slot name="page-bottom" /></template> <slot name="page-top" />
</template>
<template #page-bottom>
<slot name="page-bottom" />
</template>
</VPPage> </VPPage>
<VPHome v-else-if="frontmatter.layout === 'home'"> <VPHome v-else-if="frontmatter.layout === 'home'">
<template #home-hero-before><slot name="home-hero-before" /></template> <template #home-hero-before>
<template #home-hero-info><slot name="home-hero-info" /></template> <slot name="home-hero-before" />
<template #home-hero-image><slot name="home-hero-image" /></template> </template>
<template #home-hero-after><slot name="home-hero-after" /></template> <template #home-hero-info>
<template #home-features-before><slot name="home-features-before" /></template> <slot name="home-hero-info" />
<template #home-features-after><slot name="home-features-after" /></template> </template>
<template #home-hero-image>
<slot name="home-hero-image" />
</template>
<template #home-hero-after>
<slot name="home-hero-after" />
</template>
<template #home-features-before>
<slot name="home-features-before" />
</template>
<template #home-features-after>
<slot name="home-features-after" />
</template>
</VPHome> </VPHome>
<component <component v-else-if="frontmatter.layout && frontmatter.layout !== 'doc'" :is="frontmatter.layout" />
v-else-if="frontmatter.layout && frontmatter.layout !== 'doc'"
:is="frontmatter.layout"
/>
<CustomDoc v-else> <CustomDoc v-else>
<template #doc-top><slot name="doc-top" /></template> <template #doc-top>
<template #doc-bottom><slot name="doc-bottom" /></template> <slot name="doc-top" />
</template>
<template #doc-bottom>
<slot name="doc-bottom" />
</template>
<template #doc-footer-before><slot name="doc-footer-before" /></template> <template #doc-footer-before>
<template #doc-before><slot name="doc-before" /></template> <slot name="doc-footer-before" />
<template #doc-after><slot name="doc-after" /></template> </template>
<template #doc-before>
<slot name="doc-before" />
</template>
<template #doc-after>
<slot name="doc-after" />
</template>
<template #aside-top><slot name="aside-top" /></template> <template #aside-top>
<template #aside-outline-before><slot name="aside-outline-before" /></template> <slot name="aside-top" />
<template #aside-outline-after><slot name="aside-outline-after" /></template> </template>
<template #aside-ads-before><slot name="aside-ads-before" /></template> <template #aside-outline-before>
<template #aside-ads-after><slot name="aside-ads-after" /></template> <slot name="aside-outline-before" />
<template #aside-bottom><slot name="aside-bottom" /></template> </template>
<template #aside-outline-after>
<slot name="aside-outline-after" />
</template>
<template #aside-ads-before>
<slot name="aside-ads-before" />
</template>
<template #aside-ads-after>
<slot name="aside-ads-after" />
</template>
<template #aside-bottom>
<slot name="aside-bottom" />
</template>
</CustomDoc> </CustomDoc>
</div> </div>
</template> </template>
@@ -1,129 +0,0 @@
<script setup lang="ts">
import type { DefaultTheme } from 'vitepress/theme'
import VPImage from 'vitepress/dist/client/theme-default/components/VPImage.vue'
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue'
import VPIconArrowRight from 'vitepress/dist/client/theme-default/components/icons/VPIconArrowRight.vue'
defineProps<{
icon?: DefaultTheme.FeatureIcon
title: string
details?: string
link?: string
linkText?: string
rel?: string
target?: string
}>()
</script>
<template>
<VPLink
class="VPFeature CustomFeature"
:href="link"
:rel="rel"
:target="target"
:no-icon="true"
:tag="link ? 'a' : 'div'"
>
<article class="box">
<div v-if="typeof icon === 'object' && icon.wrap" class="icon">
<VPImage
:image="icon"
:alt="icon.alt"
:height="icon.height || 48"
:width="icon.width || 48"
/>
</div>
<VPImage
v-else-if="typeof icon === 'object'"
:image="icon"
:alt="icon.alt"
:height="icon.height || 48"
:width="icon.width || 48"
/>
<div v-else-if="icon" class="icon" v-html="icon"></div>
<h2 class="title" v-html="title"></h2>
<p v-if="details" class="details" v-html="details"></p>
<div v-if="linkText" class="link-text">
<p class="link-text-value">
{{ linkText }} <VPIconArrowRight class="link-text-icon" />
</p>
</div>
</article>
</VPLink>
</template>
<style scoped>
.VPFeature {
display: block;
border: 1px solid var(--vp-c-bg-soft);
border-radius: 12px;
height: 100%;
background-color: var(--vp-c-bg-soft);
transition: border-color 0.25s, background-color 0.25s;
}
.VPFeature.link:hover {
border-color: var(--vp-c-brand-1);
}
.box {
display: flex;
flex-direction: column;
padding: 24px;
height: 100%;
}
.box > :deep(.VPImage) {
margin-bottom: 20px;
}
.icon {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
border-radius: 6px;
background-color: var(--vp-c-default-soft);
width: 48px;
height: 48px;
font-size: 24px;
transition: background-color 0.25s;
}
.title {
line-height: 24px;
font-size: 18px;
font-weight: 500;
color: var(--color-text-active);
}
.details {
flex-grow: 1;
padding-top: 8px;
line-height: 24px;
font-size: 15px;
font-weight: 500;
color: var(--color-text-inactive);
}
.link-text {
padding-top: 8px;
}
.link-text-value {
display: flex;
align-items: center;
font-size: 14px;
font-weight: 500;
color: var(--vp-c-brand-1);
}
.link-text-icon {
display: inline-block;
margin-left: 6px;
width: 14px;
height: 14px;
fill: currentColor;
}
</style>
+45 -60
View File
@@ -1,8 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { type Ref, inject } from 'vue' import { type Ref, inject, ref } from 'vue'
import type { DefaultTheme } from 'vitepress/theme' import type { DefaultTheme } from 'vitepress/theme'
import CustomButton from './CustomButton.vue' import CustomButton from './CustomButton.vue'
import VPImage from 'vitepress/dist/client/theme-default/components/VPImage.vue' import VPImage from 'vitepress/dist/client/theme-default/components/VPImage.vue'
import HomeHeroSearchButton from './HomeHeroSearchButton.vue'
import VPLocalSearchBox from 'vitepress/dist/client/theme-default/components/VPLocalSearchBox.vue'
export interface HeroAction { export interface HeroAction {
theme?: 'brand' | 'alt' theme?: 'brand' | 'alt'
@@ -14,11 +16,14 @@ defineProps<{
name?: string name?: string
text?: string text?: string
tagline?: string tagline?: string
search?: boolean
image?: DefaultTheme.ThemeableImage image?: DefaultTheme.ThemeableImage
actions?: HeroAction[] actions?: HeroAction[]
}>() }>()
const heroImageSlotExists = inject('hero-image-slot-exists') as Ref<boolean> const heroImageSlotExists = inject('hero-image-slot-exists') as Ref<boolean>
const showSearch = ref(false)
</script> </script>
<template> <template>
@@ -27,21 +32,20 @@ const heroImageSlotExists = inject('hero-image-slot-exists') as Ref<boolean>
<div class="main"> <div class="main">
<slot name="home-hero-info"> <slot name="home-hero-info">
<h1 v-if="name" class="name"> <h1 v-if="name" class="name">
<span v-html="name" class="clip"></span> {{ name }}
</h1> </h1>
<p v-if="text" v-html="text" class="text"></p> <p v-if="text" v-html="text" class="text"></p>
<p v-if="tagline" v-html="tagline" class="tagline"></p> <p v-if="tagline" v-html="tagline" class="tagline"></p>
</slot> </slot>
<div v-if="search" class="VPHeroSearchWrapper">
<VPLocalSearchBox v-if="showSearch" @close="showSearch = false" />
<HomeHeroSearchButton @click="showSearch = true" />
</div>
<div v-if="actions" class="actions"> <div v-if="actions" class="actions">
<div v-for="action in actions" :key="action.link" class="action"> <div v-for="action in actions" :key="action.link" class="action">
<CustomButton <CustomButton tag="a" size="medium" :theme="action.theme" :text="action.text" :href="action.link" />
tag="a"
size="medium"
:theme="action.theme"
:text="action.text"
:href="action.link"
/>
</div> </div>
</div> </div>
</div> </div>
@@ -59,6 +63,9 @@ const heroImageSlotExists = inject('hero-image-slot-exists') as Ref<boolean>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
@use "@beeline/design-tokens/scss/tokens/themes";
@use "@beeline/design-tokens/scss/tokens/globals/sizes";
@use "@beeline/design-tokens/scss/mixin";
.VPHero { .VPHero {
margin-top: calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1); margin-top: calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);
padding: calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px; padding: calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px;
@@ -80,7 +87,7 @@ const heroImageSlotExists = inject('hero-image-slot-exists') as Ref<boolean>
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin: 0 auto; margin: 0 auto;
max-width: 1152px; max-width: 1080px;
} }
@media (min-width: 960px) { @media (min-width: 960px) {
@@ -95,46 +102,41 @@ const heroImageSlotExists = inject('hero-image-slot-exists') as Ref<boolean>
order: 2; order: 2;
flex-grow: 1; flex-grow: 1;
flex-shrink: 0; flex-shrink: 0;
} background-color: themes.$color-background-secondary;
padding: 98px 92px;
.VPHero.has-image .container { border-radius: sizes.$size-border-radius-x6;
text-align: center;
}
@media (min-width: 960px) {
.VPHero.has-image .container { .VPHero.has-image .container {
text-align: left; text-align: center;
} }
}
@media (min-width: 960px) {
.main {
order: 1;
width: calc((100% / 3) * 2);
}
@media (min-width: 960px) { .VPHero.has-image .main {
.main { max-width: 592px;
order: 1; }
width: calc((100% / 3) * 2);
} }
.VPHero.has-image .main { .name,
max-width: 592px; .text {
@include mixin.h1;
white-space: pre-wrap;
} }
}
.name, .VPHero.has-image .name,
.text { .VPHero.has-image .text {
max-width: 392px; margin: 0 auto;
letter-spacing: -0.4px; }
line-height: 40px;
font-size: 32px; .name {
font-weight: 700; color: themes.$color-text-active;
white-space: pre-wrap; padding-bottom: 40px;
} text-align: center;
}
.VPHero.has-image .name,
.VPHero.has-image .text {
margin: 0 auto;
}
.name {
color: var(--vp-home-hero-name-color);
} }
.clip { .clip {
@@ -144,22 +146,7 @@ const heroImageSlotExists = inject('hero-image-slot-exists') as Ref<boolean>
-webkit-text-fill-color: var(--vp-home-hero-name-color); -webkit-text-fill-color: var(--vp-home-hero-name-color);
} }
@media (min-width: 640px) {
.name,
.text {
max-width: 576px;
line-height: 56px;
font-size: 48px;
}
}
@media (min-width: 960px) { @media (min-width: 960px) {
.name,
.text {
line-height: 64px;
font-size: 56px;
}
.VPHero.has-image .name, .VPHero.has-image .name,
.VPHero.has-image .text { .VPHero.has-image .text {
margin: 0; margin: 0;
@@ -168,7 +155,6 @@ const heroImageSlotExists = inject('hero-image-slot-exists') as Ref<boolean>
.tagline { .tagline {
padding-top: 8px; padding-top: 8px;
max-width: 392px;
line-height: 28px; line-height: 28px;
font-size: 18px; font-size: 18px;
font-weight: 500; font-weight: 500;
@@ -183,7 +169,6 @@ const heroImageSlotExists = inject('hero-image-slot-exists') as Ref<boolean>
@media (min-width: 640px) { @media (min-width: 640px) {
.tagline { .tagline {
padding-top: 12px; padding-top: 12px;
max-width: 576px;
line-height: 32px; line-height: 32px;
font-size: 20px; font-size: 20px;
} }
@@ -0,0 +1,39 @@
<script setup lang="ts">
import VPHomeHero from 'vitepress/dist/client/theme-default/components/VPHomeHero.vue'
import CustomHomeFeatures from './CustomHomeFeatures.vue';
import CustomHomeServices from './CustomHomeServices.vue';
</script>
<template>
<div class="VPHome CustomHome">
<slot name="home-hero-before" />
<VPHomeHero>
<template #home-hero-info>
<slot name="home-hero-info" />
</template>
<template #home-hero-image>
<slot name="home-hero-image" />
</template>
</VPHomeHero>
<slot name="home-hero-after" />
<slot name="home-features-before" />
<CustomHomeFeatures />
<slot name="home-features-after" />
<CustomHomeServices />
<Content />
</div>
</template>
<style scoped>
.VPHome {
padding-bottom: 96px;
}
.VPHome :deep(.VPHomeSponsors) {
margin-top: 112px;
margin-bottom: -128px;
}
</style>
@@ -0,0 +1,92 @@
<script setup lang="ts">
import { withBase } from 'vitepress';
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue'
import { computed, useCssModule } from 'vue';
import { NAVBAR_HEIGHT } from '../constants'
const { disabled, scrollTo, link } = defineProps<{
icon: string
title: string
link?: string
scrollTo?: string
disabled?: boolean
}>()
const style = useCssModule()
const classes = computed(() => ({
[style.CustomFeature]: true,
[style.CustomFeatureDisabled]: disabled || !link,
[style.CustomFeatureWithScroll]: scrollTo && !disabled
}))
const handleClick = (event: Event) => {
if (scrollTo) {
const targetElTop = document.querySelector(scrollTo)?.getBoundingClientRect().top
if (targetElTop) {
event.stopPropagation()
window.scrollTo({ behavior: 'smooth', top: targetElTop + window.scrollY - NAVBAR_HEIGHT - 32 })
}
}
}
</script>
<template>
<Component :is="!disabled && link ? VPLink : 'article'" v-bind="{ ...(!disabled && link && { href: link }) }"
:class="classes" @click="handleClick">
<figure :class="$style.CustomFeatureImage">
<img :src="withBase(`img/features/${icon}.svg`)" :alt="title">
</figure>
<div :class="$style.CustomFeatureContent">
<h2 :class="$style.CustomFeatureTitle">
{{ title }}
</h2>
</div>
</Component>
</template>
<style lang="scss" module>
@use "@beeline/design-tokens/scss/tokens/globals/sizes";
@use "@beeline/design-tokens/scss/tokens/themes";
@use "@beeline/design-tokens/scss/mixin";
.CustomFeature {
$el: &;
border-radius: sizes.$size-border-radius-x6;
border: 1px solid themes.$color-border;
max-width: 344px;
&WithScroll {
cursor: pointer;
}
&Image {
background-color: themes.$color-background-secondary;
border-top-left-radius: sizes.$size-border-radius-x6;
border-top-right-radius: sizes.$size-border-radius-x6;
img {
margin: 0 auto;
width: 200px;
height: 200px;
}
}
&Content {
padding: sizes.$size-spacing-x8 sizes.$size-spacing-x6;
}
&Title {
@include mixin.h4;
color: themes.$color-text-active;
#{$el}Disabled & {
color: themes.$color-text-disabled;
}
#{$el}WithScroll & {
color: themes.$color-text-active;
}
}
}
</style>
@@ -0,0 +1,26 @@
<script setup lang="ts">
import { useData } from 'vitepress/dist/client/theme-default/composables/data'
import CustomHomeFeature from './CustomHomeFeature.vue'
const { frontmatter } = useData()
</script>
<template>
<div v-if="Array.isArray(frontmatter.features)" :class="$style.HomeFeatures">
<CustomHomeFeature v-for="feature in frontmatter.features" :key="feature.title" :title="feature.title"
:icon="feature.icon" :link="feature.link" :scrollTo="feature.scroll_to" :disabled="feature.disabled" />
</div>
</template>
<style lang="scss" module>
@use "@beeline/design-tokens/scss/tokens/globals/sizes";
.HomeFeatures {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: sizes.$size-spacing-x8 sizes.$size-spacing-x6;
max-width: 1080px;
margin: 0 auto;
margin-bottom: 80px;
}
</style>
@@ -0,0 +1,18 @@
<script setup lang="ts">
import { useData } from 'vitepress/dist/client/theme-default/composables/data'
import VPHero from 'vitepress/dist/client/theme-default/components/VPHero.vue'
const { frontmatter: fm } = useData()
</script>
<template>
<VPHero v-if="fm.hero" class="CustomHomeHero" :name="fm.hero.name" :text="fm.hero.text" :tagline="fm.hero.tagline"
:search="fm.hero.search" :image="fm.hero.image" :actions="fm.hero.actions">
<template #home-hero-info>
<slot name="home-hero-info" />
</template>
<template #home-hero-image>
<slot name="home-hero-image" />
</template>
</VPHero>
</template>
@@ -0,0 +1,100 @@
<template>
<div :class="$style.CustomHomeServiceCard">
<h3 :class="$style.CustomHomeServiceCardTitle">{{ title }}</h3>
<div :class="$style.CustomHomeServiceCardLinks">
<Component v-for="article in articles" :is="!article.disabled && article.link ? VPLink : 'div'"
v-bind="{ ...(!article.disabled && article.link && { href: article.link }) }"
:class="[$style.CustomHomeServiceCardLink, { [$style.CustomHomeServiceCardLinkDisabled]: article.disabled || !article.link }]">
<div :class="$style.CustomHomeServiceCardLinkTitle">
<div :class="$style.CustomHomeServiceCardLinkTitleIcon">
<CustomIcon :icon="(article.icon || 'cloud') as Icons" />
</div>
<div :class="$style.CustomHomeServiceCardLinkTitleText">
{{ article.title }}
</div>
</div>
<div :class="$style.CustomHomeServiceCardLinkDescription">
{{ article.description }}
</div>
</Component>
</div>
</div>
</template>
<script setup lang="ts">
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue'
import CustomIcon from './CustomIcon.vue'
import { Icons } from '@beeline/design-tokens/js/iconfont/icons'
export type ServiceArticle = {
title: string
description: string
icon: string
link?: string
disabled?: boolean
}
defineProps<{
title: string
articles: ServiceArticle[]
}>()
</script>
<style lang="scss" module>
@use "@beeline/design-tokens/scss/tokens/globals/sizes";
@use "@beeline/design-tokens/scss/tokens/themes";
@use "@beeline/design-tokens/scss/mixin";
.CustomHomeServiceCard {
background-color: themes.$color-background-secondary;
border-radius: sizes.$size-border-radius-x6;
padding: sizes.$size-spacing-x8 sizes.$size-spacing-x6;
&Title {
@include mixin.h4();
color: themes.$color-text-active;
margin-bottom: sizes.$size-spacing-x6;
}
&Links {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: sizes.$size-spacing-x6;
}
&Link {
$iconRightSpacing: 8px;
$iconSize: 20px;
color: themes.$color-text-active;
&Disabled {
color: themes.$color-text-disabled !important;
}
&Title {
margin-bottom: sizes.$size-spacing-x1;
display: flex;
align-items: center;
&Icon {
width: $iconSize;
height: $iconSize;
margin-right: $iconRightSpacing;
}
&Text {
@include mixin.subtitle2;
}
}
&Description {
padding-left: calc($iconSize + $iconRightSpacing);
color: themes.$color-text-inactive;
@include mixin.caption;
}
}
}
</style>
@@ -0,0 +1,41 @@
<template>
<div :class="$style.CustomHomeServices">
<h2 id="home-services-section-title" :class="$style.CustomHomeServicesTitle">Документация по сервисам</h2>
<div v-if="Array.isArray(frontmatter.services)" :class="$style.CustomHomeServicesList">
<CustomHomeServiceCard v-for="service in frontmatter.services" :key="service.title" :title="service.title"
:articles="service.articles" />
</div>
</div>
</template>
<script setup lang="ts">
import { useData } from 'vitepress';
import CustomHomeServiceCard from './CustomHomeServiceCard.vue';
const { frontmatter } = useData()
</script>
<style lang="scss" module>
@use "@beeline/design-tokens/scss/tokens/globals/sizes";
@use "@beeline/design-tokens/scss/tokens/themes";
@use "@beeline/design-tokens/scss/mixin";
.CustomHomeServices {
max-width: 1080px;
margin: 0 auto;
&Title {
@include mixin.h2;
text-align: center;
margin-bottom: 40px;
color: themes.$color-text-active;
}
&List {
display: flex;
flex-direction: column;
gap: sizes.$size-spacing-x6;
}
}
</style>
@@ -0,0 +1,36 @@
<template>
<i :class="['beeline-icons', `beeline-icons-${icon}`, classes]"></i>
</template>
<script setup lang="ts">
import { Icons } from '@beeline/design-tokens/js/iconfont/icons';
import { computed, useCssModule } from 'vue';
const { size = 'medium' } = defineProps<{
icon: Icons,
size?: 'large' | 'medium' | 'small'
}>()
const style = useCssModule()
const classes = computed(() => ({
[style.CustomIcon]: true,
[style.CustomIconLarge]: size === 'large',
[style.CustomIconSmall]: size === 'small'
}))
</script>
<style lang="scss" module>
@use "@beeline/design-tokens/scss/tokens/components/icon";
.CustomIcon {
font-size: icon.$icon-medium-size !important;
&Large {
font-size: icon.$icon-large-size !important;
}
&Small {
font-size: icon.$icon-small-size !important;
}
}
</style>
@@ -43,8 +43,12 @@ watchPostEffect(() => {
<div class="container"> <div class="container">
<div class="title"> <div class="title">
<CustomNavBarTitle> <CustomNavBarTitle>
<template #nav-bar-title-before><slot name="nav-bar-title-before" /></template> <template #nav-bar-title-before>
<template #nav-bar-title-after><slot name="nav-bar-title-after" /></template> <slot name="nav-bar-title-before" />
</template>
<template #nav-bar-title-after>
<slot name="nav-bar-title-after" />
</template>
</CustomNavBarTitle> </CustomNavBarTitle>
</div> </div>
@@ -0,0 +1,228 @@
<script lang="ts" setup>
import type { ButtonTranslations } from 'vitepress/types/local-search'
import { createSearchTranslate } from 'vitepress/dist/client/theme-default/support/translation'
// Button-Translations
const defaultTranslations: { button: ButtonTranslations } = {
button: {
buttonText: 'Поиск',
buttonAriaLabel: 'Поиск'
}
}
const $t = createSearchTranslate(defaultTranslations)
</script>
<template>
<button type="button" :class="$style.HomeHeroSearchButton" :aria-label="$t('button.buttonAriaLabel')">
<span :class="$style.HomeHeroSearchButtonContainer">
<!--
<svg :class="$style.HomeHeroSearchButtonIcon" width="24" height="24" viewBox="0 0 24 24" aria-label="search icon">
<path
d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z"
stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" />
</svg>
-->
<img :class="$style.HomeHeroSearchButtonIcon" src="/icons/search.svg" alt="Поиск">
<span :class="$style.HomeHeroSearchButtonPlaceholder">{{ $t('button.buttonText') }}</span>
</span>
<!--
<span class="DocSearch-Button-Keys">
<kbd class="DocSearch-Button-Key"></kbd>
<kbd class="DocSearch-Button-Key">K</kbd>
</span>
-->
</button>
</template>
<style lang="scss" module>
@use "@beeline/design-tokens/scss/tokens/themes";
@use "@beeline/design-tokens/scss/tokens/globals/sizes";
@use "@beeline/design-tokens/scss/mixin";
@use "@beeline/design-tokens/scss/tokens/components/search";
.HomeHeroSearchButton {
display: flex;
width: 100%;
align-items: center;
border-radius: search.$search-border-radius;
height: search.$search-medium-height;
background: search.$search-background-color;
&Container {
display: flex;
}
&Icon {
margin: 0 search.$search-category-icon-spacing;
color: themes.$color-text-inactive;
fill: currentColor;
}
&Placeholder {
@include mixin.body2;
color: themes.$color-text-disabled;
}
}
/*
[class*='DocSearch'] {
--docsearch-primary-color: var(--vp-c-brand-1);
--docsearch-highlight-color: var(--docsearch-primary-color);
--docsearch-text-color: var(--vp-c-text-1);
--docsearch-muted-color: var(--vp-c-text-2);
--docsearch-searchbox-shadow: none;
--docsearch-searchbox-background: transparent;
--docsearch-searchbox-focus-background: transparent;
--docsearch-key-gradient: transparent;
--docsearch-key-shadow: none;
--docsearch-modal-background: var(--vp-c-bg-soft);
--docsearch-footer-background: var(--vp-c-bg);
}
.dark [class*='DocSearch'] {
--docsearch-modal-shadow: none;
--docsearch-footer-shadow: none;
--docsearch-logo-color: var(--vp-c-text-2);
--docsearch-hit-background: var(--vp-c-default-soft);
--docsearch-hit-color: var(--vp-c-text-2);
--docsearch-hit-shadow: none;
}
*/
.DocSearch-Button {
display: flex;
justify-content: center;
align-items: center;
border-radius: 12px;
margin: 0;
padding: 0;
width: 48px;
height: 55px;
background: transparent;
transition: border-color 0.25s;
}
/*
.DocSearch-Button:hover {
// background: transparent;
}
.DocSearch-Button:focus {
outline: 1px dotted;
outline: 5px auto -webkit-focus-ring-color;
}
.DocSearch-Button:focus:not(:focus-visible) {
outline: none !important;
}
.DocSearch-Button .DocSearch-Button-Container {
display: flex;
align-items: center;
}
.DocSearch-Button .DocSearch-Search-Icon {
position: relative;
width: 16px;
height: 16px;
color: var(--vp-c-text-1);
fill: currentColor;
transition: color 0.5s;
}
.DocSearch-Button:hover .DocSearch-Search-Icon {
color: var(--vp-c-text-1);
}
@media (min-width: 768px) {
.DocSearch-Button .DocSearch-Search-Icon {
top: 1px;
margin-right: 8px;
width: 14px;
height: 14px;
color: var(--vp-c-text-2);
}
}
.DocSearch-Button .DocSearch-Button-Placeholder {
display: none;
margin-top: 2px;
padding: 0 16px 0 0;
font-size: 13px;
font-weight: 500;
color: var(--vp-c-text-2);
transition: color 0.5s;
}
.DocSearch-Button:hover .DocSearch-Button-Placeholder {
color: var(--vp-c-text-1);
}
@media (min-width: 768px) {
.DocSearch-Button .DocSearch-Button-Placeholder {
display: inline-block;
}
}
*/
/*
.DocSearch-Button .DocSearch-Button-Keys {
direction: ltr;
display: none;
min-width: auto;
}
@media (min-width: 768px) {
.DocSearch-Button .DocSearch-Button-Keys {
display: flex;
align-items: center;
}
}
.DocSearch-Button .DocSearch-Button-Key {
display: block;
margin: 2px 0 0 0;
border: 1px solid var(--vp-c-divider);
border-right: none;
border-radius: 4px 0 0 4px;
padding-left: 6px;
min-width: 0;
width: auto;
height: 22px;
line-height: 22px;
font-family: var(--vp-font-family-base);
font-size: 12px;
font-weight: 500;
transition: color 0.5s, border-color 0.5s;
}
.DocSearch-Button .DocSearch-Button-Key+.DocSearch-Button-Key {
border-right: 1px solid var(--vp-c-divider);
border-left: none;
border-radius: 0 4px 4px 0;
padding-left: 2px;
padding-right: 6px;
}
.DocSearch-Button .DocSearch-Button-Key:first-child {
font-size: 0 !important;
}
.DocSearch-Button .DocSearch-Button-Key:first-child:after {
content: 'Ctrl';
font-size: 12px;
letter-spacing: normal;
color: var(--docsearch-muted-color);
}
.mac .DocSearch-Button .DocSearch-Button-Key:first-child:after {
content: '\2318';
}
.DocSearch-Button .DocSearch-Button-Key:first-child>* {
display: none;
}
*/
</style>
+1
View File
@@ -0,0 +1 @@
export const NAVBAR_HEIGHT = 64
+5
View File
@@ -1,3 +1,8 @@
@use "@beeline/design-tokens/scss/iconfont/iconfont" with (
$font-path-iconfont: '/fonts/iconfont'
);
@use "@beeline/design-tokens/scss/iconfont/icons";
$font-path-beeline-sans: '/fonts/beeline-sans' !default; $font-path-beeline-sans: '/fonts/beeline-sans' !default;
@mixin beeline-sans-font($type, $weight, $style: normal) { @mixin beeline-sans-font($type, $weight, $style: normal) {
+131 -1
View File
@@ -4,10 +4,11 @@ layout: home
hero: hero:
name: "Документация" name: "Документация"
search: true
#text: "Документация публичного облака" #text: "Документация публичного облака"
# tagline: My great project tagline # tagline: My great project tagline
features: features_old:
- title: Начало работы - title: Начало работы
details: Начало работы в Beeline Cloud, бесплатное тестирование и переход на платную версию. details: Начало работы в Beeline Cloud, бесплатное тестирование и переход на платную версию.
link: /start/index link: /start/index
@@ -27,5 +28,134 @@ features:
details: Аккаунт пользователя Beeline Cloud. details: Аккаунт пользователя Beeline Cloud.
link: /admin/index link: /admin/index
features:
- title: Документация по сервисам
scroll_to: "#home-services-section-title"
icon: services
- title: Обзор платформы
icon: overview
link: /platform/index
- title: Начало работы
icon: start
link: /start/index
- title: Биллинг
icon: billing
link: /billing/index
disabled: true
- title: Безопасность и стандарты
icon: security
link: ''
- title: Техподдержка
icon: support
link: /platform/support/support-overview
services:
- title: Инфраструктура
articles:
- title: Виртуальные машины
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: cloud
link: /compute/index
- title: Виртуальные дата-центры на VMware
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: cloud
link: /vdc/index
- title: Объектное хранилище S3
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: cloud
- title: Готовое облако 1С
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: cloud
- title: Частное облако
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: cloud
- title: Миграция виртуальных машин
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: cloud
- title: Kubernetes
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: cloud
- title: Сеть
articles:
- title: Сетевой балансировщик
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: network
- title: Выделенные сетевые соединения
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: network
- title: CDN. Доставка контента
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: network
- title: SD-WAN. Распределенные сети
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: network
- title: Резервное копирование и восстановление
articles:
- title: Резервное копирование
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: refresh
- title: Аварийное восстановление данных
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: refresh
- title: Базы данных
articles:
- title: ClickHouse
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: database
- title: MongoDB
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: database
- title: Аналитика
articles:
- title: Визуализация и анализ данных
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: graph_up
- title: Безопасность
articles:
- title: Межсетевой экран (NGFW)
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: security
- title: Защита веб-приложений (WAF)
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: security
- title: Защита серверов и рабочих мест
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: security
- title: Защита устройств пользователей
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: security
- title: Сканер уязвимостей
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: security
- title: Курсы кибербезопасности
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: security
- title: Многофакторная аутентификация
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: security
- title: Фильтрация почтового трафика
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: security
- title: Виртуальное рабочее место
articles:
- title: Виртуальные рабочие столы (VDI)
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: magic
- title: Платформа офисного пространства
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: magic
- title: Дизайн
articles:
- title: Дизайн-платформа Yellowbe
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: palette
- title: AI инструменты
articles:
- title: AI песочница
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: robot
- title: Мультимодельная AI фабрика
description: Пояснительный текст про сервис, буквально одно-два предложения
icon: robot
--- ---
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10.345 4.281 C 9.218 4.410,8.232 4.759,7.320 5.350 C 5.764 6.359,4.686 7.989,4.353 9.837 C 4.236 10.486,4.236 11.514,4.353 12.163 C 4.686 14.011,5.764 15.641,7.320 16.650 C 9.332 17.955,11.879 18.103,14.004 17.038 C 14.418 16.831,14.937 16.507,15.111 16.347 L 15.202 16.264 16.911 17.969 C 18.434 19.488,18.639 19.679,18.795 19.720 C 19.366 19.870,19.870 19.366,19.720 18.795 C 19.679 18.639,19.488 18.434,17.969 16.911 L 16.264 15.202 16.348 15.111 C 16.492 14.954,16.862 14.356,17.060 13.961 C 17.306 13.471,17.542 12.747,17.647 12.163 C 17.764 11.514,17.764 10.486,17.647 9.837 C 17.142 7.039,14.939 4.832,12.179 4.360 C 11.625 4.265,10.795 4.229,10.345 4.281 M12.080 5.860 C 14.142 6.315,15.699 7.889,16.149 9.972 C 16.248 10.432,16.248 11.568,16.149 12.028 C 15.747 13.891,14.425 15.389,12.668 15.975 C 12.071 16.173,11.753 16.220,11.000 16.220 C 10.020 16.220,9.463 16.092,8.640 15.678 C 8.110 15.412,7.723 15.129,7.279 14.683 C 6.542 13.941,6.075 13.076,5.853 12.040 C 5.750 11.562,5.750 10.438,5.853 9.960 C 6.076 8.920,6.539 8.061,7.279 7.318 C 8.104 6.490,8.994 6.026,10.160 5.817 C 10.561 5.745,11.672 5.770,12.080 5.860 " stroke="none" fill-rule="evenodd" fill="black"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 408 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 426 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 330 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 298 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 284 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 259 KiB