polish(booking): focus treatment and specialty scroll

This commit is contained in:
Dana Medical Developer 2026-10-22 11:20:05 +00:00
parent ec46d9af67
commit 58c99d6286
2 changed files with 11 additions and 3 deletions

View File

@ -53,6 +53,8 @@
.doctor-picker__search { display: flex; align-items: center; gap: 10px; padding: 0 13px; border: 1px solid #e1e8ee; border-radius: 12px; background: #f6f8fb; } .doctor-picker__search { display: flex; align-items: center; gap: 10px; padding: 0 13px; border: 1px solid #e1e8ee; border-radius: 12px; background: #f6f8fb; }
.doctor-picker__search input { width: 100%; min-width: 0; height: 43px; border: 0; background: transparent; color: var(--navy); font: inherit; font-size: 13px; outline: none; } .doctor-picker__search input { width: 100%; min-width: 0; height: 43px; border: 0; background: transparent; color: var(--navy); font: inherit; font-size: 13px; outline: none; }
.doctor-picker__search input::placeholder { color: #81909d; } .doctor-picker__search input::placeholder { color: #81909d; }
.doctor-picker__search:focus-within { border-color: var(--coral); box-shadow: 0 0 0 3px rgba(249,94,82,.08); }
.doctor-picker__search input:focus-visible { outline: none; }
.doctor-picker__summary { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; padding: 14px 2px 10px; color: #7a8792; font-size: 11px; } .doctor-picker__summary { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; padding: 14px 2px 10px; color: #7a8792; font-size: 11px; }
.doctor-picker__total { display: inline-block; margin-left: 4px; color: var(--navy); font-weight: 600; } .doctor-picker__total { display: inline-block; margin-left: 4px; color: var(--navy); font-weight: 600; }
.doctor-picker__reset { padding: 2px 0; color: var(--coral); font: inherit; cursor: pointer; } .doctor-picker__reset { padding: 2px 0; color: var(--coral); font: inherit; cursor: pointer; }
@ -81,7 +83,7 @@
.doctor-picker__trigger { flex-shrink: 0; } .doctor-picker__trigger { flex-shrink: 0; }
.doctor-picker__panel { display: flex; flex-direction: column; flex: 1; min-height: 0; overflow: hidden; } .doctor-picker__panel { display: flex; flex-direction: column; flex: 1; min-height: 0; overflow: hidden; }
.doctor-picker__search, .doctor-picker__summary { flex-shrink: 0; } .doctor-picker__search, .doctor-picker__summary { flex-shrink: 0; }
.doctor-picker__results { flex: 1; min-height: 0; max-height: none; } .doctor-picker__results { position: relative; flex: 1; min-height: 0; max-height: none; }
.doctor-picker:has(.doctor-picker__panel) ~ * { display: none; } .doctor-picker:has(.doctor-picker__panel) ~ * { display: none; }
@media (max-width: 600px) { @media (max-width: 600px) {
.lead-modal__backdrop:has(.doctor-picker__panel) { padding-top: 12px; padding-bottom: 12px; } .lead-modal__backdrop:has(.doctor-picker__panel) { padding-top: 12px; padding-bottom: 12px; }

View File

@ -19,6 +19,7 @@ export default function DoctorPicker({ doctors, value, onChange, disabled = fals
const wrapper = useRef(null); const wrapper = useRef(null);
const trigger = useRef(null); const trigger = useRef(null);
const search = useRef(null); const search = useRef(null);
const results = useRef(null);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [query, setQuery] = useState(''); const [query, setQuery] = useState('');
const [expanded, setExpanded] = useState(''); const [expanded, setExpanded] = useState('');
@ -32,6 +33,11 @@ export default function DoctorPicker({ doctors, value, onChange, disabled = fals
useEffect(() => { useEffect(() => {
if (disabled) setOpen(false); if (disabled) setOpen(false);
}, [disabled]); }, [disabled]);
useEffect(() => {
if (!open || query.trim() || !expanded || !results.current) return;
const group = [...results.current.children].find((element) => element.dataset.group === expanded);
if (typeof group?.offsetTop === 'number') results.current.scrollTop = group.offsetTop;
}, [expanded, open, query]);
useEffect(() => { useEffect(() => {
if (!open) return undefined; if (!open) return undefined;
const outside = (event) => { if (!wrapper.current?.contains(event.target)) setOpen(false); }; const outside = (event) => { if (!wrapper.current?.contains(event.target)) setOpen(false); };
@ -94,13 +100,13 @@ export default function DoctorPicker({ doctors, value, onChange, disabled = fals
<span>{date ? 'Свободны на выбранную дату' : 'Специалисты по направлениям'} <span className="doctor-picker__total">{count}</span></span> <span>{date ? 'Свободны на выбранную дату' : 'Специалисты по направлениям'} <span className="doctor-picker__total">{count}</span></span>
{value && <button type="button" className="doctor-picker__reset" onClick={() => choose('')}>Сбросить выбор</button>} {value && <button type="button" className="doctor-picker__reset" onClick={() => choose('')}>Сбросить выбор</button>}
</div> </div>
<div className="doctor-picker__results"> <div className="doctor-picker__results" ref={results}>
{!groups.length && <p className="doctor-picker__empty">Врачи не найдены. Измените поиск или выберите другую дату.</p>} {!groups.length && <p className="doctor-picker__empty">Врачи не найдены. Измените поиск или выберите другую дату.</p>}
{groups.map((group, index) => { {groups.map((group, index) => {
const shown = Boolean(query.trim()) || expanded === group.key; const shown = Boolean(query.trim()) || expanded === group.key;
const listId = `${uid}-group-${index}`; const listId = `${uid}-group-${index}`;
return ( return (
<section className="doctor-picker__group" key={group.key}> <section className="doctor-picker__group" key={group.key} data-group={group.key}>
<h3> <h3>
<button type="button" className="doctor-picker__direction" aria-expanded={shown} aria-controls={listId} disabled={Boolean(query.trim())} onClick={() => setExpanded(shown ? '' : group.key)}> <button type="button" className="doctor-picker__direction" aria-expanded={shown} aria-controls={listId} disabled={Boolean(query.trim())} onClick={() => setExpanded(shown ? '' : group.key)}>
<span className="doctor-picker__direction-dot" aria-hidden="true" /> <span className="doctor-picker__direction-dot" aria-hidden="true" />