@politico/interactive-style
This library is an ever-evolving implementation of our design standards for
interactive projects. The goal of the library is to make it as easy and
seamless as possible to step from Figma into code. It should serve as
a one-stop shop for everything you need to build a POLITICO Interactive story,
whether you're working on an elections-specific project or not.
Quick start
Looking to dive right in? 🚀
Install the library as a dependency, and then you can start using the various
pieces provided as you need them. Note that v4
of this library is still in
pre-release, so you have to specify that that's what you want:
npm install "@politico/interactive-style@>=4.0.1-rc.0"
Styles
You may want to include our standard CSS theme in your global stylesheet.
@use "~@politico/interactive-style/int.scss";
@include int.theme();
That will give you a nice foundation on which to use more specific styles in
your components. All of our style utilities are provided as SCSS variables and
mixins, and we export them all from the int.scss
stylesheet. The easiest way
to use things like our colors, our spacing variables, or our more complicated
mixins is to @use
our main stylesheet and access what you need under the
int
namespace:
@use "~@politico/interactive-style/int.scss";
.container {
color: int.$gray-90;
@include int.sans($size: "300");
@include int.is-desktop() {
@include int.sans($size: "500");
}
}
JavaScript
This library also provides a host of components and utilities for use in your
JavaScript. Everything is available as a named export at the top level of the
library.
All of our components can be imported and used directly in your own components.
import { Well, Grid, GridItem } from '@politico/interactive-style';
<Well>
<Grid>
<GridItem>Column 1</GridItem>
<GridItem>Column 2</GridItem>
</Grid>
</Well>
And our hooks and utilites can be imported the same way.
import { sortBy } from '@politico/interactive-style';
const items = [
{ name: 'Steph', number: 30 },
{ name: 'Klay', number: 11 },
{ name: 'Draymond', number: 23 },
];
const sortedItems = sortBy(items, ['name', 'number']);
How to use the docs in Storybook
The package of documentation in Storybook includes two different kinds of docs:
guides and API documentation. The guides offer high-level introductions to
various concepts addressed by this library, like how our content follows a grid
to give the page consistent structure; all the guides are found under the
"GUIDES" header in the left nav. The API documentation offers more fine-grained
and exhaustive details on all the components, mixins, hooks, and utilities
provided by this library. If you're looking for an abstract description of our
typography system, you should probably start with the typography guide. If
you're looking for documentation on the arguments that the sortBy
utility
accepts, you should look for its API documentation in the utilities section.
Toward Reusability
This library is a result of the Toward Reusability project, documented here in
Notion. The project was an effort to create a foundation for reusable
standards and components for any individual contributor in the POLITICO
Interactive News team to use as a basis for their work. The result is
a living, iterative system for the design and development of interactive
projects.
As our needs continue to evolve this project will need to evolve with them.
Every user of this system should feel empowered to identify shortcomings, gaps,
and opportunities for improvement or expansion — and they should also feel
empowered to contribute to meeting those needs.
Anna Wiederkehr and Andrew Milligan were the main contributors responsible for
the foundations of this library. Please direct your inquiries or concerns
towards them. The relevant stakeholders are Andrew McGill and Allan James
Vestal.
Developing this library
Clone the repo and install dependencies.
npm install
You can run Storybook locally to see your changes as you develop them.
npm run storybook
Once it starts up, you should be able to see Storybook running at
http://localhost:6006.
You can run unit tests locally. We use unit tests to test easily testable
functions like utilities, and we use stories in Storybook to test React
components and to provide visual documentation for everything this library
provides. So don't be surprised if you run unit tests and only see utilities
being tested.
npm run test
You can also lint all of the JS and SCSS in the project.
npm run lint
Dummy Election Data in Storybook
Two types of mock election data can be included in stories: randomly generated
data and data sourced from an AP results API snapshot.
Using AP data
In order to make an AP snapshot available for use as dummy data, retrieve it
from the API, make any adjustments/tweaks to it that you want, and then save it
in a JSON file in .storybook/static/ap-snapshots
. For example, you might
take a snapshot and store it as
.storybook/static/ap-snapshots/2022-11-08-nm-gov-general.json
The path of the file from the ap-snapshots
directory to the .json
extension
will be used as the identifier of this snapshot in storybook, so this example
can be referenced as 2022-11-08-nm-gov-general
.
Once a snapshot is available, you can reference it in a story's dummy data
configuration like this:
import { getElectionDataParameters } from 'Utils/storybook/withElectionData';
const parameters = getElectionDataParameters([{
apSnapshot: '2022-11-08-nm-gov-general',
}]);
or using withElectionData
like this:
import { withElectionData } from 'Utils/storybook/withElectionData';
const MyStory = Template.bind({});
export default withElectionDataParameters(MyStory, [{
apSnapshot: '2022-11-08-nm-gov-general',
}]);
Helpful scripts
makeComponent
This library provides a makeComponent
script to help with creating new
components from JSON blueprints. You can define a component blueprint in the
blueprints
directory and then run the script with:
npm run makeComponent -- --blueprint blueprints/<MyBlueprint>.json
The blueprint should have the following structure:
{
"section": "elections",
"name": "MyComponent",
"description": "Tk...",
"props": [
{
"name": "foo",
"description": "Tk...",
"type": "string",
"isRequired": true,
},
{
"name": "bar",
"description": "Tk...",
"type": "bool",
"default": false,
},
{
"name": "variant",
"description": "Tk...",
"type": "oneOf",
"options": [
"a",
"b",
"c",
],
"default": "a",
},
],
"stories": [
{
"name": "MyStoryName",
"args": {
"propName": "propValue",
"expandable": "aggregationOnly"
},
"description": "Tk...",
"apSnapshot": "snap/shot"
},
]
}
Don't forget the extra --
to pass flags to the script through npm!
Publishing Storybook
You can publish a new version of Storybook with:
npm run docs:pub
If you only want to build Storybook and not publish it, you can do that with:
npm run docs:build
Publishing the Library
You can build the library with:
npm run build
If you want to run the build in watch mode so that it rebuilds every time you
change a file you can run:
npm run build:watch
You can release a new version of the library with:
npm run release
The release script accepts several arguments (remember to include --
between
npm run release
and your additional arguments):
-
--message
(or -m
) lets you set a custom git commit message to describe
the release. Note that your custom message will be automatically prefixed
with the version number, so you if provided the message "Hello world"
while
releasing v1.0.0, the commit message will be v1.0.0: Hello world
. By
default the message will just be the new version number.
-
--step
(or -s
) lets you specify how to increment the version number.
Valid choices are patch
, minor
, major
, premajor
, preminor
,
prepatch
, and prerelease
. Note that --version
takes precedence over
--step
. Generally choose patch
(wich will increment the last number,
i.e., 2.2.x
) if you're releasing a bug fix and choose minor
(which will
increment the second number, i.e., 2.x.2
) if you're releasing a new
feature. The default is patch
.
-
--version
(or -v
) lets you specify a specific version number, useful if
you want to skip a version for some reason, or provide more nuance to the
semantic version. Note that --version
takes precedence over --step
.
-
--preid
lets you specify the pre-release identifier (i.e., rc
in
2.0.1-rc.0
). This is rc
by default. It's only used when you release
a "pre" version using one of the pre*
values for step
.
The release script will automatically build the library, increment the version
number in package.json
, commit the bumped version with a commit message that
includes the new version number, tag the commit with the version number,
publish the package to npm, and push the changes along with the new tag.