[WIP] UI for item remove button

It's code for a remove button in item lists! When you click it, you see a "TODO" alert.

Not shipping this change until it's wired up!
This commit is contained in:
Emi Matchu 2021-09-30 18:12:31 -07:00
parent 818a443dfe
commit 64db3dd1b7
2 changed files with 109 additions and 28 deletions

View file

@ -408,6 +408,7 @@ export function ClosetListContents({
{itemsToShow.length > 0 ? ( {itemsToShow.length > 0 ? (
<ClosetItemList <ClosetItemList
items={itemsToShow} items={itemsToShow}
canEdit={isCurrentUser}
tradeMatchingMode={tradeMatchingMode} tradeMatchingMode={tradeMatchingMode}
/> />
) : ( ) : (
@ -446,12 +447,12 @@ export function ClosetListContents({
const ITEM_CARD_WIDTH = 112 + 16; const ITEM_CARD_WIDTH = 112 + 16;
const ITEM_CARD_HEIGHT = 171 + 16; const ITEM_CARD_HEIGHT = 171 + 16;
function ClosetItemList({ items, tradeMatchingMode }) { function ClosetItemList({ items, canEdit, tradeMatchingMode }) {
const renderItem = (item) => ( const renderItem = (item) => (
<ItemCard <ClosetListItemCard
key={item.id} key={item.id}
item={item} item={item}
variant="grid" canEdit={canEdit}
tradeMatchingMode={tradeMatchingMode} tradeMatchingMode={tradeMatchingMode}
/> />
); );
@ -521,6 +522,19 @@ function ClosetItemList({ items, tradeMatchingMode }) {
); );
} }
function ClosetListItemCard({ item, canEdit, tradeMatchingMode }) {
return (
<ItemCard
key={item.id}
item={item}
variant="grid"
tradeMatchingMode={tradeMatchingMode}
showRemoveButton={canEdit}
onRemove={() => alert("TODO")}
/>
);
}
export function buildClosetListPath(closetList) { export function buildClosetListPath(closetList) {
let ownsOrWants; let ownsOrWants;
if (closetList.ownsOrWantsItems === "OWNS") { if (closetList.ownsOrWantsItems === "OWNS") {

View file

@ -1,6 +1,7 @@
import React from "react"; import React from "react";
import { import {
Box, Box,
IconButton,
Skeleton, Skeleton,
useColorModeValue, useColorModeValue,
useTheme, useTheme,
@ -10,15 +11,18 @@ import { ClassNames } from "@emotion/react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { safeImageUrl, useCommonStyles } from "../util"; import { safeImageUrl, useCommonStyles } from "../util";
import { CheckIcon, StarIcon } from "@chakra-ui/icons"; import { CheckIcon, CloseIcon, StarIcon } from "@chakra-ui/icons";
function SquareItemCard({ function SquareItemCard({
item, item,
showRemoveButton = false,
onRemove = () => {},
tradeMatchingMode = null, tradeMatchingMode = null,
footer = null, footer = null,
...props ...props
}) { }) {
const outlineShadowValue = useToken("shadows", "outline"); const outlineShadowValue = useToken("shadows", "outline");
const mdRadiusValue = useToken("radii", "md");
const tradeMatchOwnShadowColor = useColorModeValue("green.500", "green.200"); const tradeMatchOwnShadowColor = useColorModeValue("green.500", "green.200");
const tradeMatchWantShadowColor = useColorModeValue("blue.400", "blue.200"); const tradeMatchWantShadowColor = useColorModeValue("blue.400", "blue.200");
@ -46,33 +50,70 @@ function SquareItemCard({
// SquareItemCard renders in large lists of 1k+ items, so we get a big // SquareItemCard renders in large lists of 1k+ items, so we get a big
// perf win by using Emotion directly instead of Chakra's styled-system // perf win by using Emotion directly instead of Chakra's styled-system
// Box. // Box.
<Link <div
to={`/items/${item.id}`}
className={css` className={css`
transition: all 0.2s; position: relative;
&:hover, display: flex;
&:focus {
transform: scale(1.05);
}
&:focus {
box-shadow: ${outlineShadowValue};
outline: none;
}
`} `}
{...props} role="group"
> >
<SquareItemCardLayout <Link
name={item.name} to={`/items/${item.id}`}
thumbnailImage={ className={css`
<ItemThumbnail border-radius: ${mdRadiusValue};
item={item} transition: all 0.2s;
tradeMatchingMode={tradeMatchingMode} &:hover,
/> &:focus {
} transform: scale(1.05);
boxShadow={tradeMatchShadow} }
footer={footer} &:focus {
/> box-shadow: ${outlineShadowValue};
</Link> outline: none;
}
`}
{...props}
>
<SquareItemCardLayout
name={item.name}
thumbnailImage={
<ItemThumbnail
item={item}
tradeMatchingMode={tradeMatchingMode}
/>
}
removeButton={
showRemoveButton ? (
<SquareItemCardRemoveButton onClick={onRemove} />
) : null
}
boxShadow={tradeMatchShadow}
footer={footer}
/>
</Link>
{showRemoveButton && (
<div
className={css`
position: absolute;
right: 0;
top: 0;
transform: translate(50%, -50%);
/* Apply some padding, so accidental clicks around the button
* don't click the link instead, or vice-versa! */
padding: 0.5em;
opacity: 0;
[role="group"]:hover &,
[role="group"]:focus-within &,
&:hover,
&:focus {
opacity: 1;
}
`}
>
<SquareItemCardRemoveButton onClick={onRemove} />
</div>
)}
</div>
)} )}
</ClassNames> </ClassNames>
); );
@ -363,6 +404,32 @@ function ItemThumbnailKindBadge({ colorScheme, children }) {
); );
} }
function SquareItemCardRemoveButton({ onClick }) {
const backgroundColor = useColorModeValue("gray.200", "gray.500");
return (
<IconButton
aria-label="Remove"
title="Remove"
icon={<CloseIcon />}
size="xs"
borderRadius="full"
boxShadow="lg"
backgroundColor={backgroundColor}
onClick={onClick}
_hover={{
// Override night mode's fade-out on hover
opacity: 1,
transform: "scale(1.15, 1.15)",
}}
_focus={{
transform: "scale(1.15, 1.15)",
boxShadow: "outline",
}}
/>
);
}
export function SquareItemCardSkeleton({ minHeightNumLines, footer = null }) { export function SquareItemCardSkeleton({ minHeightNumLines, footer = null }) {
return ( return (
<SquareItemCardLayout <SquareItemCardLayout