Compare commits

..

No commits in common. "77ff55353c36ebd55fc033bf38d101749246aa1d" and "a184c7557584e103e80876bad67e9d6f95f9aa2b" have entirely different histories.

5 changed files with 24 additions and 133 deletions

View file

@ -1,6 +1,6 @@
// When the species face picker changes, update and submit the main picker form.
document.addEventListener("change", (e) => {
if (!e.target.matches("species-face-picker")) return;
// When the species *face* picker changes, update and submit the main picker form.
document.addEventListener("click", (e) => {
if (!e.target.matches(".species-face-picker input[type=radio]")) return;
try {
const mainPicker = document.querySelector("#item-preview .species-color-picker");
@ -14,43 +14,8 @@ document.addEventListener("change", (e) => {
}
});
class SpeciesFacePicker extends HTMLElement {
connectedCallback() {
this.addEventListener("click", this.#handleClick);
}
get value() {
return this.querySelector("input[type=radio]:checked")?.value;
}
#handleClick(e) {
if (e.target.matches("input[type=radio]")) {
this.dispatchEvent(new Event("change", {bubbles: true}));
}
}
// Now that the face picker is ready to go, mark it as usable.
for (const options of document.querySelectorAll(".species-face-picker-options")) {
options.removeAttribute("inert");
options.removeAttribute("aria-hidden");
}
class SpeciesFacePickerOptions extends HTMLElement {
static observedAttributes = ["inert", "aria-hidden"];
connectedCallback() {
// Once this component is loaded, we stop being inert and aria-hidden. We're ready!
this.#activate();
}
attributeChangedCallback() {
// If a Turbo Frame tries to morph us into being inert again, activate again!
// (It's important that the server's HTML always return `inert`, for progressive
// enhancement; and it's important to morph this element, so radio focus state
// is preserved. To thread that needle, we have to monitor and remove!)
this.#activate();
}
#activate() {
this.removeAttribute("inert");
this.removeAttribute("aria-hidden");
}
}
customElements.define("species-face-picker", SpeciesFacePicker);
customElements.define("species-face-picker-options", SpeciesFacePickerOptions);

View file

@ -161,46 +161,9 @@ body.items-show
border-color: $error-border-color
color: $error-color
species-face-picker
display: block
.species-face-picker
position: relative
species-face-picker-options
display: flex
flex-wrap: wrap
img
width: 50px
height: 50px
transition: all 0.2s
// Calm down the default color, just a smidge! There's a lot of color
// on this page already, y'know?
opacity: .9
filter: saturate(90%)
label
display: flex
overflow: hidden
transition: all 0.2s
position: relative
line-height: 1
// NOTE: The box-shadows here were copy-pasted from Impress 2020, which uses
// Chakra UI's styling system to generate them! (The colors are from their
// color palette, too.)
&:has(input:checked)
border-radius: 6px
z-index: 1
background: #9AE6B4
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1),0 10px 10px -5px rgba(0, 0, 0, 0.04), #2F855A 0 0 2px 2px
transform: scale(1.1)
&:has(input:focus)
background: #BEE3F8
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1),0 10px 10px -5px rgba(0, 0, 0, 0.04), #4299e1 0 0 0 3px
transform: scale(1.2)
input[type=radio]
position: absolute
left: -10000px
@ -209,30 +172,21 @@ body.items-show
height: 1px
overflow: hidden
&:checked + img
opacity: 1
filter: saturate(110%)
&:disabled + img
opacity: .6
filter: saturate(0%)
label:has(input[type=radio]:disabled)
cursor: not-allowed
&:not(:checked) + img
opacity: .5
noscript
position: absolute
inset: 0
background: rgba(white, .75)
z-index: 1
cursor: auto
display: flex
align-items: center
justify-content: center
text-align: center
&:has(species-face-picker-options[inert])
&:has(.species-face-picker-options[inert])
cursor: wait
.item-zones-info

View file

@ -33,9 +33,7 @@ module ItemsHelper
def standard_species_search_links
all_species = Species.alphabetical.map(&:id)
PetType.random_basic_per_species(all_species).map do |pet_type|
human_name = pet_type.species.human_name
image = pet_type_image pet_type, :happy, :zoom,
alt: human_name, title: human_name
image = pet_type_image(pet_type, :happy, :zoom)
query = "species:#{pet_type.species.name}"
link_to(image, items_path(:q => query))
end.join.html_safe
@ -224,18 +222,6 @@ module ItemsHelper
cookies["DTIOutfitViewerIsPlaying"] == "true"
end
def item_fits?(item, pet_type)
item.appearances.any? { |a| a.fits? pet_type }
end
def species_face_tooltip(pet_type, item)
if item_fits?(item, pet_type)
"#{pet_type.species.human_name}"
else
"#{pet_type.species.human_name}: No data yet"
end
end
def item_zone_partial_fit?(appearances_in_zone, all_appearances)
appearances_in_zone.size < all_appearances.size
end
@ -244,13 +230,12 @@ module ItemsHelper
appearances_in_zone.map(&:species).uniq.map(&:human_name).sort.join(", ")
end
def pet_type_image(pet_type, emotion, size, **options)
src = pet_type_image_url(pet_type, emotion:, size:)
srcset = if size == :face
[[pet_type_image_url(pet_type, emotion:, size: :face_2x), "2x"]]
end
private
image_tag(src, srcset:, **options)
def pet_type_image(pet_type, emotion, size)
src = pet_type_image_url(pet_type, emotion:, size:)
human_name = pet_type.species.name.humanize
image_tag(src, :alt => human_name, :title => human_name)
end
def item_header_user_lists_form_state

View file

@ -502,7 +502,7 @@ class Item < ApplicationRecord
Appearance = Struct.new(:item, :body, :swf_assets) do
include ActiveModel::Serializers::JSON
delegate :present?, :empty?, to: :swf_assets
delegate :species, :fits?, :fits_all?, to: :body
delegate :species, to: :body
def attributes
{item:, body:, swf_assets:}
@ -522,14 +522,6 @@ class Item < ApplicationRecord
def attributes
{id:, species:}
end
def fits_all?
id == 0
end
def fits?(target)
fits_all? || target.body_id == id
end
end
def appearances

View file

@ -33,24 +33,19 @@
"id", "human_name", @selected_preview_pet_type.species_id)
= submit_tag "Go", name: nil
%species-face-picker
%form.species-face-picker
%noscript
This fancy species picker requires Javascript, but you can still use the
dropdowns instead!
%species-face-picker-options{
inert: true, # waits for JS to remove
.species-face-picker-options{
"inert": true, # waits for JS to remove
"aria-hidden": true, # waits for JS to remove
}
- @preview_pet_type_options.each do |pet_type|
%label{
title: species_face_tooltip(pet_type, @item),
}
%label
= radio_button_tag "species_face_id", pet_type.species_id,
checked: pet_type == @preview_outfit.pet_type,
disabled: !item_fits?(@item, pet_type)
= pet_type_image pet_type,
item_fits?(@item, pet_type) ? :happy : :sad,
:face
checked: pet_type == @preview_outfit.pet_type
= pet_type_image pet_type, :happy, :face
.item-zones-info
%section