diff --git a/package.json b/package.json
index 00f1fc7..1ea2991 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,6 @@
"@chakra-ui/icons": "^1.0.2",
"@chakra-ui/react": "^1.0.4",
"@chakra-ui/theme-tools": "^1.0.2",
- "@emotion/css": "^11.1.3",
"@emotion/react": "^11.1.4",
"@emotion/styled": "^11.0.0",
"@loadable/component": "^5.12.0",
diff --git a/src/app/HomePage.js b/src/app/HomePage.js
index 4c9ea9c..c542b54 100644
--- a/src/app/HomePage.js
+++ b/src/app/HomePage.js
@@ -1,5 +1,5 @@
import React from "react";
-import { css } from "@emotion/css";
+import { ClassNames } from "@emotion/react";
import gql from "graphql-tag";
import {
Box,
@@ -213,37 +213,41 @@ function SubmitPetForm() {
const buttonBgColorHover = useColorModeValue("green.700", "green.200");
return (
-
+
+ {({ css }) => (
+
+ )}
+
);
}
diff --git a/src/app/ItemPage.js b/src/app/ItemPage.js
index 70c93dc..a2e9536 100644
--- a/src/app/ItemPage.js
+++ b/src/app/ItemPage.js
@@ -1,5 +1,5 @@
import React from "react";
-import { css } from "@emotion/css";
+import { ClassNames } from "@emotion/react";
import {
AspectRatio,
Button,
@@ -205,55 +205,62 @@ function ItemPageOwnButton({ itemId, isChecked }) {
);
return (
-
- {
- if (e.target.checked) {
- sendAddMutation().catch((e) => {
- console.error(e);
- toast({
- title: "We had trouble adding this to the items you own.",
- description: "Check your internet connection, and try again.",
- status: "error",
- duration: 5000,
- });
- });
- } else {
- sendRemoveMutation().catch((e) => {
- console.error(e);
- toast({
- title: "We had trouble removing this from the items you own.",
- description: "Check your internet connection, and try again.",
- status: "error",
- duration: 5000,
- });
- });
- }
- }}
- />
-
-
+
+ {({ css }) => (
+
+ {
+ if (e.target.checked) {
+ sendAddMutation().catch((e) => {
+ console.error(e);
+ toast({
+ title: "We had trouble adding this to the items you own.",
+ description:
+ "Check your internet connection, and try again.",
+ status: "error",
+ duration: 5000,
+ });
+ });
+ } else {
+ sendRemoveMutation().catch((e) => {
+ console.error(e);
+ toast({
+ title:
+ "We had trouble removing this from the items you own.",
+ description:
+ "Check your internet connection, and try again.",
+ status: "error",
+ duration: 5000,
+ });
+ });
+ }
+ }}
+ />
+
+
+ )}
+
);
}
@@ -306,55 +313,62 @@ function ItemPageWantButton({ itemId, isChecked }) {
);
return (
-
- {
- if (e.target.checked) {
- sendAddMutation().catch((e) => {
- console.error(e);
- toast({
- title: "We had trouble adding this to the items you want.",
- description: "Check your internet connection, and try again.",
- status: "error",
- duration: 5000,
- });
- });
- } else {
- sendRemoveMutation().catch((e) => {
- console.error(e);
- toast({
- title: "We had trouble removing this from the items you want.",
- description: "Check your internet connection, and try again.",
- status: "error",
- duration: 5000,
- });
- });
- }
- }}
- />
-
-
+
+ {({ css }) => (
+
+ {
+ if (e.target.checked) {
+ sendAddMutation().catch((e) => {
+ console.error(e);
+ toast({
+ title: "We had trouble adding this to the items you want.",
+ description:
+ "Check your internet connection, and try again.",
+ status: "error",
+ duration: 5000,
+ });
+ });
+ } else {
+ sendRemoveMutation().catch((e) => {
+ console.error(e);
+ toast({
+ title:
+ "We had trouble removing this from the items you want.",
+ description:
+ "Check your internet connection, and try again.",
+ status: "error",
+ duration: 5000,
+ });
+ });
+ }
+ }}
+ />
+
+
+ )}
+
);
}
diff --git a/src/app/ItemTradesPage.js b/src/app/ItemTradesPage.js
index d42b230..879f151 100644
--- a/src/app/ItemTradesPage.js
+++ b/src/app/ItemTradesPage.js
@@ -1,5 +1,5 @@
import React from "react";
-import { css } from "@emotion/css";
+import { ClassNames } from "@emotion/react";
import { Box, Skeleton, useColorModeValue, useToken } from "@chakra-ui/react";
import gql from "graphql-tag";
import { useQuery } from "@apollo/client";
@@ -165,84 +165,88 @@ function ItemTradesTable({
};
return (
-
-
-
-
- {/* A small wording tweak to fit better on the xsmall screens! */}
- Last active
- Last edit
-
- {shouldShowCompareColumn && (
-
-
- {compareColumnLabel}
-
- Matches
-
- )}
-
- {userHeading}
-
- List
-
-
-
- {loading && (
- <>
-
-
-
-
-
- >
- )}
- {!loading &&
- trades.length > 0 &&
- trades.map((trade) => (
-
- ))}
- {!loading && trades.length === 0 && (
-
-
- No trades yet!
-
+
+ {({ css }) => (
+
+
+
+
+ {/* A small wording tweak to fit better on the xsmall screens! */}
+ Last active
+ Last edit
+
+ {shouldShowCompareColumn && (
+
+
+ {compareColumnLabel}
+
+ Matches
+
+ )}
+
+ {userHeading}
+
+ List
+
- )}
-
-
+
+ {loading && (
+ <>
+
+
+
+
+
+ >
+ )}
+ {!loading &&
+ trades.length > 0 &&
+ trades.map((trade) => (
+
+ ))}
+ {!loading && trades.length === 0 && (
+
+
+ No trades yet!
+
+
+ )}
+
+
+ )}
+
);
}
@@ -263,63 +267,67 @@ function ItemTradesTableRow({
);
return (
-
-
- {formatVagueDate(lastTradeActivity)}
-
- {shouldShowCompareColumn && (
-
- {matchingItems.length > 0 ? (
-
- {sortedMatchingItems.slice(0, 4).map((item) => (
-
-
- {item.name}
-
-
- ))}
- {matchingItems.length > 4 && (
- + {matchingItems.length - 4} more
- )}
-
- ) : (
- <>
- No matches
- None
- >
- )}
-
- )}
- {username}
-
+
+ {({ css }) => (
- {listName}
+
+ {formatVagueDate(lastTradeActivity)}
+
+ {shouldShowCompareColumn && (
+
+ {matchingItems.length > 0 ? (
+
+ {sortedMatchingItems.slice(0, 4).map((item) => (
+
+
+ {item.name}
+
+
+ ))}
+ {matchingItems.length > 4 && (
+ + {matchingItems.length - 4} more
+ )}
+
+ ) : (
+ <>
+ No matches
+ None
+ >
+ )}
+
+ )}
+ {username}
+
+
+ {listName}
+
+
-
-
+ )}
+
);
}
@@ -350,47 +358,51 @@ function ItemTradesTableCell({ children, as = "td", ...props }) {
const borderRadiusCss = useToken("radii", "md");
return (
-
+ {({ css }) => (
+
- {children}
-
+ thead tr:first-of-type &:first-of-type {
+ border-top-left-radius: ${borderRadiusCss};
+ }
+ thead tr:first-of-type &:last-of-type {
+ border-top-right-radius: ${borderRadiusCss};
+ }
+ tbody tr:last-of-type &:first-of-type {
+ border-bottom-left-radius: ${borderRadiusCss};
+ }
+ tbody tr:last-of-type &:last-of-type {
+ border-bottom-right-radius: ${borderRadiusCss};
+ }
+ `}
+ {...props}
+ >
+ {children}
+
+ )}
+
);
}
diff --git a/src/app/PrivacyPolicyPage.js b/src/app/PrivacyPolicyPage.js
index 50a05c7..c234e9b 100644
--- a/src/app/PrivacyPolicyPage.js
+++ b/src/app/PrivacyPolicyPage.js
@@ -1,5 +1,5 @@
import React from "react";
-import { css } from "@emotion/css";
+import { css } from "@emotion/react";
import { VStack } from "@chakra-ui/react";
import { Heading1, Heading2, Heading3 } from "./util";
@@ -11,7 +11,7 @@ function PrivacyPolicyPage() {
-
+
+ {({ css }) => (
-
- {isCurrentUser ? "Your items" : `${data.user.username}'s items`}
-
-
- {data.user.contactNeopetsUsername && (
-
-
-
- {data.user.contactNeopetsUsername}
-
-
- )}
- {data.user.contactNeopetsUsername && (
-
-
-
- Neomail
-
-
- )}
-
-
-
-
-
- Support
-
-
-
-
- {/* Usually I put "Own" before "Want", but this matches the natural
- * order on the page: the _matches_ for things you want are things
- * _this user_ owns, so they come first. I think it's also probably a
- * more natural train of thought: you come to someone's list _wanting_
- * something, and _then_ thinking about what you can offer. */}
- {!isCurrentUser && numItemsTheyOwnThatYouWant > 0 && (
-
-
-
- {numItemsTheyOwnThatYouWant > 1
- ? `${numItemsTheyOwnThatYouWant} items you want`
- : "1 item you want"}
-
-
- )}
- {!isCurrentUser && numItemsTheyWantThatYouOwn > 0 && (
-
-
-
- {numItemsTheyWantThatYouOwn > 1
- ? `${numItemsTheyWantThatYouOwn} items you own`
- : "1 item you own"}
-
-
- )}
-
-
-
-
-
-
-
+
+
+
+ {isCurrentUser ? "Your items" : `${data.user.username}'s items`}
+
+
+ {data.user.contactNeopetsUsername && (
+
+
+
+ {data.user.contactNeopetsUsername}
+
+
+ )}
+ {data.user.contactNeopetsUsername && (
+
+
+
+ Neomail
+
+
+ )}
+
+
+
+
+
+ Support
+
+
+
+
+ {/* Usually I put "Own" before "Want", but this matches the natural
+ * order on the page: the _matches_ for things you want are things
+ * _this user_ owns, so they come first. I think it's also probably a
+ * more natural train of thought: you come to someone's list _wanting_
+ * something, and _then_ thinking about what you can offer. */}
+ {!isCurrentUser && numItemsTheyOwnThatYouWant > 0 && (
+
+
+
+ {numItemsTheyOwnThatYouWant > 1
+ ? `${numItemsTheyOwnThatYouWant} items you want`
+ : "1 item you want"}
+
+
+ )}
+ {!isCurrentUser && numItemsTheyWantThatYouOwn > 0 && (
+
+
+
+ {numItemsTheyWantThatYouOwn > 1
+ ? `${numItemsTheyWantThatYouOwn} items you own`
+ : "1 item you own"}
+
+
+ )}
+
+
+
+
+
+
+
-
- {isCurrentUser && (
-
-
+
+ {isCurrentUser && (
+
+
+
+ )}
+
+ {isCurrentUser
+ ? "Items you own"
+ : `Items ${data.user.username} owns`}
+
+
+ {listsOfOwnedItems.map((closetList) => (
+ 1}
+ />
+ ))}
+
- )}
-
- {isCurrentUser ? "Items you own" : `Items ${data.user.username} owns`}
-
-
- {listsOfOwnedItems.map((closetList) => (
- 1}
- />
- ))}
-
-
-
- {isCurrentUser ? "Items you want" : `Items ${data.user.username} wants`}
-
-
- {listsOfWantedItems.map((closetList) => (
- 1}
- />
- ))}
-
-
+
+ {isCurrentUser
+ ? "Items you want"
+ : `Items ${data.user.username} wants`}
+
+
+ {listsOfWantedItems.map((closetList) => (
+ 1}
+ />
+ ))}
+
+
+ )}
+
);
}
@@ -588,21 +596,25 @@ function MarkdownAndSafeHTML({ children }) {
});
return (
-
+ {({ css }) => (
+
+ ol,
+ ul {
+ margin-left: 2em;
+ }
+ `}
+ />
+ )}
+
);
}
diff --git a/src/app/WardrobePage/Item.js b/src/app/WardrobePage/Item.js
index c305c92..eaa4939 100644
--- a/src/app/WardrobePage/Item.js
+++ b/src/app/WardrobePage/Item.js
@@ -1,5 +1,5 @@
import React from "react";
-import { css, cx } from "@emotion/css";
+import { ClassNames } from "@emotion/react";
import {
Box,
Flex,
@@ -166,35 +166,39 @@ function ItemContainer({ children, isDisabled = false }) {
);
return (
-
+ {({ css, cx }) => (
+
- {children}
-
+ input:checked:focus + & {
+ border-color: ${focusCheckedBorderColor};
+ }
+ `,
+ ])}
+ >
+ {children}
+
+ )}
+
);
}
@@ -242,39 +246,43 @@ function ItemActionButton({ icon, label, to, onClick }) {
);
return (
-
-
+ {({ css }) => (
+
+
-
+ @media (hover: none) {
+ opacity: 1;
+ }
+ `}
+ />
+
+ )}
+
);
}
diff --git a/src/app/WardrobePage/ItemsPanel.js b/src/app/WardrobePage/ItemsPanel.js
index d6ee1ab..705fc10 100644
--- a/src/app/WardrobePage/ItemsPanel.js
+++ b/src/app/WardrobePage/ItemsPanel.js
@@ -1,5 +1,5 @@
import React from "react";
-import { css } from "@emotion/css";
+import { ClassNames } from "@emotion/react";
import {
Box,
Editable,
@@ -34,50 +34,59 @@ function ItemsPanel({ outfitState, loading, dispatchToOutfit }) {
const { zonesAndItems, incompatibleItems } = outfitState;
return (
-
-
-
-
-
- {loading ? (
-
- ) : (
-
- {zonesAndItems.map(({ zoneLabel, items }) => (
-
-
-
- ))}
- {incompatibleItems.length > 0 && (
-
-
-
- }
- items={incompatibleItems}
- outfitState={outfitState}
- dispatchToOutfit={dispatchToOutfit}
- isDisabled
+
+ {({ css }) => (
+
+
+
+
+
+ {loading ? (
+
+ ) : (
+
+ {zonesAndItems.map(({ zoneLabel, items }) => (
+
+
+
+ ))}
+ {incompatibleItems.length > 0 && (
+
+
+
+ }
+ items={incompatibleItems}
+ outfitState={outfitState}
+ dispatchToOutfit={dispatchToOutfit}
+ isDisabled
+ />
+ )}
+
)}
-
- )}
-
-
+
+
+ )}
+
);
}
@@ -125,59 +134,66 @@ function ItemZoneGroup({
);
return (
-
-
- {zoneLabel}
- {afterHeader && {afterHeader}}
-
-
-
- {items.map((item) => {
- const itemNameId =
- zoneLabel.replace(/ /g, "-") + `-item-${item.id}-name`;
- const itemNode = (
-
- );
+
+ {({ css }) => (
+
+
+ {zoneLabel}
+ {afterHeader && {afterHeader}}
+
+
+
+ {items.map((item) => {
+ const itemNameId =
+ zoneLabel.replace(/ /g, "-") + `-item-${item.id}-name`;
+ const itemNode = (
+
+ );
- return (
-
- {isDisabled ? (
- itemNode
- ) : (
-
- )}
-
- );
- })}
-
-
-
+ return (
+
+ {isDisabled ? (
+ itemNode
+ ) : (
+
+ )}
+
+ );
+ })}
+
+
+
+ )}
+
);
}
@@ -273,7 +289,7 @@ function OutfitHeading({ outfitState, dispatchToOutfit }) {
*
* See react-transition-group docs for more info!
*/
-const fadeOutAndRollUpTransition = {
+const fadeOutAndRollUpTransition = (css) => ({
classNames: css`
&-exit {
opacity: 1;
@@ -292,6 +308,6 @@ const fadeOutAndRollUpTransition = {
onExit: (e) => {
e.style.height = e.offsetHeight + "px";
},
-};
+});
export default ItemsPanel;
diff --git a/src/app/WardrobePage/OutfitControls.js b/src/app/WardrobePage/OutfitControls.js
index b7673ed..a64fdf7 100644
--- a/src/app/WardrobePage/OutfitControls.js
+++ b/src/app/WardrobePage/OutfitControls.js
@@ -1,5 +1,5 @@
import React from "react";
-import { css, cx } from "@emotion/css";
+import { ClassNames } from "@emotion/react";
import {
Box,
Button,
@@ -84,120 +84,126 @@ function OutfitControls({
};
return (
-
+ {({ css, cx }) => (
+ {
- const opacity = parseFloat(getComputedStyle(e.currentTarget).opacity);
- if (opacity < 0.5) {
- // If the controls aren't visible right now, then clicks on them are
- // probably accidental. Ignore them! (We prevent default to block
- // built-in behaviors like link nav, and we stop propagation to block
- // our own custom click handlers. I don't know if I can prevent the
- // select clicks though?)
- e.preventDefault();
- e.stopPropagation();
+ @media (hover: hover) {
+ &:hover {
+ opacity: 1;
+ }
+ }
+ `,
+ focusIsLocked && "focus-is-locked"
+ )}
+ onClickCapture={(e) => {
+ const opacity = parseFloat(
+ getComputedStyle(e.currentTarget).opacity
+ );
+ if (opacity < 0.5) {
+ // If the controls aren't visible right now, then clicks on them are
+ // probably accidental. Ignore them! (We prevent default to block
+ // built-in behaviors like link nav, and we stop propagation to block
+ // our own custom click handlers. I don't know if I can prevent the
+ // select clicks though?)
+ e.preventDefault();
+ e.stopPropagation();
- // We also show the controls, by locking focus. We'll undo this when
- // the user taps elsewhere (because it will trigger a blur event from
- // our child components), in `maybeUnlockFocus`.
- setFocusIsLocked(true);
- }
- }}
- >
-
- }
- aria-label="Leave this outfit"
- d="inline-flex" // Not sure why requires this to style right! ^^`
- />
-
- {showAnimationControls && (
-
-
-
-
+ // We also show the controls, by locking focus. We'll undo this when
+ // the user taps elsewhere (because it will trigger a blur event from
+ // our child components), in `maybeUnlockFocus`.
+ setFocusIsLocked(true);
+ }
+ }}
+ >
+
+ }
+ aria-label="Leave this outfit"
+ d="inline-flex" // Not sure why requires this to style right! ^^`
+ />
+
+ {showAnimationControls && (
+
+
+
+
+
+ )}
+
+
+
+
+
+
+
+
+
+
+ {/**
+ * We try to center the species/color picker, but the left spacer will
+ * shrink more than the pose picker container if we run out of space!
+ */}
+
+
+
+
+
+
+
+
+
+
)}
-
-
-
-
-
-
-
-
-
-
- {/**
- * We try to center the species/color picker, but the left spacer will
- * shrink more than the pose picker container if we run out of space!
- */}
-
-
-
-
-
-
-
-
-
-
-
+
);
}
@@ -277,55 +283,59 @@ function PlayPauseButton() {
}, [blinkInState, setBlinkInState]);
return (
- <>
-
- {blinkInState.type === "started" && (
-
+
+ {({ css }) => (
+ <>
setBlinkInState({ type: "done" })}
- // Don't disrupt the hover state of the controls! (And the button
- // doesn't seem to click correctly, not sure why, but instead of
- // debugging I'm adding this :p)
- pointerEvents="none"
- className={css`
- @keyframes fade-in-out {
- 0% {
- opacity: 0;
- }
-
- 10% {
- opacity: 1;
- }
-
- 90% {
- opacity: 1;
- }
-
- 100% {
- opacity: 0;
- }
- }
-
- opacity: 0;
- animation: fade-in-out 2s;
- `}
+ marginTop="0.3rem" // to center-align with buttons (not sure on amt?)
+ ref={buttonRef}
/>
-
+ {blinkInState.type === "started" && (
+
+ setBlinkInState({ type: "done" })}
+ // Don't disrupt the hover state of the controls! (And the button
+ // doesn't seem to click correctly, not sure why, but instead of
+ // debugging I'm adding this :p)
+ pointerEvents="none"
+ className={css`
+ @keyframes fade-in-out {
+ 0% {
+ opacity: 0;
+ }
+
+ 10% {
+ opacity: 1;
+ }
+
+ 90% {
+ opacity: 1;
+ }
+
+ 100% {
+ opacity: 0;
+ }
+ }
+
+ opacity: 0;
+ animation: fade-in-out 2s;
+ `}
+ />
+
+ )}
+ >
)}
- >
+
);
}
diff --git a/src/app/WardrobePage/PosePicker.js b/src/app/WardrobePage/PosePicker.js
index b2ef66e..cc0ab56 100644
--- a/src/app/WardrobePage/PosePicker.js
+++ b/src/app/WardrobePage/PosePicker.js
@@ -1,7 +1,7 @@
import React from "react";
import gql from "graphql-tag";
import { useQuery } from "@apollo/client";
-import { css, cx } from "@emotion/css";
+import { ClassNames } from "@emotion/react";
import {
Box,
Button,
@@ -107,97 +107,101 @@ function PosePicker({
};
return (
-
- {({ isOpen }) => (
- <>
-
-
+
+
+
+
+ {isInSupportMode ? (
+
+ ) : (
+ <>
+
+ {numAvailablePoses <= 1 && (
+
+
+ The empty picker is hidden for most users!
+
+ You can see it because you're a Support user.
+
+
+ )}
+ >
)}
- >
- )}
-
-
- setIsInSupportMode(e.target.checked)}
- />
+
+
+ setIsInSupportMode(e.target.checked)}
+ />
+
+
-
-
-
-
-
- >
+
+
+
+ >
+ )}
+
)}
-
+
);
}
@@ -343,110 +347,118 @@ function PoseOption({
);
return (
- {
- // HACK: We need the timeout to beat the popover's focus stealing!
- const input = e.currentTarget.querySelector("input");
- setTimeout(() => input.focus(), 0);
- }}
- {...otherProps}
- >
-
-
+
+ {({ css, cx }) => (
- {poseInfo.isAvailable ? (
-
-
-
- ) : (
-
-
-
- )}
-
- {label && (
- {
+ // HACK: We need the timeout to beat the popover's focus stealing!
+ const input = e.currentTarget.querySelector("input");
+ setTimeout(() => input.focus(), 0);
+ }}
+ {...otherProps}
>
- {label}
+
+
+
+ {poseInfo.isAvailable ? (
+
+
+
+ ) : (
+
+
+
+ )}
+
+ {label && (
+
+ {label}
+
+ )}
)}
-
+
);
}
diff --git a/src/app/WardrobePage/SearchToolbar.js b/src/app/WardrobePage/SearchToolbar.js
index 0e4d0ee..e66096d 100644
--- a/src/app/WardrobePage/SearchToolbar.js
+++ b/src/app/WardrobePage/SearchToolbar.js
@@ -12,7 +12,7 @@ import {
useColorModeValue,
} from "@chakra-ui/react";
import { CloseIcon, SearchIcon } from "@chakra-ui/icons";
-import { css, cx } from "@emotion/css";
+import { ClassNames } from "@emotion/react";
import Autosuggest from "react-autosuggest";
/**
@@ -79,23 +79,27 @@ function SearchToolbar({
({ containerProps, children }) => {
const { className, ...otherContainerProps } = containerProps;
return (
-
+ {({ css, cx }) => (
+
+ {children}
+
)}
- >
- {children}
-
+
);
},
[]
@@ -111,108 +115,116 @@ function SearchToolbar({
const focusBorderColor = useColorModeValue("green.600", "green.400");
return (
-
- setSuggestions(getSuggestions(value, query, zoneLabels))
- }
- onSuggestionsClearRequested={() => setSuggestions([])}
- onSuggestionSelected={(e, { suggestion }) => {
- const valueWithoutLastWord = query.value.match(/^(.*?)\s*\S+$/)[1];
- onChange({
- ...query,
- value: valueWithoutLastWord,
- filterToZoneLabel: suggestion.zoneLabel || query.filterToZoneLabel,
- filterToItemKind: suggestion.itemKind || query.filterToItemKind,
- });
- }}
- getSuggestionValue={(zl) => zl}
- highlightFirstSuggestion={true}
- renderSuggestion={renderSuggestion}
- renderSuggestionsContainer={renderSuggestionsContainer}
- renderInputComponent={(props) => (
-
- {queryFilterText ? (
-
-
- {queryFilterText}
-
- ) : (
-
-
-
- )}
-
- {(query.value || queryFilterText) && (
-
- }
- color="gray.400"
- variant="ghost"
- colorScheme="green"
- aria-label="Clear search"
- onClick={() => {
- onChange(null);
- }}
- // Big style hacks here!
- height="calc(100% - 2px)"
- marginRight="2px"
- />
-
- )}
-
- )}
- inputProps={{
- // placeholder: "Search for items to add…",
- "aria-label": "Search for items to add…",
- focusBorderColor: focusBorderColor,
- value: query.value || "",
- ref: searchQueryRef,
- minWidth: 0,
- borderBottomRadius: suggestions.length > 0 ? "0" : "md",
- // HACK: Chakra isn't noticing the InputLeftElement swapping out
- // for the InputLeftAddon, so the styles aren't updating...
- // Hard override!
- className: css`
- padding-left: ${queryFilterText ? "1rem" : "2.5rem"} !important;
- border-bottom-left-radius: ${queryFilterText
- ? "0"
- : "0.25rem"} !important;
- border-top-left-radius: ${queryFilterText
- ? "0"
- : "0.25rem"} !important;
- `,
- onChange: (e, { newValue, method }) => {
- // The Autosuggest tries to change the _entire_ value of the element
- // when navigating suggestions, which isn't actually what we want.
- // Only accept value changes that are typed by the user!
- if (method === "type") {
- onChange({ ...query, value: newValue });
+
+ {({ css }) => (
+
+ setSuggestions(getSuggestions(value, query, zoneLabels))
}
- },
- onKeyDown: (e) => {
- if (e.key === "Escape") {
- if (suggestions.length > 0) {
- setSuggestions([]);
- return;
- }
- onChange(null);
- e.target.blur();
- } else if (e.key === "ArrowDown") {
- if (suggestions.length > 0) {
- return;
- }
- onMoveFocusDownToResults(e);
- } else if (e.key === "Backspace" && e.target.selectionStart === 0) {
+ onSuggestionsClearRequested={() => setSuggestions([])}
+ onSuggestionSelected={(e, { suggestion }) => {
+ const valueWithoutLastWord = query.value.match(/^(.*?)\s*\S+$/)[1];
onChange({
...query,
- filterToItemKind: null,
- filterToZoneLabel: null,
+ value: valueWithoutLastWord,
+ filterToZoneLabel:
+ suggestion.zoneLabel || query.filterToZoneLabel,
+ filterToItemKind: suggestion.itemKind || query.filterToItemKind,
});
- }
- },
- }}
- />
+ }}
+ getSuggestionValue={(zl) => zl}
+ highlightFirstSuggestion={true}
+ renderSuggestion={renderSuggestion}
+ renderSuggestionsContainer={renderSuggestionsContainer}
+ renderInputComponent={(props) => (
+
+ {queryFilterText ? (
+
+
+ {queryFilterText}
+
+ ) : (
+
+
+
+ )}
+
+ {(query.value || queryFilterText) && (
+
+ }
+ color="gray.400"
+ variant="ghost"
+ colorScheme="green"
+ aria-label="Clear search"
+ onClick={() => {
+ onChange(null);
+ }}
+ // Big style hacks here!
+ height="calc(100% - 2px)"
+ marginRight="2px"
+ />
+
+ )}
+
+ )}
+ inputProps={{
+ // placeholder: "Search for items to add…",
+ "aria-label": "Search for items to add…",
+ focusBorderColor: focusBorderColor,
+ value: query.value || "",
+ ref: searchQueryRef,
+ minWidth: 0,
+ borderBottomRadius: suggestions.length > 0 ? "0" : "md",
+ // HACK: Chakra isn't noticing the InputLeftElement swapping out
+ // for the InputLeftAddon, so the styles aren't updating...
+ // Hard override!
+ className: css`
+ padding-left: ${queryFilterText ? "1rem" : "2.5rem"} !important;
+ border-bottom-left-radius: ${queryFilterText
+ ? "0"
+ : "0.25rem"} !important;
+ border-top-left-radius: ${queryFilterText
+ ? "0"
+ : "0.25rem"} !important;
+ `,
+ onChange: (e, { newValue, method }) => {
+ // The Autosuggest tries to change the _entire_ value of the element
+ // when navigating suggestions, which isn't actually what we want.
+ // Only accept value changes that are typed by the user!
+ if (method === "type") {
+ onChange({ ...query, value: newValue });
+ }
+ },
+ onKeyDown: (e) => {
+ if (e.key === "Escape") {
+ if (suggestions.length > 0) {
+ setSuggestions([]);
+ return;
+ }
+ onChange(null);
+ e.target.blur();
+ } else if (e.key === "ArrowDown") {
+ if (suggestions.length > 0) {
+ return;
+ }
+ onMoveFocusDownToResults(e);
+ } else if (
+ e.key === "Backspace" &&
+ e.target.selectionStart === 0
+ ) {
+ onChange({
+ ...query,
+ filterToItemKind: null,
+ filterToZoneLabel: null,
+ });
+ }
+ },
+ }}
+ />
+ )}
+
);
}
diff --git a/src/app/WardrobePage/support/ItemSupportDrawer.js b/src/app/WardrobePage/support/ItemSupportDrawer.js
index 360c388..e7f6e73 100644
--- a/src/app/WardrobePage/support/ItemSupportDrawer.js
+++ b/src/app/WardrobePage/support/ItemSupportDrawer.js
@@ -1,7 +1,7 @@
import * as React from "react";
import gql from "graphql-tag";
import { useQuery, useMutation } from "@apollo/client";
-import { css } from "@emotion/css";
+import { ClassNames } from "@emotion/react";
import {
Badge,
Box,
@@ -454,71 +454,75 @@ function ItemSupportAppearanceLayer({
const iconButtonColor = useColorModeValue("green.800", "gray.900");
return (
-
-
-
+
+ {({ css }) => (
+
+
+
-
+
+
+
+ {itemLayer.zone.label}
+ Zone ID: {itemLayer.zone.id}
+ DTI ID: {itemLayer.id}
+
-
- {itemLayer.zone.label}
- Zone ID: {itemLayer.zone.id}
- DTI ID: {itemLayer.id}
-
-
+ )}
+
);
}
diff --git a/src/app/components/HangerSpinner.js b/src/app/components/HangerSpinner.js
index a10aa08..4faf961 100644
--- a/src/app/components/HangerSpinner.js
+++ b/src/app/components/HangerSpinner.js
@@ -1,5 +1,5 @@
import * as React from "react";
-import { css } from "@emotion/css";
+import { ClassNames } from "@emotion/react";
import { Box, useColorModeValue } from "@chakra-ui/react";
import { createIcon } from "@chakra-ui/icons";
@@ -21,74 +21,76 @@ function HangerSpinner({ size = "md", ...props }) {
const color = useColorModeValue("green.500", "green.300");
return (
- <>
-
+ {({ css }) => (
+
-
-
- >
+ `}
+ {...props}
+ >
+
+
+ )}
+
);
}
diff --git a/src/app/components/ItemCard.js b/src/app/components/ItemCard.js
index 6279733..01df824 100644
--- a/src/app/components/ItemCard.js
+++ b/src/app/components/ItemCard.js
@@ -1,5 +1,5 @@
import React from "react";
-import { css } from "@emotion/css";
+import { ClassNames } from "@emotion/react";
import {
Badge,
Box,
@@ -102,59 +102,63 @@ export function ItemThumbnail({
);
return (
-
-
+
+ {({ css }) => (
-
-
+ width={size === "lg" ? "80px" : "50px"}
+ height={size === "lg" ? "80px" : "50px"}
+ transition="all 0.15s"
+ transformOrigin="center"
+ position="relative"
+ className={css([
+ {
+ transform: "scale(0.8)",
+ },
+ !isDisabled &&
+ !isActive && {
+ [focusSelector]: {
+ opacity: "0.9",
+ transform: "scale(0.9)",
+ },
+ },
+ !isDisabled &&
+ isActive && {
+ opacity: 1,
+ transform: "none",
+ },
+ ])}
+ {...props}
+ >
+
+
+
+
+ )}
+
);
}
@@ -166,30 +170,34 @@ function ItemName({ children, isDisabled, focusSelector, ...props }) {
const theme = useTheme();
return (
-
+ {({ css }) => (
+
- {children}
-
+ {...props}
+ >
+ {children}
+
+ )}
+
);
}
diff --git a/src/app/components/OutfitPreview.js b/src/app/components/OutfitPreview.js
index d7ddc38..4209fdd 100644
--- a/src/app/components/OutfitPreview.js
+++ b/src/app/components/OutfitPreview.js
@@ -1,7 +1,7 @@
import React from "react";
import { Box, DarkMode, Flex, Text } from "@chakra-ui/react";
import { WarningIcon } from "@chakra-ui/icons";
-import { css } from "@emotion/css";
+import { ClassNames } from "@emotion/react";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import OutfitMovieLayer, {
@@ -149,104 +149,113 @@ export function OutfitLayers({
}, [setCanvasSize]);
return (
-
- {placeholder && (
-
-
+ {({ css }) => (
+
+ {placeholder && (
+
+
+ {placeholder}
+
+
+ )}
+
+ {visibleLayers.map((layer) => (
+
+
+ {layer.canvasMovieLibraryUrl ? (
+
+ ) : (
+ tags are always allowed through CORS), but
+ // this means we make the same request that the Download
+ // button makes, so it can use the cached version of this
+ // image instead of requesting it again with crossOrigin!
+ crossOrigin={getBestImageUrlForLayer(layer).crossOrigin}
+ alt=""
+ objectFit="contain"
+ maxWidth="100%"
+ maxHeight="100%"
+ />
+ )}
+
+
+ ))}
+
+
- {placeholder}
-
-
- )}
-
- {visibleLayers.map((layer) => (
-
-
- {layer.canvasMovieLibraryUrl ? (
-
- ) : (
+ {spinnerVariant === "overlay" && (
+ <>
tags are always allowed through CORS), but
- // this means we make the same request that the Download
- // button makes, so it can use the cached version of this
- // image instead of requesting it again with crossOrigin!
- crossOrigin={getBestImageUrlForLayer(layer).crossOrigin}
- alt=""
- objectFit="contain"
- maxWidth="100%"
- maxHeight="100%"
+ position="absolute"
+ top="0"
+ left="0"
+ right="0"
+ bottom="0"
+ backgroundColor="gray.900"
+ opacity="0.7"
/>
- )}
-
-
- ))}
-
-
- {spinnerVariant === "overlay" && (
- <>
-
- {/* Against the dark overlay, use the Dark Mode spinner. */}
-
-
-
- >
- )}
- {spinnerVariant === "corner" && (
-
- )}
-
-
+ {/* Against the dark overlay, use the Dark Mode spinner. */}
+
+
+
+ >
+ )}
+ {spinnerVariant === "corner" && (
+
+ )}
+
+
+ )}
+
);
}
diff --git a/yarn.lock b/yarn.lock
index d2e040b..de813b6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2750,17 +2750,6 @@
"@emotion/weak-memoize" "^0.2.5"
stylis "^4.0.3"
-"@emotion/css@^11.1.3":
- version "11.1.3"
- resolved "https://registry.yarnpkg.com/@emotion/css/-/css-11.1.3.tgz#9ed44478b19e5d281ccbbd46d74d123d59be793f"
- integrity sha512-RSQP59qtCNTf5NWD6xM08xsQdCZmVYnX/panPYvB6LQAPKQB6GL49Njf0EMbS3CyDtrlWsBcmqBtysFvfWT3rA==
- dependencies:
- "@emotion/babel-plugin" "^11.0.0"
- "@emotion/cache" "^11.1.3"
- "@emotion/serialize" "^1.0.0"
- "@emotion/sheet" "^1.0.0"
- "@emotion/utils" "^1.0.0"
-
"@emotion/hash@^0.8.0":
version "0.8.0"
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413"