Align selects ranges and modal catalog
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user