@@ -120,7 +120,7 @@ export default function PldtMetrics({ plddtData, sequence }) {
padding: '2px 10px',
fontWeight: 700,
fontSize: 13,
- color: 'var(--navy)',
+ color: 'var(--text-primary)',
}}
>
{mean !== null ? mean.toFixed(2) : '—'}
diff --git a/frontend/src/components/ProteinMetrics.jsx b/frontend/src/components/ProteinMetrics.jsx
index 751cc6d..f2ae3d8 100644
--- a/frontend/src/components/ProteinMetrics.jsx
+++ b/frontend/src/components/ProteinMetrics.jsx
@@ -10,7 +10,7 @@ export default function ProteinMetrics({ plddtData, seqLength }) {
📊
@@ -81,7 +81,7 @@ export default function ProteinMetrics({ plddtData, seqLength }) {
cy="60"
r="50"
fill="none"
- stroke="var(--navy)"
+ stroke="var(--text-primary)"
strokeWidth="8"
strokeLinecap="round"
strokeDasharray={`${(plddtData.mean / 100) * 314} 314`}
@@ -95,7 +95,7 @@ export default function ProteinMetrics({ plddtData, seqLength }) {
textAnchor="middle"
fontSize="22"
fontWeight="800"
- fill="var(--navy)"
+ fill="var(--text-primary)"
>
{plddtData ? Math.round(plddtData.mean) : '—'}
diff --git a/frontend/src/components/SequenceInput.jsx b/frontend/src/components/SequenceInput.jsx
index 16ccdf3..98cdb18 100644
--- a/frontend/src/components/SequenceInput.jsx
+++ b/frontend/src/components/SequenceInput.jsx
@@ -1,4 +1,4 @@
-import { useMemo } from 'react';
+import { useMemo, useState, memo } from 'react';
const defaultAminoAcids = 'A,C,D,E,F,G,H,I,K,L,M,N,P,Q,R,S,T,V,W,Y';
const aminoAcidsStr = (import.meta.env.VITE_VALID_AMINO_ACIDS || defaultAminoAcids).replace(
@@ -7,20 +7,33 @@ const aminoAcidsStr = (import.meta.env.VITE_VALID_AMINO_ACIDS || defaultAminoAci
);
const VALID_AMINO_ACIDS = new Set(aminoAcidsStr.split(''));
-export default function SequenceInput({ sequence, setSequence, onPredict, status }) {
+const SequenceInput = memo(function SequenceInput({ sequence: externalSeq, setSequence: setExternalSeq, onPredict, status }) {
+ const [localSeq, setLocalSeq] = useState(externalSeq || '');
+ const [prevExternalSeq, setPrevExternalSeq] = useState(externalSeq);
+
+ if (externalSeq !== prevExternalSeq) {
+ setPrevExternalSeq(externalSeq);
+ setLocalSeq(externalSeq || '');
+ }
+
const isLoading = status === 'processing';
- const charCount = sequence.trim().length;
+ const charCount = localSeq.trim().length;
const invalidChars = useMemo(() => {
const bad = new Set();
- for (const ch of sequence) {
+ for (const ch of localSeq) {
if (!VALID_AMINO_ACIDS.has(ch)) bad.add(ch);
}
return [...bad].sort();
- }, [sequence]);
+ }, [localSeq]);
const hasInvalid = invalidChars.length > 0;
+ const handlePredictClicked = () => {
+ setExternalSeq(localSeq);
+ onPredict(localSeq);
+ };
+
return (
);
-}
+});
+
+export default SequenceInput;
diff --git a/frontend/src/components/Sidebar.jsx b/frontend/src/components/Sidebar.jsx
index 6b0daa1..ea0bb80 100644
--- a/frontend/src/components/Sidebar.jsx
+++ b/frontend/src/components/Sidebar.jsx
@@ -24,6 +24,7 @@ export default function Sidebar({ activeView, onViewChange, user, onSignOut }) {