improving ui
This commit is contained in:
@@ -82,7 +82,6 @@ export function FlashcardReviewComponent() {
|
|||||||
library.id,
|
library.id,
|
||||||
{
|
{
|
||||||
fileName: library.fileName,
|
fileName: library.fileName,
|
||||||
subject: library.subject || 'Geral',
|
|
||||||
difficultyLabel: difficultyLabel(library.difficulty),
|
difficultyLabel: difficultyLabel(library.difficulty),
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
|
|||||||
@@ -203,8 +203,7 @@
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.study-tag,
|
.study-tag {
|
||||||
.study-status-badge {
|
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
@@ -214,53 +213,13 @@
|
|||||||
border: 1px solid rgba(82, 54, 17, .12);
|
border: 1px solid rgba(82, 54, 17, .12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.study-status-badge {
|
|
||||||
font-size: 11px;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.study-status-icon {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
border-radius: 999px;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background: rgba(82, 54, 17, .10);
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.study-status-badge.rag-red {
|
|
||||||
color: var(--red-deep);
|
|
||||||
background: rgba(183, 91, 77, 0.12);
|
|
||||||
border-color: rgba(183, 91, 77, 0.22);
|
|
||||||
}
|
|
||||||
|
|
||||||
.study-status-badge.rag-amber {
|
|
||||||
color: #74531c;
|
|
||||||
background: rgba(199, 149, 57, 0.14);
|
|
||||||
border-color: rgba(199, 149, 57, 0.24);
|
|
||||||
}
|
|
||||||
|
|
||||||
.study-status-badge.rag-green {
|
|
||||||
color: var(--green-deep);
|
|
||||||
background: rgba(79, 143, 90, 0.12);
|
|
||||||
border-color: rgba(79, 143, 90, 0.22);
|
|
||||||
}
|
|
||||||
|
|
||||||
.study-status-badge.rag-grey {
|
|
||||||
color: var(--muted);
|
|
||||||
background: rgba(123, 106, 80, 0.10);
|
|
||||||
border-color: rgba(123, 106, 80, 0.18);
|
|
||||||
}
|
|
||||||
|
|
||||||
.study-card-question,
|
.study-card-question,
|
||||||
.study-card-answer {
|
.study-card-answer {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
display: grid;
|
display: grid;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
gap: 16px;
|
gap: 18px;
|
||||||
min-height: 190px;
|
min-height: 190px;
|
||||||
color: var(--ink);
|
color: var(--ink);
|
||||||
font-family: "Segoe UI", Inter, Avenir, system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
|
font-family: "Segoe UI", Inter, Avenir, system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
|
||||||
@@ -271,14 +230,14 @@
|
|||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.study-back-question,
|
.study-back-answer,
|
||||||
.study-back-answer {
|
.study-back-question {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.study-back-question span,
|
.study-back-answer span,
|
||||||
.study-back-answer span {
|
.study-back-question span {
|
||||||
color: var(--blue-deep);
|
color: var(--blue-deep);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 950;
|
font-weight: 950;
|
||||||
@@ -286,30 +245,21 @@
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.study-back-question p,
|
.study-back-answer p,
|
||||||
.study-back-answer p {
|
.study-back-question p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: var(--ink);
|
color: var(--ink);
|
||||||
}
|
}
|
||||||
|
|
||||||
.study-back-question p {
|
|
||||||
color: #66543d;
|
|
||||||
font-size: clamp(15px, 1.7vw, 18px);
|
|
||||||
line-height: 1.45;
|
|
||||||
}
|
|
||||||
|
|
||||||
.study-back-answer p {
|
.study-back-answer p {
|
||||||
font-size: clamp(20px, 2.65vw, 24px);
|
font-size: clamp(20px, 2.65vw, 24px);
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.study-card-details {
|
.study-back-question p {
|
||||||
display: flex;
|
color: #66543d;
|
||||||
flex-wrap: wrap;
|
font-size: clamp(15px, 1.7vw, 18px);
|
||||||
gap: 8px;
|
line-height: 1.45;
|
||||||
color: var(--muted);
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 800;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.study-card-footer {
|
.study-card-footer {
|
||||||
@@ -324,19 +274,6 @@
|
|||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
.study-spacebar {
|
|
||||||
padding: 4px 9px;
|
|
||||||
border-radius: 8px;
|
|
||||||
color: #4f3a1d;
|
|
||||||
background: rgba(255,255,255,.58);
|
|
||||||
border: 1px solid rgba(82, 54, 17, .14);
|
|
||||||
box-shadow: inset 0 -2px 0 rgba(82, 54, 17, .08);
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 950;
|
|
||||||
letter-spacing: .08em;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
.study-controls {
|
.study-controls {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
@@ -519,7 +456,7 @@
|
|||||||
|
|
||||||
.study-queue-item {
|
.study-queue-item {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 38px minmax(0, 1fr) auto;
|
grid-template-columns: 38px minmax(0, 1fr);
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
@@ -536,11 +473,6 @@
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.study-queue-item span {
|
|
||||||
color: var(--muted);
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.study-queue-number {
|
.study-queue-number {
|
||||||
width: 38px;
|
width: 38px;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
|
|||||||
@@ -5,13 +5,7 @@ import './FlashcardStudySession.css';
|
|||||||
|
|
||||||
export interface FlashcardStudySessionLibraryMeta {
|
export interface FlashcardStudySessionLibraryMeta {
|
||||||
fileName?: string;
|
fileName?: string;
|
||||||
subject?: string;
|
|
||||||
subSubject?: string;
|
|
||||||
difficultyLabel?: string;
|
difficultyLabel?: string;
|
||||||
statusLabel?: string;
|
|
||||||
statusIcon?: string;
|
|
||||||
statusClassName?: string;
|
|
||||||
footerDetails?: string[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FlashcardStudySessionProps {
|
interface FlashcardStudySessionProps {
|
||||||
@@ -105,13 +99,13 @@ function resetTimeout(timeoutRef: { current: number | null }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formatFooter(meta: FlashcardStudySessionLibraryMeta | undefined) {
|
function formatFooter(meta: FlashcardStudySessionLibraryMeta | undefined) {
|
||||||
const main = [meta?.fileName, meta?.subSubject].filter(Boolean).join(' - ');
|
return meta?.fileName || 'Arquivo';
|
||||||
return main || 'Arquivo';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FlashcardStudySession({ cards, libraryMetaById, onAnswer, onEnd }: FlashcardStudySessionProps) {
|
export function FlashcardStudySession({ cards, libraryMetaById, onAnswer, onEnd }: FlashcardStudySessionProps) {
|
||||||
const [currentIndex, setCurrentIndex] = useState(0);
|
const [currentIndex, setCurrentIndex] = useState(0);
|
||||||
const [showAnswer, setShowAnswer] = useState(false);
|
const [showAnswer, setShowAnswer] = useState(false);
|
||||||
|
const [showBackQuestion, setShowBackQuestion] = useState(false);
|
||||||
const [submittingAnswer, setSubmittingAnswer] = useState(false);
|
const [submittingAnswer, setSubmittingAnswer] = useState(false);
|
||||||
const [cardExiting, setCardExiting] = useState(false);
|
const [cardExiting, setCardExiting] = useState(false);
|
||||||
const [stampState, setStampState] = useState<'correct' | 'wrong' | null>(null);
|
const [stampState, setStampState] = useState<'correct' | 'wrong' | null>(null);
|
||||||
@@ -134,6 +128,7 @@ export function FlashcardStudySession({ cards, libraryMetaById, onAnswer, onEnd
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCurrentIndex(0);
|
setCurrentIndex(0);
|
||||||
setShowAnswer(false);
|
setShowAnswer(false);
|
||||||
|
setShowBackQuestion(false);
|
||||||
setSubmittingAnswer(false);
|
setSubmittingAnswer(false);
|
||||||
setCardExiting(false);
|
setCardExiting(false);
|
||||||
setStampState(null);
|
setStampState(null);
|
||||||
@@ -165,10 +160,10 @@ export function FlashcardStudySession({ cards, libraryMetaById, onAnswer, onEnd
|
|||||||
if (!showAnswer) {
|
if (!showAnswer) {
|
||||||
setShowAnswer(true);
|
setShowAnswer(true);
|
||||||
}
|
}
|
||||||
} else if (e.code === 'KeyC' && showAnswer && !submittingAnswer) {
|
} else if (e.code === 'KeyC' && showAnswer && !showBackQuestion && !submittingAnswer) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
void registerReviewAnswer(true);
|
void registerReviewAnswer(true);
|
||||||
} else if (e.code === 'KeyW' && showAnswer && !submittingAnswer) {
|
} else if (e.code === 'KeyW' && showAnswer && !showBackQuestion && !submittingAnswer) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
void registerReviewAnswer(false);
|
void registerReviewAnswer(false);
|
||||||
}
|
}
|
||||||
@@ -176,12 +171,13 @@ export function FlashcardStudySession({ cards, libraryMetaById, onAnswer, onEnd
|
|||||||
|
|
||||||
window.addEventListener('keydown', handleKeyDown);
|
window.addEventListener('keydown', handleKeyDown);
|
||||||
return () => window.removeEventListener('keydown', handleKeyDown);
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
||||||
}, [cards.length, showAnswer, submittingAnswer, currentCard]);
|
}, [cards.length, currentCard, showAnswer, showBackQuestion, submittingAnswer]);
|
||||||
|
|
||||||
const goToPrevious = () => {
|
const goToPrevious = () => {
|
||||||
if (currentIndex === 0 || submittingAnswer) return;
|
if (currentIndex === 0 || submittingAnswer) return;
|
||||||
setCurrentIndex(currentIndex - 1);
|
setCurrentIndex(currentIndex - 1);
|
||||||
setShowAnswer(false);
|
setShowAnswer(false);
|
||||||
|
setShowBackQuestion(false);
|
||||||
setFlipped(false);
|
setFlipped(false);
|
||||||
setStampState(null);
|
setStampState(null);
|
||||||
setCardExiting(false);
|
setCardExiting(false);
|
||||||
@@ -196,6 +192,7 @@ export function FlashcardStudySession({ cards, libraryMetaById, onAnswer, onEnd
|
|||||||
|
|
||||||
setCurrentIndex(currentIndex + 1);
|
setCurrentIndex(currentIndex + 1);
|
||||||
setShowAnswer(false);
|
setShowAnswer(false);
|
||||||
|
setShowBackQuestion(false);
|
||||||
setFlipped(false);
|
setFlipped(false);
|
||||||
setStampState(null);
|
setStampState(null);
|
||||||
setCardExiting(false);
|
setCardExiting(false);
|
||||||
@@ -204,7 +201,7 @@ export function FlashcardStudySession({ cards, libraryMetaById, onAnswer, onEnd
|
|||||||
};
|
};
|
||||||
|
|
||||||
const registerReviewAnswer = async (correct: boolean) => {
|
const registerReviewAnswer = async (correct: boolean) => {
|
||||||
if (!currentCard || !showAnswer || submittingAnswer) return;
|
if (!currentCard || !showAnswer || showBackQuestion || submittingAnswer) return;
|
||||||
|
|
||||||
resetTimeout(stampTimerRef);
|
resetTimeout(stampTimerRef);
|
||||||
resetTimeout(advanceTimerRef);
|
resetTimeout(advanceTimerRef);
|
||||||
@@ -277,22 +274,38 @@ export function FlashcardStudySession({ cards, libraryMetaById, onAnswer, onEnd
|
|||||||
<div class="study-stage">
|
<div class="study-stage">
|
||||||
<div
|
<div
|
||||||
class={`study-flashcard${flipped ? ' is-flipped' : ''}${cardExiting ? ' is-reviewed' : ''}`}
|
class={`study-flashcard${flipped ? ' is-flipped' : ''}${cardExiting ? ' is-reviewed' : ''}`}
|
||||||
onClick={() => { if (!showAnswer && !submittingAnswer) setShowAnswer(true); }}
|
onClick={() => {
|
||||||
|
if (submittingAnswer) return;
|
||||||
|
if (!showAnswer) {
|
||||||
|
setShowAnswer(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!showBackQuestion) {
|
||||||
|
setShowBackQuestion(true);
|
||||||
|
}
|
||||||
|
}}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
role="button"
|
role="button"
|
||||||
aria-label={showAnswer ? 'Flashcard revelado' : 'Clique ou pressione Espaço para revelar'}
|
aria-label={
|
||||||
|
!showAnswer
|
||||||
|
? 'Clique ou pressione Espaço para revelar'
|
||||||
|
: showBackQuestion
|
||||||
|
? 'Flashcard com pergunta e resposta visíveis'
|
||||||
|
: 'Clique para mostrar a pergunta junto da resposta'
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<div class="study-card-face">
|
<div class="study-card-face">
|
||||||
|
{currentMeta?.difficultyLabel && (
|
||||||
<div class="study-card-meta">
|
<div class="study-card-meta">
|
||||||
<span class="study-tag">{currentMeta?.subject || 'Geral'}</span>
|
<span class="study-tag">{currentMeta.difficultyLabel}</span>
|
||||||
<span>{currentMeta?.difficultyLabel || currentMeta?.statusLabel || 'Revisão'}</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
<div class="study-card-question">
|
<div class="study-card-question">
|
||||||
{currentCard.front}
|
{currentCard.front}
|
||||||
</div>
|
</div>
|
||||||
<div class="study-card-footer">
|
<div class="study-card-footer">
|
||||||
<span>{formatFooter(currentMeta)}</span>
|
<span>{formatFooter(currentMeta)}</span>
|
||||||
<span class="study-spacebar">Espaço</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -304,35 +317,22 @@ export function FlashcardStudySession({ cards, libraryMetaById, onAnswer, onEnd
|
|||||||
)}
|
)}
|
||||||
<div class="study-card-meta">
|
<div class="study-card-meta">
|
||||||
<span class="study-tag">Resposta</span>
|
<span class="study-tag">Resposta</span>
|
||||||
{currentMeta?.statusLabel ? (
|
{currentMeta?.difficultyLabel && <span>{currentMeta.difficultyLabel}</span>}
|
||||||
<span class={`study-status-badge ${currentMeta.statusClassName || ''}`}>
|
|
||||||
{currentMeta.statusIcon && <span class="study-status-icon">{currentMeta.statusIcon}</span>}
|
|
||||||
{currentMeta.statusLabel}
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span>{currentMeta?.difficultyLabel || 'Revisão'}</span>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="study-card-answer">
|
<div class="study-card-answer">
|
||||||
<div class="study-back-question">
|
|
||||||
<span>Pergunta</span>
|
|
||||||
<p>{currentCard.front}</p>
|
|
||||||
</div>
|
|
||||||
<div class="study-back-answer">
|
<div class="study-back-answer">
|
||||||
<span>Resposta</span>
|
<span>Resposta</span>
|
||||||
<p>{currentCard.back}</p>
|
<p>{currentCard.back}</p>
|
||||||
</div>
|
</div>
|
||||||
{currentMeta?.footerDetails && currentMeta.footerDetails.length > 0 && (
|
{showBackQuestion && (
|
||||||
<div class="study-card-details">
|
<div class="study-back-question">
|
||||||
{currentMeta.footerDetails.map((detail) => (
|
<span>Pergunta</span>
|
||||||
<span key={detail}>{detail}</span>
|
<p>{currentCard.front}</p>
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div class="study-card-footer">
|
<div class="study-card-footer">
|
||||||
<span>{formatFooter(currentMeta)}</span>
|
<span>{formatFooter(currentMeta)}</span>
|
||||||
<span class="study-spacebar">C / W</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -342,14 +342,14 @@ export function FlashcardStudySession({ cards, libraryMetaById, onAnswer, onEnd
|
|||||||
<button
|
<button
|
||||||
class="study-review-button correct"
|
class="study-review-button correct"
|
||||||
onClick={() => void registerReviewAnswer(true)}
|
onClick={() => void registerReviewAnswer(true)}
|
||||||
disabled={!showAnswer || submittingAnswer}
|
disabled={!showAnswer || showBackQuestion || submittingAnswer}
|
||||||
>
|
>
|
||||||
Correto
|
Correto
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="study-review-button wrong"
|
class="study-review-button wrong"
|
||||||
onClick={() => void registerReviewAnswer(false)}
|
onClick={() => void registerReviewAnswer(false)}
|
||||||
disabled={!showAnswer || submittingAnswer}
|
disabled={!showAnswer || showBackQuestion || submittingAnswer}
|
||||||
>
|
>
|
||||||
Incorreto
|
Incorreto
|
||||||
</button>
|
</button>
|
||||||
@@ -386,16 +386,12 @@ export function FlashcardStudySession({ cards, libraryMetaById, onAnswer, onEnd
|
|||||||
<div class="study-panel-card">
|
<div class="study-panel-card">
|
||||||
<h3>Fila</h3>
|
<h3>Fila</h3>
|
||||||
<div class="study-queue">
|
<div class="study-queue">
|
||||||
{cards.slice(currentIndex, currentIndex + 5).map((card, index) => {
|
{cards.slice(currentIndex, currentIndex + 5).map((card, index) => (
|
||||||
const meta = libraryMetaById.get(card.libraryId);
|
|
||||||
return (
|
|
||||||
<div key={card.id} class="study-queue-item">
|
<div key={card.id} class="study-queue-item">
|
||||||
<span class="study-queue-number">{currentIndex + index + 1}</span>
|
<span class="study-queue-number">{currentIndex + index + 1}</span>
|
||||||
<strong>{card.front.substring(0, 40)}{card.front.length > 40 ? '...' : ''}</strong>
|
<strong>{card.front.substring(0, 40)}{card.front.length > 40 ? '...' : ''}</strong>
|
||||||
<span>{meta?.subject || ''}</span>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
))}
|
||||||
})}
|
|
||||||
{remainingCount > 5 && (
|
{remainingCount > 5 && (
|
||||||
<div class="study-queue-more">
|
<div class="study-queue-more">
|
||||||
+{remainingCount - 5} restantes
|
+{remainingCount - 5} restantes
|
||||||
|
|||||||
@@ -226,24 +226,12 @@ export function SpacedReviewComponent() {
|
|||||||
|
|
||||||
const sessionLibraryMetaById = useMemo(() => {
|
const sessionLibraryMetaById = useMemo(() => {
|
||||||
return new Map<number, FlashcardStudySessionLibraryMeta>(
|
return new Map<number, FlashcardStudySessionLibraryMeta>(
|
||||||
sessionLibraries.map((library) => {
|
sessionLibraries.map((library) => [
|
||||||
const statusMeta = STATUS_META_BY_STATUS[library.ragStatus];
|
|
||||||
return [
|
|
||||||
library.libraryId,
|
library.libraryId,
|
||||||
{
|
{
|
||||||
fileName: library.fileName,
|
fileName: library.fileName,
|
||||||
subject: library.subject || 'Geral',
|
|
||||||
subSubject: library.subSubject || 'Geral',
|
|
||||||
statusLabel: statusMeta.label,
|
|
||||||
statusIcon: statusMeta.icon,
|
|
||||||
statusClassName: statusMeta.className,
|
|
||||||
footerDetails: [
|
|
||||||
`Desempenho do arquivo: ${formatPerformance(library.performanceRate)}`,
|
|
||||||
`Última revisão: ${formatLastReviewed(library.lastReviewedAt)}`,
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
];
|
]),
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}, [sessionLibraries]);
|
}, [sessionLibraries]);
|
||||||
|
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ Formas de requisição principais:
|
|||||||
- **Background**: Gradiente radial quente (dourado/azul) sobre base `#fff8e6` com overlay de grid de papel 24px.
|
- **Background**: Gradiente radial quente (dourado/azul) sobre base `#fff8e6` com overlay de grid de papel 24px.
|
||||||
- **Layout**: CSS Grid (`grid-template-columns: 288px minmax(0, 1fr)`). Sidebar sticky com textura diagonal. Topbar integrada ao fluxo (não fixa).
|
- **Layout**: CSS Grid (`grid-template-columns: 288px minmax(0, 1fr)`). Sidebar sticky com textura diagonal. Topbar integrada ao fluxo (não fixa).
|
||||||
- **Animações**: Apenas sob ação do usuário (flip 3D do flashcard, carimbo, saída do cartão, confete canvas). Sem animações infinitas ou spinners.
|
- **Animações**: Apenas sob ação do usuário (flip 3D do flashcard, carimbo, saída do cartão, confete canvas). Sem animações infinitas ou spinners.
|
||||||
- **Flashcard**: Cartão 3D com efeito `rotateY(180deg)`, frente papel pautado com borda tracejada, verso azulado que mostra pergunta menor + resposta principal. Carimbo de feedback ("Correto"/"Incorreto") é renderizado no verso visível antes da saída do cartão. Confete canvas ao acertar.
|
- **Flashcard**: Cartão 3D com efeito `rotateY(180deg)`, frente papel pautado com borda tracejada e verso azulado focado na resposta. No verso, um clique extra revela a pergunta; enquanto essa pergunta auxiliar estiver visível, os botões "Correto" e "Incorreto" ficam bloqueados. O card não exibe status RAG nem metadados de assunto/subassunto/desempenho/última revisão. O carimbo de feedback ("Correto"/"Incorreto") é renderizado no verso visível antes da saída do cartão, e há confete canvas ao acertar.
|
||||||
- **Responsivo**: Breakpoints em 1120px (sidebar colapsada) e 760px (layout single-column).
|
- **Responsivo**: Breakpoints em 1120px (sidebar colapsada) e 760px (layout single-column).
|
||||||
|
|
||||||
### Variáveis CSS (definidas em `index.css`)
|
### Variáveis CSS (definidas em `index.css`)
|
||||||
|
|||||||
Reference in New Issue
Block a user