{ "cells": [ { "cell_type": "raw", "metadata": {}, "source": [ "---\n", "description: CSS generation for button styling\n", "output-file: css.html\n", "title: CSS\n", "\n", "---\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "#| default_exp css" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "python" } }, "outputs": [ { "ename": "ModuleNotFoundError", "evalue": "No module named 'app_starter_gui'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[1], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m#| export\u001b[39;00m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;66;03m#| hide\u001b[39;00m\n\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mapp_starter_gui\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mcore\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m Button\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mfastcore\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mtest\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;241m*\u001b[39m \u001b[38;5;66;03m# for test_assert\u001b[39;00m\n", "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'app_starter_gui'" ] } ], "source": [ "#| export\n", "#| hide\n", "from operator import attrgetter\n", "from itertools import groupby\n", "from app_starter_gui.core import Button\n", "from fastcore.test import * # for test_assert" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "from nbdev.showdoc import show_doc" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "#| export\n", "def generate_css(buttons):\n", " \"\"\"Generate CSS styling for buttons with image backgrounds\n", " \n", " Args:\n", " buttons: List of Button objects\n", " Returns:\n", " str: CSS styling with unique button IDs and hover effects\n", " \n", " Each button gets:\n", " - 230px height (180px image + 50px label)\n", " - Hover animation with lift effect\n", " - Image zoom on hover\n", " - Rounded corners\n", " \"\"\"\n", " css_template = \"\"\"\n", " #{btn_id} {{ \n", " height: 230px; /* Total height of button */\n", " width: 200px;\n", " border-radius: 15px;\n", " display: flex;\n", " flex-direction: column;\n", " padding: 0;\n", " margin: 0;\n", " overflow: hidden;\n", " transition: transform 0.2s, box-shadow 0.2s;\n", " background: none;\n", " }}\n", " \n", " #{btn_id}::before {{\n", " content: '';\n", " height: 180px; /* Image height */\n", " width: 100%;\n", " background-size: cover;\n", " background-position: center center;\n", " background-repeat: no-repeat;\n", " background-image: url('{image_url}');\n", " transition: transform 0.2s;\n", " margin: 0;\n", " padding: 0;\n", " display: block;\n", " flex-shrink: 0;\n", " position: relative;\n", " top: 0;\n", " border-radius: 15px 15px 0 0; /* Round top corners only */\n", " }}\n", " \n", " #{btn_id}:hover {{\n", " transform: translateY(-5px);\n", " box-shadow: 0 5px 15px rgba(0,0,0,0.3);\n", " }}\n", "\n", " #{btn_id} > div {{\n", " height: 50px;\n", " display: flex;\n", " align-items: center;\n", " justify-content: center;\n", " }}\n", "\n", " #{btn_id}:hover::before {{\n", " transform: scale(1.05);\n", " }}\n", " \"\"\"\n", " \n", " all_css = []\n", " \n", " # Sort buttons by app_type to match the dashboard layout\n", " buttons = sorted(buttons, key=attrgetter('app_type'))\n", " button_groups = {k: list(g) for k, g in groupby(buttons, key=attrgetter('app_type'))}\n", " \n", " for app_type, type_buttons in button_groups.items():\n", " for button_idx, button in enumerate(type_buttons, 1):\n", " btn_id = f\"btn_{app_type}_{button_idx}\"\n", " css = css_template.format(btn_id=btn_id, image_url=button.image_url)\n", " all_css.append(css)\n", " \n", " return \"\\n\".join(all_css)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "python" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'Button' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[5], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# Example usage\u001b[39;00m\n\u001b[1;32m 2\u001b[0m buttons \u001b[38;5;241m=\u001b[39m [\n\u001b[0;32m----> 3\u001b[0m \u001b[43mButton\u001b[49m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAI App\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mimg.jpg\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhttps://ai.com\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAI\u001b[39m\u001b[38;5;124m\"\u001b[39m),\n\u001b[1;32m 4\u001b[0m Button(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSearch Engine\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mimg.jpg\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhttps://search.com\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSearch\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 5\u001b[0m ]\n\u001b[1;32m 7\u001b[0m css \u001b[38;5;241m=\u001b[39m generate_css(buttons)\n\u001b[1;32m 8\u001b[0m \u001b[38;5;28mprint\u001b[39m(css)\n", "\u001b[0;31mNameError\u001b[0m: name 'Button' is not defined" ] } ], "source": [ "# Example usage\n", "buttons = [\n", " Button(\"AI App\", \"img.jpg\", \"https://ai.com\", \"AI\"),\n", " Button(\"Search Engine\", \"img.jpg\", \"https://search.com\", \"Search\")\n", "]\n", "\n", "css = generate_css(buttons)\n", "print(css)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "python" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'Button' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[4], line 16\u001b[0m\n\u001b[1;32m 13\u001b[0m test(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m#btn2\u001b[39m\u001b[38;5;124m'\u001b[39m, css\u001b[38;5;241m.\u001b[39mlower(), \u001b[38;5;28;01mlambda\u001b[39;00m x,y: x \u001b[38;5;129;01min\u001b[39;00m y)\n\u001b[1;32m 14\u001b[0m test(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mgrid-template-columns\u001b[39m\u001b[38;5;124m'\u001b[39m, css, \u001b[38;5;28;01mlambda\u001b[39;00m x,y: x \u001b[38;5;129;01min\u001b[39;00m y)\n\u001b[0;32m---> 16\u001b[0m \u001b[43mtest_generate_css\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", "Cell \u001b[0;32mIn[4], line 8\u001b[0m, in \u001b[0;36mtest_generate_css\u001b[0;34m()\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mtest_generate_css\u001b[39m():\n\u001b[1;32m 6\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mTest CSS generation includes all app types\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 7\u001b[0m buttons \u001b[38;5;241m=\u001b[39m [\n\u001b[0;32m----> 8\u001b[0m \u001b[43mButton\u001b[49m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAI App\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mimg.jpg\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhttps://ai.com\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAI\u001b[39m\u001b[38;5;124m\"\u001b[39m),\n\u001b[1;32m 9\u001b[0m Button(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSearch\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mimg.jpg\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhttps://search.com\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSearch\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 10\u001b[0m ]\n\u001b[1;32m 11\u001b[0m css \u001b[38;5;241m=\u001b[39m generate_css(buttons)\n\u001b[1;32m 12\u001b[0m test(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m#btn1\u001b[39m\u001b[38;5;124m'\u001b[39m, css\u001b[38;5;241m.\u001b[39mlower(), \u001b[38;5;28;01mlambda\u001b[39;00m x,y: x \u001b[38;5;129;01min\u001b[39;00m y)\n", "\u001b[0;31mNameError\u001b[0m: name 'Button' is not defined" ] } ], "source": [ "#| export\n", "#| hide\n", "from fastcore.test import *\n", "\n", "def test_generate_css():\n", " \"Test CSS generation includes all app types\"\n", " buttons = [\n", " Button(\"AI App\", \"img.jpg\", \"https://ai.com\", \"AI\"),\n", " Button(\"Search\", \"img.jpg\", \"https://search.com\", \"Search\")\n", " ]\n", " css = generate_css(buttons)\n", " test('#btn_ai_1', css.lower(), lambda x,y: x in y)\n", " test('#btn_search_1', css.lower(), lambda x,y: x in y)\n", "\n", "test_generate_css()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "#| hide\n", "import nbdev; nbdev.nbdev_export()" ] } ], "metadata": { "kernelspec": { "display_name": "python3", "language": "python", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 2 }