More layout and chart adjustments to better improve the design

refs: https://github.com/TryGhost/Team/issues/1462

- added back in the main title to the top chart
- brought back the main metric background and centered buttons
- adjusted lots of spacing
- made the chart ticks for main graph dynamic
- improved the look of the breakdown graph
This commit is contained in:
James Morris 2022-04-13 15:19:26 +01:00
parent 3167679b03
commit df30298651
6 changed files with 121 additions and 127 deletions

View File

@ -1,5 +1,10 @@
<section class="gh-dashboard5-section gh-dashboard5-anchor" {{did-insert this.loadCharts}}> <section class="gh-dashboard5-section gh-dashboard5-anchor" {{did-insert this.loadCharts}}>
<article class="gh-dashboard5-box"> <article class="gh-dashboard5-box">
{{#if this.hasPaidTiers}}
<div class="gh-dashboard5-title">
<h4>{{this.chartTitle}}</h4>
</div>
{{/if}}
<div class="gh-dashboard5-hero {{unless this.hasPaidTiers 'is-solo'}}"> <div class="gh-dashboard5-hero {{unless this.hasPaidTiers 'is-solo'}}">
{{#unless this.hasPaidTiers}} {{#unless this.hasPaidTiers}}
<Dashboard::v5::Parts::Metric <Dashboard::v5::Parts::Metric
@ -29,6 +34,10 @@
@height={{if this.hasPaidTiers this.chartHeight this.chartHeightSmall}} /> @height={{if this.hasPaidTiers this.chartHeight this.chartHeightSmall}} />
{{/if}} {{/if}}
</div> </div>
<div class="gh-dashboard5-chart-ticks">
<span id="gh-dashboard5-anchor-date-start"> </span>
<span id="gh-dashboard5-anchor-date-end"> </span>
</div>
{{/if}} {{/if}}
</div> </div>
@ -38,24 +47,27 @@
<Dashboard::v5::Parts::Metric <Dashboard::v5::Parts::Metric
@label={{gh-pluralize this.totalMembers "Total member" without-count=true}} @label={{gh-pluralize this.totalMembers "Total member" without-count=true}}
@value={{format-number this.totalMembers}} @value={{format-number this.totalMembers}}
@trends={{this.hasTrends}} {{!-- @trends={{this.hasTrends}} --}}
@percentage={{this.totalMembersTrend}} {{!-- @percentage={{this.totalMembersTrend}} --}}
@center={{true}}
@large={{true}} /> @large={{true}} />
</button> </button>
<button class="gh-dashboard5-stats-button {{if this.chartShowingPaid 'is-selected'}}" type="button" {{on "click" (fn this.changeChartDisplay "paid-total")}}> <button class="gh-dashboard5-stats-button {{if this.chartShowingPaid 'is-selected'}}" type="button" {{on "click" (fn this.changeChartDisplay "paid-total")}}>
<Dashboard::v5::Parts::Metric <Dashboard::v5::Parts::Metric
@label={{gh-pluralize this.paidMembers "Total paid member" without-count=true}} @label={{gh-pluralize this.paidMembers "Total paid member" without-count=true}}
@value={{format-number this.paidMembers}} @value={{format-number this.paidMembers}}
@trends={{this.hasTrends}} {{!-- @trends={{this.hasTrends}} --}}
@percentage={{this.paidMembersTrend}} {{!-- @percentage={{this.paidMembersTrend}} --}}
@center={{true}}
@large={{true}} /> @large={{true}} />
</button> </button>
<button class="gh-dashboard5-stats-button {{if this.chartShowingMrr 'is-selected'}}" type="button" {{on "click" (fn this.changeChartDisplay "mrr")}}> <button class="gh-dashboard5-stats-button {{if this.chartShowingMrr 'is-selected'}}" type="button" {{on "click" (fn this.changeChartDisplay "mrr")}}>
<Dashboard::v5::Parts::Metric <Dashboard::v5::Parts::Metric
@label="MRR" @label="Monthly Revenue (MRR)"
@value="${{gh-price-amount this.currentMRR}}" @value="${{gh-price-amount this.currentMRR}}"
@trends={{this.hasTrends}} {{!-- @trends={{this.hasTrends}} --}}
@percentage={{this.mrrTrend}} {{!-- @percentage={{this.mrrTrend}} --}}
@center={{true}}
@large={{true}} /> @large={{true}} />
</button> </button>
</div> </div>

View File

@ -4,7 +4,7 @@ import {action} from '@ember/object';
import {inject as service} from '@ember/service'; import {inject as service} from '@ember/service';
import {tracked} from '@glimmer/tracking'; import {tracked} from '@glimmer/tracking';
const DATE_FORMAT = 'D MMM YYYY'; const DATE_FORMAT = 'D MMM';
const DAYS_OPTIONS = [{ const DAYS_OPTIONS = [{
name: '7 Days', name: '7 Days',
@ -150,6 +150,15 @@ export default class Anchor extends Component {
return this.dashboardStats.siteStatus?.hasPaidTiers; return this.dashboardStats.siteStatus?.hasPaidTiers;
} }
get chartTitle() {
if (this.chartDisplay === 'paid-total' || this.chartDisplay === 'paid-breakdown') {
return 'Total paid members';
} else if (this.chartDisplay === 'mrr') {
return 'Monthly revenue (MRR)';
}
return 'Total members';
}
get chartType() { get chartType() {
if (this.chartDisplay === 'paid-breakdown') { if (this.chartDisplay === 'paid-breakdown') {
return 'bar'; return 'bar';
@ -170,7 +179,7 @@ export default class Anchor extends Component {
labels = stats.map(stat => stat.date); labels = stats.map(stat => stat.date);
newData = stats.map(stat => stat.paidSubscribed); newData = stats.map(stat => stat.paidSubscribed);
canceledData = stats.map(stat => -stat.paidCanceled); canceledData = stats.map(stat => -stat.paidCanceled);
return { return {
labels: labels, labels: labels,
datasets: [ datasets: [
@ -231,16 +240,6 @@ export default class Anchor extends Component {
} }
get chartOptions() { get chartOptions() {
let maxNumberOfTicks = 7;
if (this.selectedDaysOption.value === 30) {
maxNumberOfTicks = 15;
}
if (this.selectedDaysOption.value === 90 || this.selectedDaysOption.value === 'all') {
maxNumberOfTicks = 20;
}
if (this.chartDisplay === 'paid-breakdown') { if (this.chartDisplay === 'paid-breakdown') {
return { return {
responsive: true, responsive: true,
@ -279,18 +278,18 @@ export default class Anchor extends Component {
}, },
scales: { scales: {
yAxes: [{ yAxes: [{
offset: true, offset: false,
gridLines: { gridLines: {
drawTicks: false, drawTicks: false,
display: true, display: true,
drawBorder: false, drawBorder: false,
color: 'rgba(255, 255, 255, 0.1)', color: 'rgba(255, 255, 255, 0.1)',
lineWidth: 0, lineWidth: 0,
zeroLineColor: 'rgba(200, 204, 217, 0.75)', zeroLineColor: this.feature.nightShift ? 'rgba(200, 204, 217, 0.25)' : 'rgba(200, 204, 217, 0.65)',
zeroLineWidth: 1 zeroLineWidth: 1
}, },
ticks: { ticks: {
display: true, display: false,
maxTicksLimit: 5, maxTicksLimit: 5,
fontColor: '#7C8B9A', fontColor: '#7C8B9A',
padding: 8, padding: 8,
@ -301,35 +300,25 @@ export default class Anchor extends Component {
offset: true, offset: true,
stacked: true, stacked: true,
gridLines: { gridLines: {
color: 'rgba(200, 204, 217, 0.75)', color: this.feature.nightShift ? 'rgba(200, 204, 217, 0.25)' : 'rgba(200, 204, 217, 0.65)',
borderDash: [4,4], borderDash: [4,4],
display: true, display: true,
drawBorder: true, drawBorder: false,
drawTicks: false, drawTicks: false,
zeroLineWidth: 1, zeroLineWidth: 1,
zeroLineColor: 'rgba(200, 204, 217, 0.75)', zeroLineColor: this.feature.nightShift ? 'rgba(200, 204, 217, 0.25)' : 'rgba(200, 204, 217, 0.65)',
zeroLineBorderDash: [4,4] zeroLineBorderDash: [4,4]
}, },
ticks: { ticks: {
display: true, display: false,
maxRotation: 0, callback: function (value, index, values) {
minRotation: 0, if (index === 0) {
padding: 8, document.getElementById('gh-dashboard5-anchor-date-start').innerHTML = moment(value).format(DATE_FORMAT);
autoSkip: true, }
maxTicksLimit: maxNumberOfTicks if (index === values.length - 1) {
}, document.getElementById('gh-dashboard5-anchor-date-end').innerHTML = moment(value).format(DATE_FORMAT);
type: 'time', }
time: { return value;
displayFormats: {
millisecond: 'MMM DD',
second: 'MMM DD',
minute: 'MMM DD',
hour: 'MMM DD',
day: 'MMM DD',
week: 'MMM DD',
month: 'MMM DD',
quarter: 'MMM DD',
year: 'MMM DD'
} }
} }
}] }]
@ -392,12 +381,13 @@ export default class Anchor extends Component {
}, },
scales: { scales: {
yAxes: [{ yAxes: [{
display: true,
gridLines: { gridLines: {
drawTicks: false, drawTicks: false,
display: true, display: true,
drawBorder: false, drawBorder: false,
color: 'transparent', color: 'transparent',
zeroLineColor: this.feature.nightShift ? 'rgba(200, 204, 217, 0.25)' : 'rgba(200, 204, 217, 0.85)', zeroLineColor: this.feature.nightShift ? 'rgba(200, 204, 217, 0.25)' : 'rgba(200, 204, 217, 0.65)',
zeroLineWidth: 1 zeroLineWidth: 1
}, },
ticks: { ticks: {
@ -407,46 +397,35 @@ export default class Anchor extends Component {
padding: 8, padding: 8,
precision: 0, precision: 0,
stepSize: 1 stepSize: 1
}, }
display: true
}], }],
xAxes: [{ xAxes: [{
display: true,
scaleLabel: {
align: 'start'
},
gridLines: { gridLines: {
color: this.feature.nightShift ? 'rgba(200, 204, 217, 0.25)' : 'rgba(200, 204, 217, 0.85)', color: this.feature.nightShift ? 'rgba(200, 204, 217, 0.25)' : 'rgba(200, 204, 217, 0.65)',
borderDash: [4,4], borderDash: [4,4],
display: true, display: true,
drawBorder: true, drawBorder: true,
drawTicks: false, drawTicks: false,
zeroLineWidth: 1, zeroLineWidth: 1,
zeroLineColor: this.feature.nightShift ? 'rgba(200, 204, 217, 0.25)' : 'rgba(200, 204, 217, 0.85)', zeroLineColor: this.feature.nightShift ? 'rgba(200, 204, 217, 0.25)' : 'rgba(200, 204, 217, 0.65)',
zeroLineBorderDash: [4,4] zeroLineBorderDash: [4,4]
}, },
ticks: { ticks: {
display: true, display: false,
maxRotation: 0, callback: function (value, index, values) {
minRotation: 0, if (index === 0) {
padding: 14, document.getElementById('gh-dashboard5-anchor-date-start').innerHTML = moment(value).format(DATE_FORMAT);
autoSkip: true, }
maxTicksLimit: maxNumberOfTicks, if (index === values.length - 1) {
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Droid Sans", "Helvetica Neue", sans-serif', document.getElementById('gh-dashboard5-anchor-date-end').innerHTML = moment(value).format(DATE_FORMAT);
fontSize: 11, }
fontColor: '#ABB4BE' return value;
},
type: 'time',
time: {
displayFormats: {
millisecond: 'MMM DD',
second: 'MMM DD',
minute: 'MMM DD',
hour: 'MMM DD',
day: 'MMM DD',
week: 'MMM DD',
month: 'MMM DD',
quarter: 'MMM DD',
year: 'MMM DD'
} }
}, }
display: true
}] }]
} }
}; };

View File

@ -2,7 +2,8 @@
<article class="gh-dashboard5-box"> <article class="gh-dashboard5-box">
<Dashboard::v5::Parts::Metric <Dashboard::v5::Parts::Metric
@label="Email open rate" @label="Email open rate"
@value="{{this.currentOpenRate}}%" /> @value="{{this.currentOpenRate}}%"
/>
<div class="gh-dashboard5-chart"> <div class="gh-dashboard5-chart">
{{#if this.loading}} {{#if this.loading}}

View File

@ -4,13 +4,15 @@
<div class="gh-dashboard5-row"> <div class="gh-dashboard5-row">
<Dashboard::v5::Parts::Metric <Dashboard::v5::Parts::Metric
@label="Newsletter subscribers" @label="Newsletter subscribers"
@value={{format-number this.dataSubscribers.total}} /> @value={{format-number this.dataSubscribers.total}}
/>
</div> </div>
<div class="gh-dashboard5-row"> <div class="gh-dashboard5-row">
<Dashboard::v5::Parts::Metric <Dashboard::v5::Parts::Metric
@label="Emails sent over last 30 days" @label="Emails sent over last 30 days"
@value={{format-number this.dataEmailsSent}} /> @value={{format-number this.dataEmailsSent}}
/>
</div> </div>
</div> </div>
</article> </article>

View File

@ -1102,6 +1102,16 @@ kbd {
/* Dashboard v5 */ /* Dashboard v5 */
.gh-dashboard5 .gh-dashboard5-anchor .gh-dashboard5-stats {
background: transparent;
border-top-color: #2b2d31;
}
.gh-dashboard5 .gh-dashboard5-anchor .gh-dashboard5-stats-button {
border-color: #202429;
}
.gh-dashboard5 .gh-dashboard5-anchor .gh-dashboard5-stats-button.is-selected { .gh-dashboard5 .gh-dashboard5-anchor .gh-dashboard5-stats-button.is-selected {
border-color: #394047; border-color: #394047;
} }

View File

@ -86,7 +86,7 @@ Dashboard v5 Layout */
.gh-dashboard5-row { .gh-dashboard5-row {
flex: 1; flex: 1;
padding: 4px 0 16px 0; padding: 0 0 16px 0;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: flex-start; justify-content: flex-start;
@ -103,15 +103,15 @@ Dashboard v5 Layout */
.gh-dashboard5-title { .gh-dashboard5-title {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
margin: 0 0 16px; margin: 0 0 20px;
} }
.gh-dashboard5-title h4 { .gh-dashboard5-title h4 {
margin: 0 16px 0 0; font-size: 1.5rem;
font-size: 1.65rem;
font-weight: 600; font-weight: 600;
line-height: 1.4em; color: var(--black);
color: #15171a; margin: 0;
padding: 0;
} }
.gh-dashboard5-box { .gh-dashboard5-box {
@ -144,15 +144,15 @@ Dashboard v5 Layout */
.gh-dashboard5-selects { .gh-dashboard5-selects {
position: absolute; position: absolute;
top: 17px; top: 14px;
right: 4px; right: 2px;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
} }
.gh-dashboard5-select { .gh-dashboard5-select {
position: absolute; position: absolute;
top: 17px; top: 16px;
right: 4px; right: 4px;
} }
@ -165,11 +165,11 @@ Dashboard v5 Layout */
.gh-dashboard5-select .ember-power-select-selected-item { .gh-dashboard5-select .ember-power-select-selected-item {
font-size: 1.1rem; font-size: 1.1rem;
text-transform: uppercase; text-transform: uppercase;
font-weight: 500; font-weight: 600;
letter-spacing: .3px; letter-spacing: .3px;
line-height: 1em; line-height: 1em;
padding: 0; padding: 0;
color: var(--midgrey); color: var(--middarkgrey);
white-space: nowrap; white-space: nowrap;
} }
@ -274,8 +274,13 @@ Dashboard v5 Metric */
line-height: 1em; line-height: 1em;
margin: 0 0 12px; margin: 0 0 12px;
padding: 0; padding: 0;
color: var(--midgrey); color: var(--middarkgrey);
white-space: nowrap; white-space: nowrap;
font-size: 1.1rem;
text-transform: uppercase;
letter-spacing: .2px;
font-weight: 500;
} }
.gh-dashboard5-metric.is-large .gh-dashboard5-metric-label { .gh-dashboard5-metric.is-large .gh-dashboard5-metric-label {
@ -294,17 +299,17 @@ Dashboard v5 Metric */
.gh-dashboard5-metric-value { .gh-dashboard5-metric-value {
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
font-size: 2.6rem; font-size: 2.4rem;
font-weight: 600; font-weight: 600;
letter-spacing: -.1px; letter-spacing: -.1px;
line-height: 1em; line-height: 1em;
white-space: nowrap; white-space: nowrap;
margin: 0 0 8px; margin: 0 0 12px;
gap: 10px; gap: 10px;
} }
.gh-dashboard5-metric.is-large .gh-dashboard5-metric-value { .gh-dashboard5-metric.is-large .gh-dashboard5-metric-value {
font-size: 3.2rem; font-size: 3rem;
font-weight: 600; font-weight: 600;
margin-bottom: 0; margin-bottom: 0;
} }
@ -314,7 +319,7 @@ Dashboard v5 Metric */
} }
.gh-dashboard5-metric.is-reverse.is-large .gh-dashboard5-metric-value { .gh-dashboard5-metric.is-reverse.is-large .gh-dashboard5-metric-value {
margin-bottom: 6px; margin-bottom: 8px;
} }
.gh-dashboard5-metric-extra { .gh-dashboard5-metric-extra {
@ -434,19 +439,18 @@ Dashboard v5 Section Anchor */
} }
.gh-dashboard5-anchor .gh-dashboard5-box { .gh-dashboard5-anchor .gh-dashboard5-box {
padding: 24px 24px 8px; padding: 20px 24px 8px;
} }
.gh-dashboard5-anchor .gh-dashboard5-stats { .gh-dashboard5-anchor .gh-dashboard5-stats {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
width: calc(100% + 48px); width: calc(100% + 48px);
padding: 0 8px; padding: 8px;
margin: 12px -24px 0; margin: 4px -24px -8px;
} border-radius: 0 0 4px 4px;
background: rgba(253,253,253,1);
.gh-dashboard5-anchor .gh-dashboard5-title { border-top: 1px solid var(--whitegrey);
margin-bottom: 24px;
} }
.gh-dashboard5-anchor.is-top .gh-dashboard5-stats { .gh-dashboard5-anchor.is-top .gh-dashboard5-stats {
@ -459,19 +463,24 @@ Dashboard v5 Section Anchor */
cursor: pointer; cursor: pointer;
position: relative; position: relative;
flex: 1; flex: 1;
padding: 20px 16px 24px 16px; padding: 16px 24px 20px;
margin: 2px 4px 2px 2px; margin: 2px 8px 2px 2px;
text-align: left; text-align: left;
background: transparent; background: transparent;
border: 1px solid transparent;
border-radius: 5px; border-radius: 5px;
color: var(--black);
/* border: 1px solid #eff2f4; */
}
.gh-dashboard5-anchor .gh-dashboard5-stats-button:last-child {
margin-right: 2px;
} }
.gh-dashboard5-anchor .gh-dashboard5-stats-button.is-selected { .gh-dashboard5-anchor .gh-dashboard5-stats-button.is-selected {
color: var(--black); color: var(--black);
background: var(--white) !important; background: var(--white);
box-shadow: 0 0 12px rgb(0 0 0 / 3%); box-shadow: 0 2px 4px rgb(0 0 0 / 2%);
border: 1px solid var(--whitegrey); border: 1px solid rgb(235 235 235);
} }
.gh-dashboard5-anchor .gh-dashboard5-stats.is-solo .gh-dashboard5-stats-button.is-selected { .gh-dashboard5-anchor .gh-dashboard5-stats.is-solo .gh-dashboard5-stats-button.is-selected {
@ -498,24 +507,13 @@ Dashboard v5 Section Anchor */
.gh-dashboard5-anchor .gh-dashboard5-chart { .gh-dashboard5-anchor .gh-dashboard5-chart {
flex-direction: column; flex-direction: column;
margin-left: -16px;
margin-right: -16px;
margin-top: 12px;
} }
.gh-dashboard5-anchor .gh-dashboard5-chart-ticks { .gh-dashboard5-anchor .gh-dashboard5-chart-ticks {
flex-direction: row; flex-direction: row;
padding: 12px 0 4px; padding: 10px 0;
font-size: 1.2rem; font-size: 1.2rem;
} color: var(--midlightgrey);
.gh-dashboard5-anchor .gh-dashboard5-chart-ticks span {
opacity: 0.5;
}
.gh-dashboard5-anchor .gh-dashboard5-chart-ticks span:first-child,
.gh-dashboard5-anchor .gh-dashboard5-chart-ticks span:last-child {
opacity: 1;
} }
@ -531,10 +529,6 @@ Dashboard v5 Section Engagement */
padding-top: 28px; padding-top: 28px;
} }
.gh-dashboard5-engagement .gh-dashboard5-select {
top: 20px;
}
/* --------------------------------- /* ---------------------------------
Dashboard v5 Section Email */ Dashboard v5 Section Email */
@ -560,17 +554,13 @@ Dashboard v5 Section Email Open Rate */
} }
.gh-dashboard5-email-open-rate .gh-dashboard5-chart { .gh-dashboard5-email-open-rate .gh-dashboard5-chart {
margin: 24px 0 0; margin: 28px 0 0;
} }
.gh-dashboard5-email-open-rate .gh-dashboard5-chart-ticks { .gh-dashboard5-email-open-rate .gh-dashboard5-chart-ticks {
padding: 0 16px 0 0; padding: 0 16px 0 0;
} }
.gh-dashboard5-email-open-rate .gh-dashboard5-metric-label {
padding-top: 4px;
}
/* --------------------------------- /* ---------------------------------
Dashboard v5 Section Recent Posts */ Dashboard v5 Section Recent Posts */