|
|
|
|
@ -86,14 +86,15 @@ function StateCard({
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const LLM_FORMS_TEXT = `ФОРМ-КОНТРОЛЫ — LLM-спецификация
|
|
|
|
|
Версия: v1.0 · /components/forms |
|
|
|
|
Версия: v2.0 · /components/forms |
|
|
|
|
|
|
|
|
|
ТЕКСТОВОЕ ПОЛЕ (Input) |
|
|
|
|
CSS класс: .bb-input |
|
|
|
|
Высота: ~40px (padding: 9px 12px) |
|
|
|
|
border: 1.5px solid #e5e7eb · border-radius: 8px · font: Fira Sans 14px |
|
|
|
|
Высота: 50px · padding: 10px 12px |
|
|
|
|
border: 1px solid #ccc · border-radius: 4px · font: Fira Sans 14px |
|
|
|
|
Источник: entityform input[type=text] на perm.oclinica.ru |
|
|
|
|
Состояния: |
|
|
|
|
default: border #e5e7eb |
|
|
|
|
default: border #ccc |
|
|
|
|
focus: border #7ecfca + box-shadow 0 0 0 3px rgba(126,207,202,0.2) |
|
|
|
|
error: border #dc2626 + класс .bb-error |
|
|
|
|
disabled: opacity 0.5 + cursor not-allowed + bg #f8f9fa |
|
|
|
|
@ -101,11 +102,13 @@ border: 1.5px solid #e5e7eb · border-radius: 8px · font: Fira Sans 14px
|
|
|
|
|
МНОГОСТРОЧНЫЙ ТЕКСТ (Textarea) |
|
|
|
|
CSS класс: .bb-textarea |
|
|
|
|
Те же состояния что у Input |
|
|
|
|
min-height: 100px · resize: vertical |
|
|
|
|
min-height: 100px · resize: vertical · padding: 10px 12px |
|
|
|
|
|
|
|
|
|
ВЫПАДАЮЩИЙ СПИСОК (Select) |
|
|
|
|
CSS класс: .bb-select |
|
|
|
|
Стрелка: SVG background-image (data URI) · padding-right: 36px |
|
|
|
|
Высота: 50px · padding: 10px 36px 10px 10px |
|
|
|
|
Стрелка: SVG background-image (data URI) |
|
|
|
|
Источник: .form-control.form-select entityform на сайте |
|
|
|
|
Те же состояния что у Input |
|
|
|
|
|
|
|
|
|
ФЛАЖОК (Checkbox) |
|
|
|
|
@ -127,12 +130,20 @@ HTML: <input type="radio" class="bb-radio" name="group" />
|
|
|
|
|
CSS: .bb-toggle-track / .bb-toggle-thumb |
|
|
|
|
HTML-аналог: <input type="checkbox" role="switch" /> |
|
|
|
|
|
|
|
|
|
КОНТЕКСТ ПРИМЕНЕНИЯ НА САЙТЕ |
|
|
|
|
Input/Select используются в entityform-блоках: |
|
|
|
|
#block-entityform-block-lor-form — форма «Запишите меня!» (ЛОР) |
|
|
|
|
#block-entityform-block-lor-form-2 — форма «Узнайте стоимость операции» |
|
|
|
|
#block-entityform-block-surgery-form — форма хирургии |
|
|
|
|
Фон формы: #b8e6ed (светло-бирюзовый) |
|
|
|
|
Ширина полей: 302px (фиксированная), кнопка submit: 300px |
|
|
|
|
|
|
|
|
|
ОБЩИЕ ПРАВИЛА |
|
|
|
|
✓ Метка (label) всегда над полем, font-weight: 500 |
|
|
|
|
✓ Обязательные поля помечены * красным цветом (#dc2626) |
|
|
|
|
✓ Подсказка (hint) серым текстом под полем — font-size: 12px |
|
|
|
|
✓ Сообщение об ошибке красным (#dc2626) под полем вместо hint |
|
|
|
|
✓ Focus outline — тёмный бирюзовый #7ecfca (--brand-053m) |
|
|
|
|
✓ Focus outline — бирюзовый #7ecfca (--brand-053m) |
|
|
|
|
✓ Группы checkbox/radio — вертикальный список с gap: 10px |
|
|
|
|
✓ Toggle — для булевых настроек включить/выключить |
|
|
|
|
✕ Не использовать placeholder вместо label |
|
|
|
|
@ -207,6 +218,39 @@ export default function FormsPage() {
|
|
|
|
|
// Заблокирован
|
|
|
|
|
<Toggle disabled label="Настройка недоступна" />`;
|
|
|
|
|
|
|
|
|
|
const codeSiteCSS = `/* ── Реальный CSS с perm.oclinica.ru ─────────────────────────── */
|
|
|
|
|
|
|
|
|
|
/* Базовые стили (Bootstrap override) */ |
|
|
|
|
input[type=text], |
|
|
|
|
input[type=email] { |
|
|
|
|
padding: 0; |
|
|
|
|
height: 30px; |
|
|
|
|
border: 1px solid #ccc; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Entityform-блоки: форма записи на приём / узнать стоимость */ |
|
|
|
|
#block-entityform-block-lor-form input[type=text], |
|
|
|
|
#block-entityform-block-lor-form-2 input[type=text], |
|
|
|
|
#block-entityform-block-surgery-form input[type=text] { |
|
|
|
|
height: 50px; |
|
|
|
|
padding: 10px; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Select в entityform */ |
|
|
|
|
.field-name-field-lor-vrach .form-control.form-select { |
|
|
|
|
height: 50px; |
|
|
|
|
padding: 10px 16px; |
|
|
|
|
font-size: .9em; |
|
|
|
|
font-weight: bold; |
|
|
|
|
font-family: 'Fira Sans'; |
|
|
|
|
color: #949290; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Webform (отдельный вид форм) — скруглений нет */ |
|
|
|
|
.webform-client-form input[type=text].form-text { |
|
|
|
|
border-radius: 0; |
|
|
|
|
}`;
|
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<div className="max-w-4xl mx-auto px-8 py-10"> |
|
|
|
|
{/* Заголовок */} |
|
|
|
|
@ -230,10 +274,10 @@ export default function FormsPage() {
|
|
|
|
|
<Section |
|
|
|
|
id="input" |
|
|
|
|
title="Текстовое поле" |
|
|
|
|
subtitle="Базовый элемент ввода текста. Класс .bb-input." |
|
|
|
|
subtitle="Базовый элемент ввода текста. Класс .bb-input. Высота 50px — как на сайте oclinica.ru." |
|
|
|
|
> |
|
|
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 mb-4"> |
|
|
|
|
<StateCard label="Default" hint="Стандартное состояние"> |
|
|
|
|
<StateCard label="Default" hint="border: 1px solid #ccc · border-radius: 4px · height: 50px"> |
|
|
|
|
<FieldLabel text="Имя пациента" required /> |
|
|
|
|
<input className="bb-input" type="text" placeholder="Иван Иванов" readOnly /> |
|
|
|
|
<FieldHint text="Укажите имя как в паспорте" /> |
|
|
|
|
@ -296,10 +340,10 @@ export default function FormsPage() {
|
|
|
|
|
<Section |
|
|
|
|
id="textarea" |
|
|
|
|
title="Многострочный текст" |
|
|
|
|
subtitle="Поле для длинного ввода. Класс .bb-textarea." |
|
|
|
|
subtitle="Поле для длинного ввода. Класс .bb-textarea. border: 1px solid #ccc · border-radius: 4px." |
|
|
|
|
> |
|
|
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4"> |
|
|
|
|
<StateCard label="Default" hint="Стандартное состояние · resize: vertical"> |
|
|
|
|
<StateCard label="Default" hint="min-height: 100px · resize: vertical"> |
|
|
|
|
<FieldLabel text="Комментарий к записи" /> |
|
|
|
|
<textarea |
|
|
|
|
className="bb-textarea" |
|
|
|
|
@ -329,10 +373,10 @@ export default function FormsPage() {
|
|
|
|
|
<Section |
|
|
|
|
id="select" |
|
|
|
|
title="Выпадающий список" |
|
|
|
|
subtitle="Выбор из предопределённых вариантов. Класс .bb-select." |
|
|
|
|
subtitle="Выбор из предопределённых вариантов. Класс .bb-select. Высота 50px — как в entityform на сайте." |
|
|
|
|
> |
|
|
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4"> |
|
|
|
|
<StateCard label="Default" hint="Нативный select с кастомной стрелкой"> |
|
|
|
|
<StateCard label="Default" hint="height: 50px · кастомная стрелка SVG"> |
|
|
|
|
<FieldLabel text="Специализация" /> |
|
|
|
|
<select className="bb-select"> |
|
|
|
|
<option value="">Выберите специализацию</option> |
|
|
|
|
@ -520,7 +564,96 @@ export default function FormsPage() {
|
|
|
|
|
</div> |
|
|
|
|
</Section> |
|
|
|
|
|
|
|
|
|
{/* 7. Примеры кода */} |
|
|
|
|
{/* 7. Контекст на сайте */} |
|
|
|
|
<Section |
|
|
|
|
id="context" |
|
|
|
|
title="Контекст применения" |
|
|
|
|
subtitle="Как форм-контролы выглядят на сайте oclinica.ru — в реальных entityform-блоках." |
|
|
|
|
> |
|
|
|
|
<div className="overflow-x-auto mb-6"> |
|
|
|
|
<table className="w-full text-sm border-collapse"> |
|
|
|
|
<thead> |
|
|
|
|
<tr style={{ background: "var(--bb-sidebar-bg)" }}> |
|
|
|
|
{["Контрол", "CSS класс", "Где на сайте", "CSS-блок на сайте"].map((h) => ( |
|
|
|
|
<th |
|
|
|
|
key={h} |
|
|
|
|
className="text-left px-3 py-2 font-semibold text-xs uppercase tracking-wide" |
|
|
|
|
style={{ color: "var(--bb-text-muted)", borderBottom: "1px solid var(--bb-border)" }} |
|
|
|
|
> |
|
|
|
|
{h} |
|
|
|
|
</th> |
|
|
|
|
))} |
|
|
|
|
</tr> |
|
|
|
|
</thead> |
|
|
|
|
<tbody> |
|
|
|
|
{[ |
|
|
|
|
["Input (text)", ".bb-input", "Форма записи ЛОР, форма хирургии, «Узнайте стоимость»", "#block-entityform-block-lor-form input[type=text]"], |
|
|
|
|
["Select", ".bb-select", "Выбор врача в форме записи", ".field-name-field-lor-vrach .form-control.form-select"], |
|
|
|
|
["Checkbox", ".bb-checkbox", "Согласие на обработку данных в entityform", ".form-type-checkbox.checkbox label"], |
|
|
|
|
["Textarea", ".bb-textarea", "Комментарии (в ряде форм)", "Без специального CSS на сайте (Bootstrap)"], |
|
|
|
|
["Toggle", ".bb-toggle-track", "Не используется на сайте (UI-компонент брендбука)", "—"], |
|
|
|
|
].map(([ctrl, cls, where, block]) => ( |
|
|
|
|
<tr key={ctrl} style={{ borderBottom: "1px solid var(--bb-border)" }}> |
|
|
|
|
<td className="px-3 py-2.5 font-medium" style={{ color: "var(--bb-text)" }}>{ctrl}</td> |
|
|
|
|
<td className="px-3 py-2.5"> |
|
|
|
|
<code className="text-xs px-1.5 py-0.5 rounded" style={{ background: "var(--bb-sidebar-bg)", color: "var(--brand-073m)" }}>{cls}</code> |
|
|
|
|
</td> |
|
|
|
|
<td className="px-3 py-2.5 text-xs" style={{ color: "var(--bb-text-muted)" }}>{where}</td> |
|
|
|
|
<td className="px-3 py-2.5"> |
|
|
|
|
<code className="text-xs" style={{ color: "var(--bb-text-muted)" }}>{block}</code> |
|
|
|
|
</td> |
|
|
|
|
</tr> |
|
|
|
|
))} |
|
|
|
|
</tbody> |
|
|
|
|
</table> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
{/* Макет формы как на сайте */} |
|
|
|
|
<div className="rounded-xl overflow-hidden border" style={{ borderColor: "var(--bb-border)" }}> |
|
|
|
|
<div className="px-4 py-2 text-xs font-semibold uppercase tracking-widest" style={{ background: "var(--bb-sidebar-bg)", color: "var(--bb-text-muted)" }}> |
|
|
|
|
Макет — entityform «Узнайте стоимость операции» (oclinica.ru/lor) |
|
|
|
|
</div> |
|
|
|
|
<div style={{ background: "#b8e6ed", padding: "32px 24px" }}> |
|
|
|
|
<div |
|
|
|
|
className="mx-auto" |
|
|
|
|
style={{ |
|
|
|
|
maxWidth: 340, |
|
|
|
|
background: "#b8e6ed", |
|
|
|
|
textAlign: "center", |
|
|
|
|
}} |
|
|
|
|
> |
|
|
|
|
<p className="text-sm font-semibold mb-4" style={{ color: "#333", fontFamily: "var(--font-web)" }}> |
|
|
|
|
Узнайте стоимость операции |
|
|
|
|
</p> |
|
|
|
|
<div className="flex flex-col gap-3" style={{ alignItems: "center" }}> |
|
|
|
|
<input |
|
|
|
|
className="bb-input" |
|
|
|
|
type="text" |
|
|
|
|
placeholder="Ваше имя" |
|
|
|
|
style={{ width: 302 }} |
|
|
|
|
readOnly |
|
|
|
|
/> |
|
|
|
|
<input |
|
|
|
|
className="bb-input" |
|
|
|
|
type="text" |
|
|
|
|
placeholder="Ваш телефон" |
|
|
|
|
style={{ width: 302 }} |
|
|
|
|
readOnly |
|
|
|
|
/> |
|
|
|
|
<select className="bb-select" style={{ width: 302 }}> |
|
|
|
|
<option>Выберите врача</option> |
|
|
|
|
<option>Иванов И.И.</option> |
|
|
|
|
</select> |
|
|
|
|
<button className="bb-btn bb-btn-lg bb-btn-primary" style={{ width: 300 }}> |
|
|
|
|
Запишите меня! |
|
|
|
|
</button> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</Section> |
|
|
|
|
|
|
|
|
|
{/* 8. Примеры кода */} |
|
|
|
|
<Section |
|
|
|
|
id="code" |
|
|
|
|
title="Примеры кода" |
|
|
|
|
@ -533,18 +666,19 @@ export default function FormsPage() {
|
|
|
|
|
<CodeCopy lang="HTML — Checkbox" code={codeCheckbox} /> |
|
|
|
|
<CodeCopy lang="HTML — Radio" code={codeRadio} /> |
|
|
|
|
<CodeCopy lang="JSX (React) — Toggle" code={codeToggle} /> |
|
|
|
|
<CodeCopy lang="CSS с сайта (perm.oclinica.ru)" code={codeSiteCSS} /> |
|
|
|
|
</div> |
|
|
|
|
</Section> |
|
|
|
|
|
|
|
|
|
{/* LLM-блок */} |
|
|
|
|
<LlmBlock path="/components/forms" version="v1.0" specText={LLM_FORMS_TEXT}> |
|
|
|
|
<LlmBlock path="/components/forms" version="v2.0" specText={LLM_FORMS_TEXT}> |
|
|
|
|
<LlmSection title="Элементы ввода" /> |
|
|
|
|
<LlmTable |
|
|
|
|
headers={["Элемент", "CSS класс", "Тег", "Высота", "Описание"]} |
|
|
|
|
rows={[ |
|
|
|
|
["Input", ".bb-input", "<input>", "~40px", "Текстовое поле, email, password"], |
|
|
|
|
["Input", ".bb-input", "<input>", "50px", "Текстовое поле, email, password · как на сайте"], |
|
|
|
|
["Textarea", ".bb-textarea", "<textarea>", "≥100px", "Многострочный ввод, resize:vertical"], |
|
|
|
|
["Select", ".bb-select", "<select>", "~40px", "Выбор из списка, кастомная стрелка"], |
|
|
|
|
["Select", ".bb-select", "<select>", "50px", "Выбор из списка, кастомная стрелка · как на сайте"], |
|
|
|
|
["Checkbox", ".bb-checkbox", "<input type=checkbox>", "16×16px", "Независимый выбор"], |
|
|
|
|
["Radio", ".bb-radio", "<input type=radio>", "16×16px", "Выбор одного из группы"], |
|
|
|
|
["Toggle", ".bb-toggle-track", "React-компонент", "24px", "Булев переключатель"], |
|
|
|
|
@ -554,7 +688,7 @@ export default function FormsPage() {
|
|
|
|
|
<LlmTable |
|
|
|
|
headers={["Состояние", "Стиль"]} |
|
|
|
|
rows={[ |
|
|
|
|
["default", "border: 1.5px solid #e5e7eb"], |
|
|
|
|
["default", "border: 1px solid #ccc · border-radius: 4px"], |
|
|
|
|
["focus", "border: #7ecfca + box-shadow: 0 0 0 3px rgba(126,207,202,0.2)"], |
|
|
|
|
["error", "border: #dc2626 (+ класс .bb-error)"], |
|
|
|
|
["disabled", "opacity: 0.5 + cursor: not-allowed + bg: #f8f9fa"], |
|
|
|
|
|