{ "cells": [ { "cell_type": "markdown", "id": "690da69f-cf3d-40a9-b8e0-610339c859e9", "metadata": {}, "source": [ "# Icons" ] }, { "cell_type": "markdown", "id": "d5267848-fde6-4108-b7ff-be9e7303d0e4", "metadata": {}, "source": [ "Icons can be applied to both the `Title` of a `Panel` [widgets](./widgets.ipynb) and [commands](./commands.ipynb), providing more customization than `icon_class`." ] }, { "cell_type": "code", "execution_count": null, "id": "2b18ff57-b458-4b92-bbf3-0e660343d067", "metadata": { "tags": [] }, "outputs": [], "source": [ "from ipylab import Icon" ] }, { "cell_type": "markdown", "id": "5a05db60-7147-4466-b8e3-296e59204013", "metadata": {}, "source": [ "## SVG\n", "\n", "An icon requires both a _unique_ name, as well as an SVG string. There are some [guidelines](https://jupyterlab.readthedocs.io/en/stable/extension/ui_components.html#labicon-set-up-and-render-icons) for creating \"good\" icons. For example:\n", "- don't include the `` declaration\n", "- don't use `ids`\n", "- don't specify a `width` or `height`\n", " - ensures the icon can be used in a number of settings\n", "- use the `jp-icon*` classes on filled items\n", " - ensures the icon looks good on light and dark themes" ] }, { "cell_type": "code", "execution_count": null, "id": "a02c39d9-1284-4f84-b13f-d7028640c821", "metadata": { "tags": [] }, "outputs": [], "source": [ "SVG = \"\"\"\n", " \n", " \n", "\"\"\"" ] }, { "cell_type": "markdown", "id": "22c3c5a5-ae3c-435c-9f12-21e247cf80f3", "metadata": {}, "source": [ "Icons can be displayed directly, and sized with the `layout` member inherited from `ipywidgets.DOMWidget`." ] }, { "cell_type": "code", "execution_count": null, "id": "add039d5-35d7-44ee-a70e-7d9cf38f56eb", "metadata": { "tags": [] }, "outputs": [], "source": [ "icon = Icon(name=\"my-icon\", svgstr=SVG, layout=dict(width=\"32px\"))\n", "icon" ] }, { "cell_type": "markdown", "id": "2555a92e-3335-407d-8e8e-22d686794913", "metadata": {}, "source": [ "### More about `jp-icon` classes\n", "The interactive below isn't particuarly _robust_, but shows how the different `jp-icon-*` classes can be used." ] }, { "cell_type": "code", "execution_count": null, "id": "ccea8868-2d3e-454d-b3d5-15e16cf51f54", "metadata": { "tags": [] }, "outputs": [], "source": [ "from ipylab import Panel, JupyterFrontEnd\n", "from ipywidgets import SelectionSlider, FloatSlider, VBox\n", "from traitlets import dlink, link\n", "\n", "icon_prefix = [\"\", \"-accent\", \"-brand\", \"-contrast\", \"-warn\"]\n", "options = [\"\"] + [f\"jp-icon{sub}{i}\" for sub in icon_prefix for i in range(5)]\n", "background = SelectionSlider(description=\"background\", options=options)\n", "foreground = SelectionSlider(description=\"foreground\", options=options)\n", "\n", "repaint = lambda: SVG.replace(\"jp-icon3\", background.value).replace(\"jp-contrast0\", foreground.value)\n", "\n", "dlink((background, \"value\"), (icon, \"svgstr\"), lambda x: SVG.replace(\"jp-icon3\", x))\n", "dlink((foreground, \"value\"), (icon, \"svgstr\"), lambda x: SVG.replace(\"jp-contrast0\", x))\n", "size = FloatSlider(32, description=\"size\")\n", "dlink((size, \"value\"), (icon.layout, \"width\"), \"{}px\".format)\n", "icon_controls = VBox([background, foreground, size, icon])\n", "icon_controls" ] }, { "cell_type": "markdown", "id": "5f0a6742-3a3b-4879-8bb0-e675c80f03ed", "metadata": {}, "source": [ "## Icons on Panel Titles\n", "\n", "Once defined, an icon can be used on a panel title in place of `icon_class` " ] }, { "cell_type": "code", "execution_count": null, "id": "29a7cd8c-e26b-4a54-aca5-ae19fab2772d", "metadata": { "tags": [] }, "outputs": [], "source": [ "app = JupyterFrontEnd()\n", "panel = Panel([icon_controls])\n", "panel.title.icon = icon\n", "dlink((background, \"value\"), (panel.title, \"label\"))\n", "app.shell.add(panel, \"main\", {\"mode\": \"split-right\"})" ] }, { "cell_type": "markdown", "id": "f3018262-e383-4b8e-b0cb-b8cefd936d98", "metadata": {}, "source": [ "## Icons on Commands\n", "\n", "Icons can also assigned to [commands](./commands.ipynb) to provide additional context. " ] }, { "cell_type": "code", "execution_count": null, "id": "386a1149-26f9-4def-9eab-146baaebfdb3", "metadata": { "tags": [] }, "outputs": [], "source": [ "import asyncio\n", "import random\n", "\n", "async def randomize_icon():\n", " for i in range(10):\n", " background.value = random.choice(options)\n", " await asyncio.sleep(0.1)" ] }, { "cell_type": "code", "execution_count": null, "id": "5b16eaad-69e2-436c-a99a-d9e299977973", "metadata": { "tags": [] }, "outputs": [], "source": [ "app.commands.add_command(\n", " \"my-icon:randomize\",\n", " lambda: asyncio.get_running_loop().create_task(randomize_icon()),\n", " label=\"Randomize My Icon\",\n", " icon=icon\n", ")" ] }, { "cell_type": "markdown", "id": "dc396794-ee61-4af4-aac3-d303321eb04a", "metadata": {}, "source": [ "To see these, add the a _Command Palette_ with the same `command_id`:" ] }, { "cell_type": "code", "execution_count": null, "id": "82b36a75-235f-4ac1-92a5-b79131b480f1", "metadata": { "tags": [] }, "outputs": [], "source": [ "from ipylab.commands import CommandPalette\n", "\n", "palette = CommandPalette()\n", "palette.add_item(\"my-icon:randomize\", \"All My Commands\")" ] }, { "cell_type": "markdown", "id": "4d961ace-35da-4965-b529-703b69ce828b", "metadata": {}, "source": [ "Then open the _Command Palette_." ] }, { "cell_type": "code", "execution_count": null, "id": "0bcbb157-6741-446a-a04b-de8ad2dda74a", "metadata": { "tags": [] }, "outputs": [], "source": [ "app.commands.execute(\"apputils:activate-command-palette\")" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 5 }