Align selects ranges and modal catalog

This commit is contained in:
DCCONSTRUCTIONS
2026-07-10 22:02:32 +03:00
parent 41e491191c
commit 1fc39dfebc
8 changed files with 138 additions and 60 deletions
+49 -43
View File
@@ -384,15 +384,11 @@ export function CatalogApp() {
<ControlRow label="Плашки">
<ColorField label="Цвет плашек" value={material.panelHex} onChange={(panelHex) => updateMaterial({ panelHex })} />
</ControlRow>
<ControlRow label="Прозрачность плашки">
<RangeControl label="Прозрачность плашки" showLabel={false} value={material.panelOpacity} min={18} max={96} formatValue={(value) => `${value}%`} onChange={(panelOpacity) => updateMaterial({ panelOpacity })} />
</ControlRow>
<RangeControl label="Прозрачность плашки" value={material.panelOpacity} min={18} max={96} formatValue={(value) => `${value}%`} onChange={(panelOpacity) => updateMaterial({ panelOpacity })} />
<ControlRow label="Поля ввода">
<ColorField label="Цвет полей ввода" value={material.fieldHex} onChange={(fieldHex) => updateMaterial({ fieldHex })} />
</ControlRow>
<ControlRow label="Прозрачность полей">
<RangeControl label="Прозрачность полей" showLabel={false} value={material.fieldOpacity} min={18} max={100} formatValue={(value) => `${value}%`} onChange={(fieldOpacity) => updateMaterial({ fieldOpacity })} />
</ControlRow>
<RangeControl label="Прозрачность полей" value={material.fieldOpacity} min={18} max={100} formatValue={(value) => `${value}%`} onChange={(fieldOpacity) => updateMaterial({ fieldOpacity })} />
</>
),
},
@@ -609,48 +605,58 @@ export function CatalogApp() {
);
case "modals":
return (
<div className="catalog-grid">
<Preview title="Создание" note="форма адаптируется по ширине">
<p className="catalog-preview__explanation">Поля переходят в одну колонку на узком viewport; footer остаётся видимым, прокручивается только тело окна.</p>
<Button variant="primary" shape="pill" icon={<Icon name="plus" />} onClick={() => setCreateModalOpen(true)}>Создать проект</Button>
</Preview>
<Preview title="Подтверждение удаления" note="async-safe">
<p className="catalog-preview__explanation">Destructive-цвет появляется у подтверждения, а не окрашивает всё окно заранее.</p>
<Button variant="danger" shape="pill" icon={<Icon name="trash" />} onClick={() => setConfirmOpen(true)}>Проверить удаление</Button>
</Preview>
<Preview title="Workflow sharing" note="ENGINE / access modal">
<p className="catalog-preview__explanation">Участники, роли, приглашение и immutable-владелец. API доступа остаётся в Engine.</p>
<Button variant="primary" shape="pill" icon={<Icon name="users" />} onClick={() => setShareAccessOpen(true)}>Поделиться графом</Button>
</Preview>
<Preview title="Ссылка на модель" note="BIM / share link">
<p className="catalog-preview__explanation">Read-only ссылка, copy-state и единая механика focus/Escape/backdrop.</p>
<Button shape="pill" icon={<Icon name="copy" />} onClick={() => setShareLinkOpen(true)}>Открыть ссылку</Button>
</Preview>
<Preview title="Контекстные действия" note="BIM / measurement & object">
<p className="catalog-preview__explanation">Короткое окно действий над выбранным размером или объектом без отдельной modal-системы.</p>
<Button shape="pill" icon={<Icon name="sliders" />} onClick={() => setContextActionOpen(true)}>Действия размера</Button>
</Preview>
<Preview title="История версий" note="BIM / large data modal">
<p className="catalog-preview__explanation">Большое прокручиваемое data-окно; BIM-таблица остаётся доменной композицией внутри общего Window.</p>
<Button shape="pill" icon={<Icon name="list" />} onClick={() => setHistoryOpen(true)}>Открыть историю</Button>
</Preview>
<Preview title="Комментарий к модели" note="BIM / expandable detail">
<p className="catalog-preview__explanation">Рабочая detail-modal с контентом и вложениями, которая может расширяться без смены механики слоя.</p>
<Button shape="pill" icon={<Icon name="clipboard" />} onClick={() => setDetailOpen(true)}>Открыть комментарий</Button>
</Preview>
<div className="catalog-modal-groups">
<section className="catalog-modal-group">
<header><strong>Общие</strong><span>Launcher / Engine</span></header>
<div className="catalog-modal-grid">
<Preview title="Создание" note="адаптивная форма" className="catalog-modal-preview">
<p className="catalog-preview__explanation">Одна колонка на узком viewport; footer остаётся видимым.</p>
<Button variant="primary" shape="pill" icon={<Icon name="plus" />} onClick={() => setCreateModalOpen(true)}>Создать проект</Button>
</Preview>
<Preview title="Подтверждение" note="async-safe" className="catalog-modal-preview">
<p className="catalog-preview__explanation">Destructive-цвет появляется только у подтверждения.</p>
<Button variant="danger" shape="pill" icon={<Icon name="trash" />} onClick={() => setConfirmOpen(true)}>Проверить удаление</Button>
</Preview>
<Preview title="Workflow sharing" note="ENGINE / access" className="catalog-modal-preview">
<p className="catalog-preview__explanation">Участники, роли, приглашение и immutable-владелец.</p>
<Button variant="primary" shape="pill" icon={<Icon name="users" />} onClick={() => setShareAccessOpen(true)}>Поделиться графом</Button>
</Preview>
</div>
</section>
<section className="catalog-modal-group">
<header><strong>Работа с моделями</strong><span>BIM Viewer</span></header>
<div className="catalog-modal-grid">
<Preview title="Ссылка на модель" note="share link" className="catalog-modal-preview">
<p className="catalog-preview__explanation">Read-only ссылка и copy-state.</p>
<Button shape="pill" icon={<Icon name="copy" />} onClick={() => setShareLinkOpen(true)}>Открыть ссылку</Button>
</Preview>
<Preview title="Контекстные действия" note="measurement / object" className="catalog-modal-preview">
<p className="catalog-preview__explanation">Действия над выбранным размером или объектом.</p>
<Button shape="pill" icon={<Icon name="sliders" />} onClick={() => setContextActionOpen(true)}>Действия размера</Button>
</Preview>
<Preview title="История версий" note="large data" className="catalog-modal-preview">
<p className="catalog-preview__explanation">Прокручиваемая история BIM-версий.</p>
<Button shape="pill" icon={<Icon name="list" />} onClick={() => setHistoryOpen(true)}>Открыть историю</Button>
</Preview>
<Preview title="Комментарий" note="expandable detail" className="catalog-modal-preview">
<p className="catalog-preview__explanation">Контент, вложения и detail-состояние.</p>
<Button shape="pill" icon={<Icon name="clipboard" />} onClick={() => setDetailOpen(true)}>Открыть комментарий</Button>
</Preview>
</div>
</section>
</div>
);
case "icons":
return (
<div className="catalog-icon-catalog">
<Preview title="Размеры и поверхности" note="16 / 18 / 20 px" className="catalog-preview--wide">
<Preview title="Размеры и поверхности" note="glyph 16 px" className="catalog-preview--wide">
<div className="catalog-window-actions-demo">
<IconButton label="Добавить"><Icon name="plus" size={16} /></IconButton>
<IconButton label="Обновить"><Icon name="refresh" size={18} /></IconButton>
<IconButton label="Развернуть"><Icon name="expand" size={20} /></IconButton>
<IconButton label="Закрыть"><Icon name="close" size={18} /></IconButton>
<IconButton label="Добавить"><Icon name="plus" /></IconButton>
<IconButton label="Обновить"><Icon name="refresh" /></IconButton>
<IconButton label="Развернуть"><Icon name="expand" /></IconButton>
<IconButton label="Закрыть"><Icon name="close" /></IconButton>
</div>
<p className="catalog-preview__explanation">Иконка наследует `currentColor`; фон, размер кнопки и active-state задаёт компонент поверхности, а не SVG. Glyph оптически уменьшен на 18% без изменения hit target.</p>
<p className="catalog-preview__explanation">Все glyph-иконки используют один размер 16 px и один stroke 1.6; surface меняет только фон и hit target.</p>
</Preview>
{iconGroups.map((group) => (
<section className="catalog-icon-group" key={group.title}>
@@ -658,7 +664,7 @@ export function CatalogApp() {
<div className="catalog-icon-grid">
{group.icons.map((name) => (
<div className="catalog-icon-tile" key={name}>
<span className="catalog-icon-tile__surface"><Icon name={name} size={20} /></span>
<span className="catalog-icon-tile__surface"><Icon name={name} /></span>
<span><strong>{iconLabels[name]}</strong><code>{name}</code></span>
</div>
))}
@@ -699,7 +705,7 @@ export function CatalogApp() {
}
right={
<HeaderProfile>
<IconButton label="Уведомления"><Icon name="inbox" size={20} /></IconButton>
<IconButton label="Уведомления"><Icon name="inbox" /></IconButton>
<HeaderProfileButton>Профиль</HeaderProfileButton>
<HeaderAvatar label="DC" />
</HeaderProfile>
+64 -1
View File
@@ -215,6 +215,60 @@ textarea {
gap: 0.75rem;
}
.catalog-modal-groups {
display: grid;
gap: 1.25rem;
}
.catalog-modal-group {
display: grid;
gap: 0.65rem;
}
.catalog-modal-group > header {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 1rem;
padding-inline: 0.15rem;
}
.catalog-modal-group > header strong {
font-size: 0.9rem;
}
.catalog-modal-group > header span {
color: var(--nodedc-text-muted);
font-size: 0.68rem;
text-transform: uppercase;
}
.catalog-modal-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 0.75rem;
}
.nodedc-glass.catalog-modal-preview {
min-height: 10.5rem;
padding: 1rem;
}
.catalog-modal-preview .catalog-preview__head {
margin-bottom: 0.7rem;
}
.catalog-modal-preview .catalog-preview__body {
min-height: 0;
align-content: space-between;
gap: 0.75rem;
}
.catalog-modal-preview .nodedc-button {
width: 100%;
padding-inline: 0.75rem;
}
.catalog-history-table {
display: grid;
min-width: 46rem;
@@ -447,6 +501,10 @@ textarea {
.catalog-icon-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.catalog-modal-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 900px) {
@@ -492,7 +550,8 @@ textarea {
}
.catalog-preview__head,
.catalog-icon-group > header {
.catalog-icon-group > header,
.catalog-modal-group > header {
align-items: flex-start;
flex-direction: column;
gap: 0.25rem;
@@ -503,6 +562,10 @@ textarea {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.catalog-modal-grid {
grid-template-columns: 1fr;
}
.catalog-shell-diagram {
grid-template-columns: 1fr 1.5fr;
grid-template-rows: 3rem 7rem 7rem;