Repository: matplotlib/matplotlib
Pull request: Tick label font family via tick_params
## PR Summary
Closes #18425.  Added a `labelfont` kwarg to change tick label fonts conveniently, without changing the rest of the text.
## PR Checklist

<!-- Please mark any checkboxes that do not apply to this PR as [N/A]. -->

**Documentation and Tests**
- [x] Has pytest style unit tests (and `pytest` passes)
- [ ] Documentation is sphinx and numpydoc compliant (the docs should [build](https://matplotlib.org/devel/documenting_mpl.html#building-the-docs) without error).
- [ ] New plotting related features are documented with examples.

**Release Notes**
- [ ] New features are marked with a `.. versionadded::` directive in the docstring and documented in `doc/users/next_whats_new/`
- [ ] API changes are marked with a `.. versionchanged::` directive in the docstring and documented in `doc/api/next_api_changes/`
- [ ] Release notes conform with instructions in  `next_whats_new/README.rst` or `next_api_changes/README.rst`

<!--
Thank you so much for your PR!  To help us review your contribution, please
consider the following points:

- A development guide is available at https://matplotlib.org/devdocs/devel/index.html.

- Help with git and github is available at
  https://matplotlib.org/devel/gitwash/development_workflow.html.

- Create a separate branch for your changes and open the PR from this branch. Please avoid working on `main`.

- The PR title should summarize the changes, for example "Raise ValueError on
  non-numeric input to set_xlim".  Avoid non-descriptive titles such as
  "Addresses issue #8576".

- The summary should provide at least 1-2 sentences describing the pull request
  in detail (Why is this change required?  What problem does it solve?) and
  link to any relevant issues.

- If you are contributing fixes to docstrings, please pay attention to
  https://matplotlib.org/stable/devel/documenting_mpl.html#formatting-conventions.  In particular,
  note the difference between using single backquotes, double backquotes, and
  asterisks in the markup.

We understand that PRs can sometimes be overwhelming, especially as the
reviews start coming in.  Please let us know if the reviews are unclear or
the recommended next step seems overly demanding, if you would like help in
addressing a reviewer's comments, or if you have been waiting too long to hear
back on your PR.
-->


Problem statement:
Add fontfamily/labelfont to tick_params
<!--
Welcome! Thanks for thinking of a way to improve Matplotlib.


Before creating a new feature request please search the issues for relevant feature requests.
-->

### Problem

There is no simple way of assigning a fontfamily to tick labels without needing to either override the default fontfamily or set_x/yticklabels. We currently have access to color and size, kwarg to change the font would fit here nicely.
<!--

For example:
* I'm always frustrated when [...] because [...]
* I would like it if [...] happened when I [...] because [...]
* Here is a sample image of what I am asking for [...]
-->

### Proposed Solution

Add a fontfamily/labelfont kwarg to tick_params 

<!-- Provide a clear and concise description of a way to accomplish what you want. For example:

* Add an option so that when [...]  [...] will happen
 -->



<!-- Add any other context or screenshots about the feature request here. You can also include links to examples of other programs that have something similar to your request. For example:

* Another project [...] solved this by [...]
-->

Hints from issue discussion:
It doesn't look like anyone is working on this, so I'll try it out.
Pull request currently in review: https://github.com/matplotlib/matplotlib/pull/19110

Commit message: Tick label font family via tick_params

Patch to review:
diff --git a/doc/users/next_whats_new/tick_labelfont_param.rst b/doc/users/next_whats_new/tick_labelfont_param.rst
new file mode 100644
index 000000000000..b7d9877f542c
--- /dev/null
+++ b/doc/users/next_whats_new/tick_labelfont_param.rst
@@ -0,0 +1,8 @@
+Allow setting the tick label fonts with a keyword argument
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+``Axes.tick_params`` now accepts a *labelfontfamily* keyword that changes the tick
+label font separately from the rest of the text objects:
+
+.. code-block:: python
+
+    Axis.tick_params(labelfontfamily*='monospace')
diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py
index 2c3d93fa8d8d..25fba4951a62 100644
--- a/lib/matplotlib/axes/_base.py
+++ b/lib/matplotlib/axes/_base.py
@@ -3337,6 +3337,8 @@ def tick_params(self, axis='both', **kwargs):
             Tick label font size in points or as a string (e.g., 'large').
         labelcolor : color
             Tick label color.
+        labelfontfamily : str
+            Tick label font.
         colors : color
             Tick color and label color.
         zorder : float
diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py
index eb393f89882d..04f9730cb7f2 100644
--- a/lib/matplotlib/axis.py
+++ b/lib/matplotlib/axis.py
@@ -64,6 +64,7 @@ def __init__(
         pad=None,
         labelsize=None,
         labelcolor=None,
+        labelfontfamily=None,
         zorder=None,
         gridOn=None,  # defaults to axes.grid depending on axes.grid.which
         tick1On=True,
@@ -174,11 +175,11 @@ def __init__(
         self.label1 = mtext.Text(
             np.nan, np.nan,
             fontsize=labelsize, color=labelcolor, visible=label1On,
-            rotation=self._labelrotation[1])
+            fontfamily=labelfontfamily, rotation=self._labelrotation[1])
         self.label2 = mtext.Text(
             np.nan, np.nan,
             fontsize=labelsize, color=labelcolor, visible=label2On,
-            rotation=self._labelrotation[1])
+            fontfamily=labelfontfamily, rotation=self._labelrotation[1])
 
         self._apply_tickdir(tickdir)
 
@@ -376,7 +377,7 @@ def _apply_params(self, **kwargs):
             self.label2.set(rotation=self._labelrotation[1])
 
         label_kw = {k[5:]: v for k, v in kwargs.items()
-                    if k in ['labelsize', 'labelcolor']}
+                    if k in ['labelsize', 'labelcolor', 'labelfontfamily']}
         self.label1.set(**label_kw)
         self.label2.set(**label_kw)
 
@@ -1036,7 +1037,7 @@ def _translate_tick_params(kw, reverse=False):
         # The following lists may be moved to a more accessible location.
         allowed_keys = [
             'size', 'width', 'color', 'tickdir', 'pad',
-            'labelsize', 'labelcolor', 'zorder', 'gridOn',
+            'labelsize', 'labelcolor', 'labelfontfamily', 'zorder', 'gridOn',
             'tick1On', 'tick2On', 'label1On', 'label2On',
             'length', 'direction', 'left', 'bottom', 'right', 'top',
             'labelleft', 'labelbottom', 'labelright', 'labeltop',
diff --git a/lib/matplotlib/axis.pyi b/lib/matplotlib/axis.pyi
index 28b0d0507497..e31a6a34d5b7 100644
--- a/lib/matplotlib/axis.pyi
+++ b/lib/matplotlib/axis.pyi
@@ -8,7 +8,7 @@ from matplotlib.ticker import Locator, Formatter
 from matplotlib.transforms import Transform, Bbox
 
 import datetime
-from collections.abc import Callable, Iterable
+from collections.abc import Callable, Iterable, Sequence
 from typing import Any, Literal
 import numpy as np
 from numpy.typing import ArrayLike
@@ -36,6 +36,7 @@ class Tick(martist.Artist):
         pad: float | None = ...,
         labelsize: float | None = ...,
         labelcolor: ColorType | None = ...,
+        labelfontfamily: str | Sequence[str] | None = ...,
         zorder: float | None = ...,
         gridOn: bool | None = ...,
         tick1On: bool = ...,
diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py
index 0050f0b9c0ea..6106945c2531 100644
--- a/lib/matplotlib/tests/test_axes.py
+++ b/lib/matplotlib/tests/test_axes.py
@@ -8589,3 +8589,14 @@ def test_fill_between_axes_limits():
                     color='green', alpha=0.5, transform=ax.get_xaxis_transform())
 
     assert (ax.get_xlim(), ax.get_ylim()) == original_lims
+
+
+def test_tick_param_labelfont():
+    fig, ax = plt.subplots()
+    ax.plot([1, 2, 3, 4], [1, 2, 3, 4])
+    ax.set_xlabel('X label in Impact font', fontname='Impact')
+    ax.set_ylabel('Y label in Humor Sans', fontname='Humor Sans')
+    ax.tick_params(color='r', labelfontfamily='monospace')
+    plt.title('Title in sans-serif')
+    for text in ax.get_xticklabels():
+        assert text.get_fontfamily()[0] == 'monospace'


Code review comments:
diff_hunk: @@ -0,0 +1,8 @@
+Allow setting the tick label fonts with a keyword argument
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+``Axes.tick_params`` now accepts a *labelfontfamily* keyword that changes the tick
+label font separately from the rest of the text objects:
+
+.. code-block:: python
+
+    Axis.tick_params(labelfontfamily*='monospace')
path: doc/users/next_whats_new/tick_labelfont_param.rst
text: @user1:
```suggestion
    Axis.tick_params(labelfontfamily='monospace')
```

errant `*` here