docs(styles): explain canvas and workspace layout and interaction states
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
/* 工作区壳体、目录、账户菜单与画布浮动标题;CSS Module 负责显示,账号/画布生命周期和侧栏开关由组件管理。 */
|
||||
/* 侧栏宽度变量供侧栏本体和浮动标题共同消费,根容器至少占满动态视口高度。 */
|
||||
.shell {
|
||||
--sidebar-width: 270px;
|
||||
display: flex;
|
||||
@@ -5,6 +7,7 @@
|
||||
background: #fffefb;
|
||||
color: #37352f;
|
||||
}
|
||||
/* 侧栏插槽 sticky 固定在滚动视口顶部;裁剪展开过渡期间的内容,层级高于画布。 */
|
||||
.sidebarSlot {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
@@ -14,6 +17,7 @@
|
||||
overflow: hidden;
|
||||
z-index: 30;
|
||||
}
|
||||
/* 侧栏采用纵向 flex,导航区可滚动、账户区留在底部;最大宽度给主区域保留至少 40px。 */
|
||||
.sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -29,30 +33,38 @@
|
||||
letter-spacing: -0.15px;
|
||||
color: #37352f;
|
||||
}
|
||||
/* 顶行按钮分居两端;搜索框 focus-within 让输入聚焦时整个框有反馈。 */
|
||||
.topRow { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; color: #85817b; }
|
||||
.search { display: flex; align-items: center; gap: 7px; min-height: 32px; border: 1px solid #e6e3df; border-radius: 7px; padding: 4px 8px; color: #97938d; }
|
||||
.search:focus-within { border-color: #b2a292; box-shadow: 0 0 0 2px #b2a29218; }
|
||||
.search input { min-width: 0; width: 100%; padding: 0; background: transparent; border: 0; outline: none; font: inherit; color: #37352f; }
|
||||
.search input::placeholder { color: #9a9690; }
|
||||
/* flex:1 配合 min-height:0 才允许长目录在侧栏内部滚动。 */
|
||||
.navigation { flex: 1; min-height: 0; overflow-y: auto; padding-top: 10px; }
|
||||
/* 首页与目录链接共用行高/图标间距,长标题省略;aria-current 对当前页提供选中背景。 */
|
||||
.home, .pageLink { display: flex; align-items: center; gap: 8px; padding: 4px 8px; min-height: 30px; border-radius: 6px; font-weight: 450; }
|
||||
.home { width: fit-content; font-weight: 600; background: #ecebe8; }
|
||||
.pageLink { margin: 1px 0; }
|
||||
.pageLink svg { flex-shrink: 0; color: #87837c; }
|
||||
.pageLink span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.pageLink:hover, .pageLink[aria-current="page"] { background: #eae7e2; }
|
||||
/* 分组名称、空态提示和错误分别排版;错误允许在任意位置折行。 */
|
||||
.sectionLabel { display: flex; justify-content: space-between; padding: 18px 7px 6px; color: #9b9690; font-size: 11px; font-weight: 400; letter-spacing: 0; }
|
||||
.hint { padding: 4px 8px; color: #9a948c; line-height: 1.6; font-size: 12px; }
|
||||
.error { margin: 6px 4px; font-size: 12px; color: #b14b3c; overflow-wrap: anywhere; }
|
||||
/* 账户区域向侧栏底部靠齐,按钮占满宽度以便整行点击。 */
|
||||
.accountArea { margin-top: auto; padding-top: 6px; }
|
||||
.accountButton { display: flex; align-items: center; gap: 8px; padding: 6px 7px; min-height: 36px; width: 100%; border-radius: 6px; text-align: left; color: #37352f; }
|
||||
.accountButton:hover { background: #edeae5; }
|
||||
/* 头像固定尺寸并裁成圆形,图片 object-fit:cover;缺图时容纳首字占位。 */
|
||||
.avatar { display: grid; place-items: center; flex: 0 0 24px; width: 24px; height: 24px; overflow: hidden; border-radius: 50%; background: #e8e0d6; color: #705844; font-size: 12px; font-weight: 600; }
|
||||
.avatar img { display: block; width: 100%; height: 100%; object-fit: cover; }
|
||||
.avatarLarge { flex-basis: 36px; width: 36px; height: 36px; font-size: 16px; }
|
||||
/* 账户文字允许收缩和省略,副文字在此布局隐藏。 */
|
||||
.accountText { display: flex; flex: 1; flex-direction: column; min-width: 0; }
|
||||
.accountText strong { font-size: 13px; font-weight: 550; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
||||
.accountText small { display: none; }
|
||||
/* 原生 popover 的面板位置/宽度约束;自身可滚动且从左下角进入,不用 CSS 切换 open 状态。 */
|
||||
.accountPopup {
|
||||
position: fixed;
|
||||
inset: auto auto 50px 8px;
|
||||
@@ -73,31 +85,40 @@
|
||||
letter-spacing: -0.15px;
|
||||
transform-origin: bottom left;
|
||||
}
|
||||
/* 仅 popover 打开时播放进入动画;backdrop 保持透明,但是否可交互仍由 popover 行为决定。 */
|
||||
.accountPopup:popover-open { animation: account-enter 130ms ease-out; }
|
||||
.accountPopup::backdrop { background: transparent; }
|
||||
/* 菜单头、工作区字母头像及身份行共用纵向文字布局,长名称省略。 */
|
||||
.accountHeading { display: flex; align-items: center; gap: 10px; padding: 8px 7px 10px; }
|
||||
.workspaceAvatar { display: grid; place-items: center; flex: 0 0 36px; height: 36px; border-radius: 7px; color: #72533e; background: #eee8df; font-size: 19px; font-weight: 600; }
|
||||
.accountHeading > div, .popupIdentity > div { display: flex; flex-direction: column; min-width: 0; gap: 1px; }
|
||||
.accountHeading strong { font-size: 14px; font-weight: 600; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
||||
.accountHeading small { color: #8b8780; font-size: 12px; }
|
||||
/* 菜单分组和身份区域提供内间距,邮箱允许断行;工作区列表限制高度后独立滚动。 */
|
||||
.menuGroup { padding: 1px 0; }
|
||||
.popupIdentity { display: flex; align-items: center; gap: 8px; padding: 8px 7px 7px; }
|
||||
.popupIdentity strong { font-size: 12px; font-weight: 500; }
|
||||
.popupIdentity small { color: #8b8780; font-size: 11px; overflow-wrap: anywhere; letter-spacing: 0; }
|
||||
.workspaceList { max-height: min(220px, 30dvh); overflow-y: auto; }
|
||||
/* 菜单项整行可点,文字可收缩,图标保持宽度;disabled 态显式降低透明度。 */
|
||||
.menuItem { display: flex; align-items: center; gap: 9px; width: 100%; min-height: 31px; padding: 5px 8px; border-radius: 5px; text-align: left; font-size: 13px; line-height: 20px; font-weight: 450; }
|
||||
.menuItem > span:not(.workspaceMini) { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.menuItem > svg { flex-shrink: 0; }
|
||||
.menuItem:hover { background: #f1f0ed; }
|
||||
.menuItem:disabled { opacity: 0.45; cursor: not-allowed; }
|
||||
/* 工作区小头像与新建/登出颜色区分,separator 分隔组而不引入额外布局容器。 */
|
||||
.workspaceMini { display: grid; place-items: center; flex: 0 0 20px; height: 20px; border-radius: 4px; color: #82634c; background: #f1ebe3; font-size: 11px; font-weight: 600; }
|
||||
.newWorkspace { color: #2383e2; }
|
||||
.logout { color: #78746d; font-size: 12px; }
|
||||
.separator { height: 1px; margin: 6px 7px; background: #eeece8; }
|
||||
/* 左上浮动条以 --floating-left 定位;侧栏展开时偏移到侧栏右侧,位置和宽度作 240ms 过渡。 */
|
||||
.floating { --floating-left: 12px; position: fixed; left: var(--floating-left); top: 12px; max-width: calc(100vw - var(--floating-left) - 12px); z-index: 40; transition: left 240ms cubic-bezier(0.22, 1, 0.36, 1), max-width 240ms cubic-bezier(0.22, 1, 0.36, 1); }
|
||||
/* 展开侧栏时使用实际受视口约束的侧栏宽度计算偏移;账户 popover 也继承同一偏移变量。 */
|
||||
.floating[data-sidebar-collapsed="false"], .accountPopup[data-sidebar-collapsed="false"] { --floating-left: calc(min(var(--sidebar-width), calc(100vw - 40px)) + 12px); }
|
||||
/* 浮动条错误绝对定位于条下方,账户设置面板则沿用对话框容器。 */
|
||||
.floatingError { position: absolute; left: 0; top: 42px; width: 240px; padding: 10px; background: white; border: 1px solid #e7e2db; border-radius: 8px; color: #b14b3c; font-size: 12px; }
|
||||
.settingsPanel { color: #37352f; border-color: #e6e2dc; border-radius: 12px; }
|
||||
/* 设置表单纵向排布身份、字段及操作;提交按钮区分主动作,禁用时保留位置。 */
|
||||
.settingsForm { display: flex; flex-direction: column; gap: 16px; padding-top: 4px; }
|
||||
.settingsIdentity { display: flex; align-items: center; gap: 10px; font-size: 13px; color: #89837b; overflow-wrap: anywhere; }
|
||||
.settingsForm label { display: flex; flex-direction: column; gap: 6px; font-size: 13px; font-weight: 500; }
|
||||
@@ -106,35 +127,48 @@
|
||||
.settingsActions button { padding: 6px 12px; border: 1px solid #e2ddd6; border-radius: 6px; font-size: 13px; }
|
||||
.settingsActions button[type="submit"] { background: #37352f; color: white; border-color: #37352f; }
|
||||
.settingsActions button:disabled { opacity: 0.5; cursor: not-allowed; }
|
||||
/* 固定全视口画布置于底层;点阵背景与加载/错误状态由后续类分别承担。 */
|
||||
.graph { position: fixed; inset: 0; z-index: 0; display: flex; width: 100%; height: 100dvh; background: #fffefb; }
|
||||
.graphSurface { width: 100%; height: 100%; background-image: radial-gradient(#b8aea245 1px, transparent 1px); background-size: 22px 22px; }
|
||||
.graphStatus { position: absolute; left: 50%; top: 72px; transform: translateX(-50%); max-width: calc(100vw - 48px); padding: 8px 12px; border-radius: 6px; background: #fffefbe6; color: #9a948c; text-align: center; font-size: 13px; }
|
||||
/* 账户菜单从轻微下移/缩小过渡到正常位置与不透明状态。 */
|
||||
@keyframes account-enter { from { opacity: 0; transform: translateY(4px) scale(0.985); } to { opacity: 1; transform: translateY(0) scale(1); } }
|
||||
/* 较窄视口将侧栏目标宽度收为 240px;仍受上方 max-width 约束。 */
|
||||
@media (max-width: 600px) { .shell { --sidebar-width: 240px; } }
|
||||
/* 减少动态效果偏好下关闭菜单进入动画;浮动条过渡在文件后部单独关闭。 */
|
||||
@media (prefers-reduced-motion: reduce) { .accountPopup:popover-open { animation: none; } }
|
||||
|
||||
/* 浮动条 logo 链接沿用 Toolbar 控件尺寸与键盘焦点样式,保证和旁边按钮对齐。 */
|
||||
.logoLink { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; box-sizing: border-box; width: var(--toolbar-control-width, 32px); height: var(--toolbar-control-height, 32px); padding: 4px 6px; border-radius: 5px; }
|
||||
.logoLink img { display: block; width: var(--toolbar-icon-size, 20px); height: var(--toolbar-icon-size, 20px); }
|
||||
.logoLink:hover { background: #e9e7e3; }
|
||||
.logoLink:focus-visible { outline: 2px solid #9d7d66; outline-offset: 2px; }
|
||||
|
||||
/* 浮动头像按钮同样使用共享尺寸;从浮动条打开的账户面板改为顶端定位。 */
|
||||
.floatingAvatarButton { display: grid; place-items: center; flex: 0 0 auto; box-sizing: border-box; width: var(--toolbar-control-width, 32px); height: var(--toolbar-control-height, 32px); border-radius: 5px; }
|
||||
.floatingAvatarButton:hover { background: #e9e7e3; }
|
||||
/* clamp 把账户面板左边界限制在视口内;transform-origin 随顶部锚点改为左上。 */
|
||||
.accountPopup[data-floating="true"] { inset: 62px auto auto clamp(8px, var(--floating-left, 12px), max(8px, calc(100vw - 308px))); max-height: calc(100dvh - 76px); transform-origin: top left; }
|
||||
|
||||
/* 浮动头像采用图标尺寸,标题允许 flex 收缩但保留溢出区域给编辑错误提示。 */
|
||||
.floatingAvatarButton .avatar { flex-basis: var(--toolbar-icon-size, 20px); width: var(--toolbar-icon-size, 20px); height: var(--toolbar-icon-size, 20px); font-size: 14px; }
|
||||
.floatingTitle { flex: 1 1 auto; min-width: 0; max-width: 240px; margin: 0; color: #37352f; font-size: 14px; line-height: var(--toolbar-control-height, 32px); font-weight: 500; overflow: visible; }
|
||||
/* 中等窄屏降低标题最大宽度,不改变标题内容或编辑状态。 */
|
||||
@media (max-width: 700px) { .floatingTitle { max-width: 180px; } }
|
||||
/* 极窄且侧栏仍展开时隐藏 logo/标题/分隔,保留浮动条其余控件。 */
|
||||
@media (max-width: 420px) {
|
||||
.floating[data-sidebar-collapsed="false"] .logoLink,
|
||||
.floating[data-sidebar-collapsed="false"] .floatingTitle,
|
||||
.floating[data-sidebar-collapsed="false"] > span[aria-hidden="true"] { display: none; }
|
||||
}
|
||||
/* 按用户偏好关闭浮动条位移/宽度过渡。 */
|
||||
@media (prefers-reduced-motion: reduce) { .floating { transition: none; } }
|
||||
|
||||
/* 递归目录清除列表默认缩进,层级缩进由组件布局提供;行本身允许标题收缩。 */
|
||||
.directoryList { list-style: none; padding: 0; margin: 0; }
|
||||
.directoryRow { display: flex; align-items: center; min-width: 0; }
|
||||
.directoryRow .pageLink { flex: 1; min-width: 0; padding-left: 3px; }
|
||||
/* 可折叠项按钮与叶项占位共享 20px 列宽,保持各行标题对齐;焦点内描边不扩尺寸。 */
|
||||
.directoryToggle, .directorySpacer { flex: 0 0 20px; width: 20px; height: 26px; }
|
||||
.directoryToggle { display: grid; place-items: center; border: 0; border-radius: 4px; background: transparent; color: #87837c; cursor: pointer; }
|
||||
.directoryToggle:hover { background: #eae7e2; }
|
||||
|
||||
Reference in New Issue
Block a user