Commit ·
9eaed94
1
Parent(s): 37fc5f3
fix: UI/UX audit fixes (10 items addressed) Critical: - Fix text duplication on consecutive suggestion apply (re-index spans) - Suggestion list now updates after apply (counters + cards refresh) UX Fixes: - Sidebar scrollable (score circle always accessible) - Suggestions max-height reduced: 420→320px - Stat items: larger font + better contrast in dark mode Text: - Pricing: 'الترقية للاحترافي' → 'الترقية للخطة الاحترافية' Undo/Redo: - formatUndo/Redo now use custom stack (unified) - Formatting commands save undo state before applying - Typing tracked via debounced pushUndoStateDebounced
Browse files- src/css/components.css +7 -3
- src/index.html +1 -1
- src/js/editor.js +49 -0
src/css/components.css
CHANGED
|
@@ -961,6 +961,9 @@
|
|
| 961 |
display: flex;
|
| 962 |
flex-direction: column;
|
| 963 |
gap: var(--spacing-md);
|
|
|
|
|
|
|
|
|
|
| 964 |
}
|
| 965 |
|
| 966 |
.sidebar-card {
|
|
@@ -968,7 +971,7 @@
|
|
| 968 |
}
|
| 969 |
|
| 970 |
.suggestions-scroll {
|
| 971 |
-
max-height:
|
| 972 |
overflow-y: auto;
|
| 973 |
display: flex;
|
| 974 |
flex-direction: column;
|
|
@@ -2235,8 +2238,9 @@ input[type="range"]::-webkit-slider-thumb {
|
|
| 2235 |
display: flex;
|
| 2236 |
align-items: center;
|
| 2237 |
gap: 4px;
|
| 2238 |
-
font-size:
|
| 2239 |
-
color: var(--color-text-muted);
|
|
|
|
| 2240 |
}
|
| 2241 |
|
| 2242 |
.stat-item--sep {
|
|
|
|
| 961 |
display: flex;
|
| 962 |
flex-direction: column;
|
| 963 |
gap: var(--spacing-md);
|
| 964 |
+
max-height: calc(100vh - 140px);
|
| 965 |
+
overflow-y: auto;
|
| 966 |
+
scrollbar-width: thin;
|
| 967 |
}
|
| 968 |
|
| 969 |
.sidebar-card {
|
|
|
|
| 971 |
}
|
| 972 |
|
| 973 |
.suggestions-scroll {
|
| 974 |
+
max-height: 320px;
|
| 975 |
overflow-y: auto;
|
| 976 |
display: flex;
|
| 977 |
flex-direction: column;
|
|
|
|
| 2238 |
display: flex;
|
| 2239 |
align-items: center;
|
| 2240 |
gap: 4px;
|
| 2241 |
+
font-size: 0.8rem;
|
| 2242 |
+
color: var(--color-text-secondary, var(--color-text-muted));
|
| 2243 |
+
opacity: 0.85;
|
| 2244 |
}
|
| 2245 |
|
| 2246 |
.stat-item--sep {
|
src/index.html
CHANGED
|
@@ -819,7 +819,7 @@
|
|
| 819 |
<li class="flex items-center gap-3">
|
| 820 |
<svg class="w-5 h-5" style="color: #22c55e;" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
| 821 |
</svg><span class="text-base">تصدير PDF و Word</span></li>
|
| 822 |
-
</ul><button onclick="showPage('editor')" class="w-full py-4 rounded-2xl text-lg font-bold text-white gradient-accent transition-all hover:scale-105 hover:shadow-2xl"> الترقية للاحترافي </button>
|
| 823 |
</div><!-- Enterprise Plan -->
|
| 824 |
<div class="p-8 rounded-3xl transition-all hover:scale-105" style="background: var(--surface-color); border: 1px solid rgba(255, 255, 255, 0.08);">
|
| 825 |
<div class="text-center mb-8">
|
|
|
|
| 819 |
<li class="flex items-center gap-3">
|
| 820 |
<svg class="w-5 h-5" style="color: #22c55e;" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
| 821 |
</svg><span class="text-base">تصدير PDF و Word</span></li>
|
| 822 |
+
</ul><button onclick="showPage('editor')" class="w-full py-4 rounded-2xl text-lg font-bold text-white gradient-accent transition-all hover:scale-105 hover:shadow-2xl"> الترقية للخطة الاحترافية </button>
|
| 823 |
</div><!-- Enterprise Plan -->
|
| 824 |
<div class="p-8 rounded-3xl transition-all hover:scale-105" style="background: var(--surface-color); border: 1px solid rgba(255, 255, 255, 0.08);">
|
| 825 |
<div class="text-center mb-8">
|
src/js/editor.js
CHANGED
|
@@ -472,6 +472,32 @@ function applySuggestionAtOffsets(suggestion) {
|
|
| 472 |
hideTooltip();
|
| 473 |
// Re-focus editor so Ctrl+Z works immediately after tooltip correction
|
| 474 |
const _ed = getEditorElement(); if (_ed) _ed.focus();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 475 |
analyzeTextDelayed();
|
| 476 |
}
|
| 477 |
|
|
@@ -516,6 +542,29 @@ function applyAlternativeCorrection(suggestion, correctionText) {
|
|
| 516 |
hideTooltip();
|
| 517 |
// Re-focus editor so Ctrl+Z works immediately after tooltip correction
|
| 518 |
const _ed2 = getEditorElement(); if (_ed2) _ed2.focus();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 519 |
analyzeTextDelayed();
|
| 520 |
}
|
| 521 |
|
|
|
|
| 472 |
hideTooltip();
|
| 473 |
// Re-focus editor so Ctrl+Z works immediately after tooltip correction
|
| 474 |
const _ed = getEditorElement(); if (_ed) _ed.focus();
|
| 475 |
+
|
| 476 |
+
// Remove applied suggestion from list and re-index remaining spans
|
| 477 |
+
if (window.currentSuggestions) {
|
| 478 |
+
window.currentSuggestions = window.currentSuggestions.filter(
|
| 479 |
+
s => !(s.start === suggestion.start && s.end === suggestion.end && s.type === suggestion.type)
|
| 480 |
+
);
|
| 481 |
+
|
| 482 |
+
// Re-index remaining error spans to match updated array indices
|
| 483 |
+
const remainingSpans = document.querySelectorAll('.spelling-error, .grammar-error, .punctuation-suggestion');
|
| 484 |
+
remainingSpans.forEach(span => {
|
| 485 |
+
const newIdx = window.currentSuggestions.findIndex(s => {
|
| 486 |
+
return span.textContent === s.original && span.dataset.type === s.type;
|
| 487 |
+
});
|
| 488 |
+
if (newIdx >= 0) {
|
| 489 |
+
span.dataset.suggestionId = newIdx;
|
| 490 |
+
}
|
| 491 |
+
});
|
| 492 |
+
|
| 493 |
+
const spellingCount = window.currentSuggestions.filter(s => s.type === 'spelling').length;
|
| 494 |
+
const grammarCount = window.currentSuggestions.filter(s => s.type === 'grammar').length;
|
| 495 |
+
const punctuationCount = window.currentSuggestions.filter(s => s.type === 'punctuation').length;
|
| 496 |
+
updateSuggestionCounts(spellingCount, grammarCount, punctuationCount);
|
| 497 |
+
updateWritingScore(spellingCount, grammarCount, punctuationCount);
|
| 498 |
+
updateSuggestionsList(window.currentSuggestions);
|
| 499 |
+
}
|
| 500 |
+
|
| 501 |
analyzeTextDelayed();
|
| 502 |
}
|
| 503 |
|
|
|
|
| 542 |
hideTooltip();
|
| 543 |
// Re-focus editor so Ctrl+Z works immediately after tooltip correction
|
| 544 |
const _ed2 = getEditorElement(); if (_ed2) _ed2.focus();
|
| 545 |
+
// Remove applied suggestion from list and re-index remaining spans
|
| 546 |
+
if (window.currentSuggestions) {
|
| 547 |
+
window.currentSuggestions = window.currentSuggestions.filter(
|
| 548 |
+
s => !(s.start === suggestion.start && s.end === suggestion.end && s.type === suggestion.type)
|
| 549 |
+
);
|
| 550 |
+
|
| 551 |
+
const remainingSpans = document.querySelectorAll('.spelling-error, .grammar-error, .punctuation-suggestion');
|
| 552 |
+
remainingSpans.forEach(span => {
|
| 553 |
+
const newIdx = window.currentSuggestions.findIndex(s => {
|
| 554 |
+
return span.textContent === s.original && span.dataset.type === s.type;
|
| 555 |
+
});
|
| 556 |
+
if (newIdx >= 0) {
|
| 557 |
+
span.dataset.suggestionId = newIdx;
|
| 558 |
+
}
|
| 559 |
+
});
|
| 560 |
+
|
| 561 |
+
const spellingCount = window.currentSuggestions.filter(s => s.type === 'spelling').length;
|
| 562 |
+
const grammarCount = window.currentSuggestions.filter(s => s.type === 'grammar').length;
|
| 563 |
+
const punctuationCount = window.currentSuggestions.filter(s => s.type === 'punctuation').length;
|
| 564 |
+
updateSuggestionCounts(spellingCount, grammarCount, punctuationCount);
|
| 565 |
+
updateWritingScore(spellingCount, grammarCount, punctuationCount);
|
| 566 |
+
updateSuggestionsList(window.currentSuggestions);
|
| 567 |
+
}
|
| 568 |
analyzeTextDelayed();
|
| 569 |
}
|
| 570 |
|