Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(storybook): Storybook 7, migrate docs from READMEs to stories, add guides #109

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25,910 changes: 12,388 additions & 13,522 deletions .pnp.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .pnp.loader.mjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion .prettierrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
"semi": false,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 120
"printWidth": 120,
"proseWrap": "always"
}
217 changes: 7 additions & 210 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,221 +10,18 @@
</div>
<br />

The Propel UI Kit is a data visualization and dashboard React component library to quickly build awesome-looking analytics into your apps.
The Propel UI Kit is a data visualization and dashboard React component library to quickly build awesome-looking
analytics into your apps.

## Install
## Documentation

Note: check the [Migration guide](#migration-guide) in case you installed any of the "@propeldata/react"-prefixed dependencies before.

To install the Propel UI Kit components, run the following command:

With `yarn`:

```shell
yarn add @propeldata/ui-kit
```

or `npm`:

```shell
npm install @propeldata/ui-kit
```

You can read more about the [why and core principles](PRINCIPLES.md) behind the Propel UI Kit.

You can use the components with or without [Propel](https://www.propeldata.com). If you don't have a Propel Account yet, you can [try Propel for free](https://propeldata.com/get-started) and learn more by reading our [API docs](https://propeldata.com/docs).

## Key features

All components share the same set of key features:

- **They are responsive.** Components are responsive out of the box. They render well on desktops and laptops as well as phones and tablets.

- **They handle loading and error states for you.** No need to sweat the details of handling the different states. We've done that for you.

- **They fetch the data for you.** Components can automatically fetch the data from the Propel API when used in connected mode.

Individual components have other key features that we highlight on the component documentation pages.

## Components

Check out the different components and their documentation:

- [Time Series](/packages/ui-kit/src/components/TimeSeries/README.md)
- [Counter](/packages/ui-kit/src/components/Counter/README.md)
- [Leaderboard](/packages/ui-kit/src/components/Leaderboard/README.md)

Please [open a feature request](https://github.com/propeldata/ui-kit/issues) on GitHub for other components you'd like to have. Also, PRs are welcome 😊.

## Usage

The Propel UI Kit components are available in two modes: "Static" and "Connected".

### Static Mode

In the "Static" mode, the component will display the data you provide.

Let's take our [TimeSeries](/packages/ui-kit/src/components/TimeSeries/README.md) component as an example. If you want to fetch the data on your own instead of delegating it to the library, you can do so using the following JavaScript code:

```javascript
import { TimeSeries } from '@propeldata/ui-kit'

const labels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']

const values = [0, 1000, 200, 3000, 4000, 500, 7000]

function WeekSalesChart() {
return <TimeSeries labels={labels} values={values} />
}
```

You can customize the component using your own styles.

<p align="center">
<img src="public/images/time-series.png"/>
</p>

### Connected Mode

In the "Connected" mode, the component automatically fetches the data from the Propel API. You don't need a backend, to configure a GraphQL client, or handle loading and error states.

To learn more about querying data with Propel, read the [Metric query documentation](https://www.propeldata.com/docs/metrics).

For the Connected mode, you'll need to provide your Propel Application's access token to use Propel APIs. You can authenticate and generate an access token by following the steps outlined in [the Propel GraphQL Authentication guide](https://propeldata.com/docs/api/authentication#step-2-generate-an-access-token).

Here is an example using our [Counter](/packages/ui-kit/src/components/Counter/README.md) component:

```javascript
import { Counter } from '@propeldata/ui-kit'

function SalesCountLabel() {
const queryOptions = {
accessToken: '<PROPEL_ACCESS_TOKEN>',
metric: 'salesCount',
timeRange: {
relative: 'PREVIOUS_WEEK'
},
granularity: 'DAY'
}

return (
<p>
We reached <Counter query={queryOptions} /> last week.
</p>
)
}
```

In this mode, the component will handle the loading and error states for you, making it even easier to use.

<p align="center">
<img src="public/images/counter.gif"/>
</p>

Want to see more examples? Check out our [Storybook](https://storybook.propeldata.com)!

## Customization

We designed the Propel UI Kit to be highly customizable and easy to incorporate into your front-end applications. Here are some of the customization options available to you:

### Styles

You can apply your own custom styles to each component using the Styles interface. This interface includes a wide range of properties to customize your charts, such as font, canvas, tooltip, bar, line, and point.

For example, to change the color of the bars in your time series chart, you can use the following JavaScript code:

```javascript
function MyChart() {
// source code

const styles = {
bar: {
backgroundColor: '#532AB4'
}
}

return <TimeSeries styles={styles} />
}
```

This will change the color of the bars to a shade of purple, as shown in the following image:

<p align="center">
<img src="public/images/time-series-purple.png"/>
</p>

### Errors

You can also provide your own custom error messages by using the error prop. This will enable you to provide more accurate feedback to your users in case of technical errors or other issues.

For example, to display a custom error message when the chart data cannot be loaded, you can use the following JavaScript code:

```javascript
function MyChart() {
// source code

const title = 'Unable to connect'
const body = 'Sorry we are not able to connect at this time due to a technical error.'

return <TimeSeries error={{ title, body }} />
}
```

This will display a custom error message with a title and body text, as shown in the following image:

<p align="center">
<img src="public/images/error.png"/>
</p>

By customizing your Propel UI Kit components in this way, you can create unique, user-friendly data visualizations that fit seamlessly into your front-end applications.

## Migration guide

### 1. Update your dependencies

Remove any existing "@propeldata/react"-prefixed dependencies (for example, `@propeldata/react-counter`, `@propeldata/react-leaderboard`, and `@propeldata/react-time-series`). Then, add a new dependency on `@propeldata/ui-kit`, using npm or yarn.

**npm**

```
npm i @propeldata/ui-kit
```

**yarn**

```
yarn add @propeldata/ui-kit
```

### 2. Update your imports

Wherever you previously imported from `@propeldata/react-counter`, `@propeldata/react-leaderboard`, or `@propeldata/react-time-series`, you can now import from `@propeldata/ui-kit`. Note that `Styles` has been renamed to `ChartStyles` and is shared by all three components.

**Before**

```ts
import { Counter, CounterProps, Styles as CounterStyles } from '@propeldata/react-counter'
import { Leaderboard, LeaderboardProps, Styles as LeaderboardStyles } from '@propeldata/react-leaderboard'
import { TimeSeries, TimeSeriesProps, Styles as TimeSeriesStyles } from '@propeldata/react-time-series'
```

**After**

```ts
import {
ChartStyles,
Counter,
CounterProps,
Leaderboard,
LeaderboardProps,
TimeSeries,
TimeSeriesProps
} from '@propeldata/ui-kit'
```
Visit https://storybook.propeldata.com/ to view the full documentation.

## Contributing

If you notice any bugs or have suggestions for new features, please [open an issue](https://github.com/propeldata/ui-kit/issues) on GitHub. We welcome feedback and contributions from the community!
If you notice any bugs or have suggestions for new features, please
[open an issue](https://github.com/propeldata/ui-kit/issues) on GitHub. We welcome feedback and contributions from the
community!

## License

Expand Down
2 changes: 2 additions & 0 deletions api/token/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// DO NOT REMOVE. This file is used in the build and deploy Storybook on Vercel.
// @TODO: look for more elegant solution
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Establishing the serverless function on Vercel for Storybook setup is a bit tricky.
First of all, there is an official instruction: Deploying Storybook with Vercel.
Secondly, Serverless Functions Quickstart.
The thing is that seems like Vercel runs some simple HTTP server for the Storybook setup, which can’t handle unbundled files (e.g. *.ts).
So, I’ve seen two main roads here:

  1. Configure a dummy Next.js project to handle calls to the functions and serve static Storybook content.
  2. Find a way to force Vercel’s Storybook env to handle function calls.
    I didn’t find a quick solution for 1 and honestly, I don’t like the idea of proxying calls to static files through the next.js env.
    I decided to follow 2. The initial assumption was to pre-build a script for the serverless function with tsc to the vercel’s api/ folder (Vercel’s reserved folder). The build workflow works without errors locally and on Vercel, but for some reasons, Vercel refuses to include tsc output in the final Deployment.
    What helped was the creation of an empty file (a placeholder) and adding it to the repo, e.g. api/token/route.js.
    With this hack Vercel started to include the function to the Deployment.

9 changes: 9 additions & 0 deletions app/storybook/.storybook/defaultTheme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { create } from '@storybook/theming/create'
import packageInfo from '../../../packages/ui-kit/package.json'

export const defaultTheme = create({
base: 'light',
brandTitle: `UI-kit v.${packageInfo.version}`,
brandImage: '/propel-logo.svg'
// fontBase: '"Inter", sans-serif'
})
29 changes: 0 additions & 29 deletions app/storybook/.storybook/main.js

This file was deleted.

60 changes: 60 additions & 0 deletions app/storybook/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import type { StorybookConfig } from '@storybook/react-webpack5'
import { join, dirname } from 'path'
import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin'

/**
* This function is used to resolve the absolute path of a package.
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
*/
function getAbsolutePath(value: string): any {
return dirname(require.resolve(join(value, 'package.json')))
}

const config: StorybookConfig = {
stories: ['../documentation/**/*.mdx', '../../../packages/ui-kit/src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
getAbsolutePath('@storybook/addon-links'),
getAbsolutePath('@storybook/addon-essentials'),
getAbsolutePath('@storybook/addon-themes'),
getAbsolutePath('@storybook/addon-interactions'),
getAbsolutePath('@storybook/addon-a11y')
],
framework: {
name: getAbsolutePath('@storybook/react-webpack5'),
options: {}
},
docs: {
autodocs: 'tag',
defaultName: 'Overview'
},
features: {
storyStoreV7: true,
buildStoriesJson: true
},
staticDirs: ['../public/assets'],
webpackFinal: async (config) => {
config.module?.rules?.push({
test: /\.(ts|tsx)$/,
loader: require.resolve('babel-loader'),
exclude: /node_modules/,
options: {
presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript']
}
})

if (config.resolve) {
config.resolve.extensions?.push('.ts', '.tsx', '.mdx')
config.resolve.plugins = [
...(config.resolve.plugins || []),
new TsconfigPathsPlugin({
extensions: config.resolve.extensions,
configFile: './tsconfig.json'
})
]
}

return config
}
}

export default config
22 changes: 22 additions & 0 deletions app/storybook/.storybook/manager-head.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<link rel="shortcut icon" href="/favicon.ico" />
<style>
.sidebar-header div {
margin: 0;
padding: 0;
}
.sidebar-header a {
margin: 0;
padding: 0;
display: flex;
justify-content: center;
margin-bottom: 15px;
}
.sidebar-header a > img {
height: 50px;
margin-left: 20px;
}

.sidebar-header button {
display: none;
}
</style>
13 changes: 13 additions & 0 deletions app/storybook/.storybook/manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { addons } from '@storybook/manager-api'
import { defaultTheme } from './defaultTheme'

addons.setConfig({
theme: defaultTheme,
sidebar: {
filters: {
patterns: (item) => {
return !item.tags?.includes('pattern')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pattern tag is used to mark (hidden) stories that shouldn't be added to the Storybook's sidebar. We use it for some component stories that are part of the documentation (e.g. Leaderboard CustomStyleStory) and for non-primitive type stories (e.g. ChartBarProps).

}
}
}
})
3 changes: 3 additions & 0 deletions app/storybook/.storybook/preview-head.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<script>
window.global = window
</script>
Loading