ContentSurround

A pair of "Previous" and "Next" buttons for sequential page navigation.
This component is only available when the @nuxt/content module is installed.

Usage

Use the surround prop with the surround value you get when fetching a page surround.

<script setup lang="ts">
import { withoutTrailingSlash, withTrailingSlash } from 'ufo'

const route = useRoute()

const { data: surround } = await useAsyncData(`${route.path}-surround`, async () => {
  const surround = await queryCollectionItemSurroundings('docs', withoutTrailingSlash(route.path), {
    fields: ['description']
  })
  if (surround[0]) {
    surround[0].path = withTrailingSlash(surround[0].path)
  }
  if (surround[1]) {
    surround[1].path = withTrailingSlash(surround[1].path)
  }

  return surround
})
</script>

<template>
  <B24ContentSurround :surround="(surround as any)" />
</template>

Prev / Next

Use the prev-icon and next-icon props to customize the buttons Icon.

<script setup lang="ts">
import RocketIcon from '@bitrix24/b24icons-vue/main/RocketIcon'
import type { ContentSurroundLink } from '@bitrix24/b24ui-nuxt'

const surround = ref<ContentSurroundLink[]>([
  {
    title: 'ContentSearchButton',
    path: '/docs/components/content-search-button/',
    stem: '3.components/content-search-button',
    description: 'A pre-styled Button to open the ContentSearch modal.'
  },
  {
    title: 'ContentToc',
    path: '/docs/components/content-toc/',
    stem: '3.components/content-toc',
    description: 'A sticky Table of Contents with customizable slots.'
  }
])
</script>

<template>
  <B24ContentSurround :prev-icon="RocketIcon" :next-icon="RocketIcon" :surround="surround" />
</template>

Examples

Within a page

Use the ContentSurround component in a page to display the prev and next links:

pages/[...slug].vue
<script setup lang="ts">
const route = useRoute()

const { data: page } = await useAsyncData(route.path, () => queryCollection('docs').path(route.path).first())
if (!page.value) {
  throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
}
</script>

<template>
  <template v-if="page">
    <ProseH1>{{ page.title }}</ProseH1>

    <template v-if="page?.body?.toc?.links?.length">
      <B24ContentToc :links="page.body.toc.links" />
    </template>

    <div>
      <ContentRenderer v-if="page.body" :value="page" />

      <B24Separator v-if="surround?.filter(Boolean).length" class="my-4" />

      <B24ContentSurround :surround="(surround as any)" />
    </div>
  </template>
</template>

API

Props

Prop Default Type
as'div'any

The element or component this component should render as.

prevIconicons.arrowLeftIconComponent

The icon displayed in the prev link.

nextIconicons.arrowRightIconComponent

The icon displayed in the next link.

surround T[]
b24ui { root?: ClassNameValue; link?: ClassNameValue; linkLeading?: ClassNameValue; linkLeadingIcon?: ClassNameValue; linkTitle?: ClassNameValue; linkDescription?: ClassNameValue; }

Slots

Slot Type
link{ link: T; b24ui: object; }
link-leading{ link: T; b24ui: object; }
link-title{ link: T; b24ui: object; }
link-description{ link: T; b24ui: object; }

Theme

app.config.ts
export default defineAppConfig({
  b24ui: {
    contentSurround: {
      slots: {
        root: 'grid grid-cols-1 sm:grid-cols-2 gap-[32px]',
        link: 'group block backdrop-blur-md rounded-(--ui-border-radius-md) px-[24px] py-[32px] bg-(--ui-color-design-outline-bg) border border-(--ui-color-design-outline-stroke) border-(length:--ui-design-outline-stroke-weight) cursor-pointer focus-visible:outline-(--ui-color-accent-main-primary) transition-colors',
        linkLeading: 'inline-flex items-center rounded-full select-none mb-[16px] p-[6px] bg-(--ui-color-design-outline-bg) group-hover:bg-[color-mix(in_srgb,_var(--ui-color-design-selection-bg)_100%,_var(--ui-color-bg-state-hover-default-hex)_var(--ui-color-bg-state-hover-default-opacity))] ring-(--ui-color-design-outline-stroke) ring-(length:--ui-design-outline-stroke-weight) group-hover:ring-[color-mix(in_srgb,_var(--ui-color-design-selection-stroke)_100%,_var(--ui-color-bg-state-hover-default-hex)_var(--ui-color-bg-state-hover-default-opacity))] transition',
        linkLeadingIcon: 'size-[20px] shrink-0 text-(--ui-color-design-outline-content-icon) group-hover:text-(--ui-color-design-outline-content-icon-alt) transition-[color,translate]',
        linkTitle: 'font-(--ui-font-weight-bold) text-(length:--ui-font-size-lg)/(--ui-font-line-height-lg) text-(--ui-color-design-outline-content) mb-[4px] truncate',
        linkDescription: 'text-(length:--ui-font-size-sm)/(--ui-font-line-height-sm) text-(--ui-color-design-outline-content-secondary) text-pretty line-clamp-2'
      },
      variants: {
        direction: {
          left: {
            linkLeadingIcon: 'group-active:-translate-x-0.5'
          },
          right: {
            link: 'text-right',
            linkLeadingIcon: 'group-active:translate-x-0.5'
          }
        }
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite'

export default defineConfig({
  plugins: [
    vue(),
    bitrix24UIPluginVite({
      b24ui: {
        contentSurround: {
          slots: {
            root: 'grid grid-cols-1 sm:grid-cols-2 gap-[32px]',
            link: 'group block backdrop-blur-md rounded-(--ui-border-radius-md) px-[24px] py-[32px] bg-(--ui-color-design-outline-bg) border border-(--ui-color-design-outline-stroke) border-(length:--ui-design-outline-stroke-weight) cursor-pointer focus-visible:outline-(--ui-color-accent-main-primary) transition-colors',
            linkLeading: 'inline-flex items-center rounded-full select-none mb-[16px] p-[6px] bg-(--ui-color-design-outline-bg) group-hover:bg-[color-mix(in_srgb,_var(--ui-color-design-selection-bg)_100%,_var(--ui-color-bg-state-hover-default-hex)_var(--ui-color-bg-state-hover-default-opacity))] ring-(--ui-color-design-outline-stroke) ring-(length:--ui-design-outline-stroke-weight) group-hover:ring-[color-mix(in_srgb,_var(--ui-color-design-selection-stroke)_100%,_var(--ui-color-bg-state-hover-default-hex)_var(--ui-color-bg-state-hover-default-opacity))] transition',
            linkLeadingIcon: 'size-[20px] shrink-0 text-(--ui-color-design-outline-content-icon) group-hover:text-(--ui-color-design-outline-content-icon-alt) transition-[color,translate]',
            linkTitle: 'font-(--ui-font-weight-bold) text-(length:--ui-font-size-lg)/(--ui-font-line-height-lg) text-(--ui-color-design-outline-content) mb-[4px] truncate',
            linkDescription: 'text-(length:--ui-font-size-sm)/(--ui-font-line-height-sm) text-(--ui-color-design-outline-content-secondary) text-pretty line-clamp-2'
          },
          variants: {
            direction: {
              left: {
                linkLeadingIcon: 'group-active:-translate-x-0.5'
              },
              right: {
                link: 'text-right',
                linkLeadingIcon: 'group-active:translate-x-0.5'
              }
            }
          }
        }
      }
    })
  ]
})
Releases
Published under MIT License.

Copyright © 2024-present Bitrix24