diff --git a/docs/model_card.rst b/docs/model_card.rst
index 0128a5e0..0afdb7d2 100644
--- a/docs/model_card.rst
+++ b/docs/model_card.rst
@@ -113,6 +113,19 @@ using :meth:`.Card.select`, and you can delete sections using
To see how you can use the API in ``skops`` to create a model card, please
refer to :ref:`sphx_glr_auto_examples_plot_model_card.py`.
+You can also fold sections after adding them to the model card. This is useful
+if you have a lot of content in a section that you don't want to show by
+default. To fold a section, you can use the :attr:`.Section.folded` property:
+
+.. code-block:: python
+
+ section = card.select("Model description/Figures")
+ section.folded = True
+
+After setting :attr:`.Section.folded` to ``True``, the section will be collapsed by default
+when the model card is rendered.
+
+
Saving and Loading Model Cards
------------------------------
diff --git a/skops/card/_model_card.py b/skops/card/_model_card.py
index 32ba9b8c..12fc2057 100644
--- a/skops/card/_model_card.py
+++ b/skops/card/_model_card.py
@@ -207,6 +207,7 @@ class Section:
content: str
subsections: dict[str, Section] = field(default_factory=dict)
visible: bool = True
+ folded: bool = False
def select(self, key: str) -> Section:
"""Return a subsection or subsubsection of this section
@@ -243,7 +244,7 @@ def select(self, key: str) -> Section:
return section
def format(self) -> str:
- return self.content
+ return wrap_as_details(self.content, folded=self.folded)
def __repr__(self) -> str:
"""Generates the ``repr`` of this section.
@@ -1343,7 +1344,7 @@ def _generate_content(
if destination_path is not None and isinstance(section, PlotSection):
shutil.copy(section.path, destination_path)
- if section.subsections:
+ if section.subsections and not section.folded:
yield from self._generate_content(
section.subsections,
depth=depth + 1,
diff --git a/skops/card/tests/test_card.py b/skops/card/tests/test_card.py
index 9e625852..def12589 100644
--- a/skops/card/tests/test_card.py
+++ b/skops/card/tests/test_card.py
@@ -1918,6 +1918,50 @@ def test_toc_with_invisible_section(self, card):
assert toc == "\n".join(exptected_toc)
+class TestFoldedSection:
+ def test_folded_section(self, destination_path, model_card):
+ model_card.add(foo="Foo")
+ model_card.add(**{"foo/bar": "Foo/Bar", "foo/baz": "Foo/Baz"})
+ model_card.select("foo/baz").folded = True
+
+ foo_details = (
+ "\n Click to expand
\n\nFoo\n\n \n"
+ )
+ foo_bar_details = (
+ "\n Click to expand
\n\nFoo/Bar\n\n \n"
+ )
+ foo_baz_details = (
+ "\n Click to expand
\n\nFoo/Baz\n\n \n"
+ )
+
+ output = model_card.render()
+ assert foo_details not in output
+ assert foo_bar_details not in output
+ assert foo_baz_details in output
+
+ model_card.select("foo").folded = True
+
+ output = model_card.render()
+ assert foo_details in output
+ assert foo_bar_details not in output
+ assert foo_baz_details not in output
+
+ model_card.select("foo").folded = False
+
+ output = model_card.render()
+ assert foo_details not in output
+ assert foo_bar_details not in output
+ assert foo_baz_details in output
+
+ model_card.select("foo/bar").folded = True
+ model_card.select("foo/baz").folded = False
+
+ output = model_card.render()
+ assert foo_details not in output
+ assert foo_bar_details in output
+ assert foo_baz_details not in output
+
+
class TestCardSaveWithPlots:
def test_copy_plots(self, destination_path, model_card):
import matplotlib.pyplot as plt