UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: полировка внешних контуров и дизайн-кода
This commit is contained in:
+66
-4
@@ -52,6 +52,7 @@
|
||||
- `Принять`
|
||||
- `Добавить запрос`
|
||||
- любые акцентные toolbar-кнопки
|
||||
- это правило обязательно и для `Внешних контуров`: `Добавить запрос` не может иметь светлый текст на светлом фоне
|
||||
- Save/update button:
|
||||
- если это зафиксированный green CTA, текст должен быть контрастным и читаемым
|
||||
- hover осветляет текущий тон, а не уходит в синий
|
||||
@@ -91,6 +92,9 @@
|
||||
- assignee bubbles
|
||||
- дата
|
||||
должны быть симметричны верхней
|
||||
- Для списков карточек `Внешних контуров` используется тот же вертикальный ритм, что и у `Внутреннего контура`:
|
||||
- контейнер списка не плотнее `space-y-3`
|
||||
- нельзя лепить карточки вплотную друг к другу
|
||||
|
||||
## Dropdown и popup
|
||||
- Все dropdown/popup приводятся к единому matte glass канону.
|
||||
@@ -118,6 +122,9 @@
|
||||
- клиппинг
|
||||
- налезание на соседние блоки
|
||||
- старую “врезанную” верстку
|
||||
- Для `Свойств` в `Внешних контурах` dropdown по умолчанию открывается вверх:
|
||||
- `placement="top-start"`
|
||||
- причина: блок находится близко к `Активности`, popup не должен падать вниз в соседнюю секцию
|
||||
|
||||
### Portal anchor snippet
|
||||
```tsx
|
||||
@@ -222,12 +229,17 @@
|
||||
- Для `Внешних контуров` это значит:
|
||||
- список карточек правится на уровне `list-item.tsx`, а не через внешний wrapper
|
||||
- gap между карточками должен совпадать с каноном `Внутреннего контура`
|
||||
- актуальный gap списка на текущем каноне: `space-y-2`
|
||||
- актуальный gap списка на текущем каноне: `space-y-3`
|
||||
- при tab switch между `Открытые / Закрытые` нельзя полагаться только на route param; нужен локальный `pendingTab`, чтобы stale layout не мелькал до завершения refetch
|
||||
- toolbar-навигация и inline actions не должны использовать старые квадратные `IconButton` остатки
|
||||
- свойства `Приоритет / Метки / Статус` не должны рисовать внутренние boxed-chip артефакты
|
||||
- popup `Приоритет / Метки` не может визуально жить внутри property-row; если он открывается из blur-shell, он обязан уходить в portal и рендериться над секцией
|
||||
- filled CTA вроде `Добавить запрос` используют `nodedc-external-primary-button` и всегда имеют тёмный текст
|
||||
- filled CTA используют чёрный/почти-чёрный текст всегда; белый текст на светлом акценте запрещён
|
||||
- secondary meta-иконки в карточке списка не должны иметь отдельную серую подложку, если по канону это простой inline icon
|
||||
- empty-state не должен использовать декоративную серую подложку под SVG; media-box прозрачный, SVG выравнивается через `display:flex` и центрирование
|
||||
- detail-toolbar в карточке запроса использует общий glass-cluster для листания `prev/next`, а сами кнопки внутри кластера — круглые, без квадратной подложки
|
||||
- `Добавить запрос` в header `Внешних контуров` — это filled accent CTA с тёмным текстом, каноничным радиусом и hover в более светлый тон того же акцента
|
||||
- popup выбора `Приоритет / Метки` внутри detail view не рендерится inline в property-row; он обязан уходить в `portal`
|
||||
- секции с dropdown-trigger внутри blur/glass shell обязаны иметь `overflow: visible` и `isolation: isolate`, иначе popup визуально “тонет” внутри блока
|
||||
- при переключении `Открытые / Закрытые` store обязан очистить stale request list до нового fetch, чтобы пользователь не видел flash старой верстки
|
||||
@@ -244,13 +256,42 @@
|
||||
|
||||
- List spacing:
|
||||
```tsx
|
||||
<div key={routeTab} className="space-y-2">
|
||||
<div key={resolvedTab} className="space-y-3">
|
||||
{filteredRequestIds.map((requestId) => (
|
||||
<ExternalContoursListItem key={requestId} ... />
|
||||
))}
|
||||
</div>
|
||||
```
|
||||
|
||||
- Pending tab anti-flash:
|
||||
```tsx
|
||||
const [pendingTab, setPendingTab] = useState<TInboxIssueCurrentTab | null>(null);
|
||||
const routeTab = (searchParams.get("currentTab") as TInboxIssueCurrentTab | null) ?? currentTab;
|
||||
const resolvedTab = pendingTab ?? routeTab;
|
||||
const isTabTransitioning = loader === "init-loading" || pendingTab !== null || routeTab !== currentTab;
|
||||
```
|
||||
|
||||
- Property popup anchor:
|
||||
```tsx
|
||||
<PriorityDropdown
|
||||
placement="top-start"
|
||||
buttonContainerClassName="nodedc-external-property-control-shell ..."
|
||||
button={
|
||||
<div className="nodedc-external-property-control text-[13px] font-medium">
|
||||
...
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
```
|
||||
|
||||
- Detail toolbar cluster:
|
||||
```tsx
|
||||
<div className="nodedc-external-toolbar-cluster">
|
||||
<button type="button" className="nodedc-external-icon-button">...</button>
|
||||
<button type="button" className="nodedc-external-icon-button">...</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
- Property control:
|
||||
```tsx
|
||||
<div className="nodedc-external-property-control text-[13px] font-medium">
|
||||
@@ -261,8 +302,15 @@
|
||||
|
||||
- Root tab switch without stale flash:
|
||||
```tsx
|
||||
void handleCurrentTab(workspaceSlug, projectId, nextTab);
|
||||
router.push(`...currentTab=${nextTab}`);
|
||||
const [pendingTab, setPendingTab] = useState<TInboxIssueCurrentTab | null>(null);
|
||||
const resolvedTab = pendingTab ?? routeTab;
|
||||
const isTabTransitioning = loader === "init-loading" || pendingTab !== null || routeTab !== currentTab;
|
||||
|
||||
if (resolvedTab !== nextTab) {
|
||||
setPendingTab(nextTab);
|
||||
void handleCurrentTab(workspaceSlug, projectId, nextTab);
|
||||
router.push(`...currentTab=${nextTab}`);
|
||||
}
|
||||
```
|
||||
|
||||
- Store-side tab reset:
|
||||
@@ -281,6 +329,20 @@ const { styles, attributes } = usePopper(referenceElement, popperElement, {
|
||||
});
|
||||
```
|
||||
|
||||
- Property popup without boxed artifact:
|
||||
```tsx
|
||||
<IssueLabelSelect
|
||||
rootClassName="w-full overflow-visible"
|
||||
buttonContainerClassName="nodedc-external-property-control-shell h-full w-full overflow-visible"
|
||||
label={
|
||||
<div className="nodedc-external-property-control text-[13px] font-medium">
|
||||
<LabelPropertyIcon className="h-3.5 w-3.5 flex-shrink-0 text-tertiary" />
|
||||
<span className="truncate text-primary">...</span>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
```
|
||||
|
||||
- Контейнер секции с trigger:
|
||||
```tsx
|
||||
<div className="nodedc-external-section overflow-visible px-4 py-4">
|
||||
|
||||
Reference in New Issue
Block a user