Skip to content

Layout 布局

Layout 是 AI 应用页面的通用布局组件,可用于搭建聊天页、工作台和多面板操作界面。

它提供以下能力:

  • 页面骨架:统一组织头部、主区、底部与左右侧栏
  • 侧栏交互:支持展开、收起、拖拽改宽和 drawer 覆盖
  • 浮层布局:支持定位、拖拽和缩放
  • 代理滚动条:适用于内容列居中或限宽后,原生滚动条偏离主区右边界的场景

基础布局

Layout 提供 left-asideheadermainfooterright-aside 五个区域插槽,用于编排页面结构。

loading

布局模式

mode 控制 Layout 的整体形态,默认值为 normal

  • normal:普通页面骨架,参与文档流布局
  • floating:悬浮布局,脱离文档流,可用于构建悬浮工作区或拖拽窗口
loading

侧栏

侧栏由 leftAside / rightAside 控制,类型为 LayoutAsideOptions

侧栏内容通过 left-aside / right-aside 插槽提供。

展示形态

LayoutAsideOptions.mode 控制侧栏展示形态,默认值为 dock

  • dock:占据页面空间
  • drawer:覆盖在内容上方

drawer 的宽度优先通过 --tr-layout-drawer-width 控制,未设置时回退到侧栏展开宽度。

loading

收起行为

collapsedWidth 控制收起后还保留多少宽度,仅 dock 模式生效;collapseEffect 控制收起时的动画效果。

  • collapsedWidth > 0:收起后保留一条窄栏
  • collapsedWidth = 0:收起后完全隐藏
  • overlay:侧栏外框保留,内容层不跟随宽度滑动
  • slide:侧栏内容随宽度一起滑出
loading

宽度调整

resizable 可以开启 dock 侧栏的拖拽改宽,宽度范围由 minExpandedWidthmaxExpandedWidth 控制。

loading

侧栏受控

openexpandedWidth 是受控值,状态变化后需要通过事件同步外部状态。

defaultOpendefaultExpandedWidth 只提供初始值,适合不需要外部持续控制的场景。

loading

浮层

浮层相关配置和交互只在浮层模式(mode="floating")下生效。

  • defaultFloatingState:非受控初始状态,只在首次加载时读取
  • floatingState:受控状态,由外部维护当前位置和尺寸
  • floatingOptions:浮层行为配置,用于拖拽、缩放和尺寸约束

defaultFloatingStatefloatingState 不要同时传入

非受控浮层

非受控浮层通过 defaultFloatingState 设置初始位置和尺寸。

loading

受控浮层

受控浮层以 floatingState 作为唯一状态源,组件始终按外部状态渲染。

后续通过 update:floatingState 通知外部同步。

loading

浮层模式下的侧栏

浮层里同样可以放入侧栏、头部和主区。

loading

代理滚动条

在布局组件中,消息列表通常作为内部滚动区域存在。但当消息列表的宽度小于外层容器宽度时,浏览器原生滚动条会出现在消息列表自身的右侧,而不是外层容器的右侧。

为了解决这个布局问题,布局组件内部使用 ProxyScrollbar 渲染代理滚动条。代理滚动条与消息列表平级,通过接收消息列表的 DOM 引用来同步真实滚动状态,并将滚动条视觉上渲染到外层容器右侧。

使用要求

  • 将实际承担滚动的元素传给 scrollTarget
  • 为使 Layout.ProxyScrollbar 正常生效,传给 scrollTarget 的滚动容器需要具备明确高度,并通过 overflow: autooverflow: scroll 承担真实滚动。

scrollTarget 推荐的样式如下:

css
.scroll-host {
  height: 100%;
  overflow: auto;
}

基本结构

vue
<script setup lang="ts">
import { ref } from 'vue'
import { TrLayout } from '@opentiny/tiny-robot'

const messageListRef = ref<HTMLElement | null>(null)
</script>

<template>
  <TrLayout>
    <template #main>
      <div ref="messageListRef" class="message-list">
        <!-- messages -->
      </div>
      <TrLayout.ProxyScrollbar :scroll-target="messageListRef" />
    </template>
  </TrLayout>
</template>

使用示例

loading

注意事项

  • 代理滚动条会默认给目标滚动元素添加以下样式,用于隐藏原生滚动条
css
.tr-layout-proxy-scrollbar-target {
  scrollbar-width: none;
  -ms-overflow-style: none;

  &::-webkit-scrollbar {
    display: none;
  }
}
  • Layout.ProxyScrollbar 仅用于代理滚动条显示与拖拽,不负责内容渲染或性能优化。传入 ProxyScrollbarscrollTarget 必须是真正产生滚动的 DOM 元素。

侧栏开关

Layout.AsideToggle 是内置侧栏开关按钮,可以在 Layout 内部任意区域使用。

它给侧栏内容提供控制展开和收起的能力,默认插槽提供 { isOpen }

loading

Props

Layout

属性名说明类型默认值
mode布局模式;normal 参与普通布局,floating 会脱离普通布局,不占原来的位置空间'normal' | 'floating''normal'
leftAside左侧栏配置LayoutAsideOptions-
rightAside右侧栏配置LayoutAsideOptions-
floatingState受控浮层状态,需配合 update:floatingState 同步外部状态;不要和 defaultFloatingState 同时传入LayoutFloatingState-
defaultFloatingState非受控浮层初始状态,仅首次挂载读取一次;不要和 floatingState 同时传入LayoutFloatingState-
floatingOptions浮层行为配置,包括拖拽、缩放和尺寸约束;不参与状态控制LayoutFloatingOptions-

Layout.ProxyScrollbar

属性名说明类型默认值
scrollTarget真实滚动容器的元素,或对应组件实例的 refLayoutScrollTarget-

Layout.AsideToggle

属性名说明类型默认值
side控制的侧栏位置'left' | 'right'-

Slots

Layout

插槽名说明作用域参数
left-aside左侧栏内容-
header顶部区域-
main主区内容-
footer底部区域-
right-aside右侧栏内容-

Layout.AsideToggle

插槽名说明作用域参数
default自定义切换按钮内容{ isOpen: boolean }

Events

Layout

事件名说明回调参数
update:floatingState浮层位置或尺寸变化(value: LayoutFloatingState)
aside-open-change侧栏开关变化(detail: LayoutAsideOpenDetail)
left-aside-open-change左侧栏开关变化(detail: LayoutAsideOpenValue)
right-aside-open-change右侧栏开关变化(detail: LayoutAsideOpenValue)
aside-resize-start开始调整侧栏宽度(detail: LayoutAsideResizeDetail)
aside-resize调整侧栏宽度时持续触发(detail: LayoutAsideResizeDetail)
aside-resize-end结束调整侧栏宽度(detail: LayoutAsideResizeDetail)
left-aside-resize-start开始调整左侧栏宽度(detail: LayoutAsideResizeValue)
left-aside-resize调整左侧栏宽度时持续触发(detail: LayoutAsideResizeValue)
left-aside-resize-end结束调整左侧栏宽度(detail: LayoutAsideResizeValue)
right-aside-resize-start开始调整右侧栏宽度(detail: LayoutAsideResizeValue)
right-aside-resize调整右侧栏宽度时持续触发(detail: LayoutAsideResizeValue)
right-aside-resize-end结束调整右侧栏宽度(detail: LayoutAsideResizeValue)
floating-drag-start开始拖动浮层(detail: LayoutFloatingDragDetail)
floating-drag拖动浮层时持续触发(detail: LayoutFloatingDragDetail)
floating-drag-end结束拖动浮层(detail: LayoutFloatingDragDetail)
floating-resize-start开始调整浮层尺寸(detail: LayoutFloatingResizeDetail)
floating-resize调整浮层尺寸时持续触发(detail: LayoutFloatingResizeDetail)
floating-resize-end结束调整浮层尺寸(detail: LayoutFloatingResizeDetail)

Types

LayoutAsideOptions

字段说明类型默认值
mode侧栏模式'dock' | 'drawer''dock'
open受控开关状态boolean-
defaultOpen非受控初始开关状态booleanleft: true / right: false
expandedWidth受控展开宽度;drawer 未设置 --tr-layout-drawer-width 时会回退使用该宽度number-
defaultExpandedWidth非受控初始展开宽度;drawer 宽度回退值numberleft: 300 / right: 320
minExpandedWidth最小展开宽度边界numberleft: 200 / right: 240
maxExpandedWidth最大展开宽度边界numberleft: 560 / right: 640
collapsedWidth收起后保留的窄栏宽度,仅 dock 生效number0
collapseEffectdock 收起到窄栏时的内容动画'overlay' | 'slide''overlay'
resizable是否允许拖拽改宽,仅 dock 生效booleanfalse

LayoutAsideOpenDetail

字段说明类型
side当前侧栏位置'left' | 'right'
open当前是否展开boolean

LayoutAsideOpenValue

字段说明类型
open当前是否展开boolean

LayoutAsideResizeDetail

字段说明类型
side当前侧栏位置'left' | 'right'
expandedWidth当前侧栏宽度number

LayoutAsideResizeValue

字段说明类型
expandedWidth当前侧栏宽度number

LayoutScrollTarget

HTMLElement | Pick<ComponentPublicInstance, '$el'> | null | undefined

LayoutFloatingState

字段说明类型默认值
placement浮层位置'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center''center'
offsetX横向偏移;placementcenter 时不生效number24
offsetY纵向偏移;placementcenter 时不生效number24
width浮层宽度;非受控时表示初始值,受控时表示当前值number420
height浮层高度;非受控时表示初始值,受控时表示当前值number560

LayoutFloatingOptions

字段说明类型默认值
draggable是否允许拖动浮层booleantrue
resizable是否允许通过浮层边缘手柄调整尺寸booleanfalse
minWidth最小宽度number320
maxWidth最大宽度number视口宽度
minHeight最小高度number240
maxHeight最大高度number视口高度

LayoutFloatingDragDetail

LayoutFloatingState 一致。

LayoutFloatingResizeDetail

LayoutFloatingState 基础上增加以下字段:

字段说明类型
handle当前拖动的边或角's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw'

CSS 变量

布局基础

变量名说明
--tr-layout-height布局高度
--tr-layout-bg容器背景
--tr-layout-left-aside-bg左侧栏背景
--tr-layout-right-aside-bg右侧栏背景
--tr-layout-header-bg顶部背景
--tr-layout-main-bg主区背景
--tr-layout-footer-bg底部背景
--tr-layout-divider-color分隔线颜色
--tr-layout-overlay-bgdrawer 遮罩颜色
--tr-layout-panel-shadowdrawer 阴影
--tr-layout-floating-radius浮层圆角
--tr-layout-floating-shadow浮层阴影
--tr-layout-floating-z-index浮层层级

内容与交互

变量名说明
--tr-layout-main-min-width主区最小宽度
--tr-layout-drawer-widthdrawer 展示宽度
--tr-layout-main-scrollbar-width滚动条宽度
--tr-layout-main-scrollbar-thumb-bg滚动条滑块颜色
--tr-layout-main-scrollbar-thumb-bg-hover滑块悬停颜色
--tr-layout-main-scrollbar-thumb-bg-active滑块激活颜色