{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import panel as pn\n",
    "pn.extension()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The ``Card`` layout allows arranging multiple Panel objects in a collapsible, vertical container with a header bar. It has a list-like API with methods for interactively updating and modifying the layout, including ``append``, ``extend``, ``clear``, ``insert``, ``pop``, ``remove`` and ``__setitem__`` (for replacing the card's contents).\n",
    "\n",
    "`Card` components are very helpful for laying out components in a grid in a complex dashboard to make clear visual separations between different sections. The ability to collapse them can also be very useful to save space on a page with a lot of components.\n",
    "\n",
    "#### Parameters:\n",
    "\n",
    "* **``collapsed``** (bool): Whether the `Card` is collapsed.\n",
    "* **``collapsible``** (bool): Whether the `Card` can be expanded and collapsed.\n",
    "* **``header``** (Viewable): A Panel component to display in the header bar of the Card.\n",
    "* **``hide_header``** (bool): Whether to hide the `Card` header.\n",
    "* **``objects``** (list): The list of objects to display in the Card, which will be formatted like a `Column`. Should not generally be modified directly except when replaced in its entirety.\n",
    "* **``title``** (str): The title to display in the header bar if no explicit `header` is defined.\n",
    "\n",
    "Styling related parameters:\n",
    "\n",
    "* **``active_header_background``** (str): The background color of the header when the `Card` is expanded.\n",
    "* **``background``** (str): The background color of the content area.\n",
    "* **``header_color``** (str): The color of the header text.\n",
    "* **``button_css_classes``** (list[str]): The list of CSS classes to apply to the collapse button.\n",
    "* **``css_classes``** (list[str]): The list of CSS classes to apply to the main area.\n",
    "* **``header_background``** (str): The background color of the header.\n",
    "* **``header_css_classes``** (list[str]): The list of CSS classes to apply to the header.\n",
    "\n",
    "For details on other options for customizing the component see the [layout](../../how_to/layout/index.md) and [styling](../../how_to/styling/index.md) how-to guides.\n",
    "\n",
    "___"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A ``Card`` layout can either be instantiated as empty and populated after the fact, or by using a list of objects provided on instantiation as positional arguments. If the objects are not already Panel components they will each be converted to one using the ``pn.panel`` conversion method. Unlike the `Row` and `Column` layouts, a `Card` has an explicit `title` that will be shown in the header bar alongside the collapse button (if the `collapsible` parameter is enabled):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "w1 = pn.widgets.TextInput(name='Text:')\n",
    "w2 = pn.widgets.FloatSlider(name='Slider')\n",
    "\n",
    "card = pn.Card(w1, w2, title='Card', styles={'background': 'WhiteSmoke'})\n",
    "card"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The contents of the ``Card.objects`` list should never be modified individually, because Panel cannot detect when items in that list have changed internally, and will thus fail to update any already-rendered views of those objects. Instead, use the provided methods for adding and removing items from the list.  The only change that is safe to make directly to ``Card.objects`` is to replace the list of ``objects`` entirely.  As a simple example of using the methods, we might add an additional widget to the card using the append method:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "w3 = pn.widgets.Select(options=['A', 'B', 'C'])\n",
    "card.append(w3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "On a live server or in a notebook the `card` displayed after the previous code cell (above) will dynamically expand in size to accommodate all three widgets and the title. To see the effect in a statically rendered page, we will display the column a second time:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "card"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Whether the `Card` is collapsed or not can be controlled from Python and Javascript:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(card.collapsed)\n",
    "card.collapsed = True"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Header\n",
    "\n",
    "Instead of using a `title`, a `Card` may also be given an explicit `header` that can contain any component, e.g. in this case the Panel logo:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "logo = 'https://panel.holoviz.org/_static/logo_horizontal.png'\n",
    "\n",
    "red   = pn.Spacer(styles=dict(background='red'), height=50)\n",
    "green = pn.Spacer(styles=dict(background='green'), height=50)\n",
    "blue  = pn.Spacer(styles=dict(background='blue'), height=50)\n",
    "\n",
    "pn.Card(\n",
    "    red, green, blue,\n",
    "    header_background='#2f2f2f',\n",
    "    header_color='white',\n",
    "    header=pn.panel(logo, height=40),\n",
    "    width=300,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is also possible to render a `Card` entirely without a header:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pn.Card(\n",
    "    pn.indicators.Number(value=42, default_color='white', name='Completion', format='{value}%'),\n",
    "    styles={'background': 'lightgray'},\n",
    "    hide_header=True,\n",
    "    width=160\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Layout\n",
    "\n",
    "In general a ``Card`` does not have to be given an explicit ``width``, ``height``, or ``sizing_mode``, allowing it to adapt to the size of its contents. However in certain cases it can be useful to declare a fixed-size layout, which its responsively sized contents will then fill, making it possible to achieve equal spacing between multiple objects:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "red   = pn.Spacer(styles=dict(background='red'), sizing_mode='stretch_both')\n",
    "green = pn.Spacer(styles=dict(background='green'), sizing_mode='stretch_both')\n",
    "blue  = pn.Spacer(styles=dict(background='blue'), sizing_mode='stretch_both')\n",
    "\n",
    "pn.Card(red, green, blue, height=300, width=200, title='Fixed size')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When no fixed size is specified the column will expand to accommodate the sizing behavior of its contents:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from bokeh.plotting import figure\n",
    "\n",
    "p1 = figure(height=250, sizing_mode='stretch_width', margin=5)\n",
    "p2 = figure(height=250, sizing_mode='stretch_width', margin=5)\n",
    "\n",
    "p1.line([1, 2, 3], [1, 2, 3])\n",
    "p2.scatter([1, 2, 3], [1, 2, 3])\n",
    "\n",
    "pn.Card(p1, pn.layout.Divider(), p2, title=\"Responsive\", sizing_mode='stretch_width')"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
