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
28 changes: 13 additions & 15 deletions docs/badges_buttons.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Badges, Buttons & Icons
# Badges, Buttons & Icons {octicon}`rocket`

(badges)=

Expand Down Expand Up @@ -152,29 +152,27 @@ class

Inline icon roles are available for both the [GitHub octicon](https://octicons-git-v2.primer.now.sh/octicons/) or [FontAwesome](https://fontawesome.com/icons?d=gallery&m=free) libraries.

Octicon icons are added as SVG's directly into the page, for either 16px (`octicon-16`) or 24px (`octicon-24`) sizes.
Additional CSS classes can be added to the SVG after a semi-colon (`;`) delimiter.
Octicon icons are added as SVG's directly into the page with the `octicon` role.

A coloured icon: {octicon-16}`report;sd-text-info`, some more text.
By default the icon will be of height `1em` (i.e. the height of the font).
A specific height can be set after a semi-colon (`;`) with units of either `px`, `em` or `rem`.
Additional CSS classes can also be added to the SVG after a second semi-colon (`;`) delimiter.

A coloured icon: {octicon}`report;1em;sd-text-info`, some more text.

````{tab-set-code}
```markdown
A coloured icon: {octicon-16}`report;sd-text-info`, some more text.
```{literalinclude} ./snippets/myst/icon-octicon.txt
:language: markdown
```
```rst
A coloured icon: :octicon-16:`report;sd-text-info`, some more text.
```{literalinclude} ./snippets/rst/icon-octicon.txt
:language: rst
```
````

````{dropdown} All Octicons (16px)
```{_all-octicon}
:size: 16
```
````
````{dropdown} All Octicons
:open:

````{dropdown} All Octicons (24px)
```{_all-octicon}
:size: 24
```
````

Expand Down
2 changes: 2 additions & 0 deletions docs/cards.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ Content
Content
:::

(cards:options)=

## `card` options

width
Expand Down
19 changes: 19 additions & 0 deletions docs/grids.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,3 +287,22 @@ text-align

class
: Additional CSS classes for the grid item element.

## `grid-item-card` options

columns
: The number of columns (out of 12) a grid-item will take up.
One or four integers (for "xs sm md lg") between 1 and 12 (or `auto` to adapt to the content).

margin
: Outer margin of grid item.
One (all) or four (top bottom left right) values from: 0, 1, 2, 3, 4, 5, auto.

padding
: Inner padding of grid item.
One (all) or four (top bottom left right) values from: 0, 1, 2, 3, 4, 5.

class-item
: Additional CSS classes for the grid item element.

Plus all options from [](cards:options).
12 changes: 6 additions & 6 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,42 +57,42 @@ furo <https://sphinx-design.readthedocs.io/en/furo-theme>
:margin: 4 4 0 0
:gutter: 1

:::{grid-item-card} {octicon-16}`table` Grids
:::{grid-item-card} {octicon}`table` Grids
:link: grids
:link-type: doc

Screen size adaptable grid layouts.
:::

:::{grid-item-card} {octicon-16}`note` Cards
:::{grid-item-card} {octicon}`note` Cards
:link: cards
:link-type: doc

Flexible and extensible content containers.
:::

:::{grid-item-card} {octicon-16}`chevron-down` Dropdowns
:::{grid-item-card} {octicon}`chevron-down` Dropdowns
:link: dropdowns
:link-type: doc

Hide content in expandable containers.
:::

:::{grid-item-card} {octicon-16}`duplicate` Tabs
:::{grid-item-card} {octicon}`duplicate` Tabs
:link: tabs
:link-type: doc

Synchronisable, tabbed content sets.
:::

:::{grid-item-card} {octicon-16}`plus-circle` Badges, Buttons & Icons
:::{grid-item-card} {octicon}`plus-circle` Badges, Buttons & Icons
:link: badges_buttons
:link-type: doc

Roles and directives for {bdg-primary}`badges` and other components.
:::

:::{grid-item-card} {octicon-16}`image` CSS Styling
:::{grid-item-card} {octicon}`image` CSS Styling
:link: css_variables
:link-type: doc

Expand Down
2 changes: 1 addition & 1 deletion docs/snippets/myst/icon-octicon.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
A coloured icon: {octicon-16}`report;sd-text-info`, some more text.
A coloured icon: {octicon}`report;1em;sd-text-info`, some more text.
2 changes: 1 addition & 1 deletion docs/snippets/rst/icon-octicon.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
A coloured icon: :octicon-16:`report;sd-text-info`, some more text.
A coloured icon: :octicon:`report;1em;sd-text-info`, some more text.
4 changes: 2 additions & 2 deletions sphinx_design/article_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ def run(self) -> List[nodes.Node]:
self.set_source_info(date_column)
date_icon = nodes.raw(
"",
nodes.Text(get_octicon("calendar", size=16)),
nodes.Text(get_octicon("calendar", height="16px")),
classes=["sd-pr-2"],
format="html",
)
Expand All @@ -171,7 +171,7 @@ def run(self) -> List[nodes.Node]:
self.set_source_info(read_time_column)
read_time_icon = nodes.raw(
"",
nodes.Text(get_octicon("clock", size=16)),
nodes.Text(get_octicon("clock", height="16px")),
classes=["sd-pr-2"],
format="html",
)
Expand Down
2 changes: 1 addition & 1 deletion sphinx_design/compiled/style.min.css

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions sphinx_design/dropdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def run(self):


# Note the custom octicon here has thicker dots than:
# get_octicon("kebab-horizontal", classes="no-title", size=24)
# get_octicon("kebab-horizontal", classes=["no-title"])
KEBAB = """\
<svg viewBox="0 0 36 24" width="36" height="16" xmlns="http://www.w3.org/2000/svg"
class="octicon no-title" aria-hidden="true">
Expand Down Expand Up @@ -165,7 +165,7 @@ def run(self):
children=[
nodes.raw(
"",
nodes.Text(get_octicon("chevron-up", size=24)),
nodes.Text(get_octicon("chevron-up", height="24px")),
format="html",
)
],
Expand All @@ -176,7 +176,7 @@ def run(self):
children=[
nodes.raw(
"",
nodes.Text(get_octicon("chevron-down", size=24)),
nodes.Text(get_octicon("chevron-down", height="24px")),
format="html",
)
],
Expand Down Expand Up @@ -206,7 +206,7 @@ def run(self):
0,
nodes.raw(
"",
nodes.Text(get_octicon(node["icon"], size=16)),
nodes.Text(get_octicon(node["icon"], height="1em")),
classes=["sd-summary-icon"],
format="html",
),
Expand Down
93 changes: 48 additions & 45 deletions sphinx_design/icons.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import re
from functools import lru_cache
from typing import Any, Dict, List, Optional, Tuple, Union
from typing import Any, Dict, List, Optional, Sequence, Tuple

try:
import importlib.resources as resources
Expand All @@ -14,7 +15,6 @@
from sphinx.util.docutils import SphinxDirective, SphinxRole

from . import compiled
from .shared import make_choice

OCTICON_VERSION = "0.0.0-dd899ea"

Expand All @@ -27,8 +27,7 @@


def setup_icons(app: Sphinx) -> None:
app.add_role("octicon-16", OcticonRole(16))
app.add_role("octicon-24", OcticonRole(24))
app.add_role("octicon", OcticonRole())
app.add_directive("_all-octicon", AllOcticons)
for style in ["fa", "fas", "fab"]:
# note: fa is deprecated in v5, fas is the default and fab is the other free option
Expand All @@ -52,50 +51,57 @@ def get_octicon_data() -> Dict[str, Any]:
return json.loads(content)


def list_octicons(size: int = 16) -> List[str]:
def list_octicons() -> List[str]:
"""List available octicon names."""
return [
key
for key, data in get_octicon_data().items()
if str(size) in data.get("heights", [])
]
return list(get_octicon_data().keys())


HEIGHT_REGEX = re.compile(r"^(?P<value>\d+)(?P<unit>px|em|rem)$")


def get_octicon(
name: str,
classes: Optional[str] = None,
width: Optional[Union[int, float]] = None,
height: Optional[Union[int, float]] = None,
height: str = "1em",
classes: Sequence[str] = (),
aria_label: Optional[str] = None,
size: int = 16,
) -> str:
"""Return the HTML for an GitHub octicon SVG icon."""
assert size in [16, 24], "size must be 16 or 24"
"""Return the HTML for an GitHub octicon SVG icon.

:height: the height of the octicon, with suffix unit 'px', 'em' or 'rem'.
"""
try:
data = get_octicon_data()[name]
except KeyError:
raise KeyError(f"Unrecognised octicon: {name}")

content = data["heights"][str(size)]["path"]
match = HEIGHT_REGEX.match(height)
if not match:
raise ValueError(
f"Invalid height: '{height}', must be format <integer><px|em|rem>"
)
height_value = int(match.group("value"))
height_unit = match.group("unit")

original_height = 16
if "16" not in data["heights"]:
original_height = int(list(data["heights"].keys())[0])
elif "24" in data["heights"]:
if height_unit == "px":
if height_value >= 24:
original_height = 24
elif height_value >= 1.5:
original_height = 24
original_width = data["heights"][str(original_height)]["width"]
width_value = round(original_width * height_value / original_height, 2)
content = data["heights"][str(original_height)]["path"]
options = {
"version": "1.1",
"width": data["heights"][str(size)]["width"],
"height": int(size),
"class": f"sd-octicon sd-octicon-{name}",
"width": f"{width_value}{height_unit}",
"height": f"{height_value}{height_unit}",
"class": " ".join(("sd-octicon", f"sd-octicon-{name}", *classes)),
}

if width is not None or height is not None:
if width is None and height is not None:
width = round((int(height) * options["width"]) / options["height"], 2)
if height is None and width is not None:
height = round((int(width) * options["height"]) / options["width"], 2)
options["width"] = width
options["height"] = height

options["viewBox"] = f'0 0 {options["width"]} {options["height"]}'

if classes is not None:
options["class"] += " " + classes.strip()
options["viewBox"] = f"0 0 {original_width} {original_height}"

if aria_label is not None:
options["aria-label"] = aria_label
Expand All @@ -113,19 +119,18 @@ class OcticonRole(SphinxRole):
Additional classes can be added to the element after a semicolon.
"""

def __init__(self, size: int) -> None:
super().__init__()
self.size = size

def run(self) -> Tuple[List[nodes.Node], List[nodes.system_message]]:
"""Run the role."""
icon, classes = self.text.split(";", 1) if ";" in self.text else [self.text, ""]
values = self.text.split(";") if ";" in self.text else [self.text]
icon = values[0]
height = "1em" if len(values) < 2 else values[1]
classes = "" if len(values) < 3 else values[2]
icon = icon.strip()
try:
svg = get_octicon(icon, size=self.size, classes=classes)
except KeyError:
svg = get_octicon(icon, height=height, classes=classes.split())
except Exception as exc:
msg = self.inliner.reporter.error(
f"Unknown octicon name: {icon}",
f"Invalid octicon content: {exc}",
line=self.lineno,
)
prb = self.inliner.problematic(self.rawtext, self.rawtext, msg)
Expand All @@ -142,24 +147,22 @@ class AllOcticons(SphinxDirective):
"""

option_spec = {
"size": make_choice(["16", "24"]),
"class": directives.class_option,
}

def run(self) -> List[nodes.Node]:
"""Run the directive."""
size = int(self.options.get("size", "16"))
classes = " ".join(self.options.get("class", []))
classes = self.options.get("class", [])
list_node = nodes.bullet_list()
for icon in list_octicons(size):
for icon in list_octicons():
item_node = nodes.list_item()
item_node.extend(
(
nodes.literal(icon, icon),
nodes.Text(": "),
nodes.raw(
"",
nodes.Text(get_octicon(icon, size=size, classes=classes)),
nodes.Text(get_octicon(icon, classes=classes)),
format="html",
),
)
Expand Down
6 changes: 5 additions & 1 deletion style/_dropdown.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ details.sd-dropdown {
}

.sd-summary-icon {
margin-right: 0.5rem;
margin-right: 0.5em;
}

.sd-summary-icon svg {
Expand Down Expand Up @@ -107,6 +107,10 @@ details.sd-dropdown {
width: 100%;
}

.sd-summary-content > .sd-tab-set:first-child {
margin-top: 0;
}

@keyframes sd-fade-in {
0% {
opacity: 0;
Expand Down
4 changes: 2 additions & 2 deletions tests/test_snippets/snippet_post_article-info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
<container classes="sd-col sd-col-auto sd-d-flex sd-align-items-center" design_component="grid-item" is_div="True">
<paragraph classes="sd-p-0 sd-m-0">
<raw classes="sd-pr-2" format="html" xml:space="preserve">
<svg version="1.1" width="16" height="16" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"><path fill-rule="evenodd" d="M4.75 0a.75.75 0 01.75.75V2h5V.75a.75.75 0 011.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0113.25 16H2.75A1.75 1.75 0 011 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 014.75 0zm0 3.5h8.5a.25.25 0 01.25.25V6h-11V3.75a.25.25 0 01.25-.25h2zm-2.25 4v6.75c0 .138.112.25.25.25h10.5a.25.25 0 00.25-.25V7.5h-11z"></path></svg>
<svg version="1.1" width="16.0px" height="16px" class="sd-octicon sd-octicon-calendar" viewBox="0 0 16 16" aria-hidden="true"><path fill-rule="evenodd" d="M4.75 0a.75.75 0 01.75.75V2h5V.75a.75.75 0 011.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0113.25 16H2.75A1.75 1.75 0 011 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 014.75 0zm0 3.5h8.5a.25.25 0 01.25.25V6h-11V3.75a.25.25 0 01.25-.25h2zm-2.25 4v6.75c0 .138.112.25.25.25h10.5a.25.25 0 00.25-.25V7.5h-11z"></path></svg>
Jul 24, 2021
<container classes="sd-col sd-col-auto sd-d-flex sd-align-items-center" design_component="grid-item" is_div="True">
<paragraph classes="sd-p-0 sd-m-0">
<raw classes="sd-pr-2" format="html" xml:space="preserve">
<svg version="1.1" width="16" height="16" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"><path fill-rule="evenodd" d="M1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0zM8 0a8 8 0 100 16A8 8 0 008 0zm.5 4.75a.75.75 0 00-1.5 0v3.5a.75.75 0 00.471.696l2.5 1a.75.75 0 00.557-1.392L8.5 7.742V4.75z"></path></svg>
<svg version="1.1" width="16.0px" height="16px" class="sd-octicon sd-octicon-clock" viewBox="0 0 16 16" aria-hidden="true"><path fill-rule="evenodd" d="M1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0zM8 0a8 8 0 100 16A8 8 0 008 0zm.5 4.75a.75.75 0 00-1.5 0v3.5a.75.75 0 00.471.696l2.5 1a.75.75 0 00.557-1.392L8.5 7.742V4.75z"></path></svg>
5 min read
Loading