Your first opening
A card opening needs three things from you: the cards, which of them are already opened, and somewhere on the page for a card to leave from. This page builds the smallest one that works, then swaps it for the whole hunt in one line.
What this page builds. Press the card.
Describe the cards
A card is an id and a rarity. The ready-made face also reads a name, a line of text and art, a pixel glyph from the set that ships or one you type out.
import { GLYPHS, type GlyphCard } from "@react-cards-opening/ui";
export const cards: GlyphCard[] = [
{
id: "storm-bolt",
rarity: "epic",
name: "Storm Bolt",
line: "Strikes the same place twice, on purpose.",
art: GLYPHS.bolt,
},
];Open one
import { useCardOpening, useOpenedCards } from "@react-cards-opening/core";
import { CardOpening } from "@react-cards-opening/ui";
import { useRef } from "react";
import "@react-cards-opening/ui/styles.css";
import { cards } from "./cards";
export function OpenACard() {
const button = useRef<HTMLButtonElement>(null);
// Which cards are opened, remembered on this device under this key.
const { opened, open } = useOpenedCards("my-deal");
// The rules: the queue, and what every press means.
const hunt = useCardOpening({ cards, opened, onOpen: open });
return (
<>
<button ref={button} onClick={() => hunt.start()} disabled={hunt.running || hunt.allOpened}>
{hunt.allOpened ? "All opened" : "Open a card"}
</button>
{/* The reveal. The card flies out of the button. */}
<CardOpening opening={hunt.opening} launch={() => button.current} />
</>
);
}useOpenedCardskeeps the list of opened ids in local storage. Passnullto keep it in memory, or bring your own state.useCardOpeningtakes the cards and that list.start()queues every card still unopened and opens them one after another.CardOpeningdraws it.launchanswers where the current card comes out of.
Give it somewhere to land
A card with nowhere to go fades out where it is. Name an element with landing and it shrinks into that instead: a slot in a collection, a counter, a tab.
<CardOpening
opening={hunt.opening}
launch={() => button.current}
landing={(card) => document.getElementById(`slot-${card.id}`)}
/>Or take the whole hunt
If hiding the cards in a grid and scanning for them is what you want, CardHunt is all of the above plus the grid, the scan button and the list of finds, in one component.
import { CardHunt } from "@react-cards-opening/ui";
<CardHunt cards={cards} opened={opened} onOpen={open} levels={levels} />5 cards are hiding in here.
Run the scan. Each card opens where the beam finds it.
- Still hidden
- Still hidden
- Still hidden
- Still hidden
- Still hidden
The same idea with five cards and somewhere to hide them.