Skip to content

Commit

Permalink
[Feat] Create vizro.figures.library to enable usage in pure Dash app (
Browse files Browse the repository at this point in the history
#578)

Co-authored-by: Antony Milne <[email protected]>
  • Loading branch information
huong-li-nguyen and antonymilne authored Aug 19, 2024
1 parent c9c918e commit b32da0d
Show file tree
Hide file tree
Showing 16 changed files with 286 additions and 183 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<!--
A new scriv changelog fragment.
Uncomment the section that is right (remove the HTML comment wrapper).
-->

<!--
### Highlights ✨
- A bullet item for the Highlights ✨ category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))
-->
<!--
### Removed
- A bullet item for the Removed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

### Added

- Create `vizro.figures.library` to contain KPI card Dash components that can be used outside the Vizro framework. ([#578](https://github.com/mckinsey/vizro/pull/578))

### Changed

- Google Material icons library is served locally to enable offline functionality. ([#578](https://github.com/mckinsey/vizro/pull/578))

<!--
### Deprecated
- A bullet item for the Deprecated category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))
-->
<!--
### Fixed
- A bullet item for the Fixed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))
-->
<!--
### Security
- A bullet item for the Security category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))
-->
6 changes: 6 additions & 0 deletions vizro-core/docs/pages/API-reference/figure-callables.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
API reference for all pre-defined [`CapturedCallable`][vizro.models.types.CapturedCallable] figure functions to be used in the
[`Figure`][vizro.models.Figure]. The [how-to guide on figures](../user-guides/figure.md) contains more information.

!!! note "Using figure functions in pure Dash app"
Identical functions can also be used outside the Vizro framework in a pure Dash app by importing from the `vizro.figures.library` namespace:
```python
from vizro.figures.library import kpi_card, kpi_card_reference
```

::: vizro.figures
options:
show_source: true
Expand Down

This file was deleted.

47 changes: 44 additions & 3 deletions vizro-core/src/vizro/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,56 @@
import os

import plotly.io as pio
from dash.development.base_component import Component

from ._themes import dark, light
from ._vizro import Vizro

logging.basicConfig(level=os.getenv("VIZRO_LOG_LEVEL", "WARNING"))
pio.templates["vizro_dark"] = dark
pio.templates["vizro_light"] = light

__all__ = ["Vizro"]

__version__ = "0.1.20.dev0"

logging.basicConfig(level=os.getenv("VIZRO_LOG_LEVEL", "WARNING"))

pio.templates["vizro_dark"] = dark
pio.templates["vizro_light"] = light
# For the below _css_dist to be used by Dash, it must be retrieved by dash.resources.Css.get_all_css(). This means it
# must be added to dash.development.base_component.ComponentRegistry. The simplest way to do this is to run
# ComponentRegistry.registry.add("vizro") and this appears to be sufficient for our needs, but it is not documented
# anywhere. The same function is run (together with some others which we probably don't need) when subclassing
# Component, thanks to the metaclass ComponentMeta. So we define a dummy component to go through this safer route,
# even though we don't need the component for anything. _css_dist is automatically served on import of vizro, regardless
# of whether the Vizro class or any other bits are used.
class _Dummy(Component):
pass


# For dev versions, a branch or tag called e.g. 0.1.20.dev0 does not exist and so won't work with the CDN. We point
# to main instead, but this can be manually overridden to the current feature branch name if required.
# _git_branch = __version__ if "dev" not in __version__ else "main"
_git_branch = __version__ if "dev" not in __version__ else "main"
_library_css = ["static/css/figures"]
_base_external_url = f"https://cdn.jsdelivr.net/gh/mckinsey/vizro@{_git_branch}/vizro-core/src/vizro/"

# CSS is packaged and accessed using relative_package_path when serve_locally=False (the default) in
# the Dash instantiation. When serve_locally=True then, where defined, external_url will be used instead.
_css_dist = [
{
"namespace": "vizro",
"relative_package_path": f"{css_file}.css",
"external_url": f"{_base_external_url}{css_file}.min.css",
}
for css_file in _library_css
]

# Include font file so that figures with icons can be used outside Vizro as pure Dash components.
# The file can be served through the CDN in the same way as the CSS files but external_url is irrelevant here. The way
# the file is requested is through a relative url("./fonts/...") in the requesting CSS file. When the CSS file is
# served from the CDN then this will refer to the font file also on the CDN.
_css_dist.append(
{
"namespace": "vizro",
"relative_package_path": "static/css/fonts/material-symbols-outlined.woff2",
}
)
13 changes: 7 additions & 6 deletions vizro-core/src/vizro/_vizro.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,18 @@ def __init__(self, **kwargs):
"""
self.dash = dash.Dash(**kwargs, use_pages=True, pages_folder="", title="Vizro")
self.dash.config.external_stylesheets.extend(
[
"https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined",
]
)

# Include Vizro assets (in the static folder) as external scripts and stylesheets. We extend self.dash.config
# objects so the user can specify additional external_scripts and external_stylesheets via kwargs.
vizro_assets_folder = Path(__file__).with_name("static")
requests_pathname_prefix = self.dash.config.requests_pathname_prefix
vizro_css = [requests_pathname_prefix + path for path in self._get_external_assets(vizro_assets_folder, "css")]
# Exclude vizro/css/figures.css since these are distributed through the vizro._css_dist mechanism.
# In future we will probably handle all assets this way and none of this code will be required.
vizro_css = [
requests_pathname_prefix + path
for path in self._get_external_assets(vizro_assets_folder, "css")
if path != "vizro/css/figures.css"
]

# Ensure vizro-bootstrap.min.css is loaded in first to allow overwrites
vizro_css.sort(key=lambda x: not x.endswith("vizro-bootstrap.min.css"))
Expand Down
2 changes: 1 addition & 1 deletion vizro-core/src/vizro/figures/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from vizro.figures.kpi_cards import kpi_card, kpi_card_reference
from vizro.figures._kpi_cards import kpi_card, kpi_card_reference

# Please keep alphabetically ordered
__all__ = ["kpi_card", "kpi_card_reference"]
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ def kpi_card( # noqa: PLR0913
title = title or f"{agg_func} {value_column}".title()
value = data_frame[value_column].agg(agg_func)

header = dbc.CardHeader([html.P(icon, className="material-symbols-outlined") if icon else None, html.H2(title)])
header = dbc.CardHeader(
[
html.P(icon, className="material-symbols-outlined") if icon else None,
html.H4(title, className="card-kpi-title"),
]
)
body = dbc.CardBody(value_format.format(value=value))
return dbc.Card([header, body], className="card-kpi")

Expand Down Expand Up @@ -137,7 +142,12 @@ def kpi_card_reference( # noqa: PLR0913
delta = value - reference
delta_relative = delta / reference if reference else np.nan

header = dbc.CardHeader([html.P(icon, className="material-symbols-outlined") if icon else None, html.H2(title)])
header = dbc.CardHeader(
[
html.P(icon, className="material-symbols-outlined") if icon else None,
html.H4(title, className="card-kpi-title"),
]
)
body = dbc.CardBody(
value_format.format(value=value, reference=reference, delta=delta, delta_relative=delta_relative)
)
Expand Down
8 changes: 8 additions & 0 deletions vizro-core/src/vizro/figures/library.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""Contains unwrapped KPI card functions (suitable to use in pure Dash app)."""

from vizro.figures import kpi_card, kpi_card_reference

kpi_card = kpi_card.__wrapped__
kpi_card_reference = kpi_card_reference.__wrapped__

__all__ = ["kpi_card", "kpi_card_reference"]
9 changes: 0 additions & 9 deletions vizro-core/src/vizro/static/css/bootstrap_overwrites.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,3 @@ but do not want to take over to `vizro-bootstrap` as these settings might not be
.accordion-item .nav-link.active {
border-left: 2px solid var(--border-enabled);
}

.card-header,
.card-footer,
.card-body {
background: inherit;
border: none;
margin: 0;
padding: 0;
}
81 changes: 64 additions & 17 deletions vizro-core/src/vizro/static/css/figures.css
Original file line number Diff line number Diff line change
@@ -1,50 +1,97 @@
.card-kpi {
border-left: 4px solid var(--text-secondary);
border-left: 4px solid var(--bs-secondary);
height: 100%;
padding: 1rem;
}

/* We currently ship this CSS file with the package, so the font definitions need to live here at the moment.
The CSS is taken from https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined and the corresponding font file
downloaded to fonts/material-symbols-outlined.woff2. See:
https://developers.google.com/fonts/docs/material_symbols#self-hosting_the_font
https://fonts.google.com/knowledge/using_type/self_hosting_web_fonts
Note the relative url works with both serve_locally=True and serve_locally=False through the CDN.
*/
@font-face {
font-family: MaterialSymbolsOutlined;
src: url("./fonts/material-symbols-outlined.woff2") format("woff2");
}

.material-symbols-outlined {
direction: ltr;
display: inline-block;
font-family: MaterialSymbolsOutlined, sans-serif;
font-feature-settings: "liga";
font-size: 24px;
-webkit-font-smoothing: antialiased;
font-style: normal;
font-weight: 400;
letter-spacing: normal;
line-height: 1;
text-transform: none;
white-space: nowrap;
word-wrap: normal;
}

.card-kpi .material-symbols-outlined {
margin: auto 0;
}

/* This should be replaced, when the bootstrap theme is finalized. Currently our font tokens don't match with the
bootstrap font tokens, leading to deviations which we need to overwrite. */
.card-kpi-title {
font-size: 1.5rem;
line-height: 1;
margin: 0;
}

.card-kpi .card-header,
.card-kpi .card-footer,
.card-kpi .card-body {
background: none;
border: none;
margin: 0;
padding: 0;
}

.card-kpi .card-header {
display: flex;
flex-direction: row;
gap: 8px;
}

.card-kpi .card-header .material-symbols-outlined {
line-height: 30px;
gap: 0.5rem;
}

.card-kpi .card-body {
align-items: center;
color: var(--text-secondary);
color: var(--bs-secondary);
display: flex;
flex-grow: 1;
font-size: 3.6vh;
font-weight: 600;
padding: 1rem 0;
}

.card-kpi .card-footer {
color: var(--text-secondary);
color: var(--bs-secondary);
display: flex;
font-weight: 600;
gap: 4px;
gap: 0.25rem;
}

.card-kpi .card-footer .material-symbols-outlined {
font-size: 20px;
line-height: 20px;
font-size: 1.25rem;
}

.color-pos.card-footer {
color: #1a85ff;
.card-kpi .color-pos.card-footer {
color: var(--bs-blue);
}

.color-neg.card-footer {
color: #d41159;
.card-kpi .color-neg.card-footer {
color: var(--bs-pink);
}

.card-kpi:has(.color-pos) {
border-left: 4px solid #1a85ff;
border-left: 4px solid var(--bs-blue);
}

.card-kpi:has(.color-neg) {
border-left: 4px solid #d41159;
border-left: 4px solid var(--bs-pink);
}
Binary file not shown.
Binary file not shown.
5 changes: 0 additions & 5 deletions vizro-core/src/vizro/static/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@
src: url("./fonts/inter-variable-font.ttf") format("truetype");
}

@font-face {
font-family: RobotoMono;
src: url("./fonts/roboto-mono-variable-font.ttf") format("truetype");
}

* {
border: 0;
box-sizing: border-box;
Expand Down
Loading

0 comments on commit b32da0d

Please sign in to comment.