Instead of hand-rolling HTML, this offers helpers like `f.field`, to
help ensure the HTML is consistent, and to keep the templates more
focused on the unique form elements.
Specifically, I'm going for a more-vertical layout, cuz I want to bring
PetState over to it, and the weird grid situation wasn't gonna fit the
big pose label radios.
This hasn't worked for a while anyway! Let's remove the bits of code
where we deal with it, and the database field that signals it. (We also
make a corresponding change in Impress 2020, so it doesn't crash trying
to query based on the `prank` column.)
I also ran this snippet to clear out all the Nebula stuff in the db:
```rb
Color.transaction do
nebula = Color.where(prank: true).find_by_name("Nebula")
nebula.pet_types.includes(pet_states: :swf_assets).each do |pet_type|
pet_type.pet_states.each do |pet_state|
pet_state.parent_swf_asset_relationships.each do |psa|
psa.swf_asset.destroy!
psa.destroy!
end
pet_state.destroy!
end
pet_type.destroy!
end
nebula.destroy!
end
```
Now that we have such a convenient lil outfit viewer component we built
for the item page preview, it's easy peasy to drop it in here too! And
it's all nice and lightweight, since in this case it's basically just.
image tags, with some supporting enhancements.
Anyway, this page has no actual useful styles of its own yet. Gonna
make it look nice and such!
Right, yeah, we've been depending on an external CDN for a long time
for jQuery and the jQuery Template library, and I don't like that kind
of external dependency! Let's put it in with the rest of our libs.
When I was trying to debug slow view code one time long long ago, I was
like "let's cache any part of the template that's static!"
And like. no that's silly, I don't trust that this speeds anything up,
but it _definitely_ adds complexity. Let's just not.
The silly motivation is that I wanted to remove `.prettierignore`,
which just exists to omit that one folder from `npm run format`. But it
also seems like this is the standard place to put them—a standard
created long after we first set this up lol
Ahh right, when you indent stuff underneath a tag in HAML, it does the
same indented form in the output HTML, which adds whitespace that
creates a problem for how we're doing this list.
Before this change, the "Engulfed in Flames Effect" item showed below
the preview: `Occupies: Background Item , Lower Foreground Item`, with
an extra space before the comma.
After this change, it now shows
`Occupies: Background Item, Lower Foreground Item`, as intended.
I think this has just been broken for a long time? And I don't think
it's very useful in a world 15 years later, where our problem *used* to
be giant gaps in our library, which isn't really our data problem
anymore.
No more of this loading everything into `application.css`! I'm
arbitrarily starting here because that's where I've been playing
lately, but this is part of a larger effort to move toward a more
straightforward CSS architecture (and away from Sass even?)
I skipped this for a bit because I couldn't think of a simple way to
adapt this behavior to a web component + vanilla CSS setting, but then
I thought of CSS variables, and sat down and cranked this out!
Oh right, forgot about this lol!
The specific effect on Impress 2020 where the button label expands is,
kinda hard to implement in normal CSS/JS, and so I'm not in the mood
and I'm settling for the `title` attribute lol
Oh right, I need the error indicator to be part of a container that
also contains the outfit viewer, to appear below it!
I was motivated because I realized I forgot the Customize More button
so now I'm building it lol
We add a new `use_responsive_design` helper, for pages to opt into this
new CSS—mostly just because like… it's *worse* to apply these styles
for pages that don't expect it 😅
And then, I fix up a couple things on the item page (including in the
general items layout) to match!
I'm doing this because the species face picker layout is going to want
some responsive awareness, and I want to be doing that from the start!
Here, I remember the trick I learned when building the outfit viewer:
web components are great for making sure stuff stays initialized well
in a Turbo environment!
The problem was, after submitting the form and getting a new preview
loaded via Turbo, the part where we remove `inert` would get undone.
Additionally, this script only loads *once* per session, so if you
Turbo-nav to a different item then that part of the page never ran.
Instead, we use web components to remove the attributes on mount, then
again if they're ever reapplied by Idiomorph.
We mark the options as `inert` and `aria-hidden` while the JS is still
loading—and if the `noscript` tag tells us it's never coming, it covers
up the picker with a brief explainer!
The basics are working great! There's a few known missing things though:
- Add reasonable noscript behavior
- Disable options where there's no valid appearance
- Lay it out actually _good_, instead of just images dumped there
Adapting what the Impress 2020 UI does, but in Ruby instead!
I feel like this is case is really starting to show the power of doing
this stuff in Rails instead of via an API… we can *really* take
advantage of our models and our handy idioms at all points. This is
just so much less *code* than this feature takes in Node + GraphQL +
React.
We were previously planning a more interesting "Add to Cart"
integration with TNT, but it hasn't panned out! For now, we'll just
link to the NC Mall homepage.
Two reasons for this new title:
1. The pitch for "Get these items!" is weaker, now that we're not
getting the power-user integrations we'd planned around.
2. I literally only just thought of it now!
This doesn't do a good job maintaining state across morphs, but hey
it's Working At All in terms of wiring, and that's good!!
Also need to style up the toggle as a cute button instead of a visible
checkbox and the words "Play/pause"!
Add some unobtrusive white background for contrast, show it when the
Turbo frame is loading too, add a spinner cursor, and fix a silliness
of how we put the `position: absolute` stuff into the component-y part
of the hanger spinner instead of this specific use case lol oops!
The most notable thing here is that we keep the movie iframes running!
So if you're trying different pets for an animated item, the animation
keeps going while the new pet layers load alongside it.
This is also nice for like, the species/color picker form, so we're not
taking away input elements from people who depend on e.g. keyboard
focus.
Instead of doing all this listening to Turbo events etc to know when
outfit layers might have changed, making it a custom element and wiring
in the behavior to its actual lifecycle makes it always Just Work!
This is a cute thing that I think sets us up for other stuff down the
line: move more of the outfit appearance logic into the `Outfit` class!
Now, we set up the item page with a temporary instance of `Outfit`,
then ask for its `visible_layers`.
Still missing restricted-zones logic and such, that's next!