Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 63 additions & 1 deletion doc/_static/altair-gallery.css
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,69 @@ div.bottomnav {
min-width: 140px;
}

.gallery .image {
box-shadow:
0 0 10px rgba(110, 116, 124, 0.35),
0 0 20px rgba(110, 116, 124, 0.2);
transition: background-position 2s, box-shadow 200ms ease;
}

.gallery .image:hover {
box-shadow:
0 0 14px rgba(110, 116, 124, 0.5),
0 0 28px rgba(110, 116, 124, 0.3);
}

.gallery .imagegroup-new .image {
box-shadow:
0 0 14px rgba(255, 143, 63, 0.56),
0 0 28px rgba(255, 143, 63, 0.38);
}

.gallery .imagegroup-new .image:hover {
box-shadow:
0 0 17px rgba(255, 143, 63, 0.7),
0 0 34px rgba(255, 143, 63, 0.45);
}

.gallery .imagegroup-recent .image:hover {
box-shadow:
0 0 17px rgba(255, 143, 63, 0.7),
0 0 34px rgba(255, 143, 63, 0.45);
}

.gallery .image-tag {
position: absolute;
top: 8px;
left: 8px;
z-index: 2;
padding: 2px 8px;
border-radius: 999px;
font-size: 0.72rem;
font-weight: 700;
line-height: 1.3;
letter-spacing: 0.02em;
text-transform: uppercase;
color: #ffffff;
background: linear-gradient(135deg, #f46f2b 0%, #ff8f3f 100%);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.22);
}

.gallery-inline-tag {
display: inline-block;
padding: 2px 8px;
border-radius: 999px;
font-size: 0.72rem;
font-weight: 700;
line-height: 1.3;
letter-spacing: 0.02em;
text-transform: uppercase;
color: #ffffff;
background: linear-gradient(135deg, #f46f2b 0%, #ff8f3f 100%);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.22);
vertical-align: center;
}

.gallery .imagegroup:hover {
text-decoration: none;
}
Expand All @@ -134,7 +197,6 @@ div.bottomnav {
background-repeat: no-repeat;
margin-bottom: 5px;
overflow: hidden;
transition: background-position 2s;
}
.gallery .image:hover {
background-position: right bottom;
Expand Down
51 changes: 47 additions & 4 deletions sphinxext/altairgallery.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,40 @@
This change also introduced updated column names in some datasets (e.g., spaces
instead of underscores).

{% if recent_examples %}

.. _gallery-category-recently-added:

.. |gallery-new-pill| raw:: html

<span class="gallery-inline-tag">new</span>

Recently Added |gallery-new-pill|
~~~~~~~~~~~~~~

.. raw:: html

<span class="gallery">
{% for example in recent_examples %}
<a class="imagegroup{% if example['is_new'] %} imagegroup-recent{% endif %}" href="{{ example.name }}.html">
<span
class="image" alt="{{ example.title }}"
{% if example['use_svg'] %}
style="background-image: url(..{{ image_dir }}/{{ example.name }}-thumb.svg);"
{% else %}
style="background-image: url(..{{ image_dir }}/{{ example.name }}-thumb.png);"
{% endif %}
></span>

<span class="image-title">{{ example.title }}</span>
</a>
{% endfor %}
</span>

<div style='clear:both;'></div>

{% endif %}

{% for grouper, group in examples %}

.. _gallery-category-{{ grouper }}:
Expand All @@ -70,9 +104,12 @@

<span class="gallery">
{% for example in group %}
<a class="imagegroup" href="{{ example.name }}.html">
<a class="imagegroup{% if example['is_new'] %} imagegroup-new{% endif %}" href="{{ example.name }}.html">
{% if example['is_new'] %}
<span class="image-tag">new</span>
{% endif %}
<span
class="image" alt="{{ example.title }}"
class="image" alt="{{ example.title }}"
{% if example['use_svg'] %}
style="background-image: url(..{{ image_dir }}/{{ example.name }}-thumb.svg);"
{% else %}
Expand Down Expand Up @@ -227,9 +264,11 @@ def populate_examples(**kwds: Any) -> list[dict[str, Any]]:
method_examples = {x["name"]: x for x in iter_examples_methods_syntax()}

for example in examples:
docstring, category, code, lineno = get_docstring_and_rest(example["filename"])
docstring, category, code, lineno, is_new = get_docstring_and_rest(
example["filename"]
)
if example["name"] in method_examples:
_, _, method_code, _ = get_docstring_and_rest(
_, _, method_code, _, _ = get_docstring_and_rest(
method_examples[example["name"]]["filename"]
)
else:
Expand All @@ -250,6 +289,7 @@ def populate_examples(**kwds: Any) -> list[dict[str, Any]]:
"method_code": method_code,
"category": category.title(),
"lineno": lineno,
"is_new": is_new,
}
)

Expand Down Expand Up @@ -369,13 +409,16 @@ def main(app) -> None:
for d in examples:
examples_toc[d["category"]].append(d)

recent_examples = [example for example in examples if example["is_new"]]

encoding = "utf-8"

# Write the gallery index file
fp = target_dir / "index.rst"
index_text = GALLERY_TEMPLATE.render(
title=gallery_title,
examples=examples_toc.items(),
recent_examples=recent_examples,
image_dir="/_static",
gallery_ref=gallery_ref,
)
Expand Down
22 changes: 19 additions & 3 deletions sphinxext/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ def _parse_source_file(filename: str | Path) -> tuple[ast.Module | None, str]:
return node, content


def get_docstring_and_rest(filename: str | Path) -> tuple[str, str | None, str, int]:
def get_docstring_and_rest( # noqa: C901
filename: str | Path,
) -> tuple[str, str | None, str, int, bool]:
"""
Separate ``filename`` content between docstring and the rest.

Expand All @@ -109,6 +111,8 @@ def get_docstring_and_rest(filename: str | Path) -> tuple[str, str | None, str,
``filename`` content without the docstring
lineno: int
the line number on which the code starts
is_new: bool
whether the file includes a ``# :new:`` marker before ``# category:``

Notes
-----
Expand All @@ -120,17 +124,29 @@ def get_docstring_and_rest(filename: str | Path) -> tuple[str, str | None, str,
# Find the category comment
find_category = re.compile(r"^#\s*category:\s*(.*)$", re.MULTILINE)
match = find_category.search(content)
find_new = re.compile(r"^#\s*:new:\s*$", re.MULTILINE)
match_new = find_new.search(content)

is_new = bool(
match is not None
and match_new is not None
and match_new.start() < match.start()
)

if match is not None:
category = match.groups()[0]
# remove this comment from the content
content = find_category.sub("", content)
else:
category = None

if is_new and match_new is not None:
content = content[: match_new.start()] + content[match_new.end() :]

lineno = 1

if node is None:
return SYNTAX_ERROR_DOCSTRING, category, content, lineno
return SYNTAX_ERROR_DOCSTRING, category, content, lineno, is_new

if not isinstance(node, ast.Module):
msg = f"This function only supports modules. You provided {node.__class__.__name__}"
Expand Down Expand Up @@ -186,7 +202,7 @@ def get_docstring_and_rest(filename: str | Path) -> tuple[str, str | None, str,
"A docstring is required for the example gallery."
)
raise ValueError(msg)
return docstring, category, rest, lineno
return docstring, category, rest, lineno, is_new


def prev_this_next(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
=================================================
This example shows a basic horizontal bar chart with labels where the measured luminance to decides if the text overlay is be colored ``black`` or ``white``.
"""
# :new:
# category: bar charts
import altair as alt
from altair.datasets import data
Expand Down
3 changes: 1 addition & 2 deletions tests/examples_arguments_syntax/calculate_residuals.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
A dot plot showing each movie in the database, and the difference from the average movie rating.
The display is sorted by year to visualize everything in sequential order.
The graph is for all Movies before 2019.

Adapted from `Calculate Residuals <https://vega.github.io/vega-lite/examples/joinaggregate_residual_graph.html>`_.
"""
# category: advanced calculations
Expand Down Expand Up @@ -33,4 +32,4 @@
),
)
)
chart
chart
2 changes: 1 addition & 1 deletion tests/examples_arguments_syntax/deviation_ellipses.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
.. _@essicolo:
https://github.com/essicolo
"""

# :new:
# category: case studies
import numpy as np
import pandas as pd
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
---------------------------------------------------
Like :ref:`gallery_grouped_bar_chart2`, this example shows a grouped bar chart using the ``xOffset`` encoding channel, but in this example the bars are partly overlapping within each group.
"""
# :new:
# category: bar charts
import altair as alt
import pandas as pd
Expand All @@ -24,4 +25,4 @@
alt.layer(
base.mark_bar(size=20, stroke="white", fillOpacity=0.9).encode(fill="group:N"),
base.mark_text(dy=-5).encode(text="value:Q"),
)
)
3 changes: 2 additions & 1 deletion tests/examples_arguments_syntax/interactive_aggregation.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
The ability to slide back and fourth may help you understand how the visualization
represents the aggregation. Adapted from an example by @dwootton.
"""
# :new:
# category: interactive charts
import altair as alt
from altair.datasets import data
Expand Down Expand Up @@ -36,4 +37,4 @@
strokeWidth=alt.StrokeWidth(value=6),
x=alt.X(datum=alt.expr(threshold.name), type="quantitative")
)
).add_params(threshold)
).add_params(threshold)
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

Based on https://vega.github.io/vega-lite/examples/interactive_bar_select_highlight.html
"""

# :new:
# category: interactive charts
import altair as alt

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
It also illustrates how to use `indexof` to filter
columns based on active selection values.
"""
# :new:
# category: interactive charts

import pandas as pd
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
which here allows for multiple segments to be reordered
by holding down the shift key while clicking the legend.
"""
# :new:
# category: interactive charts
import altair as alt
from altair.datasets import data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
This is an example of a binned bar chart on the right where the filtered overlay
is adjusted by interacting with the map on the left.
"""
# :new:
# category: interactive charts
import altair as alt
from altair.datasets import data
Expand Down Expand Up @@ -58,4 +59,4 @@
right_bars = alt.layer(bars, bars_overlay)

# vertical concatenate map and bars
left_map | right_bars
left_map | right_bars
5 changes: 2 additions & 3 deletions tests/examples_arguments_syntax/maps_faceted_species.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
"""
Faceted County-Level Choropleth Maps
------------------------------------
A set of maps arranged in a grid, each showing the distribution of a species' projected habitat across US counties.
Each choropleth map uses color intensity to represent the percentage values within county boundaries.
A set of maps arranged in a grid, each showing the distribution of a species' projected habitat across US counties. Each choropleth map uses color intensity to represent the percentage values within county boundaries.
"""
# :new:
# category: maps

import altair as alt
Expand Down
1 change: 1 addition & 0 deletions tests/examples_arguments_syntax/mosaic_with_labels.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Mosaic Chart with Labels
------------------------
"""
# :new:
# category: tables

import altair as alt
Expand Down
1 change: 1 addition & 0 deletions tests/examples_arguments_syntax/polar_bar_chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
but is more commonly referred to as a polar bar chart.
The axis lines are created using pie charts with only the stroke visible.
"""
# :new:
# category: circular plots

import math
Expand Down
7 changes: 4 additions & 3 deletions tests/examples_arguments_syntax/scatter_point_paths_hover.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""
Scatter plot with point paths on hover with search box
======================================================
Scatter plot with point paths on hover and search box
=====================================================
This example combines cross-sectional analysis (comparing countries at a single point in time)
with longitudinal analysis (tracking changes in individual countries over time), using
an interactive visualization technique inspired by [this Vega example](https://vega.github.io/vega/examples/global-development/).
Expand All @@ -11,6 +11,7 @@
2. Search Box. Implements a case-insensitive regex filter for country names,
enabling dynamic, flexible data point selection to enhance exploratory analysis.
"""
# :new:
# category: interactive charts
import altair as alt
from altair.datasets import data
Expand Down Expand Up @@ -147,4 +148,4 @@
titleFontSize=12
).add_params(search_box)

chart
chart
1 change: 1 addition & 0 deletions tests/examples_arguments_syntax/selection_zorder.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
This prevents that the selected points are obscured
by those that are not selected.
"""
# :new:
# category: interactive charts

import altair as alt
Expand Down
Loading