Skip to content

Commit

Permalink
Merge pull request #111 from UrbanInstitute/feature-layercake-axes
Browse files Browse the repository at this point in the history
add layercake components, stories and docs
  • Loading branch information
rachelmarconi authored Aug 28, 2024
2 parents cf8e5c9 + dc5f605 commit d70506a
Show file tree
Hide file tree
Showing 11 changed files with 504 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const preview = {
["Theme", "Fonts"],
"Examples",
"Components",
"Layercake",
["Intro"],
"Layout",
"Logos",
"Maps",
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Patch: Update method of declaring Storybook component descriptions and add import instructions to components
- Patch: Remove description field from top level `meta` object in component `.stories.svelte` files (do not render)
- Feature: CLI command to generate new component boilerplate (`npm run create-component`)
- Feature: Add Layercake AxisX and AxisY components and docs

## v0.10.2

Expand Down
42 changes: 42 additions & 0 deletions src/lib/Layercake/AxisX.docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
## Usage

```js
import { AxisX } from "@urbaninstitute/dataviz-components";
```

## Want to update axis style straight from the Layercake repo?

Use this css instead:

```js
<style>
.tick {
font-size: 12px;
font-weight: 400;
font-family: var(--font-family-sans-serif);
}
line,
.tick line {
stroke: #DEDDDD;
}
.tick text {
fill: #000000;
}
.tick .tick-mark,
.baseline {
stroke: #000000;
}
/* This looks slightly better */
.axis.snapTicks .tick:last-child text {
transform: translateX(3px);
}
.axis.snapTicks .tick.tick-0 text {
transform: translateX(-3px);
}
.axis-label {
font-size: 12px;
}
</style>
```

## Story
60 changes: 60 additions & 0 deletions src/lib/Layercake/AxisX.stories.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<script context="module">
import AxisX from "./AxisX.svelte";
import docs from "./AxisX.docs.md?raw";
export const meta = {
title: "Layercake/AxisX",
component: AxisX,
tags: ["autodocs"],
argTypes: {
ticks: {
control: {
type: "range",
min: 1,
max: 20
},
},
axisLabel: {
control: 'text'
},
},
parameters: {
backgrounds: {
default: "light",
values: [
{ name: "light", value: "#ffffff" },
{ name: "dark", value: "#0A4C6A" }
]
},
docs: {
description: {
component: docs
}
},
githubLink: {
url: "/Layercake/AxisX.svelte"
}
}
};
</script>

<script>
import { Story, Template } from "@storybook/addon-svelte-csf";
import { LayerCake, Svg } from "layercake";
import data from "./data.json";
const xKey = "value";
const yKey = "year";
</script>

<Template let:args>
<div style="height: 150px;">
<LayerCake {data} xDomain={[0, 20]} yDomain={[0, 10]} y={yKey} x={xKey}>
<Svg>
<AxisX {...args} />
</Svg>
</LayerCake>
</div>
</Template>

<Story name="Default" />
146 changes: 146 additions & 0 deletions src/lib/Layercake/AxisX.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
<!--
@component
Generates an SVG x-axis. This component is also configured to detect if your x-scale is an ordinal scale. If so, it will place the markers in the middle of the bandwidth.
-->
<script>
import { getContext } from "svelte";
const { width, height, xScale, yRange } = getContext("LayerCake");
/**
* Extend lines from the ticks into the chart space
* @type {boolean} [gridlines=true] */
export let gridlines = false;
/**
* Show a vertical mark for each tick.
* @type {boolean} [tickMarks=false] */
export let tickMarks = true;
/**
* Show a solid line at the bottom.
* @type {boolean} [baseline=false] */
export let baseline = true;
/**
* Instead of centering the text on the first and the last items, align them to the edges of the chart.
* @type {boolean} [snapTicks=false] */
export let snapTicks = false;
/**
* A function that passes the current tick value and expects a nicely formatted value in return.
* @type {Function} [formatTick=d => d] */
export let formatTick = (d) => d;
/**
* If this is a number, it passes that along to the [d3Scale.ticks](https://github.com/d3/d3-scale) function. If this is an array, hardcodes the ticks to those values. If it's a function, passes along the default tick values and expects an array of tick values in return. If nothing, it uses the default ticks supplied by the D3 function.
* @type {number|Array|Function} [ticks] */
export let ticks = undefined;
/**
* How far over to position the text marker.
* @type {number} [xTick=0] */
export let xTick = 0;
/**
* The distance from the baseline to place each tick value.
* @type {number} [yTick=16] */
export let yTick = 16;
/**
* An optional label for the y axis
* @type {string|null} [axisLabel=null] */
export let axisLabel = "";
$: isBandwidth = typeof $xScale.bandwidth === "function";
$: tickVals = Array.isArray(ticks)
? ticks
: isBandwidth
? $xScale.domain()
: typeof ticks === "function"
? ticks($xScale.ticks())
: $xScale.ticks(ticks);
function textAnchor(i) {
if (snapTicks === true) {
if (i === 0) {
return "start";
}
if (i === tickVals.length - 1) {
return "end";
}
}
return "middle";
}
</script>

<g class="axis x-axis" class:snapTicks>
{#each tickVals as tick, i (tick)}
<g class="tick tick-{i}" transform="translate({$xScale(tick)},{Math.max(...$yRange)})">
{#if gridlines !== false}
<line class="gridline" y1={$height * -1} y2="0" x1="0" x2="0" />
{/if}
{#if tickMarks === true}
<line
class="tick-mark"
y1={0}
y2={6}
x1={isBandwidth ? $xScale.bandwidth() / 2 : 0}
x2={isBandwidth ? $xScale.bandwidth() / 2 : 0}
/>
{/if}
<text
x={isBandwidth ? $xScale.bandwidth() / 2 + xTick : xTick}
y={yTick}
dx=""
dy=""
text-anchor={textAnchor(i)}>{formatTick(tick)}</text
>
</g>
{/each}
{#if baseline === true}
<line class="baseline" y1={$height + 0.5} y2={$height + 0.5} x1="0" x2={$width} />
{/if}
{#if axisLabel}
<text
class="axis-label"
x={$width / 2}
y={$height + 40}
dy="-4"
fill={"#000"}
text-anchor="middle">{axisLabel}</text
>
{/if}
</g>

<style>
.tick {
font-size: 12px;
font-weight: 400;
font-family: var(--font-family-sans-serif);
}
line,
.tick line {
stroke: #dedddd;
}
.tick text {
fill: #000000;
}
.tick .tick-mark,
.baseline {
stroke: #000000;
}
/* This looks slightly better */
.axis.snapTicks .tick:last-child text {
transform: translateX(3px);
}
.axis.snapTicks .tick.tick-0 text {
transform: translateX(-3px);
}
.axis-label {
font-size: 12px;
}
</style>
27 changes: 27 additions & 0 deletions src/lib/Layercake/AxisY.docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## Usage

```js
import { AxisY } from "@urbaninstitute/dataviz-components";
```

## Want to update axis style straight from the Layercake repo?

Use this css instead:

```js
<style>
.tick, .axis-label {
font-size: 12px;
font-family: var(--font-family-sans-serif);
}

.tick line {
stroke: #dedddd;
}
.tick:first-of-type line {
stroke: #000000;
}
</style>
```

## Story
69 changes: 69 additions & 0 deletions src/lib/Layercake/AxisY.stories.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<script context="module">
import AxisY from "./AxisY.svelte";
import docs from "./AxisY.docs.md?raw";
export const meta = {
title: "Layercake/AxisY",
component: AxisY,
tags: ["autodocs"],
argTypes: {
ticks: {
control: {
type: "range",
min: 1,
max: 10
}
},
textAnchor: {
control: "select",
options: ["start", "middle", "end"]
},
axisLabel: {
control: "text"
},
tickLabelColor: {
control: {
type: "color"
}
}
},
parameters: {
backgrounds: {
default: "light",
values: [
{ name: "light", value: "#ffffff" },
{ name: "dark", value: "#0A4C6A" }
]
},
docs: {
description: {
component: docs
}
},
githubLink: {
url: "/Layercake/AxisY.svelte"
}
}
};
</script>

<script>
import { Story, Template } from "@storybook/addon-svelte-csf";
import { LayerCake, Svg } from "layercake";
import data from "./data.json";
const xKey = "value";
const yKey = "year";
</script>

<Template let:args>
<div style="height: 150px; width:100%;">
<LayerCake {data} xDomain={[0, 20]} yDomain={[0, 10]} y={yKey} x={xKey}>
<Svg>
<AxisY {...args} />
</Svg>
</LayerCake>
</div>
</Template>

<Story name="Default" />
Loading

0 comments on commit d70506a

Please sign in to comment.