def fmt_icon(
    self: GTSelf,
    columns: SelectExpr = None,
    rows: int | list[int] | None = None,
    height: str | None = None,
    sep: str = " ",
    stroke_color: str | None = None,
    stroke_width: str | int | None = None,
    stroke_alpha: float | None = None,
    fill_color: str | dict[str, str] | None = None,
    fill_alpha: float | None = None,
    margin_left: str | None = None,
    margin_right: str | None = None,
) -> GTSelf:
    """Use icons within a table's body cells.

    We can draw from a library of thousands of icons and selectively insert them into a table. The
    `fmt_icon()` method makes this possible by mapping input cell labels to an icon name. We are
    exclusively using Font Awesome icons here so the reference is the short icon name. Multiple
    icons can be included per cell by separating icon names with commas (e.g.,
    `"hard-drive,clock"`). The `sep=` argument allows for a common separator to be applied between
    icons.

    Parameters
    ----------
    columns
        The columns to target. Can either be a single column name or a series of column names
        provided in a list.
    rows
        In conjunction with `columns=`, we can specify which of their rows should undergo
        formatting. The default is all rows, resulting in all rows in targeted columns being
        formatted. Alternatively, we can supply a list of row indices.
    height
        The absolute height of the icon in the table cell. By default, this is set to "1em".
    sep
        In the output of icons within a body cell, `sep=` provides the separator between each icon.
    stroke_color
        The icon stroke is essentially the outline of the icon. The color of the stroke can be
        modified by applying a single color here. If not provided then the default value of
        `"currentColor"` is applied so that the stroke color matches that of the parent HTML
        element's color attribute.
    stroke_width
        The `stroke_width=` option allows for setting the color of the icon outline stroke. By
        default, the stroke width is very small at "1px" so a size adjustment here can sometimes be
        useful. If an integer value is provided then it is assumed to be in pixels.
    stroke_alpha
        The level of transparency for the icon stroke can be controlled with a decimal value between
        `0` and `1`.
    fill_color
        The fill color of the icon can be set with `fill_color=`; providing a single color here will
        change the color of the fill but not of the icon's 'stroke' or outline (use `stroke_color=`
        to modify that). A dictionary comprising the icon names with corresponding fill colors can
        alternatively be used here (e.g., `{"circle-check" = "green", "circle-xmark" = "red"}`. If
        nothing is provided then the default value of `"currentColor"` is applied so that the fill
        matches the color of the parent HTML element's color attribute.
    fill_alpha
        The level of transparency for the icon fill can be controlled with a decimal value between
        `0` and `1`.
    margin_left
        The length value for the margin that's to the left of the icon. By default, `"auto"` is
        used for this but if space is needed on the left-hand side then a length of `"0.2em"` is
        recommended as a starting point.
    margin_right
        The length value for the margin right of the icon. By default, `"auto"` is used but if
        space is needed on the right-hand side then a length of `"0.2em"` is recommended as a
        starting point.

    Returns
    -------
    GT
        The GT object is returned. This is the same object that the method is called on so that we
        can facilitate method chaining.

    Examples
    --------
    For this first example of generating icons with `fmt_icon()`, let's make a simple DataFrame that
    has two columns of Font Awesome icon names. We separate multiple icons per cell with commas. By
    default, the icons are 1 em in height; we're going to make the icons slightly larger here (so we
    can see the fine details of them) by setting height = "4em".

    ```{python}
    import pandas as pd
    from great_tables import GT

    animals_foods_df = pd.DataFrame(
        {
            "animals": ["hippo", "fish,spider", "mosquito,locust,frog", "dog,cat", "kiwi-bird"],
            "foods": ["bowl-rice", "egg,pizza-slice", "burger,lemon,cheese", "carrot,hotdog", "bacon"],
        }
    )

    (
        GT(animals_foods_df)
        .fmt_icon(
            columns=["animals", "foods"],
            height="4em"
        )
        .cols_align(
            align="center",
            columns=["animals", "foods"]
        )
    )
    ```

    Let's take a few rows from the towny dataset and make it so the `csd_type` column contains
    *Font Awesome* icon names (we want only the `"city"` and `"house-chimney"` icons here). After
    using `fmt_icon()` to format the `csd_type` column, we get icons that are representative of the
    two categories of municipality for this subset of data.

    ```{python}
    import polars as pl
    from great_tables.data import towny

    towny_mini = (
        pl.from_pandas(towny.loc[[323, 14, 26, 235]])
        .select(["name", "csd_type", "population_2021"])
        .with_columns(
           csd_type = pl.when(pl.col("csd_type") == "town")
           .then(pl.lit("house-chimney"))
           .otherwise(pl.lit("city"))
        )
    )

    (
       GT(towny_mini)
       .fmt_integer(columns="population_2021")
       .fmt_icon(columns="csd_type")
       .cols_label(
           csd_type="",
           name="City/Town",
           population_2021="Population"
       )
    )
    ```

    A fairly common thing to do with icons in tables is to indicate whether a quantity is either
    higher or lower than another. Up and down arrow symbols can serve as good visual indicators for
    this purpose. We can make use of the `"up-arrow"` and `"down-arrow"` icons here. As those
    strings are available in the `dir` column of the table derived from the `sp500` dataset,
    `fmt_icon()` can be used. We set the `fill_color` argument with a dictionary that indicates
    which color should be used for each icon.

    ```{python}
    from great_tables.data import sp500

    sp500_mini = (
        pl.from_pandas(sp500)
        .head(10)
        .select(["date", "open", "close"])
        .sort("date", descending=False)
        .with_columns(
            dir = pl.when(pl.col("close") >= pl.col("open")).then(
                pl.lit("arrow-up")).otherwise(pl.lit("arrow-down"))
        )
    )

    (
        GT(sp500_mini, rowname_col="date")
        .fmt_icon(
            columns="dir",
            fill_color={"arrow-up": "green", "arrow-down": "red"}
        )
        .cols_label(
            open="Opening Value",
            close="Closing Value",
            dir=""
        )
        .opt_stylize(style=1, color="gray")
    )
    ```
    """

    formatter = FmtIcon(
        self._tbl_data,
        height=height,
        sep=sep,
        stroke_color=stroke_color,
        stroke_width=stroke_width,
        stroke_alpha=stroke_alpha,
        fill_color=fill_color,
        fill_alpha=fill_alpha,
        margin_left=margin_left,
        margin_right=margin_right,
    )

    return fmt(
        self,
        fns=FormatFns(html=formatter.to_html, latex=formatter.to_latex, default=formatter.to_html),
        columns=columns,
        rows=rows,
    )
Use icons within a table's body cells.

    We can draw from a library of thousands of icons and selectively insert them into a table. The
    `fmt_icon()` method makes this possible by mapping input cell labels to an icon name. We are
    exclusively using Font Awesome icons here so the reference is the short icon name. Multiple
    icons can be included per cell by separating icon names with commas (e.g.,
    `"hard-drive,clock"`). The `sep=` argument allows for a common separator to be applied between
    icons.

    Parameters
    ----------
    columns
        The columns to target. Can either be a single column name or a series of column names
        provided in a list.
    rows
        In conjunction with `columns=`, we can specify which of their rows should undergo
        formatting. The default is all rows, resulting in all rows in targeted columns being
        formatted. Alternatively, we can supply a list of row indices.
    height
        The absolute height of the icon in the table cell. By default, this is set to "1em".
    sep
        In the output of icons within a body cell, `sep=` provides the separator between each icon.
    stroke_color
        The icon stroke is essentially the outline of the icon. The color of the stroke can be
        modified by applying a single color here. If not provided then the default value of
        `"currentColor"` is applied so that the stroke color matches that of the parent HTML
        element's color attribute.
    stroke_width
        The `stroke_width=` option allows for setting the color of the icon outline stroke. By
        default, the stroke width is very small at "1px" so a size adjustment here can sometimes be
        useful. If an integer value is provided then it is assumed to be in pixels.
    stroke_alpha
        The level of transparency for the icon stroke can be controlled with a decimal value between
        `0` and `1`.
    fill_color
        The fill color of the icon can be set with `fill_color=`; providing a single color here will
        change the color of the fill but not of the icon's 'stroke' or outline (use `stroke_color=`
        to modify that). A dictionary comprising the icon names with corresponding fill colors can
        alternatively be used here (e.g., `{"circle-check" = "green", "circle-xmark" = "red"}`. If
        nothing is provided then the default value of `"currentColor"` is applied so that the fill
        matches the color of the parent HTML element's color attribute.
    fill_alpha
        The level of transparency for the icon fill can be controlled with a decimal value between
        `0` and `1`.
    margin_left
        The length value for the margin that's to the left of the icon. By default, `"auto"` is
        used for this but if space is needed on the left-hand side then a length of `"0.2em"` is
        recommended as a starting point.
    margin_right
        The length value for the margin right of the icon. By default, `"auto"` is used but if
        space is needed on the right-hand side then a length of `"0.2em"` is recommended as a
        starting point.

    Returns
    -------
    GT
        The GT object is returned. This is the same object that the method is called on so that we
        can facilitate method chaining.

    Examples
    --------
    For this first example of generating icons with `fmt_icon()`, let's make a simple DataFrame that
    has two columns of Font Awesome icon names. We separate multiple icons per cell with commas. By
    default, the icons are 1 em in height; we're going to make the icons slightly larger here (so we
    can see the fine details of them) by setting height = "4em".

    ```{python}
    import pandas as pd
    from great_tables import GT

    animals_foods_df = pd.DataFrame(
        {
            "animals": ["hippo", "fish,spider", "mosquito,locust,frog", "dog,cat", "kiwi-bird"],
            "foods": ["bowl-rice", "egg,pizza-slice", "burger,lemon,cheese", "carrot,hotdog", "bacon"],
        }
    )

    (
        GT(animals_foods_df)
        .fmt_icon(
            columns=["animals", "foods"],
            height="4em"
        )
        .cols_align(
            align="center",
            columns=["animals", "foods"]
        )
    )
    ```

    Let's take a few rows from the towny dataset and make it so the `csd_type` column contains
    *Font Awesome* icon names (we want only the `"city"` and `"house-chimney"` icons here). After
    using `fmt_icon()` to format the `csd_type` column, we get icons that are representative of the
    two categories of municipality for this subset of data.

    ```{python}
    import polars as pl
    from great_tables.data import towny

    towny_mini = (
        pl.from_pandas(towny.loc[[323, 14, 26, 235]])
        .select(["name", "csd_type", "population_2021"])
        .with_columns(
           csd_type = pl.when(pl.col("csd_type") == "town")
           .then(pl.lit("house-chimney"))
           .otherwise(pl.lit("city"))
        )
    )

    (
       GT(towny_mini)
       .fmt_integer(columns="population_2021")
       .fmt_icon(columns="csd_type")
       .cols_label(
           csd_type="",
           name="City/Town",
           population_2021="Population"
       )
    )
    ```

    A fairly common thing to do with icons in tables is to indicate whether a quantity is either
    higher or lower than another. Up and down arrow symbols can serve as good visual indicators for
    this purpose. We can make use of the `"up-arrow"` and `"down-arrow"` icons here. As those
    strings are available in the `dir` column of the table derived from the `sp500` dataset,
    `fmt_icon()` can be used. We set the `fill_color` argument with a dictionary that indicates
    which color should be used for each icon.

    ```{python}
    from great_tables.data import sp500

    sp500_mini = (
        pl.from_pandas(sp500)
        .head(10)
        .select(["date", "open", "close"])
        .sort("date", descending=False)
        .with_columns(
            dir = pl.when(pl.col("close") >= pl.col("open")).then(
                pl.lit("arrow-up")).otherwise(pl.lit("arrow-down"))
        )
    )

    (
        GT(sp500_mini, rowname_col="date")
        .fmt_icon(
            columns="dir",
            fill_color={"arrow-up": "green", "arrow-down": "red"}
        )
        .cols_label(
            open="Opening Value",
            close="Closing Value",
            dir=""
        )
        .opt_stylize(style=1, color="gray")
    )
    ```
    
great_tables/_formats.py