UX: disable next arrow until input selected
- Disable right-arrow on Player1/2 until name entered - Disable right-arrow on Player3 unless name entered (skip still available) - Disable right-arrow on Race To until value present - Break type: no preselect; disable next until rule chosen - First break: no preselect; disable next until required choices Purpose: Ensure consistent UX in new game wizard Refs #28
This commit is contained in:
@@ -291,7 +291,8 @@ const Player1Step = ({ playerNameHistory, onNext, onCancel, initialValue = '' }:
|
|||||||
type="submit"
|
type="submit"
|
||||||
className={styles['arrow-btn']}
|
className={styles['arrow-btn']}
|
||||||
aria-label="Weiter"
|
aria-label="Weiter"
|
||||||
style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer' }}
|
disabled={!player1.trim()}
|
||||||
|
style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer', opacity: !player1.trim() ? 0.5 : 1 }}
|
||||||
>
|
>
|
||||||
{/* Unicode right arrow */}
|
{/* Unicode right arrow */}
|
||||||
→
|
→
|
||||||
@@ -440,7 +441,8 @@ const Player2Step = ({ playerNameHistory, onNext, onCancel, initialValue = '' }:
|
|||||||
type="submit"
|
type="submit"
|
||||||
className={styles['arrow-btn']}
|
className={styles['arrow-btn']}
|
||||||
aria-label="Weiter"
|
aria-label="Weiter"
|
||||||
style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer' }}
|
disabled={!player2.trim()}
|
||||||
|
style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer', opacity: !player2.trim() ? 0.5 : 1 }}
|
||||||
>
|
>
|
||||||
→
|
→
|
||||||
</button>
|
</button>
|
||||||
@@ -594,7 +596,8 @@ const Player3Step = ({ playerNameHistory, onNext, onCancel, initialValue = '' }:
|
|||||||
type="submit"
|
type="submit"
|
||||||
className={styles['arrow-btn']}
|
className={styles['arrow-btn']}
|
||||||
aria-label="Weiter"
|
aria-label="Weiter"
|
||||||
style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer' }}
|
disabled={!player3.trim()}
|
||||||
|
style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer', opacity: !player3.trim() ? 0.5 : 1 }}
|
||||||
>
|
>
|
||||||
→
|
→
|
||||||
</button>
|
</button>
|
||||||
@@ -794,7 +797,8 @@ const RaceToStep = ({ onNext, onCancel, initialValue = '', gameType }: RaceToSte
|
|||||||
type="submit"
|
type="submit"
|
||||||
className={styles['arrow-btn']}
|
className={styles['arrow-btn']}
|
||||||
aria-label="Weiter"
|
aria-label="Weiter"
|
||||||
style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer' }}
|
disabled={String(raceTo).trim() === ''}
|
||||||
|
style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer', opacity: String(raceTo).trim() === '' ? 0.5 : 1 }}
|
||||||
>
|
>
|
||||||
{/* Unicode right arrow */}
|
{/* Unicode right arrow */}
|
||||||
→
|
→
|
||||||
@@ -810,8 +814,8 @@ interface BreakRuleStepProps {
|
|||||||
initialValue?: BreakRule | '';
|
initialValue?: BreakRule | '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const BreakRuleStep = ({ onNext, onCancel, initialValue = 'winnerbreak' }: BreakRuleStepProps) => {
|
const BreakRuleStep = ({ onNext, onCancel, initialValue = '' }: BreakRuleStepProps) => {
|
||||||
const [rule, setRule] = useState<BreakRule>(initialValue as BreakRule);
|
const [rule, setRule] = useState<BreakRule | ''>(initialValue);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className={styles['new-game-form']} aria-label="Break-Regel wählen">
|
<form className={styles['new-game-form']} aria-label="Break-Regel wählen">
|
||||||
@@ -845,7 +849,7 @@ const BreakRuleStep = ({ onNext, onCancel, initialValue = 'winnerbreak' }: Break
|
|||||||
<button type="button" className={styles['arrow-btn']} aria-label="Zurück" onClick={onCancel} style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer' }}>
|
<button type="button" className={styles['arrow-btn']} aria-label="Zurück" onClick={onCancel} style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer' }}>
|
||||||
←
|
←
|
||||||
</button>
|
</button>
|
||||||
<button type="button" className={styles['arrow-btn']} aria-label="Weiter" onClick={() => onNext(rule)} style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer' }}>
|
<button type="button" className={styles['arrow-btn']} aria-label="Weiter" onClick={() => rule && onNext(rule as BreakRule)} disabled={!rule} style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer', opacity: !rule ? 0.5 : 1 }}>
|
||||||
→
|
→
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -862,10 +866,10 @@ interface BreakOrderStepProps {
|
|||||||
initialSecond?: number;
|
initialSecond?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BreakOrderStep = ({ players, rule, onNext, onCancel, initialFirst = 1, initialSecond }: BreakOrderStepProps) => {
|
const BreakOrderStep = ({ players, rule, onNext, onCancel, initialFirst = 0, initialSecond }: BreakOrderStepProps) => {
|
||||||
const playerCount = players.filter(Boolean).length;
|
const playerCount = players.filter(Boolean).length;
|
||||||
const [first, setFirst] = useState<number>(initialFirst);
|
const [first, setFirst] = useState<number>(initialFirst);
|
||||||
const [second, setSecond] = useState<number>(initialSecond ?? (playerCount >= 2 ? 2 : 1));
|
const [second, setSecond] = useState<number | undefined>(initialSecond);
|
||||||
|
|
||||||
const handleFirst = (idx: number) => {
|
const handleFirst = (idx: number) => {
|
||||||
setFirst(idx);
|
setFirst(idx);
|
||||||
@@ -918,12 +922,19 @@ const BreakOrderStep = ({ players, rule, onNext, onCancel, initialFirst = 1, ini
|
|||||||
aria-label="Weiter"
|
aria-label="Weiter"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (rule === 'wechselbreak' && playerCount === 3) {
|
if (rule === 'wechselbreak' && playerCount === 3) {
|
||||||
handleSecond(second);
|
if (first > 0 && (second ?? 0) > 0) {
|
||||||
|
handleSecond(second as number);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
onNext(first);
|
if (first > 0) {
|
||||||
|
onNext(first);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer' }}
|
disabled={
|
||||||
|
(rule === 'wechselbreak' && playerCount === 3) ? !(first > 0 && (second ?? 0) > 0) : !(first > 0)
|
||||||
|
}
|
||||||
|
style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer', opacity: ((rule === 'wechselbreak' && playerCount === 3) ? !(first > 0 && (second ?? 0) > 0) : !(first > 0)) ? 0.5 : 1 }}
|
||||||
>
|
>
|
||||||
→
|
→
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user