diff --git a/app/assets/stylesheets/_layout.sass b/app/assets/stylesheets/_layout.sass
index f21e6e82..257205d5 100644
--- a/app/assets/stylesheets/_layout.sass
+++ b/app/assets/stylesheets/_layout.sass
@@ -91,6 +91,8 @@ input[type=text], input[type=password], input[type=search], input[type=number],
textarea
font: inherit
+// TODO: This conflicts with button styles in embedded wardrobe-2020
+// components. It'd be nice to not apply it to ALL button elements.
a.button, input[type=submit], button
+awesome-button
&.loud
diff --git a/app/assets/stylesheets/partials/clean/_mixins.sass b/app/assets/stylesheets/partials/clean/_mixins.sass
index d599dee8..50ed22f1 100644
--- a/app/assets/stylesheets/partials/clean/_mixins.sass
+++ b/app/assets/stylesheets/partials/clean/_mixins.sass
@@ -53,7 +53,7 @@
&:hover
color: #fff
&:active
- top: 1px
+ transform: translateY(1px)
=reset-awesome-button
+border-radius(0)
diff --git a/app/javascript/item-page.js b/app/javascript/item-page.js
new file mode 100644
index 00000000..b4338630
--- /dev/null
+++ b/app/javascript/item-page.js
@@ -0,0 +1,13 @@
+import React from "react";
+import ReactDOM from "react-dom";
+
+import { AppProvider, ItemPageOutfitPreview } from "./wardrobe-2020";
+
+const rootNode = document.querySelector("#outfit-preview-root");
+const itemId = rootNode.getAttribute("data-item-id");
+ReactDOM.render(
+
+
+ ,
+ rootNode
+);
diff --git a/app/javascript/wardrobe-2020/AppProvider.js b/app/javascript/wardrobe-2020/AppProvider.js
index a4512c85..333ab415 100644
--- a/app/javascript/wardrobe-2020/AppProvider.js
+++ b/app/javascript/wardrobe-2020/AppProvider.js
@@ -2,32 +2,14 @@ import React from "react";
import * as Sentry from "@sentry/react";
import { Integrations } from "@sentry/tracing";
import { Auth0Provider } from "@auth0/auth0-react";
-import { CSSReset, ChakraProvider, extendTheme } from "@chakra-ui/react";
+import { ChakraProvider, Box } from "@chakra-ui/react";
import { ApolloProvider } from "@apollo/client";
import { useAuth0 } from "@auth0/auth0-react";
-import { mode } from "@chakra-ui/theme-tools";
import { BrowserRouter } from "react-router-dom";
+import { Global } from "@emotion/react";
import buildApolloClient from "./apolloClient";
-const theme = extendTheme({
- styles: {
- global: (props) => ({
- html: {
- // HACK: Chakra sets body as the relative position element, which is
- // fine, except its `min-height: 100%` doesn't actually work
- // unless paired with height on the root element too!
- height: "100%",
- },
- body: {
- background: mode("gray.50", "gray.800")(props),
- color: mode("green.800", "green.50")(props),
- transition: "all 0.25s",
- },
- }),
- },
-});
-
export default function AppProvider({ children }) {
React.useEffect(() => setupLogging(), []);
@@ -45,9 +27,8 @@ export default function AppProvider({ children }) {
scope=""
>
-
-
- {children}
+
+ {children}
@@ -155,3 +136,288 @@ function setupLogging() {
tracesSampleRate: 1.0,
});
}
+
+/**
+ * ScopedCSSReset applies a copy of Chakra UI's CSS reset, but only to its
+ * children (or, well, any element with the chakra-css-reset class).
+ *
+ * TODO: What about Chakra's portal elements like toast messages, which are
+ * intentionally mounted elsewhere in the document?
+ *
+ * NOTE: We use the `:where` CSS selector, instead of the .chakra-css-reset
+ * selector directly, to avoid specificity conflicts. e.g. the selector
+ * `.chakra-css-reset h1` is considered MORE specific than `.my-h1`, whereas
+ * the selector `:where(.chakra-css-reset) h1` is lower specificity.
+ */
+function ScopedCSSReset({ children }) {
+ return (
+ <>
+ {children}
+
+ >
+ );
+}
diff --git a/app/javascript/wardrobe-2020/ItemPage.js b/app/javascript/wardrobe-2020/ItemPage.js
index e6bc2dc6..f7faeb07 100644
--- a/app/javascript/wardrobe-2020/ItemPage.js
+++ b/app/javascript/wardrobe-2020/ItemPage.js
@@ -759,7 +759,7 @@ function IconCheckbox({ icon, isChecked, ...props }) {
);
}
-function ItemPageOutfitPreview({ itemId }) {
+export function ItemPageOutfitPreview({ itemId }) {
const idealPose = React.useMemo(
() => (Math.random() > 0.5 ? "HAPPY_FEM" : "HAPPY_MASC"),
[]
@@ -1018,6 +1018,7 @@ function ItemPageOutfitPreview({ itemId }) {
rowGap="4"
columnGap="6"
justifyContent="center"
+ width="100%"
>
'customize-more',
- :class => 'button'
-
-#item-preview
- %ul#item-preview-species{'data-supported-species-ids' => @supported_species_ids.join(',')}
- = standard_species_images_for(@basic_colored_pet_types_by_species_id)
- #item-preview-error
- #item-preview-swf= t '.preview.requirements_not_met'
+#outfit-preview-root{'data-item-id': @item.id}
- unless @contributors_with_counts.empty?
#item-contributors
@@ -88,17 +79,6 @@
%li= link_to(contributor.name, user_contributions_path(contributor)) + format_contribution_count(count)
%footer= t '.contributors.footer'
-:javascript
- var CURRENT_ITEM_ZONES_RESTRICT = #{@item.zones_restrict.inspect},
- IMPRESS_HOST = #{RemoteImpressHost.inspect};
-
-%script#swf-assets-not-found-template{:type => 'text/x-jquery-tmpl'}
- = twl '.preview.not_found', :item_name => h(@item.name),
- :species_name => '${species_name}',
- :color_name => '${color_name}',
- :modeling_link_url => root_path
-
- content_for :javascripts do
- = include_javascript_libraries :jquery, :swfobject, :jquery_tmpl
- = javascript_include_tag 'items/show'
+ = javascript_include_tag 'item-page', defer: true