zone badges on items
These are nice! :) The `hideSimpleZones` option I'm not sure about yet, but I figure that: 1. For a new user just doing simple outfits, I feel like the double data on the items page just looks silly, so I want to streamline for that 2. But I _do_ want to let the user think about zone complexity when things _are_ multi-zone. I did also consider just hiding the zone badge for the header you're under, but I figured the consistency of having the item and its badges look the same in all the places in the list was more important.
This commit is contained in:
parent
3a6e3fac8e
commit
dec9d76601
4 changed files with 94 additions and 3 deletions
|
@ -8,10 +8,16 @@ import {
|
||||||
Image,
|
Image,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
|
Wrap,
|
||||||
useColorModeValue,
|
useColorModeValue,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from "@chakra-ui/core";
|
} from "@chakra-ui/core";
|
||||||
import { EditIcon, DeleteIcon, InfoIcon } from "@chakra-ui/icons";
|
import {
|
||||||
|
EditIcon,
|
||||||
|
DeleteIcon,
|
||||||
|
InfoIcon,
|
||||||
|
NotAllowedIcon,
|
||||||
|
} from "@chakra-ui/icons";
|
||||||
import loadable from "@loadable/component";
|
import loadable from "@loadable/component";
|
||||||
|
|
||||||
import { safeImageUrl } from "../util";
|
import { safeImageUrl } from "../util";
|
||||||
|
@ -39,9 +45,27 @@ const LoadableItemSupportDrawer = loadable(() =>
|
||||||
* wearing/unwearing items being noticeably slower on lower-power
|
* wearing/unwearing items being noticeably slower on lower-power
|
||||||
* devices.
|
* devices.
|
||||||
*/
|
*/
|
||||||
function Item({ item, itemNameId, isWorn, isInOutfit, dispatchToOutfit }) {
|
function Item({
|
||||||
|
item,
|
||||||
|
itemNameId,
|
||||||
|
isWorn,
|
||||||
|
isInOutfit,
|
||||||
|
dispatchToOutfit,
|
||||||
|
hideSimpleZones = false,
|
||||||
|
}) {
|
||||||
const [supportDrawerIsOpen, setSupportDrawerIsOpen] = React.useState(false);
|
const [supportDrawerIsOpen, setSupportDrawerIsOpen] = React.useState(false);
|
||||||
|
|
||||||
|
const occupiedZoneLabels = getZoneLabels(
|
||||||
|
item.appearanceOn.layers.map((l) => l.zone)
|
||||||
|
);
|
||||||
|
const restrictedZoneLabels = getZoneLabels(
|
||||||
|
item.appearanceOn.restrictedZones.filter((z) => z.isCommonlyUsedByItems)
|
||||||
|
);
|
||||||
|
const zonesAreSimple =
|
||||||
|
occupiedZoneLabels.length <= 1 && restrictedZoneLabels.length === 0;
|
||||||
|
const shouldHideZones = hideSimpleZones && zonesAreSimple;
|
||||||
|
const shouldShowZones = !shouldHideZones;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ItemContainer>
|
<ItemContainer>
|
||||||
|
@ -55,7 +79,36 @@ function Item({ item, itemNameId, isWorn, isInOutfit, dispatchToOutfit }) {
|
||||||
<ItemName id={itemNameId} isWorn={isWorn}>
|
<ItemName id={itemNameId} isWorn={isWorn}>
|
||||||
{item.name}
|
{item.name}
|
||||||
</ItemName>
|
</ItemName>
|
||||||
<Box>{item.isNc && <Badge colorScheme="cyan">NC</Badge>}</Box>
|
<Wrap spacing="2" marginTop="1">
|
||||||
|
{shouldShowZones &&
|
||||||
|
occupiedZoneLabels.map((zoneLabel) => (
|
||||||
|
<Badge key={zoneLabel}>{getZoneShorthand(zoneLabel)}</Badge>
|
||||||
|
))}
|
||||||
|
{shouldShowZones &&
|
||||||
|
restrictedZoneLabels.map((zoneLabel) => (
|
||||||
|
<Tooltip
|
||||||
|
label={
|
||||||
|
<Box textAlign="center">
|
||||||
|
Restricted: This isn't a {zoneLabel} item, but you can't
|
||||||
|
wear {zoneLabel} items with it
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
placement="top"
|
||||||
|
openDelay={250}
|
||||||
|
>
|
||||||
|
<Badge
|
||||||
|
key={zoneLabel}
|
||||||
|
display="flex"
|
||||||
|
flexDirection="row"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
{getZoneShorthand(zoneLabel)}
|
||||||
|
<NotAllowedIcon marginLeft="1" />
|
||||||
|
</Badge>
|
||||||
|
</Tooltip>
|
||||||
|
))}
|
||||||
|
{item.isNc && <Badge colorScheme="cyan">NC</Badge>}
|
||||||
|
</Wrap>
|
||||||
</Box>
|
</Box>
|
||||||
<Box flex="0 0 auto">
|
<Box flex="0 0 auto">
|
||||||
<SupportOnly>
|
<SupportOnly>
|
||||||
|
@ -328,6 +381,32 @@ export function ItemListSkeleton({ count }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getZoneLabels returns the set of labels for the given zones. Sometimes an
|
||||||
|
* item occupies multiple zones of the same name, so it's especially important
|
||||||
|
* to de-duplicate them here!
|
||||||
|
*/
|
||||||
|
function getZoneLabels(zones) {
|
||||||
|
let labels = zones.map((z) => z.label);
|
||||||
|
labels = new Set(labels);
|
||||||
|
labels = [...labels].sort();
|
||||||
|
return labels;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getZoneShorthand returns a potentially shortened version of the zone label,
|
||||||
|
* to make the Item badges a bit less bulky!
|
||||||
|
*/
|
||||||
|
function getZoneShorthand(zoneLabel) {
|
||||||
|
return zoneLabel
|
||||||
|
.replace("Background Item", "BG Item")
|
||||||
|
.replace("Foreground Item", "FG Item")
|
||||||
|
.replace("Lower-body", "Lower")
|
||||||
|
.replace("Upper-body", "Upper")
|
||||||
|
.replace("Transient", "Trans")
|
||||||
|
.replace("Biology", "Bio");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* containerHasFocus is a common CSS selector, for the case where our parent
|
* containerHasFocus is a common CSS selector, for the case where our parent
|
||||||
* .item-container is hovered or the adjacent hidden radio/checkbox is
|
* .item-container is hovered or the adjacent hidden radio/checkbox is
|
||||||
|
|
|
@ -123,6 +123,7 @@ function ItemZoneGroup({ zoneLabel, items, outfitState, dispatchToOutfit }) {
|
||||||
isWorn={outfitState.wornItemIds.includes(item.id)}
|
isWorn={outfitState.wornItemIds.includes(item.id)}
|
||||||
isInOutfit={outfitState.allItemIds.includes(item.id)}
|
isInOutfit={outfitState.allItemIds.includes(item.id)}
|
||||||
dispatchToOutfit={dispatchToOutfit}
|
dispatchToOutfit={dispatchToOutfit}
|
||||||
|
hideSimpleZones
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</CSSTransition>
|
</CSSTransition>
|
||||||
|
|
|
@ -229,6 +229,7 @@ function useSearchResults(query, outfitState) {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
thumbnailUrl
|
thumbnailUrl
|
||||||
|
isNc
|
||||||
|
|
||||||
appearanceOn(speciesId: $speciesId, colorId: $colorId) {
|
appearanceOn(speciesId: $speciesId, colorId: $colorId) {
|
||||||
# This enables us to quickly show the item when the user clicks it!
|
# This enables us to quickly show the item when the user clicks it!
|
||||||
|
@ -242,6 +243,11 @@ function useSearchResults(query, outfitState) {
|
||||||
label @client
|
label @client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
restrictedZones {
|
||||||
|
id
|
||||||
|
label @client
|
||||||
|
isCommonlyUsedByItems @client
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,11 @@ function useOutfitState() {
|
||||||
label @client
|
label @client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
restrictedZones {
|
||||||
|
id
|
||||||
|
label @client
|
||||||
|
isCommonlyUsedByItems @client
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue