Oops, I shipped with the images.neopets.com TODO undone! Also, the white background was intersecting with the close X for the feedback form.
In this change, we move the xwee image into our bundle instead of depending on images.neopets.com, and we edit it to have a transparent background, which looks nicer for dark mode. (And we do a srcset!)
Previously I tried to be clever and pre-optimize by putting all the layers onto one canvas… I think this probably helped by batching their paints, but it made fades less smooth by not taking advantage of native CSS transitions, and it made us dip into JS way more often than necessary.
Here, I take the simpler approach: just layers of <img> and <canvas> tags, with each animated layer on its own canvas, and letting the browser handle transitions and compositing, and separate `setInterval` timers to manage their framerates.
I have a suspicion that batching the paints could help performance more, but honestly, maybe that batching is already happening somehow, because things look pretty great on my big-screen stress test now; and so if it _is_ relevant, I want to wait and see after testing on low-power devices.
Not 100% sure on the copy, but I like that it's a bit clearer about the value prop. I tried to work in customization for SEO, but it feels too clunky in a sentence, might need to put it elsewhere in the copy!
These changes are most relevant for playing around in the dev server, modeing against an empty database. But they'll also help in real-world modeling scenarios! e.g. modeling a new species/color combo is now a bit nicer, we don't show a blank entry in the color picker
I think it's great that we hide the button when it's not relevant, but that makes it hard to know that it exists. Here, we do some cute tricks to blink up the "Paused" button when it first appears, even if the user doesn't have the controls visible right now
We did this a while back too, but I guess something changed in Apollo: I guess it used to return identical item objects from the cache on its own, and now it returns brand new item objects. So we gotta do the object caching hacks ourselves!
This speeds up add/remove item state updates from 500ms to 100ms on my Mac, because we stop re-rendering all the Item components and their complex Chakra children.
This is especially worth doing now, because animations make long updates much more noticeable! (It interrupts the animation 😅)
Honestly kinda surprised this worked on the first go! I was worried something about the process would make the sorta like, instant-cache expectation not work.
Still thinking it might be considerate to like, keep a LRU cache of MovieClip options, so that we don't double-execute these scripts when adding stuff… we even re-execute the ones already applied lol 😅 and that adds lots of script tags to the body!
But yeah I'm not gonna push on it yet until I see evidence that it actually causes performance issues in practice
This is really very cute, but too many items it turns out are lod despite not actually being animated 🙃 it's helpful for looking for test cases tho, so I'm keeping it, but support only!
I also ended up really liking the icon-badge+tooltip design as a way to summarize lil things, so I'm trying Own/Want short badges in the same style.
reflecting further on the abstraction, I'm noticing that this isn't an Easel abstraction like I envisioned early, and that we're baking some Neopets stuff into it. And I think that's the right call, esp with the tricky MovieClip stuff coming up, where I think more barriers would hurt more than they help. So, a new name!
Did it revert? Or did I just never notice that it only worked on mount, not on new loading states?
Also, fixed a bug where we were injecting the script tag way too much, and triggering loading too much that way too!
still just for static stuff, but it's good to be working!
PosePicker got a bit broken, CSS scaling doesn't work quite right anymore, we might need to just up the internal resolution or something?
notable layout change is that the text content will now try to center itself, and we push the buttons off to the right. we also needed to tweak the layout code a bit to get the buttons to feel centered with the top two lines, bc centering against the full block just feels wrong, they want to be top-y in terms of positioning, but still feel centered-y in terms of visual balance
Honestly I don't think this is the long-term home for the Modeling link, I think it'll become a homepage-only link as we add more modules there. But I wanted to get it out of the way!
Fading the whole preview to a black overlay for the loading state was feeling aggressive, especially since loading delay wasn't working correctly!
In this change, I fix loading delay, and I add a nice subtle "corner" variant for outfit preview spinners :)
Here, we add loading skeletons to lots of individual elements, instead of doing a whole item placeholder skeleton. That helps when coming from pages where we have some data, like name and thumbnail, but things is isNc are still missing.
It looks nice, but also particularly means we can handle the loading for the preview separately, get that started faster and iterate better on it in dev!
Initially the spinner was only used in OutfitPreview, where the background was always pretty dark. Now that we use it in more general contexts, we need a light/dark distinction!
Also went and standardized out the `size` props
Here, we extract a lean WardrobePageLayout component, so that we can bundle it into the main app as a loading state for WardrobePage.
This means that clicking Start from the homepage will, instead of flashing the screen to white while WardrobePage loads, show the correctly-sized black/white page layout instead.
I think the Chakra upgrades made these overrides stop working? added !important so that they happen again!
The regression meant the homepage looked worse, always having the selects fade in :/