Components - KPIs

KPI Card

Card to show off metrics and values. Has an icon, the KPI number and a small descriptive text.

<div class="row">
    <h2>
        Adaptive height
    </h2>
</div>
<div class="row">
    <div class="col-md-4">
        <!-- KPI box component -->
        <div class="kpi-card">
            <i class="kpi-icon fa fa-gitlab" aria-hidden="true"></i>
            <h2 class="kpi-title">
                5,983
            </h2>
            <p class="kpi-description">
                Dignissim suspendisse in est ante in nibh nisl tincidunt eget
            </p>
        </div>
    </div>
    <div class="col-md-4">
        <!-- KPI box component -->
        <div class="kpi-card">
            <i class="kpi-icon fa fa-houzz" aria-hidden="true"></i>
            <h2 class="kpi-title">
                18.3k
            </h2>
            <p class="kpi-description">
                Quam vulputate dignissim suspendisse in est ante in nibh. Faucibus nisl tincidunt eget nullam non nisi est sit amet
            </p>
        </div>
    </div>
    <div class="col-md-4">
        <!-- KPI box component -->
        <div class="kpi-card">
            <i class="kpi-icon fa fa-houzz" aria-hidden="true"></i>
            <h2 class="kpi-title">
                8.3k
            </h2>
            <p class="kpi-description">
                Quam vulputate
            </p>
        </div>
    </div>
</div>


<div class="row">
    <h2>
        Same height
    </h2>
</div>
<div class="row row-equal-height">
    <div class="col-md-4">
        <!-- KPI box component -->
        <div class="kpi-card">
            <i class="kpi-icon fa fa-gitlab" aria-hidden="true"></i>
            <h2 class="kpi-title">
                5,983
            </h2>
            <p class="kpi-description">
                Dignissim suspendisse in est ante in nibh nisl tincidunt eget
            </p>
        </div>
    </div>
    <div class="col-md-4">
        <!-- KPI box component -->
        <div class="kpi-card">
            <i class="kpi-icon fa fa-houzz" aria-hidden="true"></i>
            <h2 class="kpi-title">
                18.3k
            </h2>
            <p class="kpi-description">
                Quam vulputate dignissim suspendisse in est ante in nibh. Faucibus nisl tincidunt eget nullam non nisi est sit amet
            </p>
        </div>
    </div>
    <div class="col-md-4">
        <!-- KPI box component -->
        <div class="kpi-card">
            <i class="kpi-icon fa fa-houzz" aria-hidden="true"></i>
            <h2 class="kpi-title">
                8.3k
            </h2>
            <p class="kpi-description">
                Quam vulputate
            </p>
        </div>
    </div>
</div>
/* Variables & Shared classes
========================================================================== */
:root {
    --secondary-color: #142E7B;
}
.row-equal-height {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-wrap: wrap;
    flex-wrap: wrap;
}
.row-equal-height > * {
    flex-grow: 1; /* fill the space, take all the available width */
    margin-bottom: 20px;
}
/* Fix for early content wrapping in Safari*/
.row-equal-height:before,
.row-equal-height:after {
    content: normal;
}
/* KPI Card
========================================================================== */
.kpi-card {
    background-color: var(--boxes-background);
    height: 100%;
    padding: 39px;
    border-radius: 4px;
    margin-bottom: 20px;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
    -ms-flex-direction: column;
    flex-direction: column;
    -webkit-box-align: center;
    -ms-flex-align: center;
    align-items: center;
    text-align: center;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    justify-content: center;
    text-align: center;
}
.kpi-icon {
    color: var(--highlight);
    color: var(--secondary-color);
    font-size: 4rem;
    margin-top: 0;
    margin-bottom: 13px;
    max-width: 100%;
}
.kpi-title {
    font-weight: normal;
    color: var(--highlight);
    font-size: 3.2rem;
    margin-top: 0;
    margin-bottom: 13px;
    max-width: 100%;
}
.kpi-description {
    color: var(--text);
    font-size: 1rem;
    line-height: 1.5;
    font-weight: normal;
    margin-top: 0;
    margin-bottom: 0;
    max-width: 100%;
}

An ods-aggregation example

Count the number of record of a dataset, here : the number of US hospitals

For more information about how to compute metrics, see ods-aggregation resource.

<div class="row">
    <div class="col-sm-offset-4 col-sm-4">
        <ods-dataset-context context="ushospitals"
                             ushospitals-domain="userclub"
                             ushospitals-dataset="us-hospitals">
            <!-- KPI box component -->
            <div class="kpi-card">
                <i class="kpi-icon fa fa-hospital-o" aria-hidden="true"></i>
                <h2 class="kpi-title"
                    ods-aggregation="count"
                    ods-aggregation-context="ushospitals"
                    ods-aggregation-function="COUNT">
                    {{ count | number }}
                </h2>
                <p class="kpi-description">
                    Number of hospitals
                </p>
            </div>
        </ods-dataset-context>
    </div>
</div>
/* Variables & Shared classes
========================================================================== */
:root {
    --secondary-color: #142E7B;
}
.row-equal-height {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-wrap: wrap;
    flex-wrap: wrap;
    margin-bottom: 20px;
}
/* Fix for early content wrapping in Safari*/
.row-equal-height:before,
.row-equal-height:after {
    content: normal;
}
/* KPI Card
========================================================================== */
.kpi-card {
    background-color: var(--boxes-background);
    height: 100%;
    padding: 39px;
    border-radius: 4px;
    margin-bottom: 20px;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
    -ms-flex-direction: column;
    flex-direction: column;
    -webkit-box-align: center;
    -ms-flex-align: center;
    align-items: center;
    text-align: center;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    justify-content: center;
    text-align: center;
}
.kpi-icon {
    color: var(--highlight);
    color: var(--secondary-color);
    font-size: 4rem;
    margin-top: 0;
    margin-bottom: 13px;
    max-width: 100%;
}
.kpi-title {
    font-weight: normal;
    color: var(--highlight);
    font-size: 3.2rem;
    margin-top: 0;
    margin-bottom: 13px;
    max-width: 100%;
}
.kpi-description {
    color: var(--text);
    font-size: 1rem;
    line-height: 1.5;
    font-weight: normal;
    margin-top: 0;
    margin-bottom: 0;
    max-width: 100%;
}
.kpi-description-detail {
    opacity: 0.9;
    font-style: italic;
    font-size: 0.9em;
    margin-top: 0.8em;
}

Flip KPI

This card flip on user interaction to reveal more details about the dataset and how it is computed.

<div class="row">
    <div class="col-sm-offset-4 col-sm-4">
        <ods-dataset-context context="ushospitals"
                             ushospitals-domain="userclub"
                             ushospitals-dataset="us-hospitals">
            <!-- KPI box component -->
            <div class="card-flip"

                 ng-init="isFlipped = false"
                 ng-click="isFlipped = !isFlipped"
                 ng-class="{'is-flipped': isFlipped}"

                 ods-aggregation="count"
                 ods-aggregation-context="ushospitals"
                 ods-aggregation-function="COUNT">
                <div class="kpi-card card-face card-face-front">
                    <div class="kpi-card-top"></div>
                    <div class="kpi-card-middle">
                        <i class="kpi-icon fa fa-hospital-o" aria-hidden="true"></i>
                        <h2 class="kpi-title">
                            {{ count | number }}
                        </h2>
                        <p class="kpi-description">
                            Number of hospitals
                        </p>
                    </div>
                    <div class="kpi-card-bottom">
                        <p class="hint">"How is it computed? 👉"</p>
                    </div>
                </div>
                <div class="kpi-card card-face card-face-back">
                    <p>
                        <strong>{{ count | number }}</strong> is the count of all records found in the dataset: 
                    </p>
                    <a href="{ushospitals.domainUrl}}/explore/dataset/{ushospitals.dataset.datasetid}}/information/">
                        {{ ushospitals.dataset.metas.title }}
                    </a>
                </div>
            </div>
        </ods-dataset-context>
    </div>
</div>
/* Variables & Shared classes
========================================================================== */
:root {
    --secondary-color: #142E7B;
}

/* KPI Card
========================================================================== */
.kpi-card {
    background-color: var(--boxes-background);
    height: 100%;
    padding: 39px;
    border-radius: 4px;
    margin-bottom: 20px;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
    -ms-flex-direction: column;
    flex-direction: column;
    -webkit-box-align: center;
    -ms-flex-align: center;
    align-items: center;
    text-align: center;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    justify-content: center;
    text-align: center;
}

.kpi-icon {
    color: var(--highlight);
    color: var(--secondary-color);
    font-size: 4rem;
    margin-top: 0;
    margin-bottom: 13px;
    max-width: 100%;
}

.kpi-title {
    font-weight: normal;
    color: var(--highlight);
    font-size: 3.2rem;
    margin-top: 0;
    margin-bottom: 13px;
    max-width: 100%;
}

.kpi-description {
    color: var(--text);
    font-size: 1rem;
    line-height: 1.5;
    font-weight: normal;
    margin-top: 0;
    margin-bottom: 0;
    max-width: 100%;
}

.kpi-description-detail {
    opacity: 0.9;
    font-style: italic;
    font-size: 0.9em;
    margin-top: 0.8em;
}

/* Flip component
========================================================================== */
.kpi-card.card-face-front {
    justify-content: space-between;
}

.card-flip {
    position: relative;
    height: 100%;
    width: 100%;
    -webkit-transition: -webkit-transform 0.2s;
    transition: -webkit-transform 0.2s;
    -o-transition: transform 0.2s;
    transition: transform 0.2s;
    transition: transform 0.2s, -webkit-transform 0.2s;
    -webkit-perspective: 1200px;
    perspective: 1200px;
    -webkit-transform-style: preserve-3d;
    transform-style: preserve-3d;
    border-radius: 4px;
    margin-bottom: 20px;
}

.card-face {
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
    height: 100%;
    width: 100%;
    margin-bottom: 0; /* remove kpi-card margin bottom */
}

.card-face-back {
    position: absolute;
    top: 0;
    left: 0;
    -webkit-transform: rotateY(180deg);
    transform: rotateY(180deg);
    -webkit-box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14),
    0 1px 10px 0 rgba(0, 0, 0, 0.12);
    box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14),
    0 1px 10px 0 rgba(0, 0, 0, 0.12);
}

.card-flip.is-flipped {
    -webkit-transform: rotateY(180deg);
    transform: rotateY(180deg);
}

.card-flip:hover {
    -webkit-transform: rotateY(5deg);
    transform: rotateY(5deg);
    -webkit-box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14),
    0 1px 10px 0 rgba(0, 0, 0, 0.12);
    box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14),
    0 1px 10px 0 rgba(0, 0, 0, 0.12);
}

.card-flip.is-flipped:hover {
    -webkit-transform: rotateY(180deg);
    transform: rotateY(180deg);
}

.kpi-card-bottom {
    align-self: flex-end;
    margin: 16px -27px -27px 0;
}

p.hint {
    color: darkgrey;
}

KPI sync flip

By default flip kpi will be independant. If you want multiple KPIs to all to flip when one is clicked, you have lift the state variable to a containing element.

<div class="row" ng-init="variables = {}">
    <div class="col-sm-offset-2 col-sm-4">
        <ods-dataset-context context="ushospitals"
                             ushospitals-domain="userclub"
                             ushospitals-dataset="us-hospitals">
            <!-- KPI box component -->
            <div class="card-flip"

                 ng-click="variables.isFlipped = !variables.isFlipped"
                 ng-class="{'is-flipped': variables.isFlipped}"

                 ods-aggregation="count"
                 ods-aggregation-context="ushospitals"
                 ods-aggregation-function="COUNT">
                <div class="kpi-card card-face card-face-front">
                    <div class="kpi-card-top"></div>
                    <div class="kpi-card-middle">
                        <i class="kpi-icon fa fa-hospital-o" aria-hidden="true"></i>
                        <h2 class="kpi-title">
                            {{ count | number }}
                        </h2>
                        <p class="kpi-description">
                            Number of hospitals
                        </p>
                    </div>
                    <div class="kpi-card-bottom">
                        <p class="hint">"How is it computed? 👉"</p>
                    </div>
                </div>
                <div class="kpi-card card-face card-face-back">
                    <p>
                        <strong>{{ count | number }}</strong> is the count of all records found in the dataset:
                    </p>
                    <a href="{ushospitals.domainUrl}}/explore/dataset/{ushospitals.dataset.datasetid}}/information/">
                        {{ ushospitals.dataset.metas.title }}
                    </a>
                </div>
            </div>
        </ods-dataset-context>
    </div>

    <div class="col-sm-4">
        <ods-dataset-context context="ushospitals"
                             ushospitals-domain="userclub"
                             ushospitals-dataset="us-hospitals">
            <!-- KPI box component -->
            <div class="card-flip"

                 ng-click="variables.isFlipped = !variables.isFlipped"
                 ng-class="{'is-flipped': variables.isFlipped}"

                 ods-aggregation="count"
                 ods-aggregation-context="ushospitals"
                 ods-aggregation-function="COUNT">
                <div class="kpi-card card-face card-face-front">
                    <div class="kpi-card-top"></div>
                    <div class="kpi-card-middle">
                        <i class="kpi-icon fa fa-hospital-o" aria-hidden="true"></i>
                        <h2 class="kpi-title">
                            {{ count | number }}
                        </h2>
                        <p class="kpi-description">
                            Number of hospitals
                        </p>
                    </div>
                    <div class="kpi-card-bottom">
                        <p class="hint">"How is it computed? 👉"</p>
                    </div>
                </div>
                <div class="kpi-card card-face card-face-back">
                    <p>
                        <strong>{{ count | number }}</strong> is the count of all records found in the dataset:
                    </p>
                    <a href="{ushospitals.domainUrl}}/explore/dataset/{ushospitals.dataset.datasetid}}/information/">
                        {{ ushospitals.dataset.metas.title }}
                    </a>
                </div>
            </div>
        </ods-dataset-context>
    </div>
</div>
/* Variables & Shared classes
========================================================================== */
:root {
    --secondary-color: #142E7B;
}

/* KPI Card
========================================================================== */
.kpi-card {
    background-color: var(--boxes-background);
    height: 100%;
    padding: 39px;
    border-radius: 4px;
    margin-bottom: 20px;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
    -ms-flex-direction: column;
    flex-direction: column;
    -webkit-box-align: center;
    -ms-flex-align: center;
    align-items: center;
    text-align: center;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    justify-content: center;
    text-align: center;
}

.kpi-icon {
    color: var(--highlight);
    color: var(--secondary-color);
    font-size: 4rem;
    margin-top: 0;
    margin-bottom: 13px;
    max-width: 100%;
}

.kpi-title {
    font-weight: normal;
    color: var(--highlight);
    font-size: 3.2rem;
    margin-top: 0;
    margin-bottom: 13px;
    max-width: 100%;
}

.kpi-description {
    color: var(--text);
    font-size: 1rem;
    line-height: 1.5;
    font-weight: normal;
    margin-top: 0;
    margin-bottom: 0;
    max-width: 100%;
}

.kpi-description-detail {
    opacity: 0.9;
    font-style: italic;
    font-size: 0.9em;
    margin-top: 0.8em;
}

/* Flip component
========================================================================== */
.kpi-card.card-face-front {
    justify-content: space-between;
}

.card-flip {
    position: relative;
    height: 100%;
    width: 100%;
    -webkit-transition: -webkit-transform 0.2s;
    transition: -webkit-transform 0.2s;
    -o-transition: transform 0.2s;
    transition: transform 0.2s;
    transition: transform 0.2s, -webkit-transform 0.2s;
    -webkit-perspective: 1200px;
    perspective: 1200px;
    -webkit-transform-style: preserve-3d;
    transform-style: preserve-3d;
    border-radius: 4px;
    margin-bottom: 20px;
}

.card-face {
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
    height: 100%;
    width: 100%;
    margin-bottom: 0; /* remove kpi-card margin bottom */
}

.card-face-back {
    position: absolute;
    top: 0;
    left: 0;
    -webkit-transform: rotateY(180deg);
    transform: rotateY(180deg);
    -webkit-box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14),
    0 1px 10px 0 rgba(0, 0, 0, 0.12);
    box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14),
    0 1px 10px 0 rgba(0, 0, 0, 0.12);
}

.card-flip.is-flipped {
    -webkit-transform: rotateY(180deg);
    transform: rotateY(180deg);
}

.card-flip:hover {
    -webkit-transform: rotateY(5deg);
    transform: rotateY(5deg);
    -webkit-box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14),
    0 1px 10px 0 rgba(0, 0, 0, 0.12);
    box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14),
    0 1px 10px 0 rgba(0, 0, 0, 0.12);
}

.card-flip.is-flipped:hover {
    -webkit-transform: rotateY(180deg);
    transform: rotateY(180deg);
}

.kpi-card-bottom {
    align-self: flex-end;
    margin: 16px -27px -27px 0;
}

p.hint {
    color: darkgrey;
}