Подвал работает только внутри CdsLayout — вне макета он ничего не отрисует и предупредит об этом в консоли. Верхнюю панель приложения собирает CdsHeader, содержимое обеих — CdsToolbar.
Вариации
Разделитель
Подвал прижат к нижнему краю и перекрывает контент, поэтому его границу стоит обозначить: bordered рисует линию, elevated — тень вверх. Тень нужнее, когда под подвалом продолжается длинный список.
<script setup lang="ts">
import { CdsFooter, CdsLayout, CdsMain, CdsPage, CdsRadio, CdsRadioGroup } from '@central-design-system/components';
import { ref } from 'vue';
const separator = ref('bordered');
</script>
<template>
<div class="flex flex-col gap-4">
<CdsRadioGroup v-model="separator" direction="horizontal" hide-details>
<CdsRadio value="none" label="Без разделителя" />
<CdsRadio value="bordered" label="Граница" />
<CdsRadio value="elevated" label="Тень" />
</CdsRadioGroup>
<div class="h-[240px]">
<CdsLayout container>
<CdsMain>
<CdsPage padding>
<div class="flex flex-col gap-2">
<div v-for="n in 6" :key="n" class="rounded-200 bg-surface-secondary p-4 text-content-primary">
Блок {{ n }}
</div>
</div>
</CdsPage>
</CdsMain>
<CdsFooter :bordered="separator === 'bordered'" :elevated="separator === 'elevated'">
<div class="flex h-[48px] items-center px-4 text-content-secondary">© 2026 Портал закупок</div>
</CdsFooter>
</CdsLayout>
</div>
</div>
</template>Цвет
Свойство bg-color красит фон подвала алиасом палитры, color — текст и иконки внутри. Если задан только фон, цвет текста подбирается контрастным автоматически.
<script setup lang="ts">
import { CdsFooter, CdsLayout, CdsMain, CdsPage, CdsRadio, CdsRadioGroup } from '@central-design-system/components';
import { ref } from 'vue';
const bgColor = ref('default');
</script>
<template>
<div class="flex flex-col gap-4">
<CdsRadioGroup v-model="bgColor" direction="horizontal" hide-details>
<CdsRadio value="default" label="Цвет темы" />
<CdsRadio value="neutral" label="neutral" />
<CdsRadio value="indigo" label="indigo" />
<CdsRadio value="teal" label="teal" />
</CdsRadioGroup>
<div class="h-[240px]">
<CdsLayout container>
<CdsMain>
<CdsPage padding>
<div class="rounded-200 bg-surface-secondary p-4 text-content-primary">Содержимое страницы</div>
</CdsPage>
</CdsMain>
<CdsFooter :bg-color="bgColor === 'default' ? undefined : bgColor">
<div class="flex h-[48px] items-center px-4">© 2026 Портал закупок</div>
</CdsFooter>
</CdsLayout>
</div>
</div>
</template>Плавающий режим
Свойство reveal прячет подвал при прокрутке вниз и возвращает при прокрутке вверх. Событие @reveal сообщает о смене видимости — например, чтобы подстроить счётчик выбранного.
<script setup lang="ts">
import { CdsFooter, CdsLayout, CdsMain, CdsPage } from '@central-design-system/components';
import { ref } from 'vue';
const revealed = ref(true);
</script>
<template>
<div class="h-[320px]">
<CdsLayout container>
<CdsMain>
<CdsPage padding>
<div class="mb-2 text-content-secondary">Подвал сейчас {{ revealed ? 'виден' : 'скрыт' }}</div>
<div class="flex flex-col gap-2">
<div v-for="n in 20" :key="n" class="rounded-200 bg-surface-secondary p-4 text-content-primary">
Блок {{ n }}
</div>
</div>
</CdsPage>
</CdsMain>
<CdsFooter reveal elevated @reveal="revealed = $event">
<div class="flex h-[48px] items-center px-4 text-content-secondary">Выбрано 0 из 20</div>
</CdsFooter>
</CdsLayout>
</div>
</template>Видимость
Свойство model-value убирает подвал совсем: макет перестаёт резервировать под него место, и контент занимает всю высоту. Так прячут панель действий, пока форма не изменена.
<script setup lang="ts">
import { CdsFooter, CdsLayout, CdsMain, CdsPage } from '@central-design-system/components';
</script>
<template>
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
<div class="flex flex-col gap-1">
<span class="text-content-secondary">Подвал виден</span>
<div class="h-[200px]">
<CdsLayout container>
<CdsMain>
<CdsPage padding>
<div class="rounded-200 bg-surface-secondary p-4 text-content-primary">Контент страницы</div>
</CdsPage>
</CdsMain>
<CdsFooter bordered>
<div class="flex h-[48px] items-center px-4 text-content-secondary">© 2026 Портал закупок</div>
</CdsFooter>
</CdsLayout>
</div>
</div>
<div class="flex flex-col gap-1">
<span class="text-content-secondary">:model-value="false"</span>
<div class="h-[200px]">
<CdsLayout container>
<CdsMain>
<CdsPage padding>
<div class="rounded-200 bg-surface-secondary p-4 text-content-primary">
Подвал скрыт — контент занимает всю высоту
</div>
</CdsPage>
</CdsMain>
<CdsFooter :model-value="false" bordered>
<div class="flex h-[48px] items-center px-4 text-content-secondary">© 2026 Портал закупок</div>
</CdsFooter>
</CdsLayout>
</div>
</div>
</div>
</template>Рекомендации
Сценарии использования
Подвал сайта
Копирайт слева, служебные ссылки справа — привычная раскладка, которую ищут внизу страницы. Высота задаётся содержимым, height подсказывает макету ожидаемое значение до первого замера.
<script setup lang="ts">
import { CdsFooter, CdsLayout, CdsLink, CdsMain, CdsPage } from '@central-design-system/components';
</script>
<template>
<div class="h-[280px]">
<CdsLayout container>
<CdsMain>
<CdsPage padding>
<div class="rounded-200 bg-surface-secondary p-4 text-content-primary">Содержимое страницы</div>
</CdsPage>
</CdsMain>
<CdsFooter bordered :height="56">
<div class="flex h-[56px] flex-wrap items-center justify-between gap-2 px-4">
<span class="text-content-secondary">© 2026 Портал закупок</span>
<span class="flex items-center gap-4">
<CdsLink href="#">Помощь</CdsLink>
<CdsLink href="#">Конфиденциальность</CdsLink>
<CdsLink href="#">Контакты</CdsLink>
</span>
</div>
</CdsFooter>
</CdsLayout>
</div>
</template>Панель действий формы
На длинной форме кнопки «Отмена» и «Опубликовать» живут в подвале: они видны на любой прокрутке, и до них не нужно добираться. CdsToolbarTitle растягивается и прижимает кнопки к правому краю, elevated отделяет панель от полей.
<script setup lang="ts">
import {
CdsButton,
CdsFooter,
CdsForm,
CdsLayout,
CdsMain,
CdsPage,
CdsTextArea,
CdsTextInput,
CdsToolbar,
CdsToolbarTitle
} from '@central-design-system/components';
import { ref } from 'vue';
const saving = ref(false);
function save() {
saving.value = true;
setTimeout(() => {
saving.value = false;
}, 1500);
}
</script>
<template>
<div class="h-[360px]">
<CdsLayout container>
<CdsMain>
<CdsPage padding>
<CdsForm class="flex flex-col gap-2">
<CdsTextInput label="Название закупки" />
<CdsTextInput label="Заказчик" />
<CdsTextArea label="Описание" :rows="6" />
<CdsTextInput label="Контактное лицо" />
<CdsTextInput label="Телефон" />
</CdsForm>
</CdsPage>
</CdsMain>
<CdsFooter elevated :height="56">
<CdsToolbar class="h-[56px] gap-2">
<CdsToolbarTitle class="text-content-secondary">Черновик сохраняется автоматически</CdsToolbarTitle>
<CdsButton variant="soft" color="neutral">Отмена</CdsButton>
<CdsButton :loading="saving" @click="save">Опубликовать</CdsButton>
</CdsToolbar>
</CdsFooter>
</CdsLayout>
</div>
</template>API
Пропсы
| Имя | Тип | По умолчанию | Описание |
|---|---|---|---|
bgColor | string | undefined | — | Цвет фона компонента |
bordered | boolean | undefined | false | Отображение границы. |
color | string | undefined | — | Цвет компонента |
elevated | boolean | undefined | false | Отображение тени. |
height | string | number | undefined | 50 | Высота элемента. |
modelValue | boolean | undefined | true | Видимость элемента в макете. |
reveal | boolean | undefined | false | Плавающий режим: элемент появляется/скрывается при скролле. |
revealOffset | number | undefined | 250 | Порог скролла (px), до которого плавающий элемент остаётся видимым. |
theme | string | undefined | — | Тема компонента |
События
| Имя | Тип | Описание |
|---|---|---|
focusin | [event: FocusEvent] | Фокус внутри подвала. |
reveal | [value: boolean] | Изменение видимости плавающего подвала. |
Слоты
| Имя | Тип | Описание |
|---|---|---|
default | any | Содержимое подвала (CdsToolbar и др.). |