Graphs

Graph

Works dynamically with v-for tags in each section

543210
År:årOmsætning: 1
År:årOmsætning: 3
År:årOmsætning: 2
år1år2år3

Html

                    
<div class="col-12">
    <h3 class="col-md-12"> Graph</h3>
    <h4 class="col-md-12">Works dynamically with v-for tags in each section</h4>
    <div class="chart col-md-12">
        <div class="chart-y">
            <span class="chart-y__count"><span>5</span></span>
            <span class="chart-y__count"><span>4</span></span>
            <span class="chart-y__count"><span>3</span></span>
            <span class="chart-y__count"><span>2</span></span>
            <span class="chart-y__count"><span>1</span></span>
            <span class="chart-y__count"><span>0</span></span>
        </div>
        <div class="chart-x">
            <div class="chart-x__value" :data-chart="1" @mouseover="graphHover($event)"
                @mouseleave="graphHover($event)" @mousemove="mouseMove($event)">
                <span class="chart-x__value-graph" :class="{'is-unloaded': animation === 1}" :style="{height: ((1 / 5 ) * 100) + '%' }"></span>
                <span class="tooltip">
                    <span><strong>År:</strong>år</span>
                    <span><strong>Omsætning:</strong> 1</span>
                </span>
            </div>
            <div class="chart-x__value" :data-chart="3" @mouseover="graphHover($event)"
                @mouseleave="graphHover($event)" @mousemove="mouseMove($event)">
                <span class="chart-x__value-graph" :class="{'is-unloaded': animation === 1}" :style="{height: ((3 / 5 ) * 100) + '%' }"></span>
                <span class="tooltip">
                    <span><strong>År:</strong>år</span>
                    <span><strong>Omsætning:</strong> 3</span>
                </span>
            </div>
            <div class="chart-x__value" :data-chart="1" @mouseover="graphHover($event)"
                @mouseleave="graphHover($event)" @mousemove="mouseMove($event)">
                <span class="chart-x__value-graph" :class="{'is-unloaded': animation === 1}" :style="{height: ((2 / 5 ) * 100) + '%' }"></span>
                <span class="tooltip">
                    <span><strong>År:</strong>år</span>
                    <span><strong>Omsætning:</strong> 2</span>
                </span>
            </div>
        </div>
        <div class="chart__labels">
            <span :style="{width: (3 * 100) / 3  + '%'}" class="chart__labels-item">år1</span>
            <span :style="{width: (3 * 100) / 3  + '%'}" class="chart__labels-item">år2</span>
            <span :style="{width: (3 * 100) / 3  + '%'}" class="chart__labels-item">år3</span>
        </div>
    </div>
</div>
                    
                

Scss

                    
$color-blue-big-stone: #181F3A;
$color-blue-cerulean: #0999E8;
$border-color: #E5E8F2;
$color-green-shamrock: #3CD98F;

// main chart
.chart {
	width: 100%;
	height: 450px;
	position: relative;
	padding-left: 3rem;
	padding-bottom: 3rem;
	box-sizing: border-box;
	margin-top: 2rem;

	&--expand {
		padding-left: 6rem;

		.chart-x {
			width: calc(100% - 6rem);
			left: 6rem;
		}

		.chart-labels {
			width: calc(100% - 8rem);
			left: 8rem;
		}
	}
}

//chart y axis
.chart-y {
	width: 100%;
	position: absolute;
	bottom: 3rem;
	height: calc(100% - 3rem);
	left: 0;
	display: flex;
	justify-content: space-between;
	align-items: flex-end;
	flex-direction: column;
	// chart y count
	&__count {
		border-bottom: 1px dotted rgba($color-blue-big-stone, .2);
		width: calc(100% - 3rem);
		padding-left: 1.5rem;
		right: 0;
		position: relative;
	}
	&__count span {
		position: absolute;
		left: -2rem;
	}
	&__count:first-child {
		border-top: 1px dotted rgba($color-blue-big-stone, .2);
		border-bottom: none;
	}
	&__count:last-child {
		border-bottom: 1px solid rgba(24,31,58,.3);
	}
}

// chart x axis
.chart-x {
	width: calc(100% - 3rem);
	height: calc(100% - 3rem);
	left: 3rem;
	bottom: 3rem;
	position: absolute;
	display: inline-flex;
	justify-content: space-around;
	z-index: 5;
	// chart x-value
	&__value {
		width: 100%;
		position: relative;
	}

	&__value-graph {
		content: '';
		background-color: $color-blue-cerulean;
		position: absolute;
		bottom: 0;
		width: 10px;
		border-radius: 5px 5px 0 0;
		left: 50%;
		transform: translateX(-50%);
		pointer-events: none;
		transition: all .5s cubic-bezier(0,1,.82,.86);
	}
}

// chart labels
.chart__labels {
	height: 100%;
	position: absolute;
	bottom: 0rem;
	width: calc(100% - 3rem);
	left: 3rem;
	display: flex;
	justify-content: space-around;
	align-items: flex-end;
	flex-direction: row;

	// chart labels item
	&-item {
		height: 100%;
		margin: 0 auto;
		position: relative;
		display: flex;
		align-items: flex-end;
		justify-content: center;
	}

	&-item::after {
		content: '';
		position: absolute;
		left: 0;
		width: 100%;
		height: calc(100% -3rem);
		top: 0;
		border-left: 1px dotted rgba($color-blue-big-stone, .1);
		margin-bottom: 3rem;
	}

	&-item:last-child {
		&::after {
			border-right: 1px dotted rgba($color-blue-big-stone, .1);
		}
	}

	&-item:first-child {
		&::after {
			border-left: 1px solid rgba($color-blue-big-stone, .3);
		}
	}
}

.is-unloaded {
	// important to overrule in-line styling.
	height: 0% !important;
}

// tooltop (visible on hover)
.tooltip {
	width: auto;
	height: 65px;
	background: #fff;
	display: none;
	justify-content: space-around;
	align-items: flex-start;
	-webkit-box-shadow: 0px 8px 17px -5px rgba(0,0,0,0.29);
	-moz-box-shadow: 0px 8px 17px -5px rgba(0,0,0,0.29);
	box-shadow: 0px 8px 17px -5px rgba(0,0,0,0.29);
	pointer-events: none;
	position: absolute;
	flex-direction: column;
	padding-left: 6px;
	padding-right: 6px;
	border-radius: 5px;
	border: 1px solid $border-color;
	z-index: 10000;

	&::after {
		content: '';
		width: 10px;
		height: 10px;
		z-index: 1;
		position: absolute;
		top: 0;
		background: white;
		top: -5px;
		transform: rotate(45deg);
		-webkit-box-shadow: 0px 8px 17px -5px rgba(0,0,0,0.29);
		-moz-box-shadow: 0px 8px 17px -5px rgba(0,0,0,0.29);
		box-shadow: 0px 8px 17px -5px rgba(0,0,0,0.29);
		border: 1px solid $border-color;
		border-bottom: none;
		border-right: none;
	}

	span {
		font-size: 1.2rem;
	}

	&.is-visible {
		display: flex;
	}
}

                    
                

Vue/javascript

                    
graphHover(event: Event) {
    const target = event.target as HTMLElement;
    const child = target.firstChild as HTMLElement;
    const tooltip = target.children[1] as HTMLElement;

    if (child !== null) {
        if (!child.classList.contains("active")) {
            child.classList.add("active");
            tooltip.classList.add("active");
        } else {
            child.classList.remove("active");
            tooltip.classList.remove("active");
        }
    }
}

mouseMove(event: MouseEvent) {
    const target = event.target as HTMLElement;
    const tooltip = target.children[1] as HTMLElement;

    tooltip.style.top = (event.offsetY + 25) + 'px';
    tooltip.style.left = (event.offsetX) + 'px';
}
                    
                

Linear Graph

Works dynamically with v-for tags in each section

123456
Antal:5Navn: navnnavn
Antal:3Navn: navnnavn
Antal:1Navn: navnnavn

Html

                    
<div class="col-12">
    <h3 class="col-md-12"> Linear Graph</h3>
    <h4 class="col-md-12">Works dynamically with v-for tags in each section</h4>
    <div  class="chart-line" :style="{height: (6 * 60) + 'px'}">
        <div class="chart-line-x">
            <span class="chart-line-x__count"><span>1</span></span>
            <span class="chart-line-x__count"><span>2</span></span>
            <span class="chart-line-x__count"><span>3</span></span>
            <span class="chart-line-x__count"><span>4</span></span>
            <span class="chart-line-x__count"><span>5</span></span>
            <span class="chart-line-x__count"><span>6</span></span>
        </div>
        <div class="chart-line__values">
            <div  class="chart-line__values-value" 
                :data-line="3" 
                @mouseover="graphHover($event)" 
                @mouseleave="graphHover($event)" 
                @mousemove="mouseMove($event)">
                <span class="chart-line__graph" :class="{'is-unloaded': unloaded === 0}" :style="{width: ((5 / 6) * 100) + '%' }" ></span>
                <span class="tooltip">
                    <span><strong>Antal:</strong>5</span>
                    <span><strong>Navn:</strong> navn</span>
                </span>
                <span class="chart-line__values-label">navn</span>
            </div>
            <div  class="chart-line__values-value" 
                :data-line="3" 
                @mouseover="graphHover($event)" 
                @mouseleave="graphHover($event)" 
                @mousemove="mouseMove($event)">
                <span class="chart-line__graph" :class="{'is-unloaded': unloaded === 0}" :style="{width: ((3 / 6) * 100) + '%' }" ></span>
                <span class="tooltip">
                    <span><strong>Antal:</strong>3</span>
                    <span><strong>Navn:</strong> navn</span>
                </span>
                <span class="chart-line__values-label">navn</span>
            </div>
            <div class="chart-line__values-value" 
                :data-line="3" 
                @mouseover="graphHover($event)" 
                @mouseleave="graphHover($event)" 
                @mousemove="mouseMove($event)">
                <span class="chart-line__graph" :class="{'is-unloaded': unloaded === 0}" :style="{width: ((1 / 6) * 100) + '%' }" ></span>
                <span class="tooltip">
                    <span><strong>Antal:</strong>1</span>
                    <span><strong>Navn:</strong> navn</span>
                </span>
                <span class="chart-line__values-label">navn</span>
            </div>
        </div>
    </div>
</div>
                    
                

Scss

                    
$color-blue-big-stone: #181F3A;
$color-blue-cerulean: #0999E8;
$border-color: #E5E8F2;
$color-green-shamrock: #3CD98F;

// main chart
.chart {
	width: 100%;
	height: 450px;
	position: relative;
	padding-left: 3rem;
	padding-bottom: 3rem;
	box-sizing: border-box;
	margin-top: 2rem;

	&--expand {
		padding-left: 6rem;

		.chart-x {
			width: calc(100% - 6rem);
			left: 6rem;
		}

		.chart-labels {
			width: calc(100% - 8rem);
			left: 8rem;
		}
	}
}

// tooltop (visible on hover)
.tooltip {
	width: auto;
	height: 65px;
	background: #fff;
	display: none;
	justify-content: space-around;
	align-items: flex-start;
	-webkit-box-shadow: 0px 8px 17px -5px rgba(0,0,0,0.29);
	-moz-box-shadow: 0px 8px 17px -5px rgba(0,0,0,0.29);
	box-shadow: 0px 8px 17px -5px rgba(0,0,0,0.29);
	pointer-events: none;
	position: absolute;
	flex-direction: column;
	padding-left: 6px;
	padding-right: 6px;
	border-radius: 5px;
	border: 1px solid $border-color;
	z-index: 10000;

	&::after {
		content: '';
		width: 10px;
		height: 10px;
		z-index: 1;
		position: absolute;
		top: 0;
		background: white;
		top: -5px;
		transform: rotate(45deg);
		-webkit-box-shadow: 0px 8px 17px -5px rgba(0,0,0,0.29);
		-moz-box-shadow: 0px 8px 17px -5px rgba(0,0,0,0.29);
		box-shadow: 0px 8px 17px -5px rgba(0,0,0,0.29);
		border: 1px solid $border-color;
		border-bottom: none;
		border-right: none;
	}

	span {
		font-size: 1.2rem;
	}

	&.is-visible {
		display: flex;
	}
}

// Line chart
.chart-line {
	width: 100%;
	position: relative;
	padding-bottom: 3rem;
	box-sizing: border-box;
	margin-top: 1rem;
}

// Line chart x axis
.chart-line-x {
	display: inline-flex;
	bottom: 0;
	position: absolute;
	width: 100%;
	height: 100%;
	justify-content: center;
	align-items: flex-start;

	// chart line x count
	&__count {
		width: 100%;
		right: 0;
		border-right: 1px dotted rgba(24,31,58,.2);
		border-bottom: none;
		display: flex;
		align-items: flex-end;
		height: calc(100% - 30px);
		justify-content: flex-end;
		padding-left: .5rem;
		box-sizing: border-box;
		position: relative;
		border-bottom: 1px dotted rgba(24,31,58,.2);
		border-top: 1px dotted rgba(24,31,58,.2);
	}

	&__count:first-child {
		border-left: 1px dotted rgba(24,31,58,.2);
	}

	&__count span {
		position: absolute;
		bottom: -3rem;
	}

	&:first-child .chart-line-x__count {
		span {
			right: .5rem;
		}

		.first {
			left: .5rem;
		}
	}
}

// Line chart values
.chart-line__values {
	width: 100%;
	height: calc(100% - 3rem);
	bottom: 3rem;
	position: absolute;
	display: inline-flex;
	justify-content: space-around;
	flex-direction: column;
	z-index: 5;

	&-value {
		height: 100%;
		position: relative;
	}

	&-label {
		pointer-events: none;
		transform: translateY(.75rem);
		position: absolute;
		padding-left: 1rem;
		text-transform: capitalize;
		font-size: 1.3rem;
	}
}

// Line chart coloured graph
.chart-line__graph {
	content: '';
	height: 8px;
	background-color: $color-green-shamrock;
	position: absolute;
	left: 0;
	border-radius: 200px;
	pointer-events: none;
	transform: translateY(2.5rem);
	transition: all .3s cubic-bezier(0,1,.82,.86);
}
                    
                

Vue/javascript

                    
graphHover(event: Event) {
    const target = event.target as HTMLElement;
    const child = target.firstChild as HTMLElement;
    const tooltip = target.children[1] as HTMLElement;

    if (child !== null) {
        if (!child.classList.contains("active")) {
            child.classList.add("active");
            tooltip.classList.add("active");
        } else {
            child.classList.remove("active");
            tooltip.classList.remove("active");
        }
    }
}

mouseMove(event: MouseEvent) {
    const target = event.target as HTMLElement;
    const tooltip = target.children[1] as HTMLElement;

    tooltip.style.top = (event.offsetY + 25) + 'px';
    tooltip.style.left = (event.offsetX) + 'px';
}