--- title: Flip Card Component emoji: 🎴 colorFrom: blue colorTo: indigo sdk: gradio sdk_version: 6.18.0 python_version: '3.13' app_file: app.py pinned: true license: apache-2.0 short_description: Card matching game with emoji pairs and 3D card flips --- # 🎴 Flip Card A custom **Gradio HTML component** for a memory matching card game. Flip cards, find matching emoji pairs, use presets, add custom emojis, and track completed games. Inspired by [MatchWise](https://huggingface.co/spaces/build-small-hackathon/MatchWise). The original prototype was expanded into a reusable application and now includes a custom HTML component for improved interactivity and integration. --- ## Features * Built with `gr.HTML` * Smooth 3D card flip animation * Match and wrong-pair feedback * Preset and custom emoji input * Responsive grid up to 4×4 * Result output through `props.value` * Game history display --- ## Files Structure ```text . ├── app.py # Demo Gradio app ├── flip_card.py # Reusable FlipCard component ├── requirements.txt └── README.md ``` --- ## Install and Run ```bash pip install -r requirements.txt python app.py ``` Then open `http://127.0.0.1:7860` in your browser. --- ## Quick Start ```python import gradio as gr from flip_card import FlipCard with gr.Blocks() as demo: game = FlipCard() result = gr.Textbox(label="Result") game.change( fn=lambda value: value or "", inputs=game, outputs=result, ) demo.launch() ``` --- ## Usage with Presets, Custom Emojis, and History ```python import gradio as gr from flip_card import DEFAULT_EMOJIS, PRESETS, FlipCard, update_flip_card def on_win(result: str | None, history: list[str] | None): if not result: return "", "", history or [] history = (history or []) + [result] history_text = "\n".join( f"{i}. {item}" for i, item in enumerate(reversed(history[-10:]), start=1) ) return result, history_text, history def change_preset(name: str): emojis = PRESETS.get(name, DEFAULT_EMOJIS).copy() return ( update_flip_card(emojis=emojis), emojis, ",".join(emojis), "", ) def parse_emojis(text: str | None): emojis = [item.strip() for item in (text or "").split(",") if item.strip()] emojis = list(dict.fromkeys(emojis)) return emojis[:8] if len(emojis) >= 2 else DEFAULT_EMOJIS.copy() def apply_custom(text: str | None): emojis = parse_emojis(text) return update_flip_card(emojis=emojis), emojis, "" def new_game(emojis: list[str] | None): return update_flip_card(emojis=emojis or DEFAULT_EMOJIS.copy()), "" with gr.Blocks() as demo: game = FlipCard() result = gr.Textbox(label="Result", interactive=False) history_box = gr.Textbox(label="Game History", lines=6, interactive=False) preset = gr.Dropdown( label="Preset", choices=list(PRESETS.keys()), value="Fruits", ) custom = gr.Textbox( label="Custom Emojis", value="🍎,🍍", placeholder="Example: 🐶,🐱,🦊,🐼", ) apply_btn = gr.Button("Apply Custom Emojis") new_btn = gr.Button("New Shuffled Game") current_emojis = gr.State(DEFAULT_EMOJIS.copy()) history = gr.State([]) game.change( fn=on_win, inputs=[game, history], outputs=[result, history_box, history], ) preset.change( fn=change_preset, inputs=preset, outputs=[game, current_emojis, custom, result], ) apply_btn.click( fn=apply_custom, inputs=custom, outputs=[game, current_emojis, result], ) new_btn.click( fn=new_game, inputs=current_emojis, outputs=[game, result], ) demo.launch() ``` --- ## Component API ```python FlipCard( value=None, emojis=None, cards=None, cards_json=None, grid_cols=None, game_id=None, **kwargs ) ``` ### Parameters * `value`: Final winning message. * `emojis`: List of emojis used to create matching pairs. * `cards`: Pre-built shuffled card list. * `cards_json`: Internal JSON card state. * `grid_cols`: Number of grid columns. * `game_id`: Unique id used to reset frontend state. --- ## Presets ```python from flip_card import PRESETS ``` Available presets: * `Fruits` * `Animals` * `Space` * `Food` * `Nature` * `Challenge` --- ## Updating the Component Use `update_flip_card()` when changing cards from an event handler. ```python from flip_card import update_flip_card def change_game(): return update_flip_card(emojis=["🐶", "🐱", "🦊", "🐼"]) ``` Do not return a new `FlipCard()` instance from event handlers. --- ## License MIT