Улучшено управление положением выпадающего меню в панели инструментов Markdown, добавлены ссылки на кнопки и обработка кликов вне меню. Обновлены стили календаря для поддержки переменных цвета акцента, улучшена визуализация элементов при наведении и выделении.

This commit is contained in:
Fovway 2025-11-01 13:03:19 +07:00
parent 6ed6e045fe
commit 5c025b9349
3 changed files with 197 additions and 52 deletions

View File

@ -21,28 +21,55 @@ export const MarkdownToolbar: React.FC<MarkdownToolbarProps> = ({
const [showHeaderDropdown, setShowHeaderDropdown] = useState(false);
const dispatch = useAppDispatch();
const dropdownRef = useRef<HTMLDivElement>(null);
const buttonRef = useRef<HTMLButtonElement>(null);
const menuRef = useRef<HTMLDivElement>(null);
const containerRef = useRef<HTMLDivElement>(null);
const [isDragging, setIsDragging] = useState(false);
const [startX, setStartX] = useState(0);
const [scrollLeft, setScrollLeft] = useState(0);
const [menuPosition, setMenuPosition] = useState<{ top: number; left: number } | null>(null);
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node)
!dropdownRef.current.contains(event.target as Node) &&
menuRef.current &&
!menuRef.current.contains(event.target as Node)
) {
setShowHeaderDropdown(false);
setMenuPosition(null);
}
};
const updateMenuPosition = () => {
if (buttonRef.current && showHeaderDropdown) {
const rect = buttonRef.current.getBoundingClientRect();
setMenuPosition({
top: rect.bottom + window.scrollY + 2,
left: rect.left + window.scrollX,
});
}
};
if (showHeaderDropdown) {
document.addEventListener("mousedown", handleClickOutside);
}
updateMenuPosition();
// Используем небольшой таймаут, чтобы не перехватить клик на кнопке
const timeoutId = setTimeout(() => {
document.addEventListener("mousedown", handleClickOutside);
window.addEventListener("resize", updateMenuPosition);
window.addEventListener("scroll", updateMenuPosition);
}, 100);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
return () => {
clearTimeout(timeoutId);
document.removeEventListener("mousedown", handleClickOutside);
window.removeEventListener("resize", updateMenuPosition);
window.removeEventListener("scroll", updateMenuPosition);
};
} else {
setMenuPosition(null);
}
}, [showHeaderDropdown]);
const handleMouseDown = (e: React.MouseEvent) => {
@ -118,8 +145,15 @@ export const MarkdownToolbar: React.FC<MarkdownToolbarProps> = ({
<div className="header-dropdown" ref={dropdownRef}>
<button
ref={buttonRef}
className="btnMarkdown"
onClick={() => setShowHeaderDropdown(!showHeaderDropdown)}
onMouseDown={(e) => {
e.stopPropagation();
}}
onClick={(e) => {
e.stopPropagation();
setShowHeaderDropdown(!showHeaderDropdown);
}}
title="Заголовок"
>
<Icon icon="mdi:format-header-pound" />
@ -128,14 +162,24 @@ export const MarkdownToolbar: React.FC<MarkdownToolbarProps> = ({
style={{ fontSize: "10px", marginLeft: "-2px" }}
/>
</button>
{showHeaderDropdown && (
<div className="header-dropdown-menu">
{showHeaderDropdown && menuPosition && (
<div
ref={menuRef}
className="header-dropdown-menu"
style={{
position: "fixed",
top: `${menuPosition.top}px`,
left: `${menuPosition.left}px`,
}}
>
{[1, 2, 3, 4, 5].map((level) => (
<button
key={level}
onClick={() => {
onClick={(e) => {
e.stopPropagation();
onInsert("#".repeat(level) + " ", "");
setShowHeaderDropdown(false);
setMenuPosition(null);
}}
>
H{level}

View File

@ -45,9 +45,9 @@
}
.calendar-nav-btn:hover {
background: #007bff;
background: var(--accent-color, #007bff);
color: white;
border-color: #007bff;
border-color: var(--accent-color, #007bff);
}
.calendar-weekdays {
@ -80,7 +80,7 @@
font-size: 10px;
border-radius: 3px;
cursor: pointer;
background: #f8f9fa;
background: transparent;
color: #666;
border: 1px solid transparent;
transition: all 0.2s ease;
@ -88,35 +88,41 @@
}
.calendar-day:hover {
background: #e8f4f8;
border-color: #007bff;
background: transparent;
border-color: var(--accent-color, #007bff);
}
.calendar-day.other-month {
color: #ccc;
background: #fafafa;
background: transparent;
}
.calendar-day.other-month:hover {
border-color: var(--accent-color, #007bff);
}
.calendar-day.today {
background: #007bff;
color: white;
background: transparent;
color: #666;
font-weight: 600;
border-color: #0056cc;
border-color: var(--accent-color, #007bff);
}
.calendar-day.today:hover {
background: #0056cc;
background: transparent;
border-color: var(--accent-color, #007bff);
}
.calendar-day.selected {
background: #28a745;
background: var(--accent-color, #007bff);
color: white;
font-weight: 600;
border-color: #1e7e34;
border-color: var(--accent-color, #007bff);
}
.calendar-day.selected:hover {
background: #1e7e34;
background: var(--accent-color, #007bff);
border-color: var(--accent-color, #007bff);
}
.main {

View File

@ -1261,19 +1261,17 @@ textarea:focus {
position: relative;
display: inline-block;
overflow: visible;
z-index: 1;
}
.header-dropdown-menu {
display: block;
position: absolute;
top: 100%;
right: 0;
position: fixed;
background: var(--bg-secondary);
border: 1px solid var(--border-secondary);
border-radius: 5px;
box-shadow: 0 2px 8px var(--shadow-medium);
z-index: 1000;
margin-top: 2px;
z-index: 1001;
min-width: 60px;
max-width: 120px;
}
@ -1702,27 +1700,48 @@ textarea:focus {
padding: 2px;
font-weight: 500;
position: relative;
background-color: transparent;
border: 1px solid transparent;
}
.calendar-day:hover {
background-color: var(--bg-hover);
background-color: transparent;
border-color: var(--accent-color, #007bff);
}
.calendar-day.today {
background-color: var(--accent-color, #007bff);
color: white;
background-color: transparent;
color: var(--text-primary);
font-weight: bold;
border: 1px solid var(--accent-color, #007bff);
}
.calendar-day.today:hover {
background-color: transparent;
border-color: var(--accent-color, #007bff);
}
.calendar-day.other-month {
color: var(--text-muted);
background-color: transparent;
border: 1px solid transparent;
}
.calendar-day.other-month:hover {
border-color: var(--accent-color, #007bff);
}
.calendar-day.selected {
background-color: var(--accent-color, #007bff);
color: white;
font-weight: bold;
opacity: 0.9;
opacity: 1;
border: 1px solid var(--accent-color, #007bff);
}
.calendar-day.selected:hover {
background-color: var(--accent-color, #007bff);
border-color: var(--accent-color, #007bff);
}
/* Стили календаря для PC версии (темный стиль как на изображении) */
@ -1765,29 +1784,48 @@ textarea:focus {
color: #ffffff;
font-weight: 400;
background-color: transparent;
border: 1px solid transparent;
}
.calendar-day:hover {
background-color: rgba(255, 255, 255, 0.1);
background-color: transparent;
border-color: var(--accent-color, #007bff);
}
.calendar-day.other-month {
color: #999999;
background-color: transparent;
border: 1px solid transparent;
}
.calendar-day.other-month:hover {
border-color: var(--accent-color, #007bff);
}
.calendar-day.selected {
background-color: #007bff;
background-color: var(--accent-color, #007bff);
color: white;
font-weight: 500;
opacity: 1;
border-radius: 4px;
border: 1px solid var(--accent-color, #007bff);
}
.calendar-day.selected:hover {
background-color: var(--accent-color, #007bff);
border-color: var(--accent-color, #007bff);
}
.calendar-day.today {
background-color: #007bff;
color: white;
background-color: transparent;
color: #ffffff;
font-weight: 500;
border: 1px solid var(--accent-color, #007bff);
}
.calendar-day.today:hover {
background-color: transparent;
border-color: var(--accent-color, #007bff);
}
}
@ -1878,26 +1916,45 @@ textarea:focus {
[data-theme="dark"] .calendar-day {
background-color: transparent;
color: #ffffff;
border: 1px solid transparent;
}
[data-theme="dark"] .calendar-day:hover {
background-color: rgba(255, 255, 255, 0.1);
background-color: transparent;
border-color: var(--accent-color, #007bff);
}
[data-theme="dark"] .calendar-day.other-month {
background-color: transparent;
color: #999999;
border: 1px solid transparent;
}
[data-theme="dark"] .calendar-day.other-month:hover {
border-color: var(--accent-color, #007bff);
}
[data-theme="dark"] .calendar-day.today {
background-color: #007bff;
color: white;
background-color: transparent;
color: #ffffff;
border: 1px solid var(--accent-color, #007bff);
}
[data-theme="dark"] .calendar-day.today:hover {
background-color: transparent;
border-color: var(--accent-color, #007bff);
}
[data-theme="dark"] .calendar-day.selected {
background-color: #007bff;
background-color: var(--accent-color, #007bff);
color: white;
opacity: 1;
border: 1px solid var(--accent-color, #007bff);
}
[data-theme="dark"] .calendar-day.selected:hover {
background-color: var(--accent-color, #007bff);
border-color: var(--accent-color, #007bff);
}
[data-theme="dark"] .calendar-nav {
@ -2165,55 +2222,93 @@ textarea:focus {
padding: 1px;
font-weight: 500;
position: relative;
background-color: var(--bg-tertiary);
background-color: transparent;
border: 1px solid transparent;
}
.mobile-sidebar .calendar-day:hover {
background-color: var(--bg-quaternary);
background-color: transparent;
border-color: var(--accent-color, #007bff);
}
.mobile-sidebar .calendar-day.today {
background-color: var(--accent-color, #007bff);
color: white;
background-color: transparent;
color: var(--text-primary);
font-weight: bold;
border: 1px solid var(--accent-color, #007bff);
}
.mobile-sidebar .calendar-day.today:hover {
background-color: transparent;
border-color: var(--accent-color, #007bff);
}
.mobile-sidebar .calendar-day.selected {
background-color: var(--accent-color, #007bff);
color: white;
font-weight: bold;
opacity: 0.9;
opacity: 1;
border: 1px solid var(--accent-color, #007bff);
}
.mobile-sidebar .calendar-day.selected:hover {
background-color: var(--accent-color, #007bff);
border-color: var(--accent-color, #007bff);
}
.mobile-sidebar .calendar-day.other-month {
color: var(--text-muted);
background-color: var(--bg-primary);
background-color: transparent;
border: 1px solid transparent;
}
.mobile-sidebar .calendar-day.other-month:hover {
border-color: var(--accent-color, #007bff);
}
/* Темная тема для календаря в мобильном сайдбаре */
[data-theme="dark"] .mobile-sidebar .calendar-day {
background-color: var(--bg-tertiary);
background-color: transparent;
color: var(--text-primary);
border: 1px solid transparent;
}
[data-theme="dark"] .mobile-sidebar .calendar-day:hover {
background-color: var(--bg-quaternary);
background-color: transparent;
border-color: var(--accent-color, #007bff);
}
[data-theme="dark"] .mobile-sidebar .calendar-day.other-month {
background-color: var(--bg-primary);
background-color: transparent;
color: var(--text-muted);
border: 1px solid transparent;
}
[data-theme="dark"] .mobile-sidebar .calendar-day.other-month:hover {
border-color: var(--accent-color, #007bff);
}
[data-theme="dark"] .mobile-sidebar .calendar-day.today {
background-color: var(--accent-color, #007bff);
color: white;
background-color: transparent;
color: var(--text-primary);
border: 1px solid var(--accent-color, #007bff);
}
[data-theme="dark"] .mobile-sidebar .calendar-day.today:hover {
background-color: transparent;
border-color: var(--accent-color, #007bff);
}
[data-theme="dark"] .mobile-sidebar .calendar-day.selected {
background-color: var(--accent-color, #007bff);
color: white;
opacity: 0.9;
opacity: 1;
border: 1px solid var(--accent-color, #007bff);
}
[data-theme="dark"] .mobile-sidebar .calendar-day.selected:hover {
background-color: var(--accent-color, #007bff);
border-color: var(--accent-color, #007bff);
}
[data-theme="dark"] .mobile-sidebar .calendar-nav:hover {