mirror of
https://github.com/ipfs/ipfs-blog.git
synced 2026-03-28 17:32:37 +01:00
feat: improve performance (#91)
This commit is contained in:
@@ -1,162 +0,0 @@
|
||||
<template>
|
||||
<RouterLink
|
||||
v-if="isInternal"
|
||||
:class="[classObject, type === 'link' && linkColor]"
|
||||
:to="link"
|
||||
>
|
||||
{{ item.text }}
|
||||
<SVGIcon
|
||||
v-if="iconName"
|
||||
class="cta__svg w-5 h-5"
|
||||
:name="iconName"
|
||||
:title="iconTitle"
|
||||
/>
|
||||
</RouterLink>
|
||||
<a
|
||||
v-else
|
||||
:class="[classObject, type === 'link' && linkColor]"
|
||||
:href="link"
|
||||
:target="target"
|
||||
:rel="rel"
|
||||
>
|
||||
{{ item.text }}
|
||||
<SVGIcon
|
||||
v-if="iconName"
|
||||
class="cta__svg w-5 h-5"
|
||||
:name="iconName"
|
||||
:title="iconTitle"
|
||||
/>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SVGIcon from '@theme/components/base/SVGIcon.vue'
|
||||
import { isExternal, isMailto, isTel, ensureExt } from '../util'
|
||||
|
||||
export default {
|
||||
name: 'CTA',
|
||||
components: { SVGIcon },
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: 'link',
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
iconTitle: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
iconPosition: {
|
||||
type: String,
|
||||
default: 'post',
|
||||
},
|
||||
item: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
linkColor: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
classObject() {
|
||||
return {
|
||||
btn: this.type !== 'link',
|
||||
[this.type]: true,
|
||||
[this.iconPosition]: true,
|
||||
'type-cta': true,
|
||||
}
|
||||
},
|
||||
link() {
|
||||
return ensureExt(this.item.link)
|
||||
},
|
||||
exact() {
|
||||
if (this.$site.locales) {
|
||||
return Object.keys(this.$site.locales).some(
|
||||
(rootLink) => rootLink === this.link
|
||||
)
|
||||
}
|
||||
return this.link === '/'
|
||||
},
|
||||
iconName() {
|
||||
if (this.type === 'link') {
|
||||
return this.isInternal ? 'arrow-right-icon' : 'arrow-up-icon'
|
||||
} else {
|
||||
return this.icon
|
||||
}
|
||||
},
|
||||
isNonHttpURI() {
|
||||
return isMailto(this.link) || isTel(this.link)
|
||||
},
|
||||
isBlankTarget() {
|
||||
return this.target === '_blank'
|
||||
},
|
||||
isInternal() {
|
||||
return !isExternal(this.link) && !this.isBlankTarget
|
||||
},
|
||||
target() {
|
||||
if (this.isNonHttpURI) {
|
||||
return null
|
||||
}
|
||||
if (this.item.target) {
|
||||
return this.item.target
|
||||
}
|
||||
return isExternal(this.link) ? '_blank' : ''
|
||||
},
|
||||
rel() {
|
||||
if (this.isNonHttpURI) {
|
||||
return null
|
||||
}
|
||||
if (this.item.rel) {
|
||||
return this.item.rel
|
||||
}
|
||||
return this.isBlankTarget ? 'noopener noreferrer' : ''
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="postcss">
|
||||
.btn {
|
||||
@apply rounded-full inline-flex py-2 px-6 items-center;
|
||||
@apply transition duration-300 ease-in-out;
|
||||
}
|
||||
.btn-outline {
|
||||
@apply border-solid border-2 border-transparent;
|
||||
background-image: linear-gradient(104.72deg, #1a74fc -4.4%, #4ef286 112.23%);
|
||||
background-origin: border-box;
|
||||
box-shadow: 0px 1000px 1px theme('colors.gray.light') inset;
|
||||
@apply text-deepBlue;
|
||||
}
|
||||
.btn-outline:hover {
|
||||
@apply shadow-none text-white;
|
||||
}
|
||||
.btn-fill {
|
||||
@apply bg-webBlue text-white fill-current;
|
||||
}
|
||||
.btn-fill:hover {
|
||||
@apply bg-deepBlue;
|
||||
}
|
||||
.link {
|
||||
@apply inline-flex items-center;
|
||||
@apply transition duration-300 ease-in-out;
|
||||
}
|
||||
.post {
|
||||
@apply flex-row;
|
||||
}
|
||||
|
||||
.post .cta__svg {
|
||||
@apply ml-2;
|
||||
}
|
||||
|
||||
.pre {
|
||||
@apply flex-row-reverse;
|
||||
}
|
||||
|
||||
.pre .cta__svg {
|
||||
@apply mr-2;
|
||||
}
|
||||
</style>
|
||||
@@ -1,54 +0,0 @@
|
||||
<template>
|
||||
<div :class="theme === 'dark' ? 'text-deepBlue' : 'text-white'">
|
||||
<LazyImage v-if="image" v-bind="image" class="mb-6" />
|
||||
<h3 class="type-h3 mb-3 lg:mb-6">{{ title }}</h3>
|
||||
<p class="type-p1" :class="[{ 'mb-6 lg:mb-8': cta && cta.item }]">
|
||||
{{ text }}
|
||||
</p>
|
||||
<CTA
|
||||
v-if="cta && cta.item"
|
||||
v-bind="cta"
|
||||
:link-color="
|
||||
theme === 'dark'
|
||||
? 'text-inherit hover:text-webBlue'
|
||||
: 'text-inherit border-b border-transparent hover:border-white'
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CTA from '@theme/components/CTA.vue'
|
||||
import LazyImage from '@theme/components/base/LazyImage.vue'
|
||||
export default {
|
||||
name: 'ColumnText',
|
||||
components: { CTA, LazyImage },
|
||||
props: {
|
||||
theme: {
|
||||
type: String,
|
||||
default: 'dark',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
cta: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
image: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="postcss">
|
||||
.image--eyebrow {
|
||||
max-width: 25%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,46 +0,0 @@
|
||||
<template>
|
||||
<div
|
||||
:class="[
|
||||
$page.frontmatter.slug,
|
||||
{ 'relative overflow-auto': content.subnavigation },
|
||||
]"
|
||||
>
|
||||
<Subnavigation
|
||||
v-if="content.subnavigation"
|
||||
v-bind="content.subnavigation"
|
||||
/>
|
||||
<component
|
||||
:is="block.component"
|
||||
v-for="(block, index) in content.body"
|
||||
:key="index"
|
||||
v-bind="block"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
// Import all components that can be rendered from frontmatter array
|
||||
import Column from '@theme/components/base/Column.vue'
|
||||
import Container from '@theme/components/base/Container.vue'
|
||||
import Section from '@theme/components/Section.vue'
|
||||
import Typography from '@theme/components/Typography.vue'
|
||||
|
||||
// layout compositions
|
||||
|
||||
export const components = {
|
||||
Column,
|
||||
Container,
|
||||
Section,
|
||||
Typography,
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'DynamicContent',
|
||||
components,
|
||||
props: {
|
||||
content: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -1,214 +0,0 @@
|
||||
<template>
|
||||
<div :class="['section', mergedTheme.background]">
|
||||
<div class="grid grid-margins grid-cols-12" :class="mergedTheme.grid">
|
||||
<div v-if="background.type === 'video'" class="absolute inset-0 z-0">
|
||||
<BackgroundVideo
|
||||
class="w-full h-full"
|
||||
v-bind="background"
|
||||
class-list="object-cover w-full h-full"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="background.type === 'image'" class="absolute inset-0 z-0">
|
||||
<LazyImage
|
||||
:class="[
|
||||
'w-full h-full',
|
||||
{ 'hidden md:block': background.mobileImg },
|
||||
]"
|
||||
v-bind="background.img"
|
||||
:img-class="['w-full h-full', background.size, background.position]"
|
||||
/>
|
||||
<LazyImage
|
||||
v-if="background.mobileImg"
|
||||
class="w-full h-full md:hidden"
|
||||
v-bind="background.mobileImg"
|
||||
:img-class="['w-full h-full', background.size, background.position]"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
:class="[
|
||||
'z-10',
|
||||
mergedTheme.content,
|
||||
extendedPadding
|
||||
? ['py-20 lg:pt-240px lg:pb-120px']
|
||||
: ['py-120px lg:py-140px'],
|
||||
inset ? 'col-span-10 col-start-2' : 'col-span-12',
|
||||
]"
|
||||
>
|
||||
<div v-if="title" v-transition class="grid grid-cols-12 z-10">
|
||||
<transition name="slide" appear>
|
||||
<h2
|
||||
:class="['col-span-12 section-title', mergedTheme.text]"
|
||||
:itemprop="mergedTheme.textMeta"
|
||||
>
|
||||
<span
|
||||
v-for="(t, i) in splitTitle"
|
||||
:key="i"
|
||||
class="anim"
|
||||
:style="{
|
||||
'animation-delay': i * 0.06 + 's',
|
||||
}"
|
||||
v-html="t"
|
||||
/>
|
||||
</h2>
|
||||
</transition>
|
||||
</div>
|
||||
<slot></slot>
|
||||
<div v-if="children">
|
||||
<div v-for="(child, index) in children" :key="index" class="z-10">
|
||||
<hr
|
||||
:class="[
|
||||
children.length > 2 && index === 0 ? 'my-10' : 'my-10 lg:mb-16',
|
||||
mergedTheme.hr,
|
||||
{ hidden: !title && index === 0 },
|
||||
{ hidden: child.hideDivider },
|
||||
]"
|
||||
/>
|
||||
<component :is="child.component" v-bind="child"></component>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BackgroundVideo from '@theme/components/base/BackgroundVideo.vue'
|
||||
import ColumnText from '@theme/components/ColumnText.vue'
|
||||
import Section from '@theme/components/Section.vue'
|
||||
import Column from '@theme/components/base/Column.vue'
|
||||
import Container from '@theme/components/base/Container.vue'
|
||||
import LazyImage from '@theme/components/base/LazyImage.vue'
|
||||
import TextBlock from '@theme/components/TextBlock.vue'
|
||||
|
||||
export default {
|
||||
name: 'Section',
|
||||
components: {
|
||||
BackgroundVideo,
|
||||
ColumnText,
|
||||
Column,
|
||||
Container,
|
||||
LazyImage,
|
||||
Section,
|
||||
TextBlock,
|
||||
},
|
||||
props: {
|
||||
background: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return { type: 'gradient', gradient: 'bg-gradient-1' }
|
||||
},
|
||||
},
|
||||
children: {
|
||||
type: Array,
|
||||
default: function () {
|
||||
return []
|
||||
},
|
||||
},
|
||||
extendedPadding: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
inset: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
theme: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
splitTitle() {
|
||||
return this.title.split(' ').map((s) => s + ' ')
|
||||
},
|
||||
mergedTheme() {
|
||||
switch (this.background.type) {
|
||||
case 'gradient': {
|
||||
return {
|
||||
...{
|
||||
background: this.background.gradient,
|
||||
content: '',
|
||||
text: 'text-white type-h1 lg:col-span-7',
|
||||
hr: 'hr-gradient',
|
||||
},
|
||||
...this.theme,
|
||||
}
|
||||
}
|
||||
case 'transparent': {
|
||||
return {
|
||||
...{
|
||||
background: 'bg-transparent',
|
||||
content: '',
|
||||
text: 'text-deepBlue type-h1 lg:col-span-7',
|
||||
hr: 'hr-gradient',
|
||||
},
|
||||
...this.theme,
|
||||
}
|
||||
}
|
||||
case 'image': {
|
||||
return {
|
||||
...{
|
||||
background: 'relative',
|
||||
content: '',
|
||||
text: 'text-white type-h1 lg:col-span-7',
|
||||
hr: 'hr-transparent',
|
||||
},
|
||||
...this.theme,
|
||||
}
|
||||
}
|
||||
case 'video': {
|
||||
return {
|
||||
...{
|
||||
background:
|
||||
'relative bg-gradient-2 video-min-height flex items-center',
|
||||
content: 'relative pointer-events-none',
|
||||
text: 'text-white type-h1 lg:col-span-7',
|
||||
hr: 'hr-transparent',
|
||||
},
|
||||
...this.theme,
|
||||
}
|
||||
}
|
||||
default: {
|
||||
return {
|
||||
...{
|
||||
background: '',
|
||||
content: '',
|
||||
text: '',
|
||||
hr: '',
|
||||
},
|
||||
...this.theme,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="postcss">
|
||||
@keyframes translate-slide-up {
|
||||
0% {
|
||||
transform: translateY(25%);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.section-title .anim {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
animation: translate-slide-up 0.75s cubic-bezier(0.5, 0, 0, 1) both;
|
||||
}
|
||||
|
||||
@screen lg {
|
||||
.video-min-height {
|
||||
min-height: 40vh;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,53 +0,0 @@
|
||||
<template>
|
||||
<div :class="[theme === 'dark' ? 'text-deepBlue' : 'text-white']">
|
||||
<LazyImage v-if="image" class="image--eyebrow mb-8" v-bind="image" />
|
||||
<p v-else-if="eyebrow" class="type-p3 mb-4">{{ eyebrow }}</p>
|
||||
<p class="type-h4 mb-8" v-html="text" />
|
||||
<CTA
|
||||
v-if="cta && cta.item"
|
||||
link-color="text-white border-b border-transparent hover:border-white"
|
||||
:icon="cta.icon"
|
||||
:icon-position="cta.iconPosition"
|
||||
:item="cta.item"
|
||||
:type="theme === 'dark' ? 'btn-outline' : 'link'"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CTA from '@theme/components/CTA.vue'
|
||||
import LazyImage from '@theme/components/base/LazyImage.vue'
|
||||
export default {
|
||||
name: 'TextBlock',
|
||||
components: { CTA, LazyImage },
|
||||
props: {
|
||||
eyebrow: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
theme: {
|
||||
type: String,
|
||||
default: 'dark',
|
||||
},
|
||||
cta: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
image: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="postcss">
|
||||
@screen md {
|
||||
.image--eyebrow {
|
||||
max-width: 25%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,83 +0,0 @@
|
||||
<template>
|
||||
<div class="type-p1 grid-margins">
|
||||
<h2 class="type-h2 mt-12 mb-12">Typography</h2>
|
||||
<div class="grid md:grid-cols-4 gap-8 mt-12">
|
||||
<div>
|
||||
<h1 class="type-h1">Type style 1</h1>
|
||||
<h2 class="type-h2">Type style 2</h2>
|
||||
<h3 class="type-h3">Type style 3</h3>
|
||||
<h4 class="type-h4">Type style 4</h4>
|
||||
<h5 class="type-h5 mb-12">Type style 5</h5>
|
||||
</div>
|
||||
<ul class="list-inside list-disc">
|
||||
<li>Unordered list items</li>
|
||||
<li>Unordered list items</li>
|
||||
<li>Unordered list items</li>
|
||||
</ul>
|
||||
<ol class="list-inside list-decimal">
|
||||
<li>Ordered list items</li>
|
||||
<li>Ordered list items</li>
|
||||
<li>Ordered list items</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="grid md:grid-cols-4 gap-8">
|
||||
<div>
|
||||
<h3 class="type-h5">P1</h3>
|
||||
<p class="type-p1">
|
||||
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
|
||||
<a>Soluta quibusdam aut incidunt tempore</a> assumenda eos commodi
|
||||
quia ipsam eveniet perferendis delectus, magni praesentium quas.
|
||||
Debitis mollitia quas perspiciatis vel quidem.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="type-h5">P2</h3>
|
||||
<p class="type-p2">
|
||||
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
|
||||
<a>Soluta quibusdam aut incidunt tempore</a> assumenda eos commodi
|
||||
quia ipsam eveniet perferendis delectus, magni praesentium quas.
|
||||
Debitis mollitia quas perspiciatis vel quidem.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="type-h5">P3</h3>
|
||||
<p class="type-p3">
|
||||
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
|
||||
<a>Soluta quibusdam aut incidunt tempore</a> assumenda eos commodi
|
||||
quia ipsam eveniet perferendis delectus, magni praesentium quas.
|
||||
Debitis mollitia quas perspiciatis vel quidem.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="type-h5">P4</h3>
|
||||
<p class="type-p4">
|
||||
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
|
||||
<a>Soluta quibusdam aut incidunt tempore</a> assumenda eos commodi
|
||||
quia ipsam eveniet perferendis delectus, magni praesentium quas.
|
||||
Debitis mollitia quas perspiciatis vel quidem.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="type-h2 mt-12 mb-12">Buttons</h2>
|
||||
<div class="grid md:grid-cols-4 gap-8 mb-12">
|
||||
<div v-for="(button, index) in buttons" :key="index">
|
||||
<CTA v-bind="button" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CTA from '@theme/components/CTA.vue'
|
||||
export default {
|
||||
name: 'Typography',
|
||||
components: { CTA },
|
||||
props: {
|
||||
buttons: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -1,81 +0,0 @@
|
||||
<template>
|
||||
<div class="relative">
|
||||
<video
|
||||
ref="videoElement"
|
||||
:class="classList"
|
||||
muted
|
||||
preload
|
||||
playsinline
|
||||
loop
|
||||
:poster="poster"
|
||||
>
|
||||
<source
|
||||
v-for="(src, type, index) in srcset"
|
||||
:key="index"
|
||||
:src="requireAsset(src)"
|
||||
:type="type"
|
||||
/>
|
||||
</video>
|
||||
<button
|
||||
aria-label="Toggle Video Play and Pause"
|
||||
class="absolute z-10"
|
||||
style="right: 20px; bottom: 20px"
|
||||
@click="togglePlayPause"
|
||||
>
|
||||
<SVGIcon
|
||||
:class-list="['h-4', 'w-4']"
|
||||
:name="videoBeingPlayed ? 'pause' : 'play'"
|
||||
:title="videoBeingPlayed ? 'Pause Video' : 'Play Video'"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SVGIcon from '@theme/components/base/SVGIcon.vue'
|
||||
import requireAsset from '@theme/components/mixins/requireAsset'
|
||||
|
||||
let player = null
|
||||
|
||||
export default {
|
||||
name: 'BackgroundVideo',
|
||||
components: { SVGIcon },
|
||||
mixins: [requireAsset],
|
||||
props: {
|
||||
classList: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
poster: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
srcset: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data: function () {
|
||||
return { videoBeingPlayed: false }
|
||||
},
|
||||
mounted: function () {
|
||||
player = this
|
||||
if (!window.matchMedia('prefers-reduced-motion: reduce)').matches) {
|
||||
this.playVideo()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
togglePlayPause: function () {
|
||||
return player.videoBeingPlayed ? this.pauseVideo() : this.playVideo()
|
||||
},
|
||||
playVideo: function () {
|
||||
this.$refs.videoElement.play()
|
||||
player.videoBeingPlayed = true
|
||||
},
|
||||
pauseVideo: function () {
|
||||
this.$refs.videoElement.pause()
|
||||
player.videoBeingPlayed = false
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -1,47 +0,0 @@
|
||||
<template>
|
||||
<div v-transition class="column">
|
||||
<div class="flex justify-between flex-wrap">
|
||||
<component
|
||||
:is="block.component"
|
||||
v-for="(block, index) in blocks"
|
||||
:key="index"
|
||||
v-bind="block"
|
||||
:component-index="index"
|
||||
class="w-full mb-20 lg:mb-0 last:mb-0"
|
||||
:class="computedClasses"
|
||||
></component>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ColumnText from '@theme/components/ColumnText.vue'
|
||||
|
||||
export default {
|
||||
name: 'Column',
|
||||
components: { ColumnText },
|
||||
props: {
|
||||
cols: { type: Number, default: 1 },
|
||||
blocks: { type: Array, required: true },
|
||||
},
|
||||
computed: {
|
||||
computedClasses() {
|
||||
const classes = [`col-${this.cols}`]
|
||||
|
||||
return classes
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="postcss">
|
||||
@screen lg {
|
||||
.col-2 {
|
||||
width: calc(40% - 32px);
|
||||
}
|
||||
|
||||
.col-3 {
|
||||
width: calc(30% - 32px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,24 +0,0 @@
|
||||
<template>
|
||||
<div class="grid-margins grid grid-cols-12 gap-2 lg:gap-8">
|
||||
<component :is="child.component" v-bind="child"></component>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Add as needed
|
||||
import Column from '@theme/components/base/Column.vue'
|
||||
import TextBlock from '@theme/components/TextBlock.vue'
|
||||
export default {
|
||||
name: 'Container',
|
||||
components: {
|
||||
Column,
|
||||
TextBlock,
|
||||
},
|
||||
props: {
|
||||
child: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -14,7 +14,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import withBase from '@theme/components/mixins/requireAsset'
|
||||
import withBase from '@theme/components/mixins/withBase'
|
||||
|
||||
export default {
|
||||
name: 'LazyImage',
|
||||
|
||||
8
src/.vuepress/theme/components/mixins/withBase.js
Normal file
8
src/.vuepress/theme/components/mixins/withBase.js
Normal file
@@ -0,0 +1,8 @@
|
||||
export default {
|
||||
methods: {
|
||||
withBase: function (path = '') {
|
||||
const { $withBase } = this.$root
|
||||
return path.charAt(0) === '/' ? $withBase.call(this, path) : path
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
<template>
|
||||
<Layout>
|
||||
<Section
|
||||
title="Pages"
|
||||
:component-index="0"
|
||||
:background="{ type: 'gradient', gradient: 'bg-gradient-2' }"
|
||||
/>
|
||||
<div class="container grid-margins py-10 type-rich">
|
||||
<ul>
|
||||
<li v-for="page in $pagination.pages" :key="page.title">
|
||||
<router-link class="page-link" :to="page.path">{{
|
||||
page.title
|
||||
}}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
<div>
|
||||
<router-link v-if="$pagination.hasPrev" :to="$pagination.prevLink"
|
||||
>Prev</router-link
|
||||
>
|
||||
<router-link v-if="$pagination.hasNext" :to="$pagination.nextLink"
|
||||
>Next</router-link
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Layout from '@theme/layouts/Layout.vue'
|
||||
import Section from '@theme/components/Section.vue'
|
||||
|
||||
export default {
|
||||
name: 'DirectoryPagination',
|
||||
components: {
|
||||
Layout,
|
||||
Section,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -1,22 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
<slot name="header"></slot>
|
||||
<DynamicContent
|
||||
v-if="$page.frontmatter.body"
|
||||
:content="$page.frontmatter"
|
||||
/>
|
||||
<slot></slot>
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DynamicContent from '@theme/components/DynamicContent.vue'
|
||||
|
||||
export default {
|
||||
name: 'Layout',
|
||||
components: {
|
||||
DynamicContent,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<Section
|
||||
:title="$page.title"
|
||||
:component-index="0"
|
||||
:background="{ type: 'gradient', gradient: 'bg-gradient-4' }"
|
||||
/>
|
||||
<div class="grid-margins">
|
||||
<Content class="simple-page type-rich my-10 max-w-3xl" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Section from '@theme/components/Section'
|
||||
export default {
|
||||
components: {
|
||||
Section,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="postcss">
|
||||
.simple-page.type-rich blockquote {
|
||||
@apply text-lg leading-normal pl-6;
|
||||
}
|
||||
</style>
|
||||
@@ -1,25 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-for="(block, index) in $page.frontmatter.body" :key="index">
|
||||
<h1 v-if="block.showTitle" class="type-h2 mt-12 mb-12 grid-margins">
|
||||
{{ block.component }}
|
||||
</h1>
|
||||
<component
|
||||
:is="block.component"
|
||||
v-bind="block"
|
||||
:component-index="index"
|
||||
></component>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { components } from '@theme/components/DynamicContent.vue'
|
||||
|
||||
export default {
|
||||
name: 'StyleGuide',
|
||||
components: {
|
||||
...components,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -1,22 +0,0 @@
|
||||
<template>
|
||||
<Layout>
|
||||
<ul>
|
||||
<li v-for="tag in $tag.list" :key="tag.name">
|
||||
<router-link class="page-link" :to="tag.path">{{
|
||||
tag.name
|
||||
}}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</Layout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Layout from '@theme/layouts/Layout.vue'
|
||||
|
||||
export default {
|
||||
name: 'TagIndex',
|
||||
components: {
|
||||
Layout,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -1,22 +0,0 @@
|
||||
<template>
|
||||
<Layout>
|
||||
<ul>
|
||||
<li v-for="tag in $tag.list" :key="tag.name">
|
||||
<router-link class="page-link" :to="tag.path">{{
|
||||
tag.name
|
||||
}}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</Layout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Layout from '@theme/layouts/Layout.vue'
|
||||
|
||||
export default {
|
||||
name: 'TagItem',
|
||||
components: {
|
||||
Layout,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user