From 3a711ff2ea270a64cec58500e476121a22788a38 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Thu, 22 Oct 2026 00:42:53 +0400 Subject: [PATCH] =?UTF-8?q?style(web):=20=D0=BF=D0=BE=D0=BB=D0=BE=D1=82?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=B4=D0=BE=D1=81=D0=BA=D0=B8=20=E2=80=94=20?= =?UTF-8?q?=D0=BA=D0=B0=D1=80=D1=82=D0=BE=D1=87=D0=BA=D0=B8,=20=D0=B4?= =?UTF-8?q?=D0=BE=D1=80=D0=BE=D0=B6=D0=BA=D0=B8,=20=D0=B4=D0=B0=D1=82?= =?UTF-8?q?=D1=8B=20=D0=B2=20=D1=81=D1=82=D0=B8=D0=BB=D0=B5=20=D1=81=D0=B8?= =?UTF-8?q?=D1=81=D1=82=D0=B5=D0=BC=D1=8B=20(#65)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- web/src/board/board.css | 165 ++++++++++---------- web/src/board/components/Card.tsx | 3 +- web/src/board/components/Lane.tsx | 7 +- web/src/board/components/ProblemsDrawer.tsx | 2 +- 4 files changed, 93 insertions(+), 84 deletions(-) diff --git a/web/src/board/board.css b/web/src/board/board.css index 65ff0f6..b1c6658 100644 --- a/web/src/board/board.css +++ b/web/src/board/board.css @@ -1,5 +1,5 @@ /* 3. Закреплённая шапка: заголовок и действия (PageHeader), панель управления (Panel), предупреждения, легенда */ -.sticky{position:sticky;top:env(safe-area-inset-top,0px);z-index:10;background:var(--bg);padding-block:var(--space-4) var(--space-2);margin:0 0 var(--space-2);box-shadow:0 1px 0 var(--line)} +.sticky{position:sticky;top:env(safe-area-inset-top,0px);z-index:10;background:var(--color-bg-canvas);padding-block:var(--space-4) var(--space-2);margin:0 0 var(--space-2);box-shadow:0 1px 0 var(--color-border-default)} .sticky .ui-page-header{margin-bottom:var(--space-3);gap:var(--space-2)} .stats{font-variant-numeric:tabular-nums} .stats b{color:var(--color-text-primary);font-weight:600} @@ -27,140 +27,147 @@ .legend-head{display:flex;align-items:center;gap:var(--space-2)} .legend{display:flex;flex-wrap:wrap;align-items:center;gap:2px 12px;margin:var(--space-1) 0 0;font-size:var(--fs-caption);line-height:var(--lh-caption);color:var(--color-text-secondary)} .legend span{display:inline-flex;align-items:center;gap:6px} -.legend .sep{width:1px;height:14px;background:var(--line)} +.legend .sep{width:1px;height:14px;background:var(--color-border-default)} .legend .hint{margin-left:auto} -.lg{font:inherit;font-size:13px;color:var(--muted);background:none;border:0;padding:2px 5px;border-radius:4px;cursor:pointer;display:inline-flex;align-items:center;gap:6px} -.lg:hover,.lg:focus-visible{background:var(--soft);color:var(--fg);outline:none} +.lg{font:inherit;font-size:var(--fs-caption);line-height:var(--lh-caption);color:var(--color-text-secondary);background:none;border:1px solid transparent;padding:2px 6px;border-radius:var(--radius-xs);cursor:pointer;display:inline-flex;align-items:center;gap:6px} +.lg:hover{background:var(--color-bg-hover);color:var(--color-text-primary)} +.lg:focus-visible{background:var(--color-bg-hover);color:var(--color-text-primary);border-color:var(--color-border-selected);outline:none} .lg.off{opacity:.45;text-decoration:line-through} .sw{width:10px;height:10px;border-radius:2px;display:inline-block} .ln{width:26px;height:0;border-top:2px solid var(--edge-strong);display:inline-block} .ln.dash{border-top-style:dashed;border-top-color:var(--edge)} .ln.hand{border-top-color:var(--guide)} .ln.crit{border-top-width:4px;border-top-color:var(--guide)} -.out-sw{width:16px;height:11px;border:1.5px dashed var(--muted);border-radius:3px;display:inline-block} +.out-sw{width:16px;height:11px;border:1.5px dashed var(--color-text-secondary);border-radius:3px;display:inline-block} /* 6. Доска: прокрутка только по горизонтали (вертикальная — у страницы), дорожки по эпикам, карточки абсолютные */ -.stage{display:flex;gap:10px;align-items:stretch} -.wrap{flex:1 1 auto;min-width:0;overflow-x:auto;overflow-y:hidden;border:1px solid var(--line);border-radius:8px;background:var(--card);user-select:none;-webkit-user-select:none} -.board{position:relative;min-width:max(100%,max-content)} +.stage{display:flex;gap:var(--space-3);align-items:stretch} +.wrap{flex:1 1 auto;min-width:0;overflow-x:auto;overflow-y:hidden;border:1px solid var(--color-border-default);border-radius:var(--radius-xl);background:var(--color-bg-surface);user-select:none;-webkit-user-select:none} +.board{position:relative;min-width:100%} svg.edges,svg.guides{position:absolute;inset:0;width:100%;height:100%;pointer-events:none} svg.guides{z-index:3} svg.guides line{stroke:var(--guide);stroke-width:1;stroke-dasharray:4 3} -.empty{padding:40px 16px;color:var(--muted);text-align:center} +.empty{padding:40px 16px;color:var(--color-text-secondary);text-align:center} #hubState{white-space:normal;min-width:0} -.login{max-width:560px;margin:48px auto;padding:20px 24px;background:var(--panel);border:1px solid var(--line);border-radius:8px} -.login h2{margin:0 0 8px;font-size:17px;font-weight:600} -.login p{margin:0 0 12px;font-size:14px;color:var(--muted)} -.login p.err{color:var(--p-crit)} -.login code{font-family:var(--font-mono);font-size:13px;color:var(--fg)} +.login{max-width:560px;margin:48px auto;padding:20px 24px;background:var(--color-bg-surface);border:1px solid var(--color-border-default);border-radius:var(--radius-xl)} +.login h2{margin:0 0 8px;font-size:var(--fs-lg);line-height:var(--lh-lg);font-weight:700} +.login p{margin:0 0 12px;font-size:var(--fs-body);color:var(--color-text-secondary)} +.login p.err{color:var(--color-status-error)} +.login code{font-family:var(--font-mono);font-size:13px;color:var(--color-text-primary)} .login form{display:flex;gap:8px;margin:0 0 12px} -.login input{flex:1;min-width:0;font:inherit;font-size:14px;height:34px;box-sizing:border-box;padding:0 10px;color:var(--fg);background:var(--bg);border:1px solid var(--line);border-radius:6px} -.login input:focus-visible{border-color:var(--accent);outline:none} -.lane{position:absolute;left:0;right:0;border-top:1px solid var(--line)} -.lane:nth-child(even of .lane){background:color-mix(in srgb,var(--soft) 45%,transparent)} -.lane.folded{background:color-mix(in srgb,var(--soft) 80%,transparent)} -.lane.target{box-shadow:inset 0 3px 0 var(--accent)} -.lane.target-after{box-shadow:inset 0 -3px 0 var(--accent)} +.login input{flex:1;min-width:0;font:inherit;font-size:var(--fs-body);height:var(--control-h);box-sizing:border-box;padding:0 10px;color:var(--color-text-primary);background:var(--color-bg-canvas);border:1px solid var(--color-border-default);border-radius:var(--radius-sm)} +.login input:focus-visible{border-color:var(--color-border-selected);outline:none} +.lane{position:absolute;left:0;right:0;border-top:1px solid var(--color-border-default)} +.lane:nth-child(even of .lane){background:var(--lane-alt)} +.lane.folded{background:var(--color-bg-hover)} +.lane.target{box-shadow:inset 0 3px 0 var(--color-action-primary)} +.lane.target-after{box-shadow:inset 0 -3px 0 var(--color-action-primary)} .lane.dragging{opacity:.6} .lane-head{position:absolute;left:8px;top:8px;display:flex;align-items:center;gap:4px;z-index:1} -.fold{width:18px;height:18px;border:0;background:none;color:var(--muted);cursor:pointer;padding:0;border-radius:4px;display:inline-flex;align-items:center;justify-content:center;font-size:0} -.fold::before{content:"";border:5px solid transparent;border-top:6px solid currentColor;border-bottom:0;transition:transform .15s} -.fold:hover{background:var(--soft);color:var(--fg)} -.lane.folded .fold::before{transform:rotate(-90deg)} -.lane-name{font-size:12.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);font-weight:500;cursor:grab;padding:2px 4px;border-radius:4px;user-select:none;touch-action:none} -.lane-name:hover{background:var(--soft);color:var(--fg)} -.lane-count{display:none;font-size:12.5px;color:var(--muted);margin-left:4px} +.fold{width:20px;height:20px;border:0;background:none;color:var(--color-text-secondary);cursor:pointer;padding:0;border-radius:var(--radius-xs);display:inline-flex;align-items:center;justify-content:center} +.fold svg{transition:transform .15s} +.fold:hover{background:var(--color-bg-hover);color:var(--color-text-primary)} +.fold:focus-visible,.lane-tools button:focus-visible,.card .open-card:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:1px} +.lane.folded .fold svg{transform:rotate(-90deg)} +.lane-name{font-size:var(--fs-caption);line-height:var(--lh-caption);color:var(--color-text-secondary);font-weight:600;cursor:grab;padding:2px 4px;border-radius:var(--radius-xs);user-select:none;touch-action:none} +.lane-name:hover{background:var(--color-bg-hover);color:var(--color-text-primary)} +.lane-count{display:none;font-size:var(--fs-caption);line-height:var(--lh-caption);color:var(--color-text-secondary);margin-left:4px} .lane.folded .lane-count{display:inline} .lane-tools{display:none;gap:2px} .lane:hover .lane-tools{display:inline-flex} -.lane-tools button{font:inherit;font-size:12px;line-height:1;color:var(--muted);background:var(--card);border:1px solid var(--line);border-radius:4px;width:22px;height:22px;cursor:pointer;padding:0} -.lane-tools button:hover{border-color:var(--accent);color:var(--accent)} +.lane-tools button{display:inline-flex;align-items:center;justify-content:center;color:var(--color-text-secondary);background:var(--color-bg-surface);border:1px solid var(--color-border-strong);border-radius:var(--radius-xs);width:22px;height:22px;cursor:pointer;padding:0} +.lane-tools button:hover{border-color:var(--color-action-primary);color:var(--color-action-primary)} .lane-tools button:disabled{opacity:.35;cursor:default} +.lane-tools .up svg{transform:rotate(180deg)} /* режим «по датам»: колонки по плановым датам окончания, шапка колонки над дорожками; карточки двигаются внутри своей колонки */ -.dcol{position:absolute;top:0;border-left:1px solid var(--line);box-sizing:border-box;pointer-events:none} +.dcol{position:absolute;top:0;border-left:1px solid var(--color-border-default);box-sizing:border-box;pointer-events:none} .dcol:first-of-type{border-left:0} .dcol.past{background:color-mix(in srgb,var(--p-crit) 5%,transparent)} -.dcol.today{background:color-mix(in srgb,var(--accent) 7%,transparent)} +.dcol.today{background:color-mix(in srgb,var(--color-action-primary) 7%,transparent)} /* полоса дат над доской: липнет под шапкой страницы, по горизонтали двигается вместе с доской (transform по scrollLeft) */ -.dates-bar{position:sticky;top:calc(var(--head-h,0px) + env(safe-area-inset-top,0px));z-index:9;background:var(--bg)} -.dates-in{overflow:hidden;border:1px solid var(--line);border-bottom:0;border-radius:8px 8px 0 0;background:var(--card);height:36px;box-sizing:border-box} +.dates-bar{position:sticky;top:calc(var(--head-h,0px) + env(safe-area-inset-top,0px));z-index:9;background:var(--color-bg-canvas)} +.dates-in{overflow:hidden;border:1px solid var(--color-border-default);border-bottom:0;border-radius:var(--radius-xl) var(--radius-xl) 0 0;background:var(--color-bg-surface);height:36px;box-sizing:border-box} .dates-track{position:relative;height:100%} -.dlabel{position:absolute;top:9px;font-size:12.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--fg);font-weight:600;white-space:nowrap} -.dlabel .n{font-weight:400;color:var(--muted);margin-left:6px;font-variant-numeric:tabular-nums} +.dlabel{position:absolute;top:10px;font-size:var(--fs-caption);line-height:var(--lh-caption);color:var(--color-text-primary);font-weight:600;white-space:nowrap} +.dlabel .n{font-weight:400;color:var(--color-text-secondary);margin-left:6px;font-variant-numeric:tabular-nums} .dlabel.past{color:var(--p-crit)} -.dlabel.today{color:var(--accent)} -.dlabel.none{color:var(--muted);font-weight:500} +.dlabel.today{color:var(--color-action-primary)} +.dlabel.none{color:var(--color-text-secondary);font-weight:400} .stage.bydate .wrap{border-top-left-radius:0;border-top-right-radius:0} .dsplit{position:absolute;top:0;bottom:0;width:11px;margin-left:-5px;cursor:col-resize;z-index:1} -.dsplit::after{content:"";position:absolute;left:5px;top:6px;bottom:6px;width:1px;background:var(--line)} -.dsplit:hover::after,.dsplit.on::after{background:var(--accent);width:3px;left:4px;border-radius:2px} +.dsplit::after{content:"";position:absolute;left:5px;top:6px;bottom:6px;width:1px;background:var(--color-border-default)} +.dsplit:hover::after,.dsplit.on::after{background:var(--color-action-primary);width:3px;left:4px;border-radius:2px} .dates-in.resizing{cursor:col-resize} /* горизонтальная прокрутка доски, прилипшая к низу окна: полоса всегда видна, скроллбар нарисован явно (на macOS системный прячется) */ -.hscroll{position:sticky;bottom:0;z-index:8;overflow-x:scroll;overflow-y:hidden;height:14px;background:var(--bg);padding-top:2px;box-sizing:border-box;scrollbar-width:thin;scrollbar-color:var(--edge) var(--soft)} +.hscroll{position:sticky;bottom:0;z-index:8;overflow-x:scroll;overflow-y:hidden;height:14px;background:var(--color-bg-canvas);padding-top:2px;box-sizing:border-box;scrollbar-width:thin;scrollbar-color:var(--color-border-strong) var(--color-bg-track)} .hscroll>div{height:1px} .hscroll::-webkit-scrollbar{height:12px} -.hscroll::-webkit-scrollbar-track{background:var(--soft);border-radius:6px} -.hscroll::-webkit-scrollbar-thumb{background:var(--edge);border-radius:6px;border:2px solid var(--soft)} -.hscroll::-webkit-scrollbar-thumb:hover{background:var(--accent)} +.hscroll::-webkit-scrollbar-track{background:var(--color-bg-track);border-radius:6px} +.hscroll::-webkit-scrollbar-thumb{background:var(--color-border-strong);border-radius:6px;border:2px solid var(--color-bg-track)} +.hscroll::-webkit-scrollbar-thumb:hover{background:var(--color-action-primary)} /* карточка: текст выделяется, тянуть можно только за рамку (появляется при наведении) и за уголок */ -.card{position:absolute;width:240px;height:120px;box-sizing:border-box;background:var(--card);border:1px solid var(--line);border-radius:6px;padding:12px 14px;display:flex;flex-direction:column;gap:4px;overflow:hidden;cursor:default;touch-action:none} -.card:hover{border-color:var(--accent)} +.card{position:absolute;width:240px;height:120px;box-sizing:border-box;background:var(--color-bg-surface);border:1px solid var(--color-border-default);border-radius:var(--radius-lg);padding:12px;display:flex;flex-direction:column;gap:4px;overflow:hidden;cursor:default;touch-action:none} +.card:hover{border-color:var(--color-border-strong)} .card.out{border-style:dashed;opacity:.7} .card.closed{opacity:.4} .card.closed:hover,.card.closed:focus-within{opacity:1} .edges path.closed{opacity:.4} .card.crit{box-shadow:0 0 0 2px var(--guide)} -.card.focus{box-shadow:0 0 0 2px var(--accent)} -.card.drag{cursor:grabbing;border-color:var(--accent);box-shadow:var(--shadow-popover);z-index:2} +.card.focus{box-shadow:0 0 0 2px var(--color-action-primary)} +.card.drag{cursor:grabbing;border-color:var(--color-action-primary);box-shadow:var(--shadow-popover);z-index:2} .card .title,.card .state,.card .who,.card .meta,.card .key,.card .sprint-tag{user-select:text;-webkit-user-select:text;cursor:text;touch-action:auto} .card .key{cursor:pointer} .card .meta{cursor:default} -.card .grip{position:absolute;background:var(--accent);opacity:0;cursor:grab;z-index:1;transition:opacity .12s} -.card .grip.t{left:0;right:0;top:0;height:8px;border-radius:5px 5px 0 0} -.card .grip.b{left:0;right:14px;bottom:0;height:8px;border-radius:0 0 0 5px} -.card .grip.l{left:0;top:0;bottom:0;width:8px;border-radius:5px 0 0 5px} -.card .grip.r{right:0;top:0;bottom:14px;width:8px;border-radius:0 5px 0 0} -.card:hover .grip,.card.drag .grip{opacity:.85} +.card .grip{position:absolute;background:var(--color-action-primary);opacity:0;cursor:grab;z-index:1;transition:opacity .12s} +.card .grip.t{left:0;right:0;top:0;height:8px;border-radius:11px 11px 0 0} +.card .grip.b{left:0;right:14px;bottom:0;height:8px;border-radius:0 0 0 11px} +.card .grip.l{left:0;top:0;bottom:0;width:8px;border-radius:11px 0 0 11px} +.card .grip.r{right:0;top:0;bottom:14px;width:8px;border-radius:0 11px 0 0} +.card:hover .grip,.card.drag .grip{opacity:.6} .card.drag .grip{cursor:grabbing} -.card .rsz{position:absolute;right:0;bottom:0;width:14px;height:14px;cursor:nwse-resize;background:linear-gradient(135deg,transparent 50%,var(--line) 50%);border-bottom-right-radius:5px;z-index:2} -.card:hover .rsz{background:linear-gradient(135deg,transparent 50%,var(--accent) 50%)} +.card .rsz{position:absolute;right:0;bottom:0;width:14px;height:14px;cursor:nwse-resize;background:linear-gradient(135deg,transparent 50%,var(--color-border-strong) 50%);border-bottom-right-radius:11px;z-index:2} +.card:hover .rsz{background:linear-gradient(135deg,transparent 50%,var(--color-action-primary) 50%)} .head{display:flex;align-items:center;justify-content:space-between;gap:6px;min-width:0} -.key{font-family:var(--font-mono);font-size:13.5px;font-weight:500;color:var(--accent);text-decoration:none;flex:0 0 auto} -.sprint-tag{font-size:11px;line-height:1;padding:4px 7px;border-radius:10px;background:var(--soft);color:var(--muted);max-width:55%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:0 1 auto} -.sprint-tag.sel{background:var(--accent);color:var(--accent-fg)} -.sprint-tag.none{background:transparent;border:1px dashed var(--line)} -.title{font-size:14.5px;line-height:19px;min-width:0;flex:1 1 auto;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2} -.meta{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--muted);white-space:nowrap;flex:0 0 auto} +.key{font-family:var(--font-mono);font-size:13px;font-weight:600;color:var(--color-action-primary);text-decoration:none;flex:0 0 auto} +.sprint-tag{font-size:11px;line-height:1;padding:4px 7px;border-radius:var(--radius-round);background:var(--color-bg-track);color:var(--color-text-secondary);max-width:55%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:0 1 auto} +.sprint-tag.sel{background:var(--color-action-primary);color:var(--color-text-on-primary)} +.sprint-tag.none{background:transparent;border:1px dashed var(--color-border-strong)} +.title{font-size:14.5px;line-height:19px;font-weight:600;color:var(--color-text-primary);min-width:0;flex:1 1 auto;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2} +.meta{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--color-text-secondary);white-space:nowrap;flex:0 0 auto} .kind{display:inline-flex;align-items:center;gap:4px} .kind i{width:8px;height:8px;border-radius:2px;display:inline-block} .prio{font-weight:600} /* состояние задачи (статус, срок, исполнитель) — отдельный блок под чертой, основным цветом: это главное после названия */ -.state,.who{font-size:13px;flex:0 0 auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--fg)} -.state{display:flex;align-items:center;gap:6px;margin-top:4px;padding-top:7px;border-top:1px solid var(--line)} -.status{font-size:12.5px;line-height:1;padding:4px 7px;border-radius:10px;background:var(--soft);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} +.state,.who{font-size:13px;flex:0 0 auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--color-text-primary)} +.state{display:flex;align-items:center;gap:6px;margin-top:4px;padding-top:7px;border-top:1px solid var(--color-border-default)} +/* статус — вид Badge (neutral) */ +.status{font-size:var(--fs-caption);line-height:var(--lh-caption);font-weight:600;padding:1px 8px;border:1px solid var(--color-border-default);border-radius:var(--radius-round);background:var(--color-bg-track);color:var(--color-text-secondary);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} .due{font-variant-numeric:tabular-nums;font-weight:600;flex:0 0 auto} -.who::before{content:"";display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--accent);margin-right:5px;vertical-align:1px} -.who.none{color:var(--muted);font-style:italic} -.who.none::before{background:transparent;border:1px solid var(--muted)} +.who::before{content:"";display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--color-action-primary);margin-right:5px;vertical-align:1px} +.who.none{color:var(--color-text-secondary);font-style:italic} +.who.none::before{background:transparent;border:1px solid var(--color-text-secondary)} -/* 7. Панель проблем справа от доски, липнет под шапкой и прокручивается внутри себя */ -.drawer{flex:0 0 340px;max-width:40%;overflow:auto;box-sizing:border-box;align-self:flex-start;position:sticky;top:calc(var(--head-h,0px) + 8px);max-height:calc(100vh - var(--head-h,0px) - 24px);font-size:var(--fs-body)} -.drawer-head{display:flex;justify-content:space-between;align-items:center;gap:var(--space-2)} -.board-h2{margin:0;font-size:var(--fs-lg);line-height:var(--lh-lg);font-weight:600;color:var(--color-text-primary)} +/* 7. Панель проблем справа от доски, липнет под шапкой; прокручивается содержимое внутри рамки Panel */ +.drawer{flex:0 0 340px;max-width:40%;box-sizing:border-box;align-self:flex-start;position:sticky;top:calc(var(--head-h,0px) + 8px);max-height:calc(100vh - var(--head-h,0px) - 24px);display:flex;font-size:var(--fs-body)} +.drawer>.ui-panel{display:flex;flex-direction:column;gap:var(--space-3);min-height:0;min-width:0;flex:1 1 auto;padding:var(--space-4) 0 var(--space-4) var(--space-4)} +.drawer-head{display:flex;justify-content:space-between;align-items:center;gap:var(--space-2);padding-right:var(--space-4)} +.drawer-body{overflow-y:auto;min-height:0;padding-right:var(--space-4)} +.board-h2{margin:0;font-size:var(--fs-lg);line-height:var(--lh-lg);font-weight:700;color:var(--color-text-primary)} .board-h3{margin:var(--space-3) 0 var(--space-1);font-size:var(--fs-caption);line-height:var(--lh-caption);font-weight:600;color:var(--color-text-secondary)} +.board-h3:first-child{margin-top:0} .drawer ul{margin:0;padding-left:18px} .drawer li{margin:3px 0} -.drawer .k{font-family:var(--font-mono);font-size:13px;color:var(--color-action-primary);text-decoration:none} -.drawer .ok{color:var(--color-status-success);margin:var(--space-2) 0 0} -.drawer .why{color:var(--muted)} +.drawer .k{font-family:var(--font-mono);font-size:13px;font-weight:600;color:var(--color-action-primary);text-decoration:none} +.drawer .ok{color:var(--color-status-success);margin:0} +.drawer .why{color:var(--color-text-secondary)} /* 8. Экспорт JSON и таблица связей (включаются из меню «Ещё») */ .export{display:flex;flex-direction:column;gap:var(--space-2);margin:0 0 var(--space-2)} -.export textarea{font-family:var(--font-mono);font-size:11.5px;width:100%;box-sizing:border-box;height:180px;border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--card);color:var(--fg);padding:8px;resize:vertical} +.export textarea{font-family:var(--font-mono);font-size:11.5px;width:100%;box-sizing:border-box;height:180px;border:1px solid var(--color-border-default);border-radius:var(--radius-sm);background:var(--color-bg-surface);color:var(--color-text-primary);padding:8px;resize:vertical} .link-table{margin-top:var(--space-3)} .tbl{max-width:100%;overflow-x:auto;margin-top:var(--space-2)} table{border-collapse:collapse;font-size:var(--fs-body);min-width:520px} -th,td{text-align:left;padding:6px 10px;border-bottom:1px solid var(--line);vertical-align:top} +th,td{text-align:left;padding:6px 10px;border-bottom:1px solid var(--color-border-default);vertical-align:top} th{font-size:var(--fs-caption);font-weight:600;color:var(--color-text-secondary)} td.k{font-family:var(--font-mono);font-size:12px;white-space:nowrap;color:var(--color-action-primary)} @@ -171,8 +178,8 @@ td.k{font-family:var(--font-mono);font-size:12px;white-space:nowrap;color:var(-- @media (max-width:640px){.sticky{position:static}.dates-bar{position:static}} /* «Открыть карточку» в заголовке карточки (R-1) */ -.card .open-card{margin-left:6px;color:var(--muted);text-decoration:none;font-size:13px} -.card .open-card:hover,.card .open-card:focus-visible{color:var(--accent);outline:none} +.card .open-card{margin-left:6px;color:var(--color-text-secondary);text-decoration:none;display:inline-flex;align-items:center;border-radius:var(--radius-xs)} +.card .open-card:hover{color:var(--color-action-primary)} /* слой измерения: карточки шириной CW с высотой по содержимому, невидим */ .measure{position:absolute;left:-100000px;top:0;visibility:hidden;pointer-events:none} .measure .card{position:static;height:auto} diff --git a/web/src/board/components/Card.tsx b/web/src/board/components/Card.tsx index 5c22ddd..c94ce92 100644 --- a/web/src/board/components/Card.tsx +++ b/web/src/board/components/Card.tsx @@ -1,5 +1,6 @@ import { memo, type PointerEvent } from "react"; import { Link } from "react-router"; +import { IconOpen } from "../../ui/icons.tsx"; import { BOARD_CARD_STATE } from "../../issues/modal.ts"; import { CW, JIRA_URL, KIND, PRIO } from "../constants.ts"; import { lineClamp, type Rect, type RelBox } from "../layout/layout.ts"; @@ -34,7 +35,7 @@ export const Card = memo(function Card({ node: n, box, rel, multiSprint, sprintS
{n.key} {!n.stub && ⓘ} + aria-label={`Открыть карточку ${n.key}`}>} {showTag && (n.sprint ? {n.sprint.replace(/^AWPCA_/, "")} : без спринта)} diff --git a/web/src/board/components/Lane.tsx b/web/src/board/components/Lane.tsx index a4eadcb..40d5895 100644 --- a/web/src/board/components/Lane.tsx +++ b/web/src/board/components/Lane.tsx @@ -1,4 +1,5 @@ import { useRef, useState, type PointerEvent } from "react"; +import { IconChevronDown } from "../../ui/icons.tsx"; import type { LaneGeom } from "../layout/layout.ts"; import { plural } from "../model/util.ts"; @@ -39,12 +40,12 @@ export function Lane({ g, index, last, count, lanes, boardTop, targetClass, onTo return (
- {g.name} {plural(count, "задача", "задачи", "задач")} - - + +
diff --git a/web/src/board/components/ProblemsDrawer.tsx b/web/src/board/components/ProblemsDrawer.tsx index 264df9d..fc59236 100644 --- a/web/src/board/components/ProblemsDrawer.tsx +++ b/web/src/board/components/ProblemsDrawer.tsx @@ -20,7 +20,7 @@ export function ProblemsDrawer({ problems, onClose }: { problems: Problems; onCl