Disable faces that can't be the chosen color

This commit is contained in:
Emi Matchu 2021-02-03 01:41:03 -08:00
parent 8de85fbc63
commit a293dc56b5

View file

@ -871,11 +871,16 @@ function SpeciesFacesPicker({
speciesName={speciesFace.speciesName} speciesName={speciesFace.speciesName}
colorId={speciesFace.colorId} colorId={speciesFace.colorId}
neopetsImageHash={speciesFace.neopetsImageHash} neopetsImageHash={speciesFace.neopetsImageHash}
isCompatible={ isSelected={speciesFace.speciesId === selectedSpeciesId}
// If the face color doesn't match the current color, this is a
// fallback face for an invalid species/color pair.
isValid={
speciesFace.colorId === selectedColorId || selectedColorIsBasic
}
bodyIsCompatible={
allBodiesAreCompatible || allBodiesAreCompatible ||
compatibleBodyIds.includes(speciesFace.bodyId) compatibleBodyIds.includes(speciesFace.bodyId)
} }
isSelected={speciesFace.speciesId === selectedSpeciesId}
couldProbablyModelMoreData={couldProbablyModelMoreData} couldProbablyModelMoreData={couldProbablyModelMoreData}
onChange={onChange} onChange={onChange}
isLoading={isLoading || loadingGQL} isLoading={isLoading || loadingGQL}
@ -919,8 +924,9 @@ function SpeciesFaceOption({
speciesName, speciesName,
colorId, colorId,
neopetsImageHash, neopetsImageHash,
isCompatible,
isSelected, isSelected,
bodyIsCompatible,
isValid,
couldProbablyModelMoreData, couldProbablyModelMoreData,
onChange, onChange,
isLoading, isLoading,
@ -945,24 +951,31 @@ function SpeciesFaceOption({
const [labelIsHovered, setLabelIsHovered] = React.useState(false); const [labelIsHovered, setLabelIsHovered] = React.useState(false);
const [inputIsFocused, setInputIsFocused] = React.useState(false); const [inputIsFocused, setInputIsFocused] = React.useState(false);
const isHappy = isLoading || isCompatible; const isDisabled = isLoading || !isValid || !bodyIsCompatible;
const isHappy = isLoading || (isValid && bodyIsCompatible);
const emotionId = isHappy ? "1" : "2"; const emotionId = isHappy ? "1" : "2";
const cursor = isLoading ? "wait" : isDisabled ? "not-allowed" : "pointer";
let disabledExplanation = null;
if (!isValid) {
disabledExplanation = "(Can't be this color)";
} else if (!bodyIsCompatible) {
disabledExplanation = couldProbablyModelMoreData
? "(Not modeled yet)"
: "(Not compatible)";
}
const tooltipLabel = ( const tooltipLabel = (
<div style={{ textAlign: "center" }}> <div style={{ textAlign: "center" }}>
{speciesName} {speciesName}
{!isLoading && !isCompatible && ( {disabledExplanation && (
<div style={{ fontStyle: "italic", fontSize: "0.75em" }}> <div style={{ fontStyle: "italic", fontSize: "0.75em" }}>
{couldProbablyModelMoreData {disabledExplanation}
? "(Not modeled yet)"
: "(Not compatible)"}
</div> </div>
)} )}
</div> </div>
); );
const cursor = isLoading ? "wait" : !isCompatible ? "not-allowed" : "pointer";
// NOTE: Because we render quite a few of these, avoiding using Chakra // NOTE: Because we render quite a few of these, avoiding using Chakra
// elements like Box helps with render performance! // elements like Box helps with render performance!
return ( return (
@ -992,7 +1005,7 @@ function SpeciesFaceOption({
// It's possible to get this selected via the SpeciesColorPicker, // It's possible to get this selected via the SpeciesColorPicker,
// even if this would normally be disabled. If so, make this // even if this would normally be disabled. If so, make this
// option enabled, so keyboard users can focus and change it. // option enabled, so keyboard users can focus and change it.
disabled={!isSelected && (isLoading || !isCompatible)} disabled={isDisabled && !isSelected}
onChange={() => onChange({ speciesId, colorId })} onChange={() => onChange({ speciesId, colorId })}
onFocus={() => setInputIsFocused(true)} onFocus={() => setInputIsFocused(true)}
onBlur={() => setInputIsFocused(false)} onBlur={() => setInputIsFocused(false)}
@ -1040,13 +1053,13 @@ function SpeciesFaceOption({
width={50} width={50}
height={50} height={50}
data-is-loading={isLoading} data-is-loading={isLoading}
data-is-compatible={!isLoading && isCompatible} data-is-disabled={isDisabled}
className={css` className={css`
filter: saturate(90%); filter: saturate(90%);
opacity: 0.9; opacity: 0.9;
transition: all 0.2s; transition: all 0.2s;
&[data-is-compatible="false"] { &[data-is-disabled="true"] {
filter: saturate(0%); filter: saturate(0%);
opacity: 0.6; opacity: 0.6;
} }
@ -1056,15 +1069,15 @@ function SpeciesFaceOption({
pulse; pulse;
} }
input:checked + * &[data-is-compatible="false"] { input:checked + * &[data-body-is-disabled="false"] {
opacity: 0.85;
}
input:checked + * &[data-is-compatible="true"] {
opacity: 1; opacity: 1;
filter: saturate(110%); filter: saturate(110%);
} }
input:checked + * &[data-body-is-disabled="true"] {
opacity: 0.85;
}
@keyframes pulse { @keyframes pulse {
from { from {
opacity: 0.5; opacity: 0.5;
@ -1190,9 +1203,9 @@ function CrossFadeImage(incomingImageProps) {
// If the current image _is_ the incoming image, we'll allow // If the current image _is_ the incoming image, we'll allow
// new props to come in and affect it. But if it's a new image // new props to come in and affect it. But if it's a new image
// incoming, we want to stick to the last props the current // incoming, we want to stick to the last props the current
// image had! (This matters for e.g. `isCompatible` becoming // image had! (This matters for e.g. `bodyIsCompatible`
// true in `SpeciesFaceOption` and restoring color, before // becoming true in `SpeciesFaceOption` and restoring color,
// the new color's image loads in.) // before the new color's image loads in.)
{...(incomingImageIsCurrentImage ? incomingImageProps : {})} {...(incomingImageIsCurrentImage ? incomingImageProps : {})}
/> />
</div> </div>