From 9475d52054c02a7e35c6acbf9f2bbe5b8d3f4c14 Mon Sep 17 00:00:00 2001 From: Nayte Date: Sat, 13 Dec 2025 19:35:58 +0100 Subject: [PATCH 1/3] [Site] New facet menu demo WIP --- .../Controller/Demo/LiveDemoController.php | 1 + ux.symfony.com/src/Enum/AnimalzType.php | 44 + ux.symfony.com/src/Model/Animalz.php | 26 + .../src/Service/AnimalzRepository.php | 100 +++ .../src/Service/LiveDemoRepository.php | 13 + .../src/Service/data/animalz-properties.json | 806 ++++++++++++++++++ .../src/Twig/Components/Animalz/FacetMenu.php | 90 ++ .../src/Twig/Components/Animalz/Results.php | 61 ++ .../components/Animalz/FacetMenu.html.twig | 43 + .../components/Animalz/Results.html.twig | 21 + .../demos/live_component/animalz.html.twig | 20 + 11 files changed, 1225 insertions(+) create mode 100644 ux.symfony.com/src/Enum/AnimalzType.php create mode 100644 ux.symfony.com/src/Model/Animalz.php create mode 100644 ux.symfony.com/src/Service/AnimalzRepository.php create mode 100644 ux.symfony.com/src/Service/data/animalz-properties.json create mode 100644 ux.symfony.com/src/Twig/Components/Animalz/FacetMenu.php create mode 100644 ux.symfony.com/src/Twig/Components/Animalz/Results.php create mode 100644 ux.symfony.com/templates/components/Animalz/FacetMenu.html.twig create mode 100644 ux.symfony.com/templates/components/Animalz/Results.html.twig create mode 100644 ux.symfony.com/templates/demos/live_component/animalz.html.twig diff --git a/ux.symfony.com/src/Controller/Demo/LiveDemoController.php b/ux.symfony.com/src/Controller/Demo/LiveDemoController.php index afbfb9cb0e6..c02b5915780 100644 --- a/ux.symfony.com/src/Controller/Demo/LiveDemoController.php +++ b/ux.symfony.com/src/Controller/Demo/LiveDemoController.php @@ -93,6 +93,7 @@ public function invoice(LiveDemoRepository $liveDemoRepository, ?Invoice $invoic } #[Route('/{demo}', name: 'app_demo_live_component_demo')] + #[Route('/animalz', name: 'app_demo_live_component_animalz')] #[Route('/auto-validating-form', name: 'app_demo_live_component_auto_validating_form')] #[Route('/chartjs', name: 'app_demo_live_component_chartjs')] #[Route('/dependent-form-fields', name: 'app_demo_live_component_dependent_form_fields')] diff --git a/ux.symfony.com/src/Enum/AnimalzType.php b/ux.symfony.com/src/Enum/AnimalzType.php new file mode 100644 index 00000000000..6c3f2d72768 --- /dev/null +++ b/ux.symfony.com/src/Enum/AnimalzType.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace App\Enum; + +enum AnimalzType: string +{ + case Normal = 'NORMAL'; + case Water = 'WATER'; + case Flying = 'FLYING'; + case Bug = 'BUG'; + case Fight = 'FIGHT'; + case Dark = 'DARK'; + case Poison = 'POISON'; + case Grass = 'GRASS'; + case Fairy = 'FAIRY'; + case Fossil = 'FOSSIL'; + + public function getColor(): string + { + return match ($this) { + self::Normal => '#9fa19f', + self::Water => '#2980ef', + self::Flying => '#81b9ef', + self::Bug => '#91a119', + self::Fight => '#ff8100', + self::Dark => '#4f3f3d', + self::Poison => '#9141cb', + self::Grass => '#3fa129', + self::Fairy => '#ef70ef', + self::Fossil => '#5060e1', + }; + } +} diff --git a/ux.symfony.com/src/Model/Animalz.php b/ux.symfony.com/src/Model/Animalz.php new file mode 100644 index 00000000000..6095039b323 --- /dev/null +++ b/ux.symfony.com/src/Model/Animalz.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace App\Model; + +use App\Enum\AnimalzType; + +final class Animalz +{ + public function __construct( + public string $name, + public AnimalzType $type1, + public ?AnimalzType $type2, + public int $legs, + public string $description, + ) { + } +} diff --git a/ux.symfony.com/src/Service/AnimalzRepository.php b/ux.symfony.com/src/Service/AnimalzRepository.php new file mode 100644 index 00000000000..18f60e29c4d --- /dev/null +++ b/ux.symfony.com/src/Service/AnimalzRepository.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace App\Service; + +use App\Enum\AnimalzType; +use App\Model\Animalz; + +class AnimalzRepository +{ + private const string DATA_FILE = __DIR__.'/data/animalz-properties.json'; + + /** @var list|null */ + private ?array $zanimalz = null; + + /** + * @return list + */ + public function findAll(): array + { + return $this->zanimalz ??= $this->loadZanimalz(); + } + + /** + * @return list + */ + public function findByNameAndTypeAndLegs(?string $name, ?AnimalzType $type, ?int $maxLegs): array + { + $zanimalz = $this->findAll(); + + if (null !== $name && '' !== $name) { + $zanimalz = array_filter( + $zanimalz, + fn (Animalz $animalz): bool => str_contains( + strtolower($animalz->name), + strtolower($name), + ), + ); + } + + if (null !== $type) { + $zanimalz = array_filter( + $zanimalz, + fn (Animalz $animalz): bool => $animalz->type1 === $type || $animalz->type2 === $type, + ); + } + + if (null !== $maxLegs) { + $zanimalz = array_filter( + $zanimalz, + fn (Animalz $animalz): bool => $animalz->legs <= $maxLegs, + ); + } + + $zanimalz = array_values($zanimalz); + usort($zanimalz, fn (Animalz $a, Animalz $b): int => $a->name <=> $b->name); + + return $zanimalz; + } + + public function getMaxLegs(): int + { + $zanimalz = $this->findAll(); + + return max(array_map(fn (Animalz $a): int => $a->legs, $zanimalz)); + } + + /** + * @return list + */ + private function loadZanimalz(): array + { + $content = file_get_contents(self::DATA_FILE); + + if (false === $content) { + return []; + } + + $data = json_decode($content, true, 512, \JSON_THROW_ON_ERROR); + + return array_map( + fn (array $item): Animalz => new Animalz( + $item['name'], + AnimalzType::from($item['type'][0]), + isset($item['type'][1]) ? AnimalzType::from($item['type'][1]) : null, + $item['legs'], + $item['description'], + ), + $data, + ); + } +} diff --git a/ux.symfony.com/src/Service/LiveDemoRepository.php b/ux.symfony.com/src/Service/LiveDemoRepository.php index c65a6a16f14..05d548db01d 100644 --- a/ux.symfony.com/src/Service/LiveDemoRepository.php +++ b/ux.symfony.com/src/Service/LiveDemoRepository.php @@ -21,6 +21,19 @@ class LiveDemoRepository public function findAll(): array { return [ + new LiveDemo( + identifier: 'animalz', + name: 'Facet Filtering', + description: 'Filter results based on a facet menu, with URL parameters.', + author: 'Nayte', + publishedAt: '2025-12-12', + tags: ['facets', 'filter', 'LiveAction'], + longDescription: <<<'EOF' + This demo showcases faceted search with two Live Components working together. + + Filter a list of animals by their **number of legs**, **weight**, or **natural habitat** using a dynamic facet menu that updates the results in real time. + EOF, + ), new LiveDemo( 'infinite-scroll-2', name: 'Infinite Scroll - 2/2', diff --git a/ux.symfony.com/src/Service/data/animalz-properties.json b/ux.symfony.com/src/Service/data/animalz-properties.json new file mode 100644 index 00000000000..8495c2c813f --- /dev/null +++ b/ux.symfony.com/src/Service/data/animalz-properties.json @@ -0,0 +1,806 @@ +[ + { + "name": "dog", + "type": ["NORMAL", "FIGHT"], + "legs": 4, + "description": "Loyal companion and versatile working animal." + }, + { + "name": "cat", + "type": ["NORMAL", "DARK"], + "legs": 4, + "description": "Independent and mysterious nocturnal hunter." + }, + { + "name": "horse", + "type": ["NORMAL"], + "legs": 4, + "description": "Powerful and graceful equine companion." + }, + { + "name": "cow", + "type": ["NORMAL"], + "legs": 4, + "description": "Gentle bovine providing milk and leather." + }, + { + "name": "elephant", + "type": ["NORMAL"], + "legs": 4, + "description": "Largest land mammal with incredible memory." + }, + { + "name": "giraffe", + "type": ["NORMAL"], + "legs": 4, + "description": "Tallest living terrestrial animal." + }, + { + "name": "lion", + "type": ["NORMAL", "FIGHT"], + "legs": 4, + "description": "King of the savanna and apex predator." + }, + { + "name": "tiger", + "type": ["NORMAL", "FIGHT"], + "legs": 4, + "description": "Striped jungle hunter and powerful swimmer." + }, + { + "name": "bear", + "type": ["NORMAL", "FIGHT"], + "legs": 4, + "description": "Powerful omnivore found across many habitats." + }, + { + "name": "wolf", + "type": ["NORMAL", "FIGHT"], + "legs": 4, + "description": "Social pack hunter with keen senses." + }, + { + "name": "fox", + "type": ["NORMAL", "DARK"], + "legs": 4, + "description": "Cunning nocturnal canine with bushy tail." + }, + { + "name": "rabbit", + "type": ["NORMAL"], + "legs": 4, + "description": "Fluffy herbivore known for rapid reproduction." + }, + { + "name": "deer", + "type": ["NORMAL"], + "legs": 4, + "description": "Graceful forest dweller with antlers." + }, + { + "name": "monkey", + "type": ["NORMAL"], + "legs": 4, + "description": "Intelligent primate with prehensile tail." + }, + { + "name": "gorilla", + "type": ["NORMAL", "FIGHT"], + "legs": 4, + "description": "Powerful great ape and gentle giant." + }, + { + "name": "hippopotamus", + "type": ["NORMAL", "WATER"], + "legs": 4, + "description": "Massive semi-aquatic African mammal." + }, + { + "name": "rhinoceros", + "type": ["NORMAL", "FIGHT"], + "legs": 4, + "description": "Armored herbivore with distinctive horn." + }, + { + "name": "zebra", + "type": ["NORMAL"], + "legs": 4, + "description": "Striped equine native to Africa." + }, + { + "name": "kangaroo", + "type": ["NORMAL", "FIGHT"], + "legs": 2, + "description": "Hopping marsupial with powerful legs." + }, + { + "name": "koala", + "type": ["NORMAL"], + "legs": 4, + "description": "Eucalyptus-eating Australian marsupial." + }, + { + "name": "panda", + "type": ["NORMAL"], + "legs": 4, + "description": "Bamboo-loving bear from China." + }, + { + "name": "snake", + "type": ["NORMAL", "POISON"], + "legs": 0, + "description": "Legless reptile with forked tongue." + }, + { + "name": "turtle", + "type": ["NORMAL", "WATER"], + "legs": 4, + "description": "Shelled reptile with slow pace." + }, + { + "name": "crocodile", + "type": ["NORMAL", "WATER"], + "legs": 4, + "description": "Ancient aquatic predator with powerful jaws." + }, + { + "name": "fly", + "type": ["BUG", "FLYING"], + "legs": 6, + "description": "Common flying insect with compound eyes." + }, + { + "name": "ant", + "type": ["BUG"], + "legs": 6, + "description": "Tiny but incredibly strong social insect." + }, + { + "name": "spider", + "type": ["BUG", "POISON"], + "legs": 8, + "description": "Eight-legged web-spinning predator." + }, + { + "name": "bee", + "type": ["BUG", "FLYING"], + "legs": 6, + "description": "Pollinating insect that produces honey." + }, + { + "name": "butterfly", + "type": ["BUG", "FLYING"], + "legs": 6, + "description": "Colorful winged insect with metamorphosis." + }, + { + "name": "mosquito", + "type": ["BUG", "FLYING"], + "legs": 6, + "description": "Blood-sucking flying pest." + }, + { + "name": "cockroach", + "type": ["BUG", "DARK"], + "legs": 6, + "description": "Resilient nocturnal scavenger insect." + }, + { + "name": "beetle", + "type": ["BUG"], + "legs": 6, + "description": "Hard-shelled insect in diverse forms." + }, + { + "name": "grasshopper", + "type": ["GRASS", "BUG"], + "legs": 6, + "description": "Jumping insect with powerful hind legs." + }, + { + "name": "dragonfly", + "type": ["BUG", "FLYING"], + "legs": 6, + "description": "Ancient aerial predator with four wings." + }, + { + "name": "ladybug", + "type": ["BUG", "FLYING"], + "legs": 6, + "description": "Spotted beetle beloved by gardeners." + }, + { + "name": "wasp", + "type": ["FLYING", "POISON"], + "legs": 6, + "description": "Stinging insect with narrow waist." + }, + { + "name": "millipede", + "type": ["BUG"], + "legs": 100, + "description": "Multi-legged arthropod that curls defensively." + }, + { + "name": "scorpion", + "type": ["FIGHT", "POISON"], + "legs": 8, + "description": "Venomous arachnid with curved tail." + }, + { + "name": "tick", + "type": ["BUG", "POISON"], + "legs": 8, + "description": "Blood-feeding parasitic arachnid." + }, + { + "name": "flea", + "type": ["BUG"], + "legs": 6, + "description": "Tiny jumping blood-sucking parasite." + }, + { + "name": "moth", + "type": ["BUG", "FLYING"], + "legs": 6, + "description": "Nocturnal cousin of the butterfly." + }, + { + "name": "cricket", + "type": ["BUG", "DARK"], + "legs": 6, + "description": "Chirping nocturnal jumping insect." + }, + { + "name": "caterpillar", + "type": ["BUG"], + "legs": 16, + "description": "Larval stage of butterflies and moths." + }, + { + "name": "firefly", + "type": ["BUG", "FLYING"], + "legs": 6, + "description": "Bioluminescent beetle lighting up nights." + }, + { + "name": "mantis", + "type": ["BUG", "FIGHT"], + "legs": 6, + "description": "Ambush predator with raptorial forelegs." + }, + { + "name": "cicada", + "type": ["BUG", "FLYING"], + "legs": 6, + "description": "Loud singing insect emerging periodically." + }, + { + "name": "whale", + "type": ["WATER"], + "legs": 0, + "description": "Largest animal ever to exist on Earth." + }, + { + "name": "dolphin", + "type": ["WATER"], + "legs": 0, + "description": "Intelligent and playful marine mammal." + }, + { + "name": "shark", + "type": ["WATER", "FIGHT"], + "legs": 0, + "description": "Apex ocean predator with keen senses." + }, + { + "name": "octopus", + "type": ["WATER", "DARK"], + "legs": 8, + "description": "Intelligent cephalopod with eight arms." + }, + { + "name": "jellyfish", + "type": ["WATER", "POISON"], + "legs": 24, + "description": "Translucent drifting cnidarian with stingers." + }, + { + "name": "starfish", + "type": ["WATER"], + "legs": 5, + "description": "Five-armed echinoderm that regenerates limbs." + }, + { + "name": "seahorse", + "type": ["WATER"], + "legs": 0, + "description": "Tiny fish where males carry offspring." + }, + { + "name": "crab", + "type": ["WATER"], + "legs": 10, + "description": "Sideways-walking crustacean with pincers." + }, + { + "name": "lobster", + "type": ["WATER"], + "legs": 10, + "description": "Large marine crustacean considered delicacy." + }, + { + "name": "shrimp", + "type": ["WATER"], + "legs": 10, + "description": "Small swimming crustacean in many cuisines." + }, + { + "name": "oyster", + "type": ["WATER"], + "legs": 0, + "description": "Pearl-producing bivalve mollusk." + }, + { + "name": "squid", + "type": ["WATER", "DARK"], + "legs": 10, + "description": "Fast-swimming cephalopod with ten arms." + }, + { + "name": "seal", + "type": ["WATER", "NORMAL"], + "legs": 4, + "description": "Playful pinniped found on rocky shores." + }, + { + "name": "walrus", + "type": ["WATER", "NORMAL"], + "legs": 4, + "description": "Tusked Arctic marine mammal." + }, + { + "name": "orca", + "type": ["WATER", "FIGHT"], + "legs": 0, + "description": "Apex predator also called killer whale." + }, + { + "name": "manatee", + "type": ["WATER", "GRASS"], + "legs": 2, + "description": "Gentle herbivorous sea cow." + }, + { + "name": "stingray", + "type": ["WATER", "POISON"], + "legs": 0, + "description": "Flat cartilaginous fish with venomous tail." + }, + { + "name": "eel", + "type": ["WATER", "DARK"], + "legs": 0, + "description": "Snake-like fish found in many waters." + }, + { + "name": "salmon", + "type": ["WATER"], + "legs": 0, + "description": "Migratory fish returning to spawn upstream." + }, + { + "name": "tuna", + "type": ["WATER"], + "legs": 0, + "description": "Fast-swimming pelagic fish." + }, + { + "name": "clownfish", + "type": ["WATER"], + "legs": 0, + "description": "Colorful reef fish living in anemones." + }, + { + "name": "swordfish", + "type": ["WATER"], + "legs": 0, + "description": "Large predatory fish with elongated bill." + }, + { + "name": "urchin", + "type": ["WATER", "POISON"], + "legs": 0, + "description": "Spiny spherical echinoderm." + }, + { + "name": "coral", + "type": ["WATER", "GRASS"], + "legs": 0, + "description": "Colonial marine invertebrate building reefs." + }, + { + "name": "pigeon", + "type": ["FLYING"], + "legs": 2, + "description": "Common urban bird with homing ability." + }, + { + "name": "eagle", + "type": ["FLYING", "FIGHT"], + "legs": 2, + "description": "Majestic raptor with powerful talons." + }, + { + "name": "owl", + "type": ["FLYING", "DARK"], + "legs": 2, + "description": "Nocturnal hunter with rotating head." + }, + { + "name": "parrot", + "type": ["FLYING"], + "legs": 2, + "description": "Colorful bird that can mimic speech." + }, + { + "name": "sparrow", + "type": ["FLYING"], + "legs": 2, + "description": "Small common songbird worldwide." + }, + { + "name": "crow", + "type": ["FLYING"], + "legs": 2, + "description": "Intelligent black bird using tools." + }, + { + "name": "seagull", + "type": ["FLYING", "WATER"], + "legs": 2, + "description": "Coastal bird known for scavenging." + }, + { + "name": "pelican", + "type": ["FLYING", "WATER"], + "legs": 2, + "description": "Large bird with expandable throat pouch." + }, + { + "name": "flamingo", + "type": ["FLYING", "WATER"], + "legs": 2, + "description": "Pink wading bird standing on one leg." + }, + { + "name": "swan", + "type": ["FLYING", "WATER"], + "legs": 2, + "description": "Elegant waterfowl symbolizing grace." + }, + { + "name": "duck", + "type": ["FLYING", "WATER"], + "legs": 2, + "description": "Dabbling waterfowl with waterproof feathers." + }, + { + "name": "goose", + "type": ["FLYING", "WATER"], + "legs": 2, + "description": "Migratory waterfowl flying in formation." + }, + { + "name": "chicken", + "type": ["NORMAL", "FLYING"], + "legs": 2, + "description": "Domesticated fowl raised for eggs and meat." + }, + { + "name": "rooster", + "type": ["NORMAL", "FIGHT"], + "legs": 2, + "description": "Male chicken known for crowing at dawn." + }, + { + "name": "turkey", + "type": ["NORMAL"], + "legs": 2, + "description": "Large game bird native to Americas." + }, + { + "name": "peacock", + "type": ["NORMAL"], + "legs": 2, + "description": "Colorful bird with spectacular tail display." + }, + { + "name": "penguin", + "type": ["WATER", "FLYING"], + "legs": 2, + "description": "Flightless bird adapted for swimming." + }, + { + "name": "ostrich", + "type": ["NORMAL", "FLYING"], + "legs": 2, + "description": "Largest living bird, flightless runner." + }, + { + "name": "hummingbird", + "type": ["FLYING"], + "legs": 2, + "description": "Tiny bird that hovers while feeding." + }, + { + "name": "woodpecker", + "type": ["FLYING"], + "legs": 2, + "description": "Bird that drums on trees for insects." + }, + { + "name": "toucan", + "type": ["FLYING"], + "legs": 2, + "description": "Tropical bird with oversized colorful bill." + }, + { + "name": "falcon", + "type": ["FLYING", "FIGHT"], + "legs": 2, + "description": "Fastest animal diving at incredible speeds." + }, + { + "name": "hawk", + "type": ["FLYING", "FIGHT"], + "legs": 2, + "description": "Sharp-eyed raptor hunting from above." + }, + { + "name": "vulture", + "type": ["FLYING"], + "legs": 2, + "description": "Scavenging bird cleaning up carcasses." + }, + { + "name": "bat", + "type": ["FLYING", "DARK"], + "legs": 2, + "description": "Only mammal capable of true flight." + }, + { + "name": "flytrap", + "type": ["GRASS", "FIGHT"], + "legs": 2, + "description": "Iconic carnivorous plant that snaps shut on prey." + }, + { + "name": "nepenthes", + "type": ["GRASS", "WATER"], + "legs": 1, + "description": "Passive trap plant with tube-shaped pitfall." + }, + { + "name": "sundew", + "type": ["GRASS", "DARK"], + "legs": 1, + "description": "Carnivorous plant with sticky tentacle-like leaves." + }, + { + "name": "rafflesia", + "type": ["GRASS", "POISON"], + "legs": 0, + "description": "Giant parasitic flower emitting rotting smell." + }, + { + "name": "titan", + "type": ["GRASS", "DARK"], + "legs": 1, + "description": "Massive flower smelling like decaying flesh." + }, + { + "name": "banyan", + "type": ["GRASS", "DARK"], + "legs": 100, + "description": "Tree that wraps and kills its host." + }, + { + "name": "cordyceps", + "type": ["GRASS", "POISON"], + "legs": 1, + "description": "Zombie fungus that controls insect minds." + }, + { + "name": "hydnellum", + "type": ["GRASS", "DARK"], + "legs": 1, + "description": "Fungus oozing blood-red droplets." + }, + { + "name": "clathrus", + "type": ["GRASS", "DARK"], + "legs": 5, + "description": "Tentacle-shaped fungus emerging from egg." + }, + { + "name": "dragon", + "type": ["FAIRY", "FOSSIL"], + "legs": 4, + "description": "Legendary fire-breathing winged reptile." + }, + { + "name": "unicorn", + "type": ["FAIRY"], + "legs": 4, + "description": "Magical horse with a single spiraling horn." + }, + { + "name": "phoenix", + "type": ["FAIRY", "FLYING"], + "legs": 2, + "description": "Immortal bird reborn from its own ashes." + }, + { + "name": "kraken", + "type": ["FAIRY", "WATER"], + "legs": 8, + "description": "Colossal sea monster dragging ships underwater." + }, + { + "name": "bigfoot", + "type": ["FAIRY"], + "legs": 2, + "description": "Elusive ape-like creature of North American forests." + }, + { + "name": "yeti", + "type": ["FAIRY"], + "legs": 2, + "description": "Abominable snowman of the Himalayas." + }, + { + "name": "nessie", + "type": ["FAIRY", "WATER"], + "legs": 4, + "description": "Legendary lake monster of Scottish Loch Ness." + }, + { + "name": "chupacabra", + "type": ["FAIRY", "DARK"], + "legs": 2, + "description": "Blood-sucking creature terrorizing livestock." + }, + { + "name": "mothman", + "type": ["FAIRY", "FLYING"], + "legs": 2, + "description": "Winged humanoid harbinger of disaster." + }, + { + "name": "jackalope", + "type": ["FAIRY"], + "legs": 4, + "description": "Antlered rabbit of American folklore." + }, + { + "name": "thunderbird", + "type": ["FAIRY", "FLYING"], + "legs": 2, + "description": "Giant bird creating storms with its wings." + }, + { + "name": "kelpie", + "type": ["FAIRY", "WATER"], + "legs": 4, + "description": "Shape-shifting water horse luring travelers." + }, + { + "name": "wendigo", + "type": ["FAIRY", "DARK"], + "legs": 2, + "description": "Cannibalistic spirit of frozen wilderness." + }, + { + "name": "basilisk", + "type": ["FAIRY", "POISON"], + "legs": 0, + "description": "Serpent king whose gaze turns victims to stone." + }, + { + "name": "marsupilami", + "type": ["FAIRY", "NORMAL"], + "legs": 4, + "description": "Long-tailed spotted creature from Palombia." + }, + { + "name": "tyrannosaurus", + "type": ["FOSSIL", "FIGHT"], + "legs": 2, + "description": "King of dinosaurs with massive jaws." + }, + { + "name": "velociraptor", + "type": ["FOSSIL", "FIGHT"], + "legs": 2, + "description": "Swift pack-hunting feathered predator." + }, + { + "name": "pterodactyl", + "type": ["FOSSIL", "FLYING"], + "legs": 2, + "description": "Flying reptile ruling prehistoric skies." + }, + { + "name": "mosasaurus", + "type": ["FOSSIL", "WATER"], + "legs": 4, + "description": "Massive marine lizard apex predator." + }, + { + "name": "triceratops", + "type": ["FOSSIL"], + "legs": 4, + "description": "Three-horned herbivore with bony frill." + }, + { + "name": "ammonite", + "type": ["FOSSIL", "WATER"], + "legs": 8, + "description": "Spiral-shelled ancient cephalopod." + }, + { + "name": "mammoth", + "type": ["FOSSIL", "NORMAL"], + "legs": 4, + "description": "Woolly elephant of the Ice Age." + }, + { + "name": "smilodon", + "type": ["FOSSIL", "FIGHT"], + "legs": 4, + "description": "Saber-toothed cat with elongated fangs." + }, + { + "name": "stegosaurus", + "type": ["FOSSIL"], + "legs": 4, + "description": "Plated dinosaur with spiked tail." + }, + { + "name": "ankylosaurus", + "type": ["FOSSIL"], + "legs": 4, + "description": "Armored dinosaur with club tail." + }, + { + "name": "brachiosaurus", + "type": ["FOSSIL"], + "legs": 4, + "description": "Long-necked giant reaching treetops." + }, + { + "name": "trilobite", + "type": ["FOSSIL", "WATER"], + "legs": 18, + "description": "Ancient armored arthropod of Paleozoic seas." + }, + { + "name": "dodo", + "type": ["FOSSIL", "FLYING"], + "legs": 2, + "description": "Flightless bird driven to extinction." + }, + { + "name": "megalodon", + "type": ["FOSSIL", "WATER"], + "legs": 0, + "description": "Colossal prehistoric shark with giant teeth." + }, + { + "name": "archaeopteryx", + "type": ["FOSSIL", "FLYING"], + "legs": 2, + "description": "Feathered dinosaur bridging reptiles and birds." + } +] diff --git a/ux.symfony.com/src/Twig/Components/Animalz/FacetMenu.php b/ux.symfony.com/src/Twig/Components/Animalz/FacetMenu.php new file mode 100644 index 00000000000..39ed7e23878 --- /dev/null +++ b/ux.symfony.com/src/Twig/Components/Animalz/FacetMenu.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace App\Twig\Components\Animalz; + +use App\Enum\AnimalzType; +use App\Service\AnimalzRepository; +use Symfony\UX\LiveComponent\Attribute\AsLiveComponent; +use Symfony\UX\LiveComponent\Attribute\LiveAction; +use Symfony\UX\LiveComponent\Attribute\LiveProp; +use Symfony\UX\LiveComponent\ComponentToolsTrait; +use Symfony\UX\LiveComponent\DefaultActionTrait; + +#[AsLiveComponent(name: 'Animalz:FacetMenu', template: 'components/Animalz/FacetMenu.html.twig')] +final class FacetMenu +{ + use ComponentToolsTrait; + use DefaultActionTrait; + + private const array EMITTABLE_PROPS = ['name', 'type', 'maxLegs']; + + #[LiveProp(writable: true, onUpdated: 'emitChange', url: true)] + public ?string $name = null; + + #[LiveProp(writable: true, onUpdated: 'emitChange', url: true)] + public ?AnimalzType $type = null; + + #[LiveProp(writable: true, onUpdated: 'emitChange', url: true)] + public ?int $maxLegs = null; + + public function __construct( + private readonly AnimalzRepository $animalzRepository, + ) { + } + + #[LiveAction] + public function reset(): void + { + $this->name = null; + $this->type = null; + $this->maxLegs = null; + + $this->emitChange(); + } + + public function emitChange(): void + { + $this->nullTheProps(); + $this->emit('facetSetted', $this->convertPropertiesToAssociativeArray()); + } + + /** @return list */ + public function getTypeChoices(): array + { + return AnimalzType::cases(); + } + + public function getLegsMax(): int + { + return $this->animalzRepository->getMaxLegs(); + } + + /** @return array */ + private function convertPropertiesToAssociativeArray(): array + { + $props = array_intersect_key( + get_object_vars($this), + array_flip(self::EMITTABLE_PROPS), + ); + + if ($props['type'] instanceof AnimalzType) { + $props['type'] = $props['type']->value; + } + + return $props; + } + + private function nullTheProps(): void + { + $this->name = '' === $this->name ? null : $this->name; + } +} diff --git a/ux.symfony.com/src/Twig/Components/Animalz/Results.php b/ux.symfony.com/src/Twig/Components/Animalz/Results.php new file mode 100644 index 00000000000..16c4a33f632 --- /dev/null +++ b/ux.symfony.com/src/Twig/Components/Animalz/Results.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace App\Twig\Components\Animalz; + +use App\Enum\AnimalzType; +use App\Model\Animalz; +use App\Service\AnimalzRepository; +use Symfony\UX\LiveComponent\Attribute\AsLiveComponent; +use Symfony\UX\LiveComponent\Attribute\LiveArg; +use Symfony\UX\LiveComponent\Attribute\LiveListener; +use Symfony\UX\LiveComponent\Attribute\LiveProp; +use Symfony\UX\LiveComponent\DefaultActionTrait; + +#[AsLiveComponent(name: 'Animalz:Results', template: 'components/Animalz/Results.html.twig')] +final class Results +{ + use DefaultActionTrait; + + #[LiveProp(url: true)] + public ?string $name = null; + + #[LiveProp(url: true)] + public ?AnimalzType $type = null; + + #[LiveProp(url: true)] + public ?int $maxLegs = null; + + public function __construct( + private readonly AnimalzRepository $animalzRepository, + ) { + } + + #[LiveListener('facetSetted')] + public function reload( + #[LiveArg] + ?string $name, + #[LiveArg] + ?string $type, + #[LiveArg] + ?int $maxLegs, + ): void { + $this->name = $name; + $this->type = null !== $type ? AnimalzType::tryFrom($type) : null; + $this->maxLegs = $maxLegs; + } + + /** @return Animalz[] */ + public function getResults(): array + { + return $this->animalzRepository->findByNameAndTypeAndLegs($this->name, $this->type, $this->maxLegs); + } +} diff --git a/ux.symfony.com/templates/components/Animalz/FacetMenu.html.twig b/ux.symfony.com/templates/components/Animalz/FacetMenu.html.twig new file mode 100644 index 00000000000..e54e25c4d69 --- /dev/null +++ b/ux.symfony.com/templates/components/Animalz/FacetMenu.html.twig @@ -0,0 +1,43 @@ +
+
+
+ Filters + +
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
diff --git a/ux.symfony.com/templates/components/Animalz/Results.html.twig b/ux.symfony.com/templates/components/Animalz/Results.html.twig new file mode 100644 index 00000000000..c049f8c1230 --- /dev/null +++ b/ux.symfony.com/templates/components/Animalz/Results.html.twig @@ -0,0 +1,21 @@ +
+
+ Results + {{ this.results|length }} +
+
+
+ {% for result in this.results %} + {% set color1 = result.type1.color %} + {% set color2 = result.type2 ? result.type2.color : null %} + {% set background = color2 is null + ? color1 + : 'linear-gradient(110deg, ' ~ color1 ~ ' 0%, ' ~ color1 ~ ' 40%, ' ~ color2 ~ ' 60%, ' ~ color2 ~ ' 100%)' + %} +
{{ result.name|capitalize }}
+ {% else %} +

No animalz found.

+ {% endfor %} +
+
+
diff --git a/ux.symfony.com/templates/demos/live_component/animalz.html.twig b/ux.symfony.com/templates/demos/live_component/animalz.html.twig new file mode 100644 index 00000000000..ab1150c7b30 --- /dev/null +++ b/ux.symfony.com/templates/demos/live_component/animalz.html.twig @@ -0,0 +1,20 @@ +{% extends 'demos/live_demo.html.twig' %} + +{% block demo_content %} +
+
+ +
+
+ +
+
+{% endblock %} + +{% block code_block_left %} + +{% endblock %} + +{% block code_block_right %} + +{% endblock %} From 9c2698f91787305bd704e00f2a5dde8203a93ac1 Mon Sep 17 00:00:00 2001 From: Nayte Date: Sat, 13 Dec 2025 20:32:59 +0100 Subject: [PATCH 2/3] [Minor][Site] typo on description --- ux.symfony.com/src/Service/LiveDemoRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ux.symfony.com/src/Service/LiveDemoRepository.php b/ux.symfony.com/src/Service/LiveDemoRepository.php index 05d548db01d..5ddf0d491e8 100644 --- a/ux.symfony.com/src/Service/LiveDemoRepository.php +++ b/ux.symfony.com/src/Service/LiveDemoRepository.php @@ -42,7 +42,7 @@ public function findAll(): array publishedAt: '2024-06-07', tags: ['grid', 'pagination', 'loading', 'scroll'], longDescription: << Date: Tue, 16 Dec 2025 16:48:07 +0100 Subject: [PATCH 3/3] [Site] Address PR review feedback - Use PascalCase for enum values (Normal instead of NORMAL) - Use named arguments in Animalz constructor - Cache this.results in template variable to avoid double call --- ux.symfony.com/src/Enum/AnimalzType.php | 20 +- .../src/Service/AnimalzRepository.php | 10 +- .../src/Service/data/animalz-properties.json | 268 +++++++++--------- .../components/Animalz/Results.html.twig | 5 +- 4 files changed, 152 insertions(+), 151 deletions(-) diff --git a/ux.symfony.com/src/Enum/AnimalzType.php b/ux.symfony.com/src/Enum/AnimalzType.php index 6c3f2d72768..6074152f4c9 100644 --- a/ux.symfony.com/src/Enum/AnimalzType.php +++ b/ux.symfony.com/src/Enum/AnimalzType.php @@ -15,16 +15,16 @@ enum AnimalzType: string { - case Normal = 'NORMAL'; - case Water = 'WATER'; - case Flying = 'FLYING'; - case Bug = 'BUG'; - case Fight = 'FIGHT'; - case Dark = 'DARK'; - case Poison = 'POISON'; - case Grass = 'GRASS'; - case Fairy = 'FAIRY'; - case Fossil = 'FOSSIL'; + case Normal = 'Normal'; + case Water = 'Water'; + case Flying = 'Flying'; + case Bug = 'Bug'; + case Fight = 'Fight'; + case Dark = 'Dark'; + case Poison = 'Poison'; + case Grass = 'Grass'; + case Fairy = 'Fairy'; + case Fossil = 'Fossil'; public function getColor(): string { diff --git a/ux.symfony.com/src/Service/AnimalzRepository.php b/ux.symfony.com/src/Service/AnimalzRepository.php index 18f60e29c4d..ca69287aac2 100644 --- a/ux.symfony.com/src/Service/AnimalzRepository.php +++ b/ux.symfony.com/src/Service/AnimalzRepository.php @@ -88,11 +88,11 @@ private function loadZanimalz(): array return array_map( fn (array $item): Animalz => new Animalz( - $item['name'], - AnimalzType::from($item['type'][0]), - isset($item['type'][1]) ? AnimalzType::from($item['type'][1]) : null, - $item['legs'], - $item['description'], + name: $item['name'], + type1: AnimalzType::from($item['type'][0]), + type2: isset($item['type'][1]) ? AnimalzType::from($item['type'][1]) : null, + legs: $item['legs'], + description: $item['description'], ), $data, ); diff --git a/ux.symfony.com/src/Service/data/animalz-properties.json b/ux.symfony.com/src/Service/data/animalz-properties.json index 8495c2c813f..d0bf0ec58b2 100644 --- a/ux.symfony.com/src/Service/data/animalz-properties.json +++ b/ux.symfony.com/src/Service/data/animalz-properties.json @@ -1,805 +1,805 @@ [ { "name": "dog", - "type": ["NORMAL", "FIGHT"], + "type": ["Normal", "Fight"], "legs": 4, "description": "Loyal companion and versatile working animal." }, { "name": "cat", - "type": ["NORMAL", "DARK"], + "type": ["Normal", "Dark"], "legs": 4, "description": "Independent and mysterious nocturnal hunter." }, { "name": "horse", - "type": ["NORMAL"], + "type": ["Normal"], "legs": 4, "description": "Powerful and graceful equine companion." }, { "name": "cow", - "type": ["NORMAL"], + "type": ["Normal"], "legs": 4, "description": "Gentle bovine providing milk and leather." }, { "name": "elephant", - "type": ["NORMAL"], + "type": ["Normal"], "legs": 4, "description": "Largest land mammal with incredible memory." }, { "name": "giraffe", - "type": ["NORMAL"], + "type": ["Normal"], "legs": 4, "description": "Tallest living terrestrial animal." }, { "name": "lion", - "type": ["NORMAL", "FIGHT"], + "type": ["Normal", "Fight"], "legs": 4, "description": "King of the savanna and apex predator." }, { "name": "tiger", - "type": ["NORMAL", "FIGHT"], + "type": ["Normal", "Fight"], "legs": 4, "description": "Striped jungle hunter and powerful swimmer." }, { "name": "bear", - "type": ["NORMAL", "FIGHT"], + "type": ["Normal", "Fight"], "legs": 4, "description": "Powerful omnivore found across many habitats." }, { "name": "wolf", - "type": ["NORMAL", "FIGHT"], + "type": ["Normal", "Fight"], "legs": 4, "description": "Social pack hunter with keen senses." }, { "name": "fox", - "type": ["NORMAL", "DARK"], + "type": ["Normal", "Dark"], "legs": 4, "description": "Cunning nocturnal canine with bushy tail." }, { "name": "rabbit", - "type": ["NORMAL"], + "type": ["Normal"], "legs": 4, "description": "Fluffy herbivore known for rapid reproduction." }, { "name": "deer", - "type": ["NORMAL"], + "type": ["Normal"], "legs": 4, "description": "Graceful forest dweller with antlers." }, { "name": "monkey", - "type": ["NORMAL"], + "type": ["Normal"], "legs": 4, "description": "Intelligent primate with prehensile tail." }, { "name": "gorilla", - "type": ["NORMAL", "FIGHT"], + "type": ["Normal", "Fight"], "legs": 4, "description": "Powerful great ape and gentle giant." }, { "name": "hippopotamus", - "type": ["NORMAL", "WATER"], + "type": ["Normal", "Water"], "legs": 4, "description": "Massive semi-aquatic African mammal." }, { "name": "rhinoceros", - "type": ["NORMAL", "FIGHT"], + "type": ["Normal", "Fight"], "legs": 4, "description": "Armored herbivore with distinctive horn." }, { "name": "zebra", - "type": ["NORMAL"], + "type": ["Normal"], "legs": 4, "description": "Striped equine native to Africa." }, { "name": "kangaroo", - "type": ["NORMAL", "FIGHT"], + "type": ["Normal", "Fight"], "legs": 2, "description": "Hopping marsupial with powerful legs." }, { "name": "koala", - "type": ["NORMAL"], + "type": ["Normal"], "legs": 4, "description": "Eucalyptus-eating Australian marsupial." }, { "name": "panda", - "type": ["NORMAL"], + "type": ["Normal"], "legs": 4, "description": "Bamboo-loving bear from China." }, { "name": "snake", - "type": ["NORMAL", "POISON"], + "type": ["Normal", "Poison"], "legs": 0, "description": "Legless reptile with forked tongue." }, { "name": "turtle", - "type": ["NORMAL", "WATER"], + "type": ["Normal", "Water"], "legs": 4, "description": "Shelled reptile with slow pace." }, { "name": "crocodile", - "type": ["NORMAL", "WATER"], + "type": ["Normal", "Water"], "legs": 4, "description": "Ancient aquatic predator with powerful jaws." }, { "name": "fly", - "type": ["BUG", "FLYING"], + "type": ["Bug", "Flying"], "legs": 6, "description": "Common flying insect with compound eyes." }, { "name": "ant", - "type": ["BUG"], + "type": ["Bug"], "legs": 6, "description": "Tiny but incredibly strong social insect." }, { "name": "spider", - "type": ["BUG", "POISON"], + "type": ["Bug", "Poison"], "legs": 8, "description": "Eight-legged web-spinning predator." }, { "name": "bee", - "type": ["BUG", "FLYING"], + "type": ["Bug", "Flying"], "legs": 6, "description": "Pollinating insect that produces honey." }, { "name": "butterfly", - "type": ["BUG", "FLYING"], + "type": ["Bug", "Flying"], "legs": 6, "description": "Colorful winged insect with metamorphosis." }, { "name": "mosquito", - "type": ["BUG", "FLYING"], + "type": ["Bug", "Flying"], "legs": 6, "description": "Blood-sucking flying pest." }, { "name": "cockroach", - "type": ["BUG", "DARK"], + "type": ["Bug", "Dark"], "legs": 6, "description": "Resilient nocturnal scavenger insect." }, { "name": "beetle", - "type": ["BUG"], + "type": ["Bug"], "legs": 6, "description": "Hard-shelled insect in diverse forms." }, { "name": "grasshopper", - "type": ["GRASS", "BUG"], + "type": ["Grass", "Bug"], "legs": 6, "description": "Jumping insect with powerful hind legs." }, { "name": "dragonfly", - "type": ["BUG", "FLYING"], + "type": ["Bug", "Flying"], "legs": 6, "description": "Ancient aerial predator with four wings." }, { "name": "ladybug", - "type": ["BUG", "FLYING"], + "type": ["Bug", "Flying"], "legs": 6, "description": "Spotted beetle beloved by gardeners." }, { "name": "wasp", - "type": ["FLYING", "POISON"], + "type": ["Flying", "Poison"], "legs": 6, "description": "Stinging insect with narrow waist." }, { "name": "millipede", - "type": ["BUG"], + "type": ["Bug"], "legs": 100, "description": "Multi-legged arthropod that curls defensively." }, { "name": "scorpion", - "type": ["FIGHT", "POISON"], + "type": ["Fight", "Poison"], "legs": 8, "description": "Venomous arachnid with curved tail." }, { "name": "tick", - "type": ["BUG", "POISON"], + "type": ["Bug", "Poison"], "legs": 8, "description": "Blood-feeding parasitic arachnid." }, { "name": "flea", - "type": ["BUG"], + "type": ["Bug"], "legs": 6, "description": "Tiny jumping blood-sucking parasite." }, { "name": "moth", - "type": ["BUG", "FLYING"], + "type": ["Bug", "Flying"], "legs": 6, "description": "Nocturnal cousin of the butterfly." }, { "name": "cricket", - "type": ["BUG", "DARK"], + "type": ["Bug", "Dark"], "legs": 6, "description": "Chirping nocturnal jumping insect." }, { "name": "caterpillar", - "type": ["BUG"], + "type": ["Bug"], "legs": 16, "description": "Larval stage of butterflies and moths." }, { "name": "firefly", - "type": ["BUG", "FLYING"], + "type": ["Bug", "Flying"], "legs": 6, "description": "Bioluminescent beetle lighting up nights." }, { "name": "mantis", - "type": ["BUG", "FIGHT"], + "type": ["Bug", "Fight"], "legs": 6, "description": "Ambush predator with raptorial forelegs." }, { "name": "cicada", - "type": ["BUG", "FLYING"], + "type": ["Bug", "Flying"], "legs": 6, "description": "Loud singing insect emerging periodically." }, { "name": "whale", - "type": ["WATER"], + "type": ["Water"], "legs": 0, "description": "Largest animal ever to exist on Earth." }, { "name": "dolphin", - "type": ["WATER"], + "type": ["Water"], "legs": 0, "description": "Intelligent and playful marine mammal." }, { "name": "shark", - "type": ["WATER", "FIGHT"], + "type": ["Water", "Fight"], "legs": 0, "description": "Apex ocean predator with keen senses." }, { "name": "octopus", - "type": ["WATER", "DARK"], + "type": ["Water", "Dark"], "legs": 8, "description": "Intelligent cephalopod with eight arms." }, { "name": "jellyfish", - "type": ["WATER", "POISON"], + "type": ["Water", "Poison"], "legs": 24, "description": "Translucent drifting cnidarian with stingers." }, { "name": "starfish", - "type": ["WATER"], + "type": ["Water"], "legs": 5, "description": "Five-armed echinoderm that regenerates limbs." }, { "name": "seahorse", - "type": ["WATER"], + "type": ["Water"], "legs": 0, "description": "Tiny fish where males carry offspring." }, { "name": "crab", - "type": ["WATER"], + "type": ["Water"], "legs": 10, "description": "Sideways-walking crustacean with pincers." }, { "name": "lobster", - "type": ["WATER"], + "type": ["Water"], "legs": 10, "description": "Large marine crustacean considered delicacy." }, { "name": "shrimp", - "type": ["WATER"], + "type": ["Water"], "legs": 10, "description": "Small swimming crustacean in many cuisines." }, { "name": "oyster", - "type": ["WATER"], + "type": ["Water"], "legs": 0, "description": "Pearl-producing bivalve mollusk." }, { "name": "squid", - "type": ["WATER", "DARK"], + "type": ["Water", "Dark"], "legs": 10, "description": "Fast-swimming cephalopod with ten arms." }, { "name": "seal", - "type": ["WATER", "NORMAL"], + "type": ["Water", "Normal"], "legs": 4, "description": "Playful pinniped found on rocky shores." }, { "name": "walrus", - "type": ["WATER", "NORMAL"], + "type": ["Water", "Normal"], "legs": 4, "description": "Tusked Arctic marine mammal." }, { "name": "orca", - "type": ["WATER", "FIGHT"], + "type": ["Water", "Fight"], "legs": 0, "description": "Apex predator also called killer whale." }, { "name": "manatee", - "type": ["WATER", "GRASS"], + "type": ["Water", "Grass"], "legs": 2, "description": "Gentle herbivorous sea cow." }, { "name": "stingray", - "type": ["WATER", "POISON"], + "type": ["Water", "Poison"], "legs": 0, "description": "Flat cartilaginous fish with venomous tail." }, { "name": "eel", - "type": ["WATER", "DARK"], + "type": ["Water", "Dark"], "legs": 0, "description": "Snake-like fish found in many waters." }, { "name": "salmon", - "type": ["WATER"], + "type": ["Water"], "legs": 0, "description": "Migratory fish returning to spawn upstream." }, { "name": "tuna", - "type": ["WATER"], + "type": ["Water"], "legs": 0, "description": "Fast-swimming pelagic fish." }, { "name": "clownfish", - "type": ["WATER"], + "type": ["Water"], "legs": 0, "description": "Colorful reef fish living in anemones." }, { "name": "swordfish", - "type": ["WATER"], + "type": ["Water"], "legs": 0, "description": "Large predatory fish with elongated bill." }, { "name": "urchin", - "type": ["WATER", "POISON"], + "type": ["Water", "Poison"], "legs": 0, "description": "Spiny spherical echinoderm." }, { "name": "coral", - "type": ["WATER", "GRASS"], + "type": ["Water", "Grass"], "legs": 0, "description": "Colonial marine invertebrate building reefs." }, { "name": "pigeon", - "type": ["FLYING"], + "type": ["Flying"], "legs": 2, "description": "Common urban bird with homing ability." }, { "name": "eagle", - "type": ["FLYING", "FIGHT"], + "type": ["Flying", "Fight"], "legs": 2, "description": "Majestic raptor with powerful talons." }, { "name": "owl", - "type": ["FLYING", "DARK"], + "type": ["Flying", "Dark"], "legs": 2, "description": "Nocturnal hunter with rotating head." }, { "name": "parrot", - "type": ["FLYING"], + "type": ["Flying"], "legs": 2, "description": "Colorful bird that can mimic speech." }, { "name": "sparrow", - "type": ["FLYING"], + "type": ["Flying"], "legs": 2, "description": "Small common songbird worldwide." }, { "name": "crow", - "type": ["FLYING"], + "type": ["Flying"], "legs": 2, "description": "Intelligent black bird using tools." }, { "name": "seagull", - "type": ["FLYING", "WATER"], + "type": ["Flying", "Water"], "legs": 2, "description": "Coastal bird known for scavenging." }, { "name": "pelican", - "type": ["FLYING", "WATER"], + "type": ["Flying", "Water"], "legs": 2, "description": "Large bird with expandable throat pouch." }, { "name": "flamingo", - "type": ["FLYING", "WATER"], + "type": ["Flying", "Water"], "legs": 2, "description": "Pink wading bird standing on one leg." }, { "name": "swan", - "type": ["FLYING", "WATER"], + "type": ["Flying", "Water"], "legs": 2, "description": "Elegant waterfowl symbolizing grace." }, { "name": "duck", - "type": ["FLYING", "WATER"], + "type": ["Flying", "Water"], "legs": 2, "description": "Dabbling waterfowl with waterproof feathers." }, { "name": "goose", - "type": ["FLYING", "WATER"], + "type": ["Flying", "Water"], "legs": 2, "description": "Migratory waterfowl flying in formation." }, { "name": "chicken", - "type": ["NORMAL", "FLYING"], + "type": ["Normal", "Flying"], "legs": 2, "description": "Domesticated fowl raised for eggs and meat." }, { "name": "rooster", - "type": ["NORMAL", "FIGHT"], + "type": ["Normal", "Fight"], "legs": 2, "description": "Male chicken known for crowing at dawn." }, { "name": "turkey", - "type": ["NORMAL"], + "type": ["Normal"], "legs": 2, "description": "Large game bird native to Americas." }, { "name": "peacock", - "type": ["NORMAL"], + "type": ["Normal"], "legs": 2, "description": "Colorful bird with spectacular tail display." }, { "name": "penguin", - "type": ["WATER", "FLYING"], + "type": ["Water", "Flying"], "legs": 2, "description": "Flightless bird adapted for swimming." }, { "name": "ostrich", - "type": ["NORMAL", "FLYING"], + "type": ["Normal", "Flying"], "legs": 2, "description": "Largest living bird, flightless runner." }, { "name": "hummingbird", - "type": ["FLYING"], + "type": ["Flying"], "legs": 2, "description": "Tiny bird that hovers while feeding." }, { "name": "woodpecker", - "type": ["FLYING"], + "type": ["Flying"], "legs": 2, "description": "Bird that drums on trees for insects." }, { "name": "toucan", - "type": ["FLYING"], + "type": ["Flying"], "legs": 2, "description": "Tropical bird with oversized colorful bill." }, { "name": "falcon", - "type": ["FLYING", "FIGHT"], + "type": ["Flying", "Fight"], "legs": 2, "description": "Fastest animal diving at incredible speeds." }, { "name": "hawk", - "type": ["FLYING", "FIGHT"], + "type": ["Flying", "Fight"], "legs": 2, "description": "Sharp-eyed raptor hunting from above." }, { "name": "vulture", - "type": ["FLYING"], + "type": ["Flying"], "legs": 2, "description": "Scavenging bird cleaning up carcasses." }, { "name": "bat", - "type": ["FLYING", "DARK"], + "type": ["Flying", "Dark"], "legs": 2, "description": "Only mammal capable of true flight." }, { "name": "flytrap", - "type": ["GRASS", "FIGHT"], + "type": ["Grass", "Fight"], "legs": 2, "description": "Iconic carnivorous plant that snaps shut on prey." }, { "name": "nepenthes", - "type": ["GRASS", "WATER"], + "type": ["Grass", "Water"], "legs": 1, "description": "Passive trap plant with tube-shaped pitfall." }, { "name": "sundew", - "type": ["GRASS", "DARK"], + "type": ["Grass", "Dark"], "legs": 1, "description": "Carnivorous plant with sticky tentacle-like leaves." }, { "name": "rafflesia", - "type": ["GRASS", "POISON"], + "type": ["Grass", "Poison"], "legs": 0, "description": "Giant parasitic flower emitting rotting smell." }, { "name": "titan", - "type": ["GRASS", "DARK"], + "type": ["Grass", "Dark"], "legs": 1, "description": "Massive flower smelling like decaying flesh." }, { "name": "banyan", - "type": ["GRASS", "DARK"], + "type": ["Grass", "Dark"], "legs": 100, "description": "Tree that wraps and kills its host." }, { "name": "cordyceps", - "type": ["GRASS", "POISON"], + "type": ["Grass", "Poison"], "legs": 1, "description": "Zombie fungus that controls insect minds." }, { "name": "hydnellum", - "type": ["GRASS", "DARK"], + "type": ["Grass", "Dark"], "legs": 1, "description": "Fungus oozing blood-red droplets." }, { "name": "clathrus", - "type": ["GRASS", "DARK"], + "type": ["Grass", "Dark"], "legs": 5, "description": "Tentacle-shaped fungus emerging from egg." }, { "name": "dragon", - "type": ["FAIRY", "FOSSIL"], + "type": ["Fairy", "Fossil"], "legs": 4, "description": "Legendary fire-breathing winged reptile." }, { "name": "unicorn", - "type": ["FAIRY"], + "type": ["Fairy"], "legs": 4, "description": "Magical horse with a single spiraling horn." }, { "name": "phoenix", - "type": ["FAIRY", "FLYING"], + "type": ["Fairy", "Flying"], "legs": 2, "description": "Immortal bird reborn from its own ashes." }, { "name": "kraken", - "type": ["FAIRY", "WATER"], + "type": ["Fairy", "Water"], "legs": 8, "description": "Colossal sea monster dragging ships underwater." }, { "name": "bigfoot", - "type": ["FAIRY"], + "type": ["Fairy"], "legs": 2, "description": "Elusive ape-like creature of North American forests." }, { "name": "yeti", - "type": ["FAIRY"], + "type": ["Fairy"], "legs": 2, "description": "Abominable snowman of the Himalayas." }, { "name": "nessie", - "type": ["FAIRY", "WATER"], + "type": ["Fairy", "Water"], "legs": 4, "description": "Legendary lake monster of Scottish Loch Ness." }, { "name": "chupacabra", - "type": ["FAIRY", "DARK"], + "type": ["Fairy", "Dark"], "legs": 2, "description": "Blood-sucking creature terrorizing livestock." }, { "name": "mothman", - "type": ["FAIRY", "FLYING"], + "type": ["Fairy", "Flying"], "legs": 2, "description": "Winged humanoid harbinger of disaster." }, { "name": "jackalope", - "type": ["FAIRY"], + "type": ["Fairy"], "legs": 4, "description": "Antlered rabbit of American folklore." }, { "name": "thunderbird", - "type": ["FAIRY", "FLYING"], + "type": ["Fairy", "Flying"], "legs": 2, "description": "Giant bird creating storms with its wings." }, { "name": "kelpie", - "type": ["FAIRY", "WATER"], + "type": ["Fairy", "Water"], "legs": 4, "description": "Shape-shifting water horse luring travelers." }, { "name": "wendigo", - "type": ["FAIRY", "DARK"], + "type": ["Fairy", "Dark"], "legs": 2, "description": "Cannibalistic spirit of frozen wilderness." }, { "name": "basilisk", - "type": ["FAIRY", "POISON"], + "type": ["Fairy", "Poison"], "legs": 0, "description": "Serpent king whose gaze turns victims to stone." }, { "name": "marsupilami", - "type": ["FAIRY", "NORMAL"], + "type": ["Fairy", "Normal"], "legs": 4, "description": "Long-tailed spotted creature from Palombia." }, { "name": "tyrannosaurus", - "type": ["FOSSIL", "FIGHT"], + "type": ["Fossil", "Fight"], "legs": 2, "description": "King of dinosaurs with massive jaws." }, { "name": "velociraptor", - "type": ["FOSSIL", "FIGHT"], + "type": ["Fossil", "Fight"], "legs": 2, "description": "Swift pack-hunting feathered predator." }, { "name": "pterodactyl", - "type": ["FOSSIL", "FLYING"], + "type": ["Fossil", "Flying"], "legs": 2, "description": "Flying reptile ruling prehistoric skies." }, { "name": "mosasaurus", - "type": ["FOSSIL", "WATER"], + "type": ["Fossil", "Water"], "legs": 4, "description": "Massive marine lizard apex predator." }, { "name": "triceratops", - "type": ["FOSSIL"], + "type": ["Fossil"], "legs": 4, "description": "Three-horned herbivore with bony frill." }, { "name": "ammonite", - "type": ["FOSSIL", "WATER"], + "type": ["Fossil", "Water"], "legs": 8, "description": "Spiral-shelled ancient cephalopod." }, { "name": "mammoth", - "type": ["FOSSIL", "NORMAL"], + "type": ["Fossil", "Normal"], "legs": 4, "description": "Woolly elephant of the Ice Age." }, { "name": "smilodon", - "type": ["FOSSIL", "FIGHT"], + "type": ["Fossil", "Fight"], "legs": 4, "description": "Saber-toothed cat with elongated fangs." }, { "name": "stegosaurus", - "type": ["FOSSIL"], + "type": ["Fossil"], "legs": 4, "description": "Plated dinosaur with spiked tail." }, { "name": "ankylosaurus", - "type": ["FOSSIL"], + "type": ["Fossil"], "legs": 4, "description": "Armored dinosaur with club tail." }, { "name": "brachiosaurus", - "type": ["FOSSIL"], + "type": ["Fossil"], "legs": 4, "description": "Long-necked giant reaching treetops." }, { "name": "trilobite", - "type": ["FOSSIL", "WATER"], + "type": ["Fossil", "Water"], "legs": 18, "description": "Ancient armored arthropod of Paleozoic seas." }, { "name": "dodo", - "type": ["FOSSIL", "FLYING"], + "type": ["Fossil", "Flying"], "legs": 2, "description": "Flightless bird driven to extinction." }, { "name": "megalodon", - "type": ["FOSSIL", "WATER"], + "type": ["Fossil", "Water"], "legs": 0, "description": "Colossal prehistoric shark with giant teeth." }, { "name": "archaeopteryx", - "type": ["FOSSIL", "FLYING"], + "type": ["Fossil", "Flying"], "legs": 2, "description": "Feathered dinosaur bridging reptiles and birds." } diff --git a/ux.symfony.com/templates/components/Animalz/Results.html.twig b/ux.symfony.com/templates/components/Animalz/Results.html.twig index c049f8c1230..0a97c052e5a 100644 --- a/ux.symfony.com/templates/components/Animalz/Results.html.twig +++ b/ux.symfony.com/templates/components/Animalz/Results.html.twig @@ -1,11 +1,12 @@ +{% set results = this.results %}
Results - {{ this.results|length }} + {{ results|length }}
- {% for result in this.results %} + {% for result in results %} {% set color1 = result.type1.color %} {% set color2 = result.type2 ? result.type2.color : null %} {% set background = color2 is null