From 2729a0e5fb62f26316ee1c5358d063491570f687 Mon Sep 17 00:00:00 2001 From: Kael Date: Sat, 1 Dec 2018 05:05:34 +1100 Subject: [PATCH] feat: add sparkline component (#4923) * feat: add sparkline * fix: sparkline porps * feat(sparkline): add show-label prop * refactor(VSparkline): rename file to .ts * refactor(VSparkline): add types * test: update a-la-carte snapshots * style: combine imports * docs: add props as wrapperFor * docs: add sparklines page and example * fix: use non-boolean smooth values in rect * docs: add meta info, "new" tag in drawer * docs: update sparkline playground and prop descriptions * docs: reduce width slider max value * docs: add type for "type" prop * docs: add labels to playground button groups * docs: fix "type" prop definition * enh: reduce default auto-draw duration for type="bar" * docs: add AppDrawer.sparklines string Co-authored-by: qingwei.li --- packages/api-generator/src/map.js | 9 ++ .../vuetify/src/components/VSparkline/Bar.ts | 70 +++++++++++ .../src/components/VSparkline/Trend.ts | 80 +++++++++++++ .../src/components/VSparkline/VSparkline.ts | 50 ++++++++ .../VSparkline/components/gradient.ts | 35 ++++++ .../components/VSparkline/components/path.ts | 24 ++++ .../components/VSparkline/components/rect.ts | 62 ++++++++++ .../components/VSparkline/components/text.ts | 32 +++++ .../src/components/VSparkline/helpers/core.ts | 21 ++++ .../src/components/VSparkline/helpers/math.ts | 31 +++++ .../src/components/VSparkline/helpers/path.ts | 36 ++++++ .../src/components/VSparkline/index.ts | 5 + .../src/components/VSparkline/mixins/props.ts | 40 +++++++ packages/vuetify/src/components/index.ts | 1 + .../importA-la-carte.spec.js.snap | 1 + .../__snapshots__/importFull.spec.js.snap | 1 + .../__snapshots__/importLib.spec.js.snap | 1 + .../test/integration/importA-la-carte.spec.js | 2 + .../test/integration/importLib.spec.js | 2 + .../vuetifyjs.com/src/data/drawerItems.json | 1 + .../src/data/pages/components/Sparklines.json | 24 ++++ .../src/examples/sparklines/playground.vue | 112 ++++++++++++++++++ .../src/lang/en/components/Sparklines.json | 23 ++++ packages/vuetifyjs.com/src/lang/en/meta.json | 6 + .../src/lang/en/vuetify/AppDrawer.json | 1 + 25 files changed, 670 insertions(+) create mode 100644 packages/vuetify/src/components/VSparkline/Bar.ts create mode 100644 packages/vuetify/src/components/VSparkline/Trend.ts create mode 100644 packages/vuetify/src/components/VSparkline/VSparkline.ts create mode 100644 packages/vuetify/src/components/VSparkline/components/gradient.ts create mode 100644 packages/vuetify/src/components/VSparkline/components/path.ts create mode 100644 packages/vuetify/src/components/VSparkline/components/rect.ts create mode 100644 packages/vuetify/src/components/VSparkline/components/text.ts create mode 100644 packages/vuetify/src/components/VSparkline/helpers/core.ts create mode 100644 packages/vuetify/src/components/VSparkline/helpers/math.ts create mode 100644 packages/vuetify/src/components/VSparkline/helpers/path.ts create mode 100644 packages/vuetify/src/components/VSparkline/index.ts create mode 100644 packages/vuetify/src/components/VSparkline/mixins/props.ts create mode 100644 packages/vuetifyjs.com/src/data/pages/components/Sparklines.json create mode 100644 packages/vuetifyjs.com/src/examples/sparklines/playground.vue create mode 100644 packages/vuetifyjs.com/src/lang/en/components/Sparklines.json diff --git a/packages/api-generator/src/map.js b/packages/api-generator/src/map.js index 3a5f3696e49..c0a4dc90196 100755 --- a/packages/api-generator/src/map.js +++ b/packages/api-generator/src/map.js @@ -720,6 +720,15 @@ module.exports = { 'v-snackbar': { slots: ['default'] }, + 'v-sparkline': { + props: [ + { + name: 'type', + type: "'trend' | 'bar'", + default: "'trend'" + } + ] + }, 'v-select': VSelect, 'v-slider': { events: [ diff --git a/packages/vuetify/src/components/VSparkline/Bar.ts b/packages/vuetify/src/components/VSparkline/Bar.ts new file mode 100644 index 00000000000..ce2fd0af076 --- /dev/null +++ b/packages/vuetify/src/components/VSparkline/Bar.ts @@ -0,0 +1,70 @@ +import mixins from '../../util/mixins' +import { VNode } from 'vue' + +import props from './mixins/props' +import Rect from './components/rect' +import Text from './components/text' +import Gradient from './components/gradient' +import { genPoints } from './helpers/core' + +export default mixins(props).extend({ + name: 'bar', + + props: { + autoDrawDuration: { + type: Number, + default: 500 + } + }, + + render (h): VNode { + if (!this.data || this.data.length < 2) return undefined as never + const { width, height, padding, lineWidth } = this + const viewWidth = width || 300 + const viewHeight = height || 75 + const boundary = { + minX: padding, + minY: padding, + maxX: viewWidth - padding, + maxY: viewHeight - padding + } + const props = this.$props + + props.points = genPoints(this.data, boundary) + + const totalWidth = boundary.maxX / (props.points.length - 1) + + props.boundary = boundary + props.id = 'sparkline-bar-' + this._uid + props.lineWidth = lineWidth || (totalWidth - (padding || 5)) + props.offsetX = (totalWidth - props.lineWidth) / 2 + + return h('svg', { + attrs: { + width: width || '100%', + height: height || '25%', + viewBox: `0 0 ${viewWidth} ${viewHeight}` + } + }, [ + h(Gradient, { props }), + h(Rect, { props }), + this.showLabel ? h(Text, { props }) : undefined as never, + h('g', { + attrs: { + transform: `scale(1,-1) translate(0,-${boundary.maxY})`, + 'clip-path': `url(#${props.id}-clip)`, + fill: `url(#${props.id})` + } + }, [ + h('rect', { + attrs: { + x: 0, + y: 0, + width: viewWidth, + height: viewHeight + } + }) + ]) + ]) + } +}) diff --git a/packages/vuetify/src/components/VSparkline/Trend.ts b/packages/vuetify/src/components/VSparkline/Trend.ts new file mode 100644 index 00000000000..35ab6a11ee2 --- /dev/null +++ b/packages/vuetify/src/components/VSparkline/Trend.ts @@ -0,0 +1,80 @@ +import { VNode } from 'vue' +import mixins, { ExtractVue } from '../../util/mixins' + +import props from './mixins/props' +import Path from './components/path' +import Text from './components/text' +import Gradient from './components/gradient' +import { genPoints } from './helpers/core' + +interface options { + $refs: { + path: InstanceType + } +} + +export default mixins>(props).extend({ + name: 'trend', + + data: () => ({ + lastLength: 0 + }), + + watch: { + data: { + immediate: true, + handler () { + this.$nextTick(() => { + if (!this.autoDraw) { + return + } + + const path = this.$refs.path.$el + const length = path.getTotalLength() + + path.style.transition = 'none' + path.style.strokeDasharray = length + ' ' + length + path.style.strokeDashoffset = Math.abs(length - (this.lastLength || 0)).toString() + path.getBoundingClientRect() + path.style.transition = `stroke-dashoffset ${this.autoDrawDuration}ms ${this.autoDrawEasing}` + path.style.strokeDashoffset = '0' + this.lastLength = length + }) + } + } + }, + + render (h): VNode { + if (!this.data || this.data.length < 2) return undefined as never + const { width, height, padding } = this + const viewWidth = width || 300 + const viewHeight = height || 75 + const boundary = { + minX: padding, + minY: padding, + maxX: viewWidth - padding, + maxY: viewHeight - padding + } + const props = this.$props + + props.boundary = boundary + props.id = 'sparkline-trend-' + this._uid + props.points = genPoints(this.data, boundary) + + return h('svg', { + attrs: { + 'stroke-width': this.lineWidth || 1, + width: width || '100%', + height: height || '25%', + viewBox: `0 0 ${viewWidth} ${viewHeight}` + } + }, [ + h(Gradient, { props }), + this.showLabel ? h(Text, { props }) : undefined as never, + h(Path, { + props, + ref: 'path' + }) + ]) + } +}) diff --git a/packages/vuetify/src/components/VSparkline/VSparkline.ts b/packages/vuetify/src/components/VSparkline/VSparkline.ts new file mode 100644 index 00000000000..d5d1c69204d --- /dev/null +++ b/packages/vuetify/src/components/VSparkline/VSparkline.ts @@ -0,0 +1,50 @@ +import Vue from 'vue' +import { PropValidator } from 'vue/types/options' + +import bar from './Bar' +import trend from './Trend' +import props from './mixins/props' + +const COMPONENTS = { + bar, + trend +} + +export type SparklineItem = number | { value: number } + +export interface Boundary { + minX: number + minY: number + maxX: number + maxY: number +} + +export interface Point { + x: number + y: number + value: number +} + +export default Vue.extend({ + name: 'v-sparkline', + + functional: true, + + $_wrapperFor: props, + + props: { + type: { + type: String, + default: 'trend', + validator: (val: string) => ['trend', 'bar'].includes(val) + } as PropValidator<'trend' | 'bar'> + }, + + render (h, { props, data }) { + return h('div', { + staticClass: 'sparkline' + }, [ + h(COMPONENTS[props.type], data) + ]) + } +}) diff --git a/packages/vuetify/src/components/VSparkline/components/gradient.ts b/packages/vuetify/src/components/VSparkline/components/gradient.ts new file mode 100644 index 00000000000..0129ddaea11 --- /dev/null +++ b/packages/vuetify/src/components/VSparkline/components/gradient.ts @@ -0,0 +1,35 @@ +/* eslint-disable no-multi-spaces, object-property-newline */ + +import Vue, { VNode } from 'vue' +import { Prop } from 'vue/types/options' + +export default Vue.extend({ + props: ['gradient', 'id', 'gradientDirection'] as any as { + gradient: Prop + id: Prop + gradientDirection: Prop + }, + + render (h): VNode { + const { gradient, id, gradientDirection } = this + const len = gradient.length - 1 + const stops = gradient.slice().reverse().map((color, index) => + h('stop', { + attrs: { + offset: index / len, + 'stop-color': color + } + }) + ) + + return h('defs', [ + h('linearGradient', { + attrs: { + id, + x1: +(gradientDirection === 'left'), y1: +(gradientDirection === 'top'), + x2: +(gradientDirection === 'right'), y2: +(gradientDirection === 'bottom') + } + }, stops) + ]) + } +}) diff --git a/packages/vuetify/src/components/VSparkline/components/path.ts b/packages/vuetify/src/components/VSparkline/components/path.ts new file mode 100644 index 00000000000..9ba4202442b --- /dev/null +++ b/packages/vuetify/src/components/VSparkline/components/path.ts @@ -0,0 +1,24 @@ +import Vue, { VNode } from 'vue' +import { Prop } from 'vue/types/options' + +import { Point } from '../VSparkline' +import { genPath } from '../helpers/path' + +export default Vue.extend().extend({ + props: ['smooth', 'radius', 'id', 'points'] as any as { + smooth: Prop + radius: Prop + id: Prop + points: Prop + }, + + render (h): VNode { + const { smooth, id } = this + const radius = smooth === true ? 8 : Number(smooth) + const d = genPath(this.points, radius) + + return h('path', { + attrs: { d, fill: 'none', stroke: `url(#${id})` } + }) + } +}) diff --git a/packages/vuetify/src/components/VSparkline/components/rect.ts b/packages/vuetify/src/components/VSparkline/components/rect.ts new file mode 100644 index 00000000000..2b62697d36a --- /dev/null +++ b/packages/vuetify/src/components/VSparkline/components/rect.ts @@ -0,0 +1,62 @@ +import Vue, { VNode } from 'vue' +import { Prop } from 'vue/types/options' + +import { Boundary, Point } from '../VSparkline' + +export default Vue.extend({ + props: [ + 'id', + 'smooth', + 'boundary', + 'lineWidth', + 'gradient', + 'autoDrawDuration', + 'autoDraw', + 'points', + 'offsetX' + ] as any as { + id: Prop + smooth: Prop + boundary: Prop + lineWidth: Prop + gradient: Prop + autoDrawDuration: Prop + autoDraw: Prop + points: Prop + offsetX: Prop + }, + + render (h): VNode { + const { maxY } = this.boundary + const rounding = typeof this.smooth === 'number' + ? this.smooth + : this.smooth ? 2 : 0 + + return h('clipPath', { + attrs: { + id: `${this.id}-clip` + } + }, this.points.map((item, index) => + h('rect', { + attrs: { + x: item.x - this.offsetX, + y: 0, + width: this.lineWidth, + height: maxY - item.y, + rx: rounding, + ry: rounding + } + }, [ + this.autoDraw ? h('animate', { + attrs: { + attributeName: 'height', + from: 0, + to: maxY - item.y, + dur: `${this.autoDrawDuration}ms`, + fill: 'freeze' + } + }) : undefined as never + ]) + )) + } +}) diff --git a/packages/vuetify/src/components/VSparkline/components/text.ts b/packages/vuetify/src/components/VSparkline/components/text.ts new file mode 100644 index 00000000000..37c3c454a98 --- /dev/null +++ b/packages/vuetify/src/components/VSparkline/components/text.ts @@ -0,0 +1,32 @@ +import Vue, { VNode } from 'vue' +import { Prop } from 'vue/types/options' + +import { Boundary, Point } from '../VSparkline' + +export default Vue.extend({ + props: ['points', 'boundary', 'offsetX'] as any as { + points: Prop + boundary: Prop + offsetX: Prop + }, + + render (h): VNode { + const offsetX = (this.offsetX || 0) / 2 + + return h('g', { + style: { + fontSize: '8', + textAnchor: 'middle', + dominantBaseline: 'mathematical', + fill: this.$vuetify.theme.secondary + } + }, this.points.map(item => ( + h('text', { + attrs: { + x: item.x - offsetX, + y: this.boundary.maxY + 2 + } + }, item.value.toString()) + ))) + } +}) diff --git a/packages/vuetify/src/components/VSparkline/helpers/core.ts b/packages/vuetify/src/components/VSparkline/helpers/core.ts new file mode 100644 index 00000000000..0a33c52d416 --- /dev/null +++ b/packages/vuetify/src/components/VSparkline/helpers/core.ts @@ -0,0 +1,21 @@ +import { SparklineItem, Boundary, Point } from '../VSparkline' + +export function genPoints (points: SparklineItem[], boundary: Boundary): Point[] { + const { minX, minY, maxX, maxY } = boundary + const normalisedPoints = points.map(item => (typeof item === 'number' ? item : item.value)) + const minValue = Math.min(...normalisedPoints) - 0.001 + const gridX = (maxX - minX) / (normalisedPoints.length - 1) + const gridY = (maxY - minY) / (Math.max(...normalisedPoints) + 0.001 - minValue) + + return normalisedPoints.map((value, index) => { + return { + x: index * gridX + minX, + y: + maxY - + (value - minValue) * gridY + + +(index === normalisedPoints.length - 1) * 0.00001 - + +(index === 0) * 0.00001, + value + } + }) +} diff --git a/packages/vuetify/src/components/VSparkline/helpers/math.ts b/packages/vuetify/src/components/VSparkline/helpers/math.ts new file mode 100644 index 00000000000..3c46d68b35d --- /dev/null +++ b/packages/vuetify/src/components/VSparkline/helpers/math.ts @@ -0,0 +1,31 @@ +import { Point } from '../VSparkline' + +function int (value: string | number): number { + return parseInt(value, 10) +} + +/** + * https://en.wikipedia.org/wiki/Collinearity + * x=(x1+x2)/2 + * y=(y1+y2)/2 + */ +export function checkCollinear (p0: Point, p1: Point, p2: Point): boolean { + return int(p0.x + p2.x) === int(2 * p1.x) && int(p0.y + p2.y) === int(2 * p1.y) +} + +export function getDistance (p1: Point, p2: Point): number { + return Math.sqrt( + Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2) + ) +} + +export function moveTo (to: Point, from: Point, radius: number) { + const vector = { x: to.x - from.x, y: to.y - from.y } + const length = Math.sqrt((vector.x * vector.x) + (vector.y * vector.y)) + const unitVector = { x: vector.x / length, y: vector.y / length } + + return { + x: from.x + unitVector.x * radius, + y: from.y + unitVector.y * radius + } +} diff --git a/packages/vuetify/src/components/VSparkline/helpers/path.ts b/packages/vuetify/src/components/VSparkline/helpers/path.ts new file mode 100644 index 00000000000..3f9ae2b0ff1 --- /dev/null +++ b/packages/vuetify/src/components/VSparkline/helpers/path.ts @@ -0,0 +1,36 @@ +import { Point } from '../VSparkline' +import { checkCollinear, getDistance, moveTo } from './math' + +/** + * From https://github.com/unsplash/react-trend/blob/master/src/helpers/DOM.helpers.js#L18 + */ +export function genPath (points: Point[], radius: number) { + const start = points.shift()! + + return ( + `M${start.x} ${start.y}` + + points + .map((point, index) => { + const next = points[index + 1] + const prev = points[index - 1] || start + const isCollinear = next && checkCollinear(next, point, prev) + + if (!next || isCollinear) { + return `L${point.x} ${point.y}` + } + + const threshold = Math.min( + getDistance(prev, point), + getDistance(next, point) + ) + const isTooCloseForRadius = threshold / 2 < radius + const radiusForPoint = isTooCloseForRadius ? threshold / 2 : radius + + const before = moveTo(prev, point, radiusForPoint) + const after = moveTo(next, point, radiusForPoint) + + return `L${before.x} ${before.y}S${point.x} ${point.y} ${after.x} ${after.y}` + }) + .join('') + ) +} diff --git a/packages/vuetify/src/components/VSparkline/index.ts b/packages/vuetify/src/components/VSparkline/index.ts new file mode 100644 index 00000000000..13d0340c997 --- /dev/null +++ b/packages/vuetify/src/components/VSparkline/index.ts @@ -0,0 +1,5 @@ +import VSparkline from './VSparkline' + +export { VSparkline } + +export default VSparkline diff --git a/packages/vuetify/src/components/VSparkline/mixins/props.ts b/packages/vuetify/src/components/VSparkline/mixins/props.ts new file mode 100644 index 00000000000..d9bd7d3742b --- /dev/null +++ b/packages/vuetify/src/components/VSparkline/mixins/props.ts @@ -0,0 +1,40 @@ +import Vue from 'vue' +import { Prop } from 'vue/types/options' + +import { SparklineItem } from '../VSparkline' + +export default Vue.extend({ + props: { + data: { + type: Array as Prop, + required: true + }, + gradient: { + type: Array as Prop, + required: true + }, + gradientDirection: { + type: String as Prop<'top' | 'bottom' | 'left' | 'right'>, + validator: (val: string) => ['top', 'bottom', 'left', 'right'].includes(val), + default: 'top' + }, + autoDraw: Boolean, + autoDrawDuration: { + type: Number, + default: 2000 + }, + autoDrawEasing: { + type: String, + default: 'ease' + }, + height: Number, + width: Number, + padding: { + type: Number, + default: 8 + }, + smooth: [Boolean, Number], + lineWidth: Number, + showLabel: Boolean + } +}) diff --git a/packages/vuetify/src/components/index.ts b/packages/vuetify/src/components/index.ts index 8fd584944c6..f69b758791b 100644 --- a/packages/vuetify/src/components/index.ts +++ b/packages/vuetify/src/components/index.ts @@ -48,6 +48,7 @@ export * from './VResponsive' export * from './VSelect' export * from './VSlider' export * from './VSnackbar' +export * from './VSparkline' export * from './VSpeedDial' export * from './VStepper' export * from './VSubheader' diff --git a/packages/vuetify/test/integration/__snapshots__/importA-la-carte.spec.js.snap b/packages/vuetify/test/integration/__snapshots__/importA-la-carte.spec.js.snap index b94d836d183..5a4bf4e142b 100644 --- a/packages/vuetify/test/integration/__snapshots__/importA-la-carte.spec.js.snap +++ b/packages/vuetify/test/integration/__snapshots__/importA-la-carte.spec.js.snap @@ -99,6 +99,7 @@ Array [ "VSlider", "VSnackbar", "VSpacer", + "VSparkline", "VSpeedDial", "VStepper", "VStepperContent", diff --git a/packages/vuetify/test/integration/__snapshots__/importFull.spec.js.snap b/packages/vuetify/test/integration/__snapshots__/importFull.spec.js.snap index a0738e9aebe..c44cfc1f94c 100644 --- a/packages/vuetify/test/integration/__snapshots__/importFull.spec.js.snap +++ b/packages/vuetify/test/integration/__snapshots__/importFull.spec.js.snap @@ -114,6 +114,7 @@ Array [ "VSlider", "VSnackbar", "VSpacer", + "VSparkline", "VSpeedDial", "VStepper", "VStepperContent", diff --git a/packages/vuetify/test/integration/__snapshots__/importLib.spec.js.snap b/packages/vuetify/test/integration/__snapshots__/importLib.spec.js.snap index 330acf17e9e..927804dbb67 100644 --- a/packages/vuetify/test/integration/__snapshots__/importLib.spec.js.snap +++ b/packages/vuetify/test/integration/__snapshots__/importLib.spec.js.snap @@ -99,6 +99,7 @@ Array [ "VSlider", "VSnackbar", "VSpacer", + "VSparkline", "VSpeedDial", "VStepper", "VStepperContent", diff --git a/packages/vuetify/test/integration/importA-la-carte.spec.js b/packages/vuetify/test/integration/importA-la-carte.spec.js index f2c791a3781..0f57b47651c 100644 --- a/packages/vuetify/test/integration/importA-la-carte.spec.js +++ b/packages/vuetify/test/integration/importA-la-carte.spec.js @@ -50,6 +50,7 @@ import VResponsive from '@/components/VResponsive' import VSelect from '@/components/VSelect' import VSlider from '@/components/VSlider' import VSnackbar from '@/components/VSnackbar' +import VSparkline from '@/components/VSparkline' import VSpeedDial from '@/components/VSpeedDial' import VStepper from '@/components/VStepper' import VSubheader from '@/components/VSubheader' @@ -118,6 +119,7 @@ const components = { VSelect, VSlider, VSnackbar, + VSparkline, VSpeedDial, VStepper, VSubheader, diff --git a/packages/vuetify/test/integration/importLib.spec.js b/packages/vuetify/test/integration/importLib.spec.js index ee698083647..71ad8785a6d 100644 --- a/packages/vuetify/test/integration/importLib.spec.js +++ b/packages/vuetify/test/integration/importLib.spec.js @@ -80,6 +80,7 @@ import Vuetify, { VSelect, VSlider, VSnackbar, + VSparkline, VSpeedDial, VStepper, VStepperContent, @@ -213,6 +214,7 @@ const components = { VSelect, VSlider, VSnackbar, + VSparkline, VSpeedDial, VStepper, VStepperContent, diff --git a/packages/vuetifyjs.com/src/data/drawerItems.json b/packages/vuetifyjs.com/src/data/drawerItems.json index 6562fdbb9a4..6847daf62ba 100644 --- a/packages/vuetifyjs.com/src/data/drawerItems.json +++ b/packages/vuetifyjs.com/src/data/drawerItems.json @@ -136,6 +136,7 @@ { "text": "ratings", "to": "ratings" }, { "text": "sheets", "to": "sheets" }, { "text": "snackbars", "to": "snackbars" }, + { "text": "sparklines", "to": "sparklines" }, { "text": "steppers", "to": "steppers" }, { "text": "subheaders", "to": "subheaders" }, { "text": "tabs", "to": "tabs" }, diff --git a/packages/vuetifyjs.com/src/data/pages/components/Sparklines.json b/packages/vuetifyjs.com/src/data/pages/components/Sparklines.json new file mode 100644 index 00000000000..d1c83442202 --- /dev/null +++ b/packages/vuetifyjs.com/src/data/pages/components/Sparklines.json @@ -0,0 +1,24 @@ +{ + "title": "header", + "titleText": "headerText", + "children": [ + { + "type": "section", + "children": [ + { + "type": "usage", + "value": "playground" + } + ] + }, + { + "type": "section", + "children": [ + { + "type": "api", + "value": ["v-sparkline"] + } + ] + } + ] +} diff --git a/packages/vuetifyjs.com/src/examples/sparklines/playground.vue b/packages/vuetifyjs.com/src/examples/sparklines/playground.vue new file mode 100644 index 00000000000..7f0a3118037 --- /dev/null +++ b/packages/vuetifyjs.com/src/examples/sparklines/playground.vue @@ -0,0 +1,112 @@ + + + diff --git a/packages/vuetifyjs.com/src/lang/en/components/Sparklines.json b/packages/vuetifyjs.com/src/lang/en/components/Sparklines.json new file mode 100644 index 00000000000..dbf6b696979 --- /dev/null +++ b/packages/vuetifyjs.com/src/lang/en/components/Sparklines.json @@ -0,0 +1,23 @@ +{ + "header": "# Sparkline", + "headerText": "The sparkline component can be used to create simple graphs, like GitHub's contribution chart.\n\nAny [SVG attribute](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute) may be used in addition to the ones listed below.", + "examples": { + "playground": { + "header": "", + "desc": "" + } + }, + "props": { + "autoDraw": "Trace the length of the line when first rendered", + "autoDrawDuration": "Amount of time (in ms) to run the trace animation", + "autoDrawEasing": "The easing function to use for the trace animation", + "data": "An array of data points", + "gradient": "An array of colors to use as a linear-gradient", + "gradientDirection": "The direction the gradient should run", + "lineWidth": "The thickness of the line, in px", + "padding": "Low `smooth` or high `line-width` values may result in cropping, increase padding to compensate", + "showLabel": "Show labels below each data point", + "smooth": "Number of px to use as a corner radius. `true` defaults to 8, `false` is 0", + "type": "Choose between a trendline or bars" + } +} diff --git a/packages/vuetifyjs.com/src/lang/en/meta.json b/packages/vuetifyjs.com/src/lang/en/meta.json index 53e05fe6828..e9804bae90e 100644 --- a/packages/vuetifyjs.com/src/lang/en/meta.json +++ b/packages/vuetifyjs.com/src/lang/en/meta.json @@ -425,6 +425,12 @@ "description": "Snackbar component for Vuetify Framework", "keywords": "snackbar" }, + "components/sparklines": { + "h1": "Sparklines", + "title": "Sparkline Component", + "description": "Sparkline component for Vuetify Framework", + "keywords": "sparkline, graph, chart, line" + }, "components/steppers": { "h1": "Steppers", "title": "Stepper Component", diff --git a/packages/vuetifyjs.com/src/lang/en/vuetify/AppDrawer.json b/packages/vuetifyjs.com/src/lang/en/vuetify/AppDrawer.json index 169485f6763..19d5bd1c555 100644 --- a/packages/vuetifyjs.com/src/lang/en/vuetify/AppDrawer.json +++ b/packages/vuetifyjs.com/src/lang/en/vuetify/AppDrawer.json @@ -83,6 +83,7 @@ "ratings": "Ratings", "sheets": "Sheets", "snackbars": "Snackbars", + "sparklines": "Sparklines", "steppers": "Steppers", "subheaders": "Subheaders", "tabs": "Tabs",