diff --git a/.babelrc.json b/.babelrc.json
new file mode 100644
index 000000000..f6dd6cb0a
--- /dev/null
+++ b/.babelrc.json
@@ -0,0 +1,16 @@
+{
+ "sourceType": "unambiguous",
+ "presets": [
+ [
+ "@babel/preset-env",
+ {
+ "targets": {
+ "chrome": 100
+ }
+ }
+ ],
+ "@babel/preset-typescript",
+ "@babel/preset-react"
+ ],
+ "plugins": []
+}
diff --git a/.eslintignore b/.eslintignore
index 472c33bbd..1cd74997d 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -2,7 +2,7 @@
node_modules/
# generated files
-.docz/
+storybook-static/
lib/
# other
@@ -12,4 +12,3 @@ assets/
fixtures/
src/icons/
-src/gatsby-theme-docz
diff --git a/.eslintrc.js b/.eslintrc.js
index d3cc2aa46..9b19edb18 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -8,7 +8,9 @@ module.exports = {
'plugin:jest/recommended',
'plugin:promise/recommended',
'plugin:unicorn/recommended',
- 'prettier'
+ 'prettier',
+ 'plugin:storybook/recommended',
+ 'plugin:storybook/recommended'
],
env: {
node: true,
@@ -21,11 +23,8 @@ module.exports = {
rules: {
// conflicts with stylelint rule
'unicorn/numeric-separators-style': 'off',
-
'unicorn/no-useless-undefined': 'off',
-
'@typescript-eslint/no-unsafe-return': 'off',
-
'@typescript-eslint/no-unsafe-assignment': 'off',
'react/require-default-props': 'off',
// Often used for this library
@@ -35,7 +34,7 @@ module.exports = {
'no-prototype-builtins': 'off',
// https://basarat.gitbooks.io/typescript/docs/tips/defaultIsBad.html
'import/prefer-default-export': 'off',
- 'import/no-default-export': 'error',
+ 'import/no-default-export': 'off',
// Too restrictive: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/destructuring-assignment.md
'react/destructuring-assignment': 'off',
// No jsx extension: https://github.com/facebook/create-react-app/issues/87#issuecomment-234627904
@@ -47,14 +46,21 @@ module.exports = {
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-use-before-define': [
'error',
- { functions: false, classes: true, variables: true, typedefs: true }
+ {
+ functions: false,
+ classes: true,
+ variables: true,
+ typedefs: true
+ }
],
// Common abbreviations are known and readable
'unicorn/prevent-abbreviations': 'off',
// Airbnb prefers forEach
'unicorn/no-array-for-each': 'off',
// It's not accurate in the monorepo style
- 'import/no-extraneous-dependencies': 'off'
+ 'import/no-extraneous-dependencies': 'off',
+ // Storybook Template.bind returns any type
+ '@typescript-eslint/no-unsafe-member-access': 'off'
},
overrides: [
{
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index a8c44b020..778fa5e9f 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -18,12 +18,14 @@ jobs:
node-version: 18
- name: Install dependencies
uses: bahmutov/npm-install@v1
+ with:
+ install-command: npm i --legacy-peer-deps
- name: Build docs
run: npm run build:documentation
- uses: actions/upload-artifact@v3
with:
- name: docz-dist
- path: .docz/dist
+ name: storybook-dist
+ path: storybook-static
deploy:
if: github.ref == 'refs/heads/main'
@@ -32,7 +34,7 @@ jobs:
steps:
- uses: actions/download-artifact@v3
with:
- name: docz-dist
+ name: storybook-dist
path: public
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
diff --git a/.gitignore b/.gitignore
index a1a225f40..1f033e583 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,7 +8,7 @@ coverage/
junit.xml
# project files
-.docz/
+storybook-static/
*.tgz
.npmrc
node_modules/
diff --git a/.prettierignore b/.prettierignore
index a61cd3fe3..483a9c42c 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,2 +1 @@
-package-lock.json
-*.mdx
+package-lock.json
\ No newline at end of file
diff --git a/.storybook/FreenowTheme.ts b/.storybook/FreenowTheme.ts
new file mode 100644
index 000000000..86ded7728
--- /dev/null
+++ b/.storybook/FreenowTheme.ts
@@ -0,0 +1,41 @@
+// .storybook/FreenowTheme.ts
+import { create } from '@storybook/theming/create';
+import logo from '../public/assets/freenow-logo.svg';
+
+export default create({
+ base: 'light',
+
+ // Typography
+ fontBase: '"Open Sans", sans-serif',
+ fontCode: 'monospace',
+
+ brandTitle: 'FREENOW',
+ brandUrl: 'https://wave.free-now.com/',
+ brandImage: logo,
+ brandTarget: '_self',
+
+ //
+ colorPrimary: '#CA0928',
+ colorSecondary: '#585C6D',
+
+ // UI
+ appBg: '#ffffff',
+ appContentBg: '#ffffff',
+ appBorderColor: '#585C6D',
+ appBorderRadius: 4,
+
+ // Text colors
+ textColor: '#10162F',
+ textInverseColor: '#ffffff',
+
+ // Toolbar default and active colors
+ barTextColor: '#9E9E9E',
+ barSelectedColor: '#585C6D',
+ barBg: '#ffffff',
+
+ // Form colors
+ inputBg: '#ffffff',
+ inputBorder: '#10162F',
+ inputTextColor: '#10162F',
+ inputBorderRadius: 2
+});
diff --git a/.storybook/main.ts b/.storybook/main.ts
new file mode 100644
index 000000000..043b59d09
--- /dev/null
+++ b/.storybook/main.ts
@@ -0,0 +1,21 @@
+import { StorybookConfig } from '@storybook/react-webpack5';
+
+const config: StorybookConfig = {
+ stories: ['../**/*.storybook.mdx', '../src/**/*.stories.@(ts|tsx)'],
+ addons: [
+ '@storybook/addon-links',
+ '@storybook/addon-essentials',
+ '@storybook/addon-interactions',
+ '@storybook/addon-viewport'
+ ],
+ framework: {
+ name: '@storybook/react-webpack5',
+ options: {}
+ },
+ docs: {
+ autodocs: true
+ },
+ staticDirs: ['../public']
+};
+
+export default config;
diff --git a/.storybook/manager.ts b/.storybook/manager.ts
new file mode 100644
index 000000000..2c0cbe8ed
--- /dev/null
+++ b/.storybook/manager.ts
@@ -0,0 +1,7 @@
+// .storybook/manager.ts
+import { addons } from '@storybook/manager-api';
+import FreenowTheme from './FreenowTheme';
+
+addons.setConfig({
+ theme: FreenowTheme
+});
diff --git a/.storybook/preview.ts b/.storybook/preview.ts
new file mode 100644
index 000000000..f22b7de98
--- /dev/null
+++ b/.storybook/preview.ts
@@ -0,0 +1,77 @@
+import { Preview } from '@storybook/react';
+import { themes } from '@storybook/theming';
+
+export const preview: Preview = {
+ parameters: {
+ actions: { argTypesRegex: '^on[A-Z].*' },
+ viewMode: 'docs',
+ controls: {
+ expanded: true,
+ matchers: {
+ color: /(background|color)$/i,
+ date: /Date$/
+ }
+ },
+ docs: {
+ theme: themes.light
+ },
+ backgrounds: {
+ default: 'light',
+ values: [
+ { name: 'light', value: '#FFFFFF' },
+ { name: 'dark', value: '#001E3E' }
+ ]
+ },
+ viewport: {
+ viewports: {
+ mobile: {
+ name: 'Mobile',
+ styles: {
+ height: '568px',
+ width: '320px'
+ },
+ type: 'mobile'
+ },
+ mobile_landscape: {
+ name: 'Mobile landscape',
+ styles: {
+ height: '320px',
+ width: '568px'
+ },
+ type: 'mobile'
+ },
+ tablet: {
+ name: 'Tablet',
+ styles: {
+ height: '1112px',
+ width: '834px'
+ },
+ type: 'tablet'
+ },
+ tablet_landscape: {
+ name: 'Tablet landscape',
+ styles: {
+ height: '834px',
+ width: '1112px'
+ },
+ type: 'tablet'
+ },
+ desktop: {
+ name: 'Desktop',
+ styles: {
+ height: '1080px',
+ width: '1920px'
+ },
+ type: 'desktop'
+ }
+ }
+ },
+ options: {
+ storySort: {
+ order: ['Welcome', 'Essentials', 'Components', 'Form Elements']
+ }
+ }
+ }
+};
+
+export default preview;
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 0ec23681f..3ab53ad47 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -104,17 +104,18 @@ If an unreviewed ticket reports a bug, try and reproduce it. If you can reproduc
Our documentation is great but it can always be improved. Did you find a typo? Do you think that something should be clarified? Go ahead and suggest a documentation patch!
-We use [Docz](https://www.docz.site) to run our documentation site at [wave.free-now.com](https://wave.free-now.com/).
+We use [Storybook](https://storybook.js.org) to run our documentation site at [wave.free-now.com](https://wave.free-now.com/).
To add a new component to our documentation site:
-1. Create a new file with the `.md` extension for your component in `/components/[component]/docs`.
-2. Add the markdown header for the page name, route and parent menu
-3. Include a brief description, examples as well as the the `Playground` and `Props` components of [Docz].
+1. Create a new file with the `.stories.tsx` prefix for your component in `/src/stories`.
+2. Include a brief description and examples. Props should be configurable via Storybook
+
+To learn more how to add stories go to [Storybook docs](https://storybook.js.org/docs/react/writing-stories/introduction)
### Reporting pains and use cases
-Speak outloud for us to understand your pains is valuable, challenge current approaches and help us to understand how to do better. Make sure to verify that the topic hasn't being touched yet on the issues poll otherwise open a new one and let's start the conversation
+Speak out loud for us to understand your pains is valuable, challenge current approaches and help us to understand how to do better. Make sure to verify that the topic hasn't being touched yet on the issues poll otherwise open a new one and let's start the conversation
### Take from the backlog
diff --git a/docs/accessibility.mdx b/docs/accessibility.mdx
deleted file mode 100644
index b92ec622c..000000000
--- a/docs/accessibility.mdx
+++ /dev/null
@@ -1,33 +0,0 @@
----
-name: Accessibility
-route: /a11y
-cardHeadline: Accessibility (a11y)
-cardSubHeadline: Accessible design not only helps users with disabilities; it provides better user experiences for everyone.
----
-
-## Overview
-
-Our goal is to provide a consistent user experience for all users, whether they’re navigating with a mouse/touchscreen, keyboard, or screen reader.
-
-An accessible product should:
-
-- Give all users the same quality of experience
-- Adapt to users and situations
-
-Individually accessible elements and components are part of building accessible products, but the accessibility efforts need for manual testing. When designing new UIs, rely as much as possible on Wave existing components and follow accessible patterns. If you're creating a new component or pattern (one that doesn't exist in Wave), keep in mind accessibility practices before your implementation.
-
-## Mission
-
-The Wave Design System team wants as many people as possible to be able to use Wave powered products. For example, that means you should be able to:
-
-- **zoom** in up to 300% without the text spilling off the screen
-- navigate most of the website using just a **keyboard**
-- listen to most of the website using a **screen reader**
-
-## Aid development process
-
-- How to [audit Web a11y Video](https://www.youtube.com/watch?v=cOmehxAU_4s)
-- Use the [a11y project checklist](https://www.a11yproject.com/checklist/) and aim for at least A level compliance
-- Use [axe dev tools](https://chrome.google.com/webstore/detail/axe-devtools-web-accessib/lhdoppojpmngadmnindnejefpokejbdd) for accessibility testing. Check more at [deque Axe](https://www.deque.com/axe/devtools/) and learn [how to use it with this Video](https://www.youtube.com/watch?v=dyU9yrRJ5Eg)
-- Use [Lighthouse Chrome extension](https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=en) for accessibility score. Check more at [Web.dev a11y](https://web.dev/accessibility-scoring/)
-- Use [accessible queries](https://testing-library.com/docs/queries/about#priority) when writing tests. This assume you are using [testing-library](https://testing-library.com/)
diff --git a/docs/accessibility.storybook.mdx b/docs/accessibility.storybook.mdx
new file mode 100644
index 000000000..c1e1e8128
--- /dev/null
+++ b/docs/accessibility.storybook.mdx
@@ -0,0 +1,34 @@
+import { Meta } from '@storybook/blocks';
+
+
+
+# Accessibility (a11y)
+
+Accessible design not only helps users with disabilities; it provides better user experiences for everyone.
+
+## Overview
+
+Our goal is to provide a consistent user experience for all users, whether they’re navigating with a mouse/touchscreen, keyboard, or screen reader.
+
+An accessible product should:
+
+- Give all users the same quality of experience
+- Adapt to users and situations
+
+Individually accessible elements and components are part of building accessible products, but the accessibility efforts need for manual testing. When designing new UIs, rely as much as possible on Wave existing components and follow accessible patterns. If you're creating a new component or pattern (one that doesn't exist in Wave), keep in mind accessibility practices before your implementation.
+
+## Mission
+
+The Wave Design System team wants as many people as possible to be able to use Wave powered products. For example, that means you should be able to:
+
+- **zoom** in up to 300% without the text spilling off the screen
+- navigate most of the website using just a **keyboard**
+- listen to most of the website using a **screen reader**
+
+## Aid development process
+
+- How to [audit Web a11y Video](https://www.youtube.com/watch?v=cOmehxAU_4s)
+- Use the [a11y project checklist](https://www.a11yproject.com/checklist/) and aim for at least A level compliance
+- Use [axe dev tools](https://chrome.google.com/webstore/detail/axe-devtools-web-accessib/lhdoppojpmngadmnindnejefpokejbdd) for accessibility testing. Check more at [deque Axe](https://www.deque.com/axe/devtools/) and learn [how to use it with this Video](https://www.youtube.com/watch?v=dyU9yrRJ5Eg)
+- Use [Lighthouse Chrome extension](https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=en) for accessibility score. Check more at [Web.dev a11y](https://web.dev/accessibility-scoring/)
+- Use [accessible queries](https://testing-library.com/docs/queries/about#priority) when writing tests. This assume you are using [testing-library](https://testing-library.com/)
diff --git a/docs/assets/by-freenow.svg b/docs/assets/by-freenow.svg
new file mode 100644
index 000000000..f50002cd9
--- /dev/null
+++ b/docs/assets/by-freenow.svg
@@ -0,0 +1,41 @@
+
+
+
diff --git a/docs/assets/color-icon.svg b/docs/assets/color-icon.svg
new file mode 100644
index 000000000..49becfde0
--- /dev/null
+++ b/docs/assets/color-icon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/assets/components-icon.svg b/docs/assets/components-icon.svg
new file mode 100644
index 000000000..e0df8c260
--- /dev/null
+++ b/docs/assets/components-icon.svg
@@ -0,0 +1,10 @@
+
+
+
diff --git a/docs/assets/figma-logo-with-text.svg b/docs/assets/figma-logo-with-text.svg
new file mode 100644
index 000000000..a61bfee3e
--- /dev/null
+++ b/docs/assets/figma-logo-with-text.svg
@@ -0,0 +1,39 @@
+
+
+
diff --git a/docs/assets/figma-logo.svg b/docs/assets/figma-logo.svg
new file mode 100644
index 000000000..643018332
--- /dev/null
+++ b/docs/assets/figma-logo.svg
@@ -0,0 +1,18 @@
+
+
+
diff --git a/docs/assets/freenow.svg b/docs/assets/freenow.svg
new file mode 100644
index 000000000..226fea423
--- /dev/null
+++ b/docs/assets/freenow.svg
@@ -0,0 +1,29 @@
+
+
+
diff --git a/docs/assets/github-logo.svg b/docs/assets/github-logo.svg
new file mode 100644
index 000000000..a6711870b
--- /dev/null
+++ b/docs/assets/github-logo.svg
@@ -0,0 +1,43 @@
+
+
+
diff --git a/docs/assets/map.svg b/docs/assets/map.svg
new file mode 100644
index 000000000..156eebb4d
--- /dev/null
+++ b/docs/assets/map.svg
@@ -0,0 +1,1851 @@
+
+
+
diff --git a/docs/assets/menu-icon.svg b/docs/assets/menu-icon.svg
new file mode 100644
index 000000000..4d643f863
--- /dev/null
+++ b/docs/assets/menu-icon.svg
@@ -0,0 +1,17 @@
+
+
+
diff --git a/docs/assets/spacing-icon.svg b/docs/assets/spacing-icon.svg
new file mode 100644
index 000000000..b1b25bc6a
--- /dev/null
+++ b/docs/assets/spacing-icon.svg
@@ -0,0 +1,15 @@
+
+
+
diff --git a/docs/assets/typography-icon.svg b/docs/assets/typography-icon.svg
new file mode 100644
index 000000000..a4b355d3b
--- /dev/null
+++ b/docs/assets/typography-icon.svg
@@ -0,0 +1,18 @@
+
+
+
diff --git a/docs/assets/warning-icon.svg b/docs/assets/warning-icon.svg
new file mode 100644
index 000000000..ec6449bf3
--- /dev/null
+++ b/docs/assets/warning-icon.svg
@@ -0,0 +1,15 @@
+
+
+
diff --git a/docs/assets/wave-background.svg b/docs/assets/wave-background.svg
new file mode 100644
index 000000000..66caf1801
--- /dev/null
+++ b/docs/assets/wave-background.svg
@@ -0,0 +1,90 @@
+
+
+
diff --git a/docs/assets/wave-ds-logo.svg b/docs/assets/wave-ds-logo.svg
new file mode 100644
index 000000000..dd105f0fd
--- /dev/null
+++ b/docs/assets/wave-ds-logo.svg
@@ -0,0 +1,51 @@
+
+
+
diff --git a/docs/assets/wave-logo.svg b/docs/assets/wave-logo.svg
new file mode 100644
index 000000000..efaaf7477
--- /dev/null
+++ b/docs/assets/wave-logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/browser-support.mdx b/docs/browser-support.storybook.mdx
similarity index 53%
rename from docs/browser-support.mdx
rename to docs/browser-support.storybook.mdx
index 7c2a4e483..89b4f9b58 100644
--- a/docs/browser-support.mdx
+++ b/docs/browser-support.storybook.mdx
@@ -1,13 +1,14 @@
----
-name: Browser support
-route: /browser-support
-cardHeadline: Browser support
-cardSubHeadline: Creating a consistent experience across browsers and devices.
----
+import { Meta } from '@storybook/blocks';
+
+
+
+# Browser support
+
+Creating a consistent experience across browsers and devices.
## Supported Devices
The design system should be universally accessible. Components might not look perfect in all scenarios, but everything
should still be accessible to the user.
-**Currently, we are supporting the latest 2 versions of Chrome, Firefox, Safari, Edge and Internet Explorer 11.**
+**Currently, we are supporting the latest 2 versions of Chrome, Firefox, Safari, and Edge.**
diff --git a/docs/contributing.mdx b/docs/contributing.storybook.mdx
similarity index 80%
rename from docs/contributing.mdx
rename to docs/contributing.storybook.mdx
index fa9aa18e7..68440c244 100644
--- a/docs/contributing.mdx
+++ b/docs/contributing.storybook.mdx
@@ -1,13 +1,13 @@
----
-name: Contributing
-route: /contributing
-cardHeadline: Contributing
-cardSubHeadline: Everyone is welcome to make contributions to the design system. To make sure that everyone can contribute, we have decided to write out a few steps that help you add your contributions.
----
-
-import workflowImageUrl from './contributing-new-pattern-workflow.svg'
+import { Meta } from '@storybook/blocks';
+import workflowImageUrl from './contributing-new-pattern-workflow.svg';
import { ImageModal } from './components/ImageModal';
+
+
+# Contributing
+
+Everyone is welcome to make contributions to the design system. To make sure that everyone can contribute, we have decided to write out a few steps that help you add your contributions.
+
## Reporting Bugs
The design system is used in many places. We have a hard time keeping our eyes on all of them to keep up with the issues
@@ -27,13 +27,13 @@ should be added to the design system.
This is the submission process for new components, essentials and improvements to existing components:
1. [Create a Github issue](https://github.com/freenowtech/wave/issues/new) with the basic information and gather
-feedback from the maintainers and your fellow developers
+ feedback from the maintainers and your fellow developers
2. Align with the maintainers and other developers on the API of the component
3. After the development is done, open a pull request, keeping the
-[development guidelines](../CONTRIBUTING.md) in mind. You will get feedback here, but we recommend check-ins with
-designers and developers during the development
+ [development guidelines](../CONTRIBUTING.md) in mind. You will get feedback here, but we recommend check-ins with
+ designers and developers during the development
4. With the required approvals, you can merge your branch to main and it will be released by the maintainers in the
-next version of `@freenow/wave`
+ next version of `@freenow/wave`
If you need any help during the process, don't hesitate to reach out to one of the maintainers.
@@ -51,7 +51,6 @@ Descriptions, FAQs and explanations are all valuable for us! Documentation PRs a
All the documentation pages are Markdown-based. You don't need to know how to write code to contribute.
-
## Other Contributions
Not all contributions have to be made in design, code and pull requests. You can for example help your team adopt the
diff --git a/docs/get-started.storybook.mdx b/docs/get-started.storybook.mdx
new file mode 100644
index 000000000..87ce28630
--- /dev/null
+++ b/docs/get-started.storybook.mdx
@@ -0,0 +1,47 @@
+import { Meta } from '@storybook/blocks';
+import WaveLogo from './assets/wave-ds-logo.svg';
+import ByFreenow from './assets/by-freenow.svg';
+
+import { Box } from '../src/components/Box/Box';
+import { Card } from '../src/components/Card/Card';
+import { Headline } from '../src/components/Headline/Headline';
+import { Text } from '../src/components/Text/Text';
+
+
+
+
+
+
+
+
+Welcome to the Design System of FREE NOW. Thanks for stopping by! This is the place where you find the latest components and essentials, that enable you to rapidly build your product.
+
+## Installation
+
+To bring the design system into your project, install it as a package:
+
+```bash
+npm i @freenow/wave
+```
+
+## Usage
+
+All of our components are exported by name from `@freenow/wave`, so you can import them with:
+
+```jsx
+import { Card, Headline, Text } from '@freenow/wave';
+
+export default () => (
+
+ Welcome
+ FREE NOW Design System
+
+);
+```
+
+You'll see this:
+
+
+ Welcome
+ FREE NOW Design System
+
diff --git a/docs/index.mdx b/docs/index.mdx
deleted file mode 100644
index ef53a06b8..000000000
--- a/docs/index.mdx
+++ /dev/null
@@ -1,49 +0,0 @@
----
-name: Get Started
-route: '/'
-cardHeadline: Wave Design System
-cardSubHeadline: Welcome to the Design System of FREE NOW. Thanks for stopping by! This is the place where you find the latest components and essentials, that enable you to rapidly build your product.
----
-
-## Installation
-
-To bring the design system into your project, install it as a package:
-
-```bash
-npm i @freenow/wave
-```
-
-## Usage
-
-All of our components are exported by name from `@freenow/wave`, so you can import them with:
-
-```jsx
-import { Button, Card, Headline, Text } from '@freenow/wave';
-
-export default () => (
-
- Welcome
- FREE NOW Design System
-
-);
-```
-
-## Dynamic Imports & Create React App
-
-If you are using create-react-app for your project, you are already set up and can use the library without additional
-configuration. If you're configuring babel and webpack on your own, please make sure you have the
-[dynamic imports plugin](https://babeljs.io/docs/en/babel-plugin-syntax-dynamic-import) set up in your configuration.
-
-```bash
-npm install --save-dev @babel/plugin-syntax-dynamic-import
-```
-
-```js
-// babel.config.js
-module.exports = {
- plugins: ['@babel/plugin-syntax-dynamic-import']
-};
-```
-
-We've decided to use dynamic imports to better support tree shaking and reduce the bundle
-size this library will take up in your project.
diff --git a/docs/index.storybook.mdx b/docs/index.storybook.mdx
new file mode 100644
index 000000000..944ec9065
--- /dev/null
+++ b/docs/index.storybook.mdx
@@ -0,0 +1,297 @@
+import { Meta, Unstyled } from '@storybook/addon-docs';
+import WaveLogo from './assets/wave-ds-logo.svg';
+import ByFreenow from './assets/by-freenow.svg';
+import FreenowLogo from './assets/freenow.svg';
+import WaveBackground from './assets/wave-background.svg';
+import Map from './assets/map.svg';
+import ColorIcon from './assets/color-icon.svg';
+import TypographyIcon from './assets/typography-icon.svg';
+import SpacingIcon from './assets/spacing-icon.svg';
+import ComponentsIcon from './assets/components-icon.svg';
+import MenuIcon from './assets/menu-icon.svg';
+import FigmaIcon from './assets/figma-logo.svg';
+import FigmaLogo from './assets/figma-logo-with-text.svg';
+import GithubLogo from './assets/github-logo.svg';
+import WarningIcon from './assets/warning-icon.svg';
+
+import {
+ ParcelIcon,
+ SheetOutlineIcon,
+ DiamondIcon,
+ SpeedometerIcon,
+ ArrowRightIcon,
+ MagnifyingGlassIcon,
+ AlertIcon,
+ PenIcon
+} from '../src/icons/';
+import { Box } from '../src/components/Box/Box';
+import { Button } from '../src/components/Button/Button';
+import { Card } from '../src/components/Card/Card';
+import { Headline } from '../src/components/Headline/Headline';
+import { Text } from '../src/components/Text/Text';
+import { Logo } from '../src/components/Logo/Logo';
+import { Link } from '../src/components/Link/Link';
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Develop experiences faster with our UI component library
+
+ Our Wave design system offers a comprehensive suite of UI components to help you ship new features faster.
+
+
+
+
+
+
+
-
- );
-};
diff --git a/src/components/Accordion/types.ts b/src/components/Accordion/types.ts
index bb930eb8f..063a9e2e8 100644
--- a/src/components/Accordion/types.ts
+++ b/src/components/Accordion/types.ts
@@ -1,13 +1,36 @@
-import { ReactNode } from 'react';
-
export interface AccordionProps {
+ /**
+ * Heading of the Accordion section
+ */
heading?: string;
+ /**
+ * Description of the section
+ */
description?: string;
+ /**
+ * Extra text below description
+ */
info?: string;
+ /**
+ * Text on the button
+ */
buttonLabel?: string;
+ /**
+ * UI style
+ * @default default
+ */
variant?: 'compact' | 'default';
+ /**
+ * Render accordion initially opened
+ * @default false
+ */
defaultExpanded?: boolean;
- children: ReactNode;
+ /**
+ * Callback, runs after the accordion is opened
+ */
onExpand?: () => void;
+ /**
+ * Callback, runs after the accordion is closed
+ */
onCollapse?: () => void;
}
diff --git a/src/components/Banner/Banner.tsx b/src/components/Banner/Banner.tsx
index 7b58780fe..f37ace9eb 100644
--- a/src/components/Banner/Banner.tsx
+++ b/src/components/Banner/Banner.tsx
@@ -75,11 +75,12 @@ type DismissFunc = () => void;
interface BannerProps {
/**
- * Overrides the banner position.
+ * Set banner position
*/
position?: 'top' | 'bottom';
/**
* Set the appropriate background color, screen position, and animation.
+ * @default info
*/
variant?: 'info' | 'success' | 'danger';
/**
@@ -152,7 +153,7 @@ const Banner: React.FC = ({ children, onClose, ...rest }: BannerPro
const renderChildren = () => {
if (typeof children === 'function') {
- return children(dismissFunction) as ReactNode;
+ return children(dismissFunction);
}
return children;
diff --git a/src/components/Banner/docs/Banner.mdx b/src/components/Banner/docs/Banner.mdx
deleted file mode 100644
index f4e2ee18a..000000000
--- a/src/components/Banner/docs/Banner.mdx
+++ /dev/null
@@ -1,166 +0,0 @@
----
-name: Banner
-menu: Components
-route: /components/banner
----
-
-import { Banner } from '../Banner';
-import { Text, Headline, Button } from '../..';
-import { BannerCreator } from './BannerCreator';
-import { BannerPropsTable } from './BannerPropsTable';
-import { ContainedBanner } from './ContainedBanner';
-
-# Banner
-
-Banner is a strong visual pattern that is used to display an important information or state which remains until the
-cause is resolved or the banner is dismissed by the user.
-
-- Banner can include any kind of content, i.e. icons, links, copy
-- Banner should be dismissible
-- Banner **info** and **success** appear at the bottom of the screen (sticky)
-- Banner **error** appears at the top of the screen (sticky)
-- Banner appears and disappears via slide in/out animation combined with soft fade and smooth easing
-
-To properly hide the banner with the correct animation, it is recommended to call the dismiss function that can be used
-when providing a function as the child. This will also unmount the component once the animation is completed.
-
-If you need the banner to be placed top or bottom without depending on the variant make sure to align with the design team
-and bear in mind that you can use the **position** prop for it.
-
-## Variants
-
-With these buttons, you can trigger a banner to appear on the current page. You can also see some example banner
-variations with content below.
-
-
-
-### Info Banner
-
-
-
- In order to continuously improve our websites, and show offers and advertisements that are suited to you, we use
- cookies, tracking and (re-) targeting technologies. Please see our Cookie policy for more information. Tracking
- and (re-) targeting technologies will only be used if you click on "Agree".
-
-
-
-```jsx
-
-
- In order to continuously improve our websites, and show offers and advertisements that are suited to you, we use
- cookies, tracking and (re-)targeting technologies. Please see our Cookie policy for more information. Tracking
- and (re-)targeting technologies will only be used if you click on "Agree".
-
-
-```
-
-### Success Banner
-
-
-
- Booking radius updated
-
-
-
-```jsx
-
-
- Booking radius updated
-
-
-```
-
-### Success Banner with Headline & Text
-
-
-
- Booking radius updated
-
-
- accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum
- dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr.
-
-
-
-```jsx
-
-
- Booking radius updated
-
-
- accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum
- dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr.
-
-
-```
-
-### Error Banner
-
-
-
- Something went wrong :(
-
-
-
-```jsx
-
-
- Something went wrong :(
-
-
-```
-
-### Dismissible Banner
-
-
- {dismiss => (
-
- )}
-
-
-```jsx
-
- {dismiss => (
-
- )}
-
-```
-
-## API
-
-
-
-### Dismiss
-
-Banner provides a function to dismiss the component with an animation. The
-dismiss function is available either through render props or a hook. After the
-animation has finished the `onClose` callback will be called.
-
-#### Render Props
-
-```jsx
-
- {dismiss => }
-
-```
-
-#### Hook
-
-```jsx
-const InsideBanner = () => {
- const dismiss = useBannerDismiss();
- return ;
-};
-
-const BannerWrapper = () => {
- return (
-
-
-
- )
-};
-```
diff --git a/src/components/Banner/docs/Banner.stories.tsx b/src/components/Banner/docs/Banner.stories.tsx
new file mode 100644
index 000000000..d58917de5
--- /dev/null
+++ b/src/components/Banner/docs/Banner.stories.tsx
@@ -0,0 +1,95 @@
+import React from 'react';
+import { Meta, StoryObj } from '@storybook/react';
+import { Banner } from '../Banner';
+import { Text } from '../../Text/Text';
+import { Button } from '../../Button/Button';
+
+const meta: Meta = {
+ title: 'Components/Banner',
+ component: Banner,
+ argTypes: {
+ children: {
+ description:
+ 'Content of the banner. Can be `ReactNode` or a render function that receives a dismiss method',
+ control: { type: 'none' }
+ },
+ position: {
+ table: {
+ defaultValue: {
+ summary: 'Depends on the variant prop value',
+ detail: `
+ info → top\nsuccess → top\ndanger → bottom
+ `
+ }
+ }
+ }
+ },
+ args: {
+ children: (
+
+ In order to continuously improve our websites, and show offers and advertisements that are suited to
+ you, we use cookies, tracking and (re-) targeting technologies. Please see our Cookie policy for more
+ information. Tracking and (re-) targeting technologies will only be used if you click on Agree.
+
+ )
+ },
+ decorators: [
+ Story => (
+
+
+ Page
+
+
+
+ )
+ ]
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ children: Hello
+ }
+};
+
+export const Success: Story = {
+ args: {
+ variant: 'success'
+ }
+};
+
+export const Danger: Story = {
+ args: {
+ variant: 'danger',
+ children: Oops! Something went wrong
+ }
+};
+
+export const PositionTop: Story = {
+ args: {
+ position: 'top'
+ }
+};
+
+export const WithDismissedFn: Story = {
+ args: {
+ children: dismiss => (
+ <>
+ If you are tired of this banner, hit the button 👉
+
+ >
+ )
+ }
+};
diff --git a/src/components/Banner/docs/Banner.storybook.mdx b/src/components/Banner/docs/Banner.storybook.mdx
new file mode 100644
index 000000000..26a69d935
--- /dev/null
+++ b/src/components/Banner/docs/Banner.storybook.mdx
@@ -0,0 +1,54 @@
+import { Meta, ArgTypes, Primary, Story, Stories } from '@storybook/blocks';
+import * as BannerStories from './Banner.stories';
+import { Advice } from '../../../docs/Advice';
+
+
+
+# Banner
+
+Banner is a strong visual pattern that is used to display important information or state which remains until the
+cause is resolved or the banner is dismissed by the user.
+
+- Banner can include any kind of content, i.e. icons, links, copy
+- Banner should be dismissible
+- Banner **info** and **success** appear at the bottom of the screen (sticky)
+- Banner **error** appears at the top of the screen (sticky)
+- Banner appears and disappears via slide in/out animation combined with soft fade and smooth easing
+
+To properly hide the banner with the correct animation, it is recommended to call the dismiss function that can be used
+when providing a function as the child. This will also unmount the component once the animation is completed.
+
+If you need the banner to be placed top or bottom without depending on the variant make sure to align with the design team
+and bear in mind that you can use the **position** prop for it.
+
+
+
+## Properties
+
+
+
+
+ The `Banner` uses `position:sticky` for positioning. It means it will always be rendered on top/bottom of the
+ viewport ([MDN](http://developer.mozilla.org/en-US/docs/Web/CSS/position)).
+
+
+## Visibility management (dismiss function)
+
+Banner provides a function to dismiss the component with an animation.
+The dismiss function is available either through render props or a hook.
+After the animation has finished the onClose callback will be called.
+
+
+
+```tsx
+
+ {dismiss => (
+ <>
+ If you are tired of this banner, hit the button 👉
+
+ >
+ )}
+
+```
+
+
diff --git a/src/components/Banner/docs/BannerCreator.tsx b/src/components/Banner/docs/BannerCreator.tsx
deleted file mode 100644
index 7da37769d..000000000
--- a/src/components/Banner/docs/BannerCreator.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import React, { FC, useState } from 'react';
-import styled from 'styled-components';
-import { BannerProps, Button, Text } from '../..';
-import { Banner, DismissFunc } from '../Banner';
-
-const FlexContainer = styled.div`
- display: flex;
- justify-content: space-between;
- align-items: center;
-`;
-
-interface ExampleBannerProps extends Pick {
- text: string;
-}
-
-const handleDismiss = (dismiss: DismissFunc) => () => {
- dismiss();
-};
-
-const DismissibleBanner = ({ text, variant, position }: ExampleBannerProps) => (
-
- {dismiss => (
-
- {text}
-
-
- )}
-
-);
-
-export const BannerCreator: FC = () => {
- const [banners, setBanners] = useState([]);
-
- const addBannerHandler = ({ variant, position }: Pick) => () => {
- setBanners(currentBanners => [
- ...currentBanners,
- { text: `Banner in variant "${variant}"`, variant, position }
- ]);
- };
-
- return (
- <>
- {banners.map((it, index) => (
- // eslint-disable-next-line react/no-array-index-key
-
- ))}
-
-
-
-
- >
- );
-};
diff --git a/src/components/Banner/docs/BannerPropsTable.tsx b/src/components/Banner/docs/BannerPropsTable.tsx
deleted file mode 100644
index 95599fe92..000000000
--- a/src/components/Banner/docs/BannerPropsTable.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { FC } from 'react';
-import * as React from 'react';
-import { PropsTable } from '../../../docs/PropsTable';
-
-export const BannerPropsTable: FC = () => {
- const props = [
- {
- name: 'position',
- type: '"top" | "bottom"',
- description: 'Overrides the banner position.',
- defaultValue: '-'
- },
- {
- name: 'variant',
- type: '"info" | "success" | "danger"',
- description: 'Set the appropriate background color, screen position, and animation.',
- defaultValue: '-'
- },
- {
- name: 'onClose',
- type: '() => void',
- description:
- 'A function that will be called after the user has dismissed the banner and the banner has disappeared.',
- defaultValue: '-'
- }
- ];
- return ;
-};
diff --git a/src/components/Banner/docs/ContainedBanner.ts b/src/components/Banner/docs/ContainedBanner.ts
deleted file mode 100644
index d0fe21a4f..000000000
--- a/src/components/Banner/docs/ContainedBanner.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import styled from 'styled-components';
-import { Banner } from '../Banner';
-
-export const ContainedBanner = styled(Banner)`
- position: initial;
- transition: none;
-`;
diff --git a/src/components/Box/docs/Box.mdx b/src/components/Box/docs/Box.mdx
deleted file mode 100644
index 95206b6da..000000000
--- a/src/components/Box/docs/Box.mdx
+++ /dev/null
@@ -1,26 +0,0 @@
----
-name: Box
-menu: Components
-route: /components/box
----
-
-import { Playground } from 'docz';
-import { Box } from '../Box';
-import { StyledSystemLinks } from '../../../docs/StyledSystemLinks'
-
-# Box
-
-This component serves as a wrapper component for most layout related needs. Use Box to set values such as `display`,
-`width`, `height`, and more. In practice, this component is used frequently as a wrapper around other components to
-achieve Box Model related styling.
-
-
-
-## Examples
-
-
- Box can be used to create both inline and
- block-level elements,
- elements with fixed or responsive width and height,
- and more!
-
diff --git a/src/components/Box/docs/Box.stories.tsx b/src/components/Box/docs/Box.stories.tsx
new file mode 100644
index 000000000..b71b7cedd
--- /dev/null
+++ b/src/components/Box/docs/Box.stories.tsx
@@ -0,0 +1,32 @@
+import { Meta, StoryObj } from '@storybook/react';
+import { Box } from '../Box';
+
+const meta: Meta = {
+ title: 'Components/Box',
+ component: Box
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ children: 'By default it is a block `div` element'
+ }
+};
+
+export const Inline: Story = {
+ args: {
+ as: 'span',
+ children: 'I can be inline when `as` prop is used'
+ }
+};
+
+export const Responsive: Story = {
+ args: {
+ children: 'I can be responsive',
+ bg: '#FF9CFC',
+ width: [1, 1, 1 / 2]
+ }
+};
diff --git a/src/components/Box/docs/Box.storybook.mdx b/src/components/Box/docs/Box.storybook.mdx
new file mode 100644
index 000000000..9f48d99e5
--- /dev/null
+++ b/src/components/Box/docs/Box.storybook.mdx
@@ -0,0 +1,20 @@
+import { Meta, Primary, Stories } from '@storybook/blocks';
+import * as BoxStories from './Box.stories';
+import { StyledSystemLinks } from '../../../docs/StyledSystemLinks';
+
+
+
+# Box
+
+This component serves as a wrapper component for most layout related needs. Use Box to set values such as display, width, height, and more. In practice, this component is used frequently as a wrapper around other components to achieve Box Model related styling.
+
+
+
+## Properties
+
+
+
+
diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx
index 6f2a951ee..6fa7d0ffb 100644
--- a/src/components/Button/Button.tsx
+++ b/src/components/Button/Button.tsx
@@ -142,7 +142,7 @@ const invertedVariantStyles = variant({
}
});
-const Button: React.FC = styled(BaseButton).attrs({ theme })`
+const Button = styled(BaseButton).attrs({ theme })`
transition: background ease 200ms, border-color ease 200ms, color ease 200ms, fill ease 200ms;
${p => (p.inverted ? invertedVariantStyles : variantStyles)};
diff --git a/src/components/Button/TextButton.tsx b/src/components/Button/TextButton.tsx
index 9853b3ff7..0b1d5696c 100644
--- a/src/components/Button/TextButton.tsx
+++ b/src/components/Button/TextButton.tsx
@@ -82,7 +82,7 @@ const invertedVariantStyles = variant({
}
});
-const TextButton: React.FC = styled(BaseButton)`
+const TextButton = styled(BaseButton)`
transition: color 200ms, fill 200ms;
${props => (props.inverted ? invertedVariantStyles(props) : variantStyles(props))};
diff --git a/src/components/Button/docs/Button.mdx b/src/components/Button/docs/Button.mdx
deleted file mode 100644
index f2f30251d..000000000
--- a/src/components/Button/docs/Button.mdx
+++ /dev/null
@@ -1,71 +0,0 @@
----
-name: Button
-menu: Components
-route: /components/button
----
-
-import { Playground } from 'docz';
-import { Button } from '../Button';
-import { TextButton } from '../TextButton';
-import { Box } from '../../Box/Box';
-import { Headline } from '../../Headline/Headline';
-import { Text } from '../../Text/Text';
-import { TrashBinIcon, CloseIcon } from '../../../icons/index';
-import { ButtonPropsTable } from './ButtonPropsTable';
-import { Combination } from '../../../docs/Combination'
-import { StyledSystemLinks } from '../../../docs/StyledSystemLinks'
-
-# Button
-
-Renders a `button` tag. This module exposes two types of buttons `` and ``.
-Take a look to the [MDN web docs - Button](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button) to know more
-about some of the default props supported by a button along with some accessibility concerns.
-
-The purpose of the buttons is to trigger an interaction like order, confirmation or submit. For navigation
-targets consider a link. Use the primary button only once per screen and avoid putting two primary buttons next to each other.
-Use the secondary button for less important actions and in multi button scenarios.
-
-## Properties
-
-
-
-
-
-
-
-## Examples
-
-
-
- Text Only
-
-
-### Icons
-
-Sometimes an icon can help clarify the usage of the button. The recommended sizes for the icons:
-* `` — 20px for regular button
-* `` — 18px for small button
-
-
-
-
-
-
-
-## Combinations
-
-### Button
-
-
- {(props, i) => }
-
-
-### TextButton
-
-
- {(props, i) => Button}
-
diff --git a/src/components/Button/docs/Button.stories.tsx b/src/components/Button/docs/Button.stories.tsx
new file mode 100644
index 000000000..097bfae8c
--- /dev/null
+++ b/src/components/Button/docs/Button.stories.tsx
@@ -0,0 +1,100 @@
+import { StoryObj, Meta } from '@storybook/react';
+import React from 'react';
+import { Button } from '../Button';
+import TrashBinIcon from '../../../icons/actions/TrashBinIcon';
+import { onDarkBackground } from '../../../docs/parameters';
+
+const meta: Meta = {
+ title: 'Components/Button/Button',
+ component: Button,
+ args: {
+ children: 'Button title'
+ },
+ argTypes: {
+ children: {
+ description: 'Button caption'
+ },
+ variant: {
+ control: 'radio',
+ options: ['primary', 'secondary', 'danger']
+ },
+ size: {
+ control: 'radio',
+ options: ['small', 'medium']
+ },
+ as: {
+ description: 'html tag to use',
+ control: 'text',
+ table: {
+ defaultValue: {
+ summary: 'button'
+ }
+ }
+ },
+ ref: {
+ table: {
+ disable: true
+ }
+ },
+ theme: {
+ table: {
+ disable: true
+ }
+ },
+ forwardedAs: {
+ table: {
+ disable: true
+ }
+ }
+ }
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {};
+
+export const Secondary: Story = {
+ args: {
+ variant: 'secondary'
+ }
+};
+
+export const Danger: Story = {
+ args: {
+ variant: 'danger'
+ }
+};
+
+export const Disabled: Story = {
+ args: {
+ disabled: true
+ }
+};
+
+export const Small: Story = {
+ args: {
+ size: 'small'
+ }
+};
+
+export const Inverted: Story = {
+ args: {
+ inverted: true
+ },
+ parameters: {
+ ...onDarkBackground
+ }
+};
+
+export const WithIcon: Story = {
+ args: {
+ children: (
+ <>
+ Remove
+ >
+ ),
+ variant: 'danger'
+ }
+};
diff --git a/src/components/Button/docs/Button.storybook.mdx b/src/components/Button/docs/Button.storybook.mdx
new file mode 100644
index 000000000..83324bf55
--- /dev/null
+++ b/src/components/Button/docs/Button.storybook.mdx
@@ -0,0 +1,35 @@
+import { Meta, Primary, ArgTypes, Story, Stories, Source } from '@storybook/blocks';
+import { StyledSystemLinks } from '../../../docs/StyledSystemLinks';
+import * as ButtonStories from './Button.stories';
+
+
+
+# Button
+
+Renders a `button` tag. This module exposes two types of buttons `` and ``.
+Take a look to the [MDN web docs - Button](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button) to know more
+about some of the default props supported by a button along with some accessibility concerns.
+
+The purpose of the buttons is to trigger an interaction like order, confirmation or submit. For navigation
+targets consider a link. Use the primary button only once per screen and avoid putting two primary buttons next to each other.
+Use the secondary button for less important actions and in multi button scenarios.
+
+
+
+## Properties
+
+
+
+
+
+## Icons
+
+Sometimes an icon can help clarify the usage of the button. The recommended sizes for the icons:
+
+- `` — 20px for regular button
+- `` — 18px for small button
+
+
+
+
+
diff --git a/src/components/Button/docs/ButtonPropsTable.tsx b/src/components/Button/docs/ButtonPropsTable.tsx
deleted file mode 100644
index 4b4204166..000000000
--- a/src/components/Button/docs/ButtonPropsTable.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import React, { FC } from 'react';
-import { PropsTable } from '../../../docs/PropsTable';
-
-export const ButtonPropsTable: FC = () => {
- const props = [
- {
- name: 'variant',
- type: '"primary" | "secondary" | "danger"',
- description: 'Define style of the button component, defaults to primary',
- defaultValue: '"primary"'
- },
- {
- name: 'size',
- type: '"medium" | "small"',
- description: 'Adjusts the size of the button',
- defaultValue: '"medium"'
- },
- {
- name: 'block',
- type: 'boolean',
- description: 'Sets the button width to 100% of the parent',
- defaultValue: '-',
- deprecated: true
- },
- {
- name: 'inverted',
- type: 'boolean',
- description: 'Adjust colors for display on a dark background',
- defaultValue: '-'
- }
- ];
- return ;
-};
diff --git a/src/components/Button/docs/TextButton.stories.tsx b/src/components/Button/docs/TextButton.stories.tsx
new file mode 100644
index 000000000..7db53b263
--- /dev/null
+++ b/src/components/Button/docs/TextButton.stories.tsx
@@ -0,0 +1,82 @@
+import React from 'react';
+import { StoryObj, Meta } from '@storybook/react';
+import { TextButton } from '../TextButton';
+import { onDarkBackground } from '../../../docs/parameters';
+
+const meta: Meta = {
+ title: 'Components/Button/TextButton',
+ component: TextButton,
+ args: {
+ children: 'TextButton title'
+ },
+ argTypes: {
+ children: {
+ description: 'Button caption'
+ },
+ variant: {
+ control: 'radio',
+ options: ['default', 'danger']
+ },
+ size: {
+ control: 'radio',
+ options: ['small', 'medium']
+ },
+ as: {
+ description: 'html tag to use',
+ table: {
+ control: 'text',
+ defaultValue: {
+ summary: 'button'
+ }
+ }
+ },
+ ref: {
+ table: {
+ disable: true
+ }
+ },
+ theme: {
+ table: {
+ disable: true
+ }
+ },
+ forwardedAs: {
+ table: {
+ disable: true
+ }
+ }
+ }
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {};
+
+export const Danger: Story = {
+ args: {
+ variant: 'danger'
+ }
+};
+
+export const Disabled: Story = {
+ args: {
+ disabled: true
+ }
+};
+
+export const Small: Story = {
+ args: {
+ size: 'small'
+ }
+};
+
+export const Inverted: Story = {
+ args: {
+ inverted: true
+ },
+ parameters: {
+ ...onDarkBackground
+ }
+};
diff --git a/src/components/Button/docs/TextButton.storybook.mdx b/src/components/Button/docs/TextButton.storybook.mdx
new file mode 100644
index 000000000..b39322ea0
--- /dev/null
+++ b/src/components/Button/docs/TextButton.storybook.mdx
@@ -0,0 +1,22 @@
+import { Meta, Primary, ArgTypes, Stories } from '@storybook/blocks';
+import { StyledSystemLinks } from '../../../docs/StyledSystemLinks';
+import * as TextButtonStories from './TextButton.stories';
+
+
+
+# Button
+
+Renders a `button` tag.
+
+The purpose of the buttons is to trigger an interaction like order, confirmation or submit. For navigation
+targets consider a link.
+
+
+
+## Properties
+
+
+
+
+
+
diff --git a/src/components/Card/Card.tsx b/src/components/Card/Card.tsx
index bc6c953ef..c36a38d95 100644
--- a/src/components/Card/Card.tsx
+++ b/src/components/Card/Card.tsx
@@ -25,6 +25,7 @@ type CardProps = BorderRadiusProps &
PaddingProps & {
/**
* Set the visual depth of the card by adding a shadow (available values: 0, 100, 200, 300)
+ * @default 0
*/
level?: ResponsiveValue<0 | 100 | 200 | 300>;
};
diff --git a/src/components/Card/docs/Card.mdx b/src/components/Card/docs/Card.mdx
deleted file mode 100644
index 8f06d5978..000000000
--- a/src/components/Card/docs/Card.mdx
+++ /dev/null
@@ -1,35 +0,0 @@
----
-name: Card
-menu: Components
-route: /components/card
----
-
-import { Playground } from 'docz';
-import { Card } from '../Card';
-import { Text } from '../../Text/Text';
-import { CardPropsTable } from './CardPropsTable'
-import { StyledSystemLinks } from '../../../docs/StyledSystemLinks'
-import { Combination } from '../../../docs/Combination'
-
-# Card
-
-## Properties
-
-
-
-
-
-
-## Examples
-
-
-
- Content
-
-
-
-## Combinations
-
-
- {(props, i) => Card Content}
-
diff --git a/src/components/Card/docs/Card.stories.tsx b/src/components/Card/docs/Card.stories.tsx
new file mode 100644
index 000000000..b1af5dfb5
--- /dev/null
+++ b/src/components/Card/docs/Card.stories.tsx
@@ -0,0 +1,41 @@
+import React from 'react';
+import { Meta, StoryObj } from '@storybook/react';
+import { Card } from '../Card';
+import { Button } from '../../Button/Button';
+
+const meta: Meta = {
+ title: 'Components/Card',
+ component: Card,
+ argTypes: {
+ ref: { table: { disable: true } },
+ forwardedAs: { table: { disable: true } },
+ theme: { table: { disable: true } },
+ as: { table: { disable: true } },
+ children: { description: 'Defines the inner content of the card' },
+ level: {
+ options: [0, 100, 200, 300],
+ control: 'radio'
+ }
+ },
+ args: {
+ children: 'Card Contents'
+ }
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {};
+
+export const WithLevel: Story = {
+ args: {
+ level: 300
+ }
+};
+
+export const WithReactComponent = {
+ args: {
+ children:
+ }
+};
diff --git a/src/components/Card/docs/Card.storybook.mdx b/src/components/Card/docs/Card.storybook.mdx
new file mode 100644
index 000000000..45cb2e4c7
--- /dev/null
+++ b/src/components/Card/docs/Card.storybook.mdx
@@ -0,0 +1,17 @@
+import { Meta, ArgTypes, Primary, Stories } from '@storybook/blocks';
+import { StyledSystemLinks } from '../../../docs/StyledSystemLinks';
+import * as CardStories from './Card.stories';
+
+
+
+# Card
+
+
+
+## Properties
+
+
+
+
+
+
diff --git a/src/components/Card/docs/CardPropsTable.tsx b/src/components/Card/docs/CardPropsTable.tsx
deleted file mode 100644
index b64a3455c..000000000
--- a/src/components/Card/docs/CardPropsTable.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import { FC } from 'react';
-import * as React from 'react';
-import { PropsTable } from '../../../docs/PropsTable';
-
-export const CardPropsTable: FC = () => {
- const props = [
- {
- name: 'level',
- type: '0 | 100 | 200 | 300',
- description: 'Set the visual depth of the card by adding a shadow',
- defaultValue: '0'
- }
- ];
- return ;
-};
diff --git a/src/components/Checkbox/docs/Checkbox.mdx b/src/components/Checkbox/docs/Checkbox.mdx
deleted file mode 100644
index 80620c45b..000000000
--- a/src/components/Checkbox/docs/Checkbox.mdx
+++ /dev/null
@@ -1,56 +0,0 @@
----
-name: Checkbox
-menu: Components
-route: /components/Checkbox
----
-
-import { Playground } from 'docz';
-import { Checkbox } from '../Checkbox';
-import { CheckboxPropsTable } from './CheckboxPropsTable';
-
-# Checkbox
-
-Checkboxes are used for a list of options where the user may select multiple options, including all or none. A
-stand-alone checkbox is used for a single option that the user can turn on or off.
-
-You can provide the label as either a `string` or as a react component. If a `string` is provided as the label, it
-will be wrapped with the [Text](/components/Text) component.
-
-## Properties
-
-
-
-
-
-### States
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-### Sizes
-
-
-
-
-
-
-
-## Playground
-
-
-
-
diff --git a/src/components/Checkbox/docs/Checkbox.stories.tsx b/src/components/Checkbox/docs/Checkbox.stories.tsx
new file mode 100644
index 000000000..688c4e3f1
--- /dev/null
+++ b/src/components/Checkbox/docs/Checkbox.stories.tsx
@@ -0,0 +1,57 @@
+import { Meta, StoryObj } from '@storybook/react';
+import { Checkbox } from '../Checkbox';
+
+const meta: Meta = {
+ title: 'Form Elements/Checkbox',
+ component: Checkbox,
+ argTypes: {
+ size: {
+ control: 'radio',
+ options: ['small', 'medium', 'large']
+ },
+ textVerticalAlign: {
+ control: 'radio',
+ options: ['center', 'top']
+ }
+ },
+ args: {
+ label: 'Accept T&C'
+ }
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {};
+
+export const Selected: Story = {
+ args: {
+ defaultChecked: true
+ }
+};
+
+export const Error: Story = {
+ args: {
+ label: 'With Error',
+ error: true
+ }
+};
+
+export const Disabled: Story = {
+ args: {
+ disabled: true
+ }
+};
+
+export const Indeterminate: Story = {
+ args: {
+ indeterminate: true
+ }
+};
+
+export const Size: Story = {
+ args: {
+ size: 'large'
+ }
+};
diff --git a/src/components/Checkbox/docs/Checkbox.storybook.mdx b/src/components/Checkbox/docs/Checkbox.storybook.mdx
new file mode 100644
index 000000000..afe662f40
--- /dev/null
+++ b/src/components/Checkbox/docs/Checkbox.storybook.mdx
@@ -0,0 +1,20 @@
+import { Meta, Primary, ArgTypes, Stories } from '@storybook/blocks';
+import * as CheckboxStories from './Checkbox.stories';
+
+
+
+# Checkbox
+
+Checkboxes are used for a list of options where the user may select multiple options, including all or none. A
+stand-alone checkbox is used for a single option that the user can turn on or off.
+
+You can provide the label as either a `string` or as a React component. If a `string` is provided as the label, it
+will be wrapped with the [Text](/components/Text) component.
+
+
+
+## Properties
+
+
+
+{' '}
diff --git a/src/components/Checkbox/docs/CheckboxPropsTable.tsx b/src/components/Checkbox/docs/CheckboxPropsTable.tsx
deleted file mode 100644
index 06ba2428e..000000000
--- a/src/components/Checkbox/docs/CheckboxPropsTable.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import { FC } from 'react';
-import * as React from 'react';
-import { PropsTable } from '../../../docs/PropsTable';
-
-export const CheckboxPropsTable: FC = () => {
- const props = [
- {
- name: 'label',
- type: 'string | React element',
- description: 'Sets a label for the checkbox',
- defaultValue: ''
- },
- {
- name: 'error',
- type: 'boolean',
- description: 'Sets styles to indicate an error',
- defaultValue: ''
- },
- {
- name: 'disabled',
- type: 'boolean',
- description: 'Sets the state of the checkbox disabled',
- defaultValue: ''
- },
- {
- name: 'size',
- type: '"large" | "medium" | "small"',
- description: 'Adjusts the size of the checkbox label',
- defaultValue: '"medium"'
- },
- {
- name: 'textVerticalAlign',
- type: '"top" | "center"',
- description: 'Adjusts the vertical alignment of the checkbox',
- defaultValue: '"center"'
- },
- {
- name: 'indeterminate',
- type: 'boolean',
- description: 'Sets the checkbox in the indeterminate state',
- defaultValue: 'false'
- }
- ];
- return ;
-};
diff --git a/src/components/Datepicker/DatepickerRangeInput.tsx b/src/components/Datepicker/DatepickerRangeInput.tsx
index 0689c035d..bef8afc74 100644
--- a/src/components/Datepicker/DatepickerRangeInput.tsx
+++ b/src/components/Datepicker/DatepickerRangeInput.tsx
@@ -126,12 +126,12 @@ interface DatepickerRangeInputProps extends MarginProps, WidthProps {
maxDate?: Date;
/**
* Accepts a number for first day of the week from 0 (Sunday) to 6 (Saturday).
- * Default: 1
+ * @default 1
*/
firstDayOfWeek?: FirstDayOfWeek;
/**
* Function that runs for each date and returns boolean whether date is disabled or not.
- * Default: () => false
+ * @default () => false
*/
isDateBlocked?: (date: Date) => boolean;
/**
@@ -140,13 +140,13 @@ interface DatepickerRangeInputProps extends MarginProps, WidthProps {
*/
placement?: 'left' | 'right' | 'center';
/**
- * String to format dates.
- * Default: dd/MM/yyyy
+ * String to format dates. See the format at [date-fns docs](https://date-fns.org/v2.29.3/docs/format)
+ * @default dd/MM/yyyy
*/
displayFormat?: string;
/**
* String to define the locale in ISO-639-1
- * Default: en-US
+ * @default en-US
*/
locale?: string;
/**
@@ -163,7 +163,7 @@ interface DatepickerRangeInputProps extends MarginProps, WidthProps {
*/
endInputId?: string;
/**
- * Determines the variant
+ * Show two (`'normal'`) or one (`'compact'`) month in the datepicker
* @value `'compact'` displays only a single month
* @default 'normal'
*/
diff --git a/src/components/Datepicker/DatepickerSingleInput.tsx b/src/components/Datepicker/DatepickerSingleInput.tsx
index 2e07afcd7..72360b7ea 100644
--- a/src/components/Datepicker/DatepickerSingleInput.tsx
+++ b/src/components/Datepicker/DatepickerSingleInput.tsx
@@ -40,22 +40,22 @@ interface DatepickerSingleInputProps extends MarginProps, WidthProps {
maxDate?: Date;
/**
* Accepts a number for first day of the week from 0 (Sunday) to 6 (Saturday).
- * Default: 1
+ * @default 1
*/
firstDayOfWeek?: FirstDayOfWeek;
/**
* Function that runs for each date and returns boolean whether date is disabled or not.
- * Default: () => false
+ * @default () => false
*/
isDateBlocked?: (date: Date) => boolean;
/**
- * String to format dates.
- * Default: dd/MM/yyyy
+ * String to format dates. See the format at [date-fns docs](https://date-fns.org/v2.29.3/docs/format)
+ * @default dd/MM/yyyy
*/
displayFormat?: string;
/**
* String to define the locale in ISO-639-1
- * Default: en-US
+ * @default en-US
*/
locale?: string;
/**
diff --git a/src/components/Datepicker/Month.tsx b/src/components/Datepicker/Month.tsx
index 1f3a1526e..1ae8a903d 100644
--- a/src/components/Datepicker/Month.tsx
+++ b/src/components/Datepicker/Month.tsx
@@ -3,7 +3,6 @@ import { useMonth, FirstDayOfWeek } from '@datepicker-react/hooks';
import styled from 'styled-components';
import { format } from 'date-fns';
-import { generateId } from '../../utils/ids';
import { Colors } from '../../essentials';
import { Text } from '../Text/Text';
import { Day } from './Day';
@@ -57,12 +56,14 @@ const Month: FC = ({ year, month, firstDayOfWeek, locale }: MonthPro
))}
- {days.map(day => {
+ {days.map((day, index) => {
if (typeof day === 'object') {
return ;
}
- return ;
+ // we can use index as a key since the array is never reordered
+ // eslint-disable-next-line react/no-array-index-key
+ return ;
})}
diff --git a/src/components/Datepicker/docs/ControlledDatepickerRangeInput.tsx b/src/components/Datepicker/docs/ControlledDatepickerRangeInput.tsx
deleted file mode 100644
index a9ca84d1d..000000000
--- a/src/components/Datepicker/docs/ControlledDatepickerRangeInput.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { FC } from 'react';
-import * as React from 'react';
-import { DatepickerRangeInput } from '../DatepickerRangeInput';
-
-export const ControlledDatepickerRangeInput: FC = props => {
- const [startValue, setStartValue] = React.useState();
- const [endValue, setEndValue] = React.useState();
-
- return (
- {
- setStartValue(date.startDate);
- setEndValue(date.endDate);
- }}
- {...props}
- />
- );
-};
diff --git a/src/components/Datepicker/docs/ControlledDatepickerSingleInput.tsx b/src/components/Datepicker/docs/ControlledDatepickerSingleInput.tsx
deleted file mode 100644
index 1aa0bf699..000000000
--- a/src/components/Datepicker/docs/ControlledDatepickerSingleInput.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import * as React from 'react';
-import { FC } from 'react';
-import { DatepickerSingleInput } from '../DatepickerSingleInput';
-
-export const ControlledDatepickerSingleInput: FC = props => {
- const [value, setValue] = React.useState();
-
- return ;
-};
diff --git a/src/components/Datepicker/docs/DatePicker.stories.tsx b/src/components/Datepicker/docs/DatePicker.stories.tsx
new file mode 100644
index 000000000..1d3bf505b
--- /dev/null
+++ b/src/components/Datepicker/docs/DatePicker.stories.tsx
@@ -0,0 +1,85 @@
+import React, { useState } from 'react';
+import { Meta, StoryObj } from '@storybook/react';
+import { DatePicker } from '../index';
+
+const meta: Meta = {
+ title: 'Form Elements/Datepicker/DatePicker',
+ component: DatePicker,
+ argTypes: {
+ firstDayOfWeek: {
+ type: 'number',
+ defaultValue: 1,
+ control: {
+ type: 'number',
+ min: 1,
+ max: 6
+ }
+ },
+ displayFormat: {
+ control: 'radio',
+ options: ['dd/MM/yyyy', 'E, d MMM, y', 'do LLLL']
+ }
+ },
+ args: {
+ label: 'Date'
+ }
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {},
+ render: ({ minDate, maxDate, onChange, ...args }) => {
+ const [value, setValue] = useState();
+
+ return (
+ {
+ onChange?.(val);
+ setValue(val);
+ }}
+ />
+ );
+ }
+};
+
+const TODAY = new Date();
+const minDate = new Date();
+minDate.setMonth(TODAY.getMonth() - 1);
+const maxDate = new Date();
+maxDate.setMonth(TODAY.getMonth() + 1);
+
+export const WithRestrictedDays: Story = {
+ ...Default,
+ args: {
+ minDate,
+ maxDate
+ }
+};
+
+export const WithDayAvailabilityFunction: Story = {
+ ...Default,
+ args: {
+ isDateBlocked: date => date.getDate() % 2 === 0
+ }
+};
+
+export const WithErrorHandler: Story = {
+ ...Default,
+ args: {
+ errorHandler: 'The expected format is dd/MM/yyyy'
+ }
+};
+
+export const Disabled: Story = {
+ ...Default,
+ args: {
+ disabled: true
+ }
+};
diff --git a/src/components/Datepicker/docs/DatePicker.storybook.mdx b/src/components/Datepicker/docs/DatePicker.storybook.mdx
new file mode 100644
index 000000000..ba5b029be
--- /dev/null
+++ b/src/components/Datepicker/docs/DatePicker.storybook.mdx
@@ -0,0 +1,76 @@
+import { Meta, ArgTypes, Primary, Story, Stories, Unstyled } from '@storybook/blocks';
+
+import { StyledSystemLinks } from '../../../docs/StyledSystemLinks';
+import { DatepickerOnModal } from './DatepickerOnModal';
+import * as DatePickerStories from './DatePicker.stories';
+
+
+
+# Datepicker
+
+
+
+### Properties
+
+
+
+
+
+## Usage
+
+### Restricted dates range
+
+There are two ways to restrict selectable dates.
+
+If you need to allow dates no later than some date or only after a certain date, use `minDate` and `maxDate`
+properties. They accept plain JavaScript `Date`.
+
+For example, the datepicker allow to select dates one month away from the current date:
+
+
+
+If the restriction is more complex, provide a restriction function to the `isDateBlocked` property.
+The function will be called for each date at render, passing the `Date` object to it.
+
+For example, a function which disables every even day in the calendar `(date:Date) => date.getDate() % 2 === 0`:
+
+
+
+### Datepicker on Modal
+
+If you need to show the Datepicker in a Modal window, we recommend to set the modal `dismissable` prop to `false` to avoid
+occasional closing.
+
+
+
+
+
+Example code:
+
+```tsx
+export const DatepickerOnModal = () => {
+ const [showModal, setShowModal] = useState(false);
+ const [value, setValue] = useState();
+
+ return (
+ <>
+ {!showModal && }
+ {showModal && (
+ setShowModal(false)}>
+ {dismiss => (
+ <>
+ New Event
+
+
+
+ Cancel
+ >
+ )}
+
+ )}
+ >
+ );
+};
+```
+
+
diff --git a/src/components/Datepicker/docs/DateRangePicker.stories.tsx b/src/components/Datepicker/docs/DateRangePicker.stories.tsx
new file mode 100644
index 000000000..4aec261a4
--- /dev/null
+++ b/src/components/Datepicker/docs/DateRangePicker.stories.tsx
@@ -0,0 +1,100 @@
+import React, { useState } from 'react';
+import { Meta, StoryObj } from '@storybook/react';
+import { DateRangePicker } from '../index';
+
+const meta: Meta = {
+ title: 'Form Elements/Datepicker/DateRangePicker',
+ component: DateRangePicker,
+ argTypes: {
+ firstDayOfWeek: {
+ type: 'number',
+ defaultValue: 1,
+ control: {
+ type: 'number',
+ min: 1,
+ max: 6
+ }
+ },
+ displayFormat: {
+ control: 'radio',
+ options: ['dd/MM/yyyy', 'E, d MMM, y', 'do LLLL']
+ },
+ variant: {
+ control: 'radio',
+ options: ['normal', 'compact']
+ }
+ },
+ args: {
+ label: 'Rides between'
+ }
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ render: ({ onChange, ...args }) => {
+ const [range, setRange] = useState<{ startDate?: Date; endDate?: Date }>();
+
+ return (
+ {
+ onChange?.(newRange);
+ setRange(newRange);
+ }}
+ />
+ );
+ }
+};
+
+export const Compact: Story = {
+ ...Default,
+ args: {
+ variant: 'compact'
+ }
+};
+
+const TODAY = new Date();
+const minDate = new Date();
+minDate.setMonth(TODAY.getMonth() - 1);
+const maxDate = new Date();
+maxDate.setMonth(TODAY.getMonth() + 1);
+
+export const WithRestrictedDays: Story = {
+ ...Default,
+ args: {
+ minDate,
+ maxDate
+ }
+};
+
+export const WithDayAvailabilityFunction: Story = {
+ ...Default,
+ args: {
+ isDateBlocked: date => date.getDate() % 2 === 0
+ }
+};
+
+export const WithErrorHandler: Story = {
+ ...Default,
+ args: {
+ errorHandler: 'The expected format is dd/MM/yyyy'
+ }
+};
+
+export const Disabled: Story = {
+ ...Default,
+ args: {
+ disabled: true
+ }
+};
+
+export const WithManualPlacement: Story = {
+ ...Default,
+ args: {
+ placement: 'center'
+ }
+};
diff --git a/src/components/Datepicker/docs/DateRangePicker.storybook.mdx b/src/components/Datepicker/docs/DateRangePicker.storybook.mdx
new file mode 100644
index 000000000..734bb034c
--- /dev/null
+++ b/src/components/Datepicker/docs/DateRangePicker.storybook.mdx
@@ -0,0 +1,76 @@
+import { Meta, ArgTypes, Primary, Story, Stories, Unstyled } from '@storybook/blocks';
+
+import { StyledSystemLinks } from '../../../docs/StyledSystemLinks';
+import { DatepickerOnModal } from './DatepickerOnModal';
+import * as DateRangePickerStories from './DateRangePicker.stories';
+
+
+
+# DateRangePicker
+
+
+
+### Properties
+
+
+
+
+
+## Usage
+
+### Restricted dates range
+
+There are two ways to restrict selectable dates.
+
+If you need to allow dates no later than some date or only after a certain date, use `minDate` and `maxDate`
+properties. They accept plain JavaScript `Date`.
+
+For example, the datepicker allow to select dates one month away from the current date:
+
+
+
+If the restriction is more complex, provide a restriction function to the `isDateBlocked` property.
+The function will be called for each date at render, passing the `Date` object to it.
+
+For example, a function which disables every even day in the calendar `(date:Date) => date.getDate() % 2 === 0`:
+
+
+
+### Datepicker on Modal
+
+If you need to show the Datepicker in a Modal window, we recommend to set the modal `dismissable` prop to `false` to avoid
+occasional closing.
+
+
+
+
+
+Example code:
+
+```tsx
+export const DatepickerOnModal = () => {
+ const [showModal, setShowModal] = useState(false);
+ const [value, setValue] = useState<{ startDate?: Date; endDate?: Date }>();
+
+ return (
+ <>
+ {!showModal && }
+ {showModal && (
+ setShowModal(false)}>
+ {dismiss => (
+ <>
+ New Event
+
+
+
+ Cancel
+ >
+ )}
+
+ )}
+ >
+ );
+};
+```
+
+
diff --git a/src/components/Datepicker/docs/Datepicker.mdx b/src/components/Datepicker/docs/Datepicker.mdx
deleted file mode 100644
index 99ff26ea4..000000000
--- a/src/components/Datepicker/docs/Datepicker.mdx
+++ /dev/null
@@ -1,81 +0,0 @@
----
-name: Datepicker
-menu: Components
-route: /components/date-picker
----
-
-import { Playground } from 'docz';
-import { StyledSystemLinks } from '../../../docs/StyledSystemLinks';
-import { DatepickerRangeInput as DateRangePicker } from '../DatepickerRangeInput';
-import { DatepickerSingleInput as DatePicker } from '../DatepickerSingleInput';
-import { ControlledDatepickerSingleInput } from './ControlledDatepickerSingleInput';
-import { ControlledDatepickerRangeInput } from './ControlledDatepickerRangeInput';
-import { DatepickerOnModal } from './DatepickerOnModal';
-import { DatepickerSingleInputPropsTable } from './DatepickerSingleInputPropsTable';
-import { DatepickerRangeInputPropsTable } from './DatepickerRangeInputPropsTable';
-
-# Datepicker
-
-## Single
-
-
-
-### Single datepicker props
-
-
-
-
-
-## Range
-
-
-
-### Range datepicker props
-
-
-
-
-
-## Datepicker on Modal
-
-If you need to show the Datepicker in a Modal window, we recommend to set the modal `dismissable` prop to `false` to avoid
-occasional closing.
-
-
-
-Example code:
-
-```jsx
-export const DatepickerOnModal = () => {
- const [showModal, setShowModal] = useState(false);
- const [value, setValue] = React.useState();
-
- return (
- <>
- {!showModal && }
- {showModal && (
- setShowModal(false)}>
- {dismiss => (
- <>
- New Event
-
-
-
- Cancel
- >
- )}
-
- )}
- >
- );
-};
-```
-
-## Playground
-
-
-
-
-
-
-
diff --git a/src/components/Datepicker/docs/DatepickerOnModal.tsx b/src/components/Datepicker/docs/DatepickerOnModal.tsx
index 5d7589526..81151e1c3 100644
--- a/src/components/Datepicker/docs/DatepickerOnModal.tsx
+++ b/src/components/Datepicker/docs/DatepickerOnModal.tsx
@@ -1,10 +1,11 @@
import React, { FC, useState } from 'react';
import { Button, Headline, Modal, TextButton } from '../..';
-import { ControlledDatepickerSingleInput } from './ControlledDatepickerSingleInput';
+import { DatePicker } from '../index';
export const DatepickerOnModal: FC = () => {
const [showModal, setShowModal] = useState(false);
+ const [value, setValue] = useState();
return (
<>
@@ -17,7 +18,7 @@ export const DatepickerOnModal: FC = () => {
<>
New Event
-
+
diff --git a/src/components/Datepicker/docs/DatepickerRangeInputPropsTable.tsx b/src/components/Datepicker/docs/DatepickerRangeInputPropsTable.tsx
deleted file mode 100644
index 0a7f704c1..000000000
--- a/src/components/Datepicker/docs/DatepickerRangeInputPropsTable.tsx
+++ /dev/null
@@ -1,105 +0,0 @@
-import React, { FC } from 'react';
-
-import { PropsTable } from '../../../docs/PropsTable';
-
-export const DatepickerRangeInputPropsTable: FC = () => {
- const props = [
- {
- name: 'startPlaceholder',
- type: 'string',
- description: 'Placeholder for start date.'
- },
- {
- name: 'endPlaceholder',
- type: 'string',
- description: 'Placeholder for end date.'
- },
- {
- name: 'label',
- type: 'string',
- description: 'Label for the input.'
- },
- {
- name: 'onClose',
- type: 'Function => void',
- description: 'Function that is used when datepicker closes without selected date.'
- },
- {
- name: 'value',
- type: 'DateRange (interface containing startDate and endDate properties)',
- description: 'Set the value for the date.'
- },
- {
- name: 'onChange',
- type: 'Function (change: DateRange) => void',
- description: 'Function that is used when datepicker selects new date.'
- },
- {
- name: 'minDate',
- type: 'Date',
- description: 'Minimal date to select from.'
- },
- {
- name: 'maxDate',
- type: 'Date',
- description: 'Maximum date to select from.'
- },
- {
- name: 'firstDayOfWeek',
- type: 'FirstDayOfWeek (number from 0-6)',
- description: 'Accepts a number for first day of the week from 0 (Sunday) to 6 (Saturday).',
- defaultValue: '1'
- },
- {
- name: 'isDateBlocked',
- type: 'Function => boolean',
- description: 'Function that runs for each date and returns boolean whether date is disabled or not.',
- defaultValue: '() => false'
- },
- {
- name: 'placement',
- type: "'left' | 'right' | 'center'",
- description: 'Used to align the datepicker in relation to input.',
- defaultValue: 'left'
- },
- {
- name: 'displayFormat',
- type: 'string',
- description: 'String to format dates.',
- defaultValue: 'dd/MM/yyyy'
- },
- {
- name: 'locale',
- type: 'string',
- description: 'String to define the locale in ISO-639-1.',
- defaultValue: 'en-US'
- },
- {
- name: 'errorHandler',
- type: '(Function => void) | string',
- description: 'Text to be shown if error filling the input or fn to be trigger as a callback when error.'
- },
- {
- name: 'startInputId',
- type: 'string',
- description: 'The id to be assigned to the start date input.'
- },
- {
- name: 'endInputId',
- type: 'string',
- description: 'The id to be assigned to the end date input.'
- },
- {
- name: 'variant',
- type: "'compact' | 'normal'",
- description: "Determines the variant, 'compact' displays only a single month",
- defaultValue: "'normal'"
- },
- {
- name: 'disabled',
- type: 'boolean',
- description: 'Determines whether the datePicker is disabled or not.'
- }
- ];
- return ;
-};
diff --git a/src/components/Datepicker/docs/DatepickerSingleInputPropsTable.tsx b/src/components/Datepicker/docs/DatepickerSingleInputPropsTable.tsx
deleted file mode 100644
index ffc6ad4bd..000000000
--- a/src/components/Datepicker/docs/DatepickerSingleInputPropsTable.tsx
+++ /dev/null
@@ -1,83 +0,0 @@
-import React, { FC } from 'react';
-
-import { PropsTable } from '../../../docs/PropsTable';
-
-export const DatepickerSingleInputPropsTable: FC = () => {
- const props = [
- {
- name: 'placeholder',
- type: 'string',
- description: 'Placeholder for the input.'
- },
- {
- name: 'label',
- type: 'string',
- description: 'Label for the input.'
- },
- {
- name: 'onClose',
- type: 'Function => void',
- description: 'Function that is used when datepicker closes without selected date.'
- },
- {
- name: 'onChange',
- type: 'Function => void',
- description: 'Function that is used when datepicker selects new date.'
- },
- {
- name: 'minDate',
- type: 'Date',
- description: 'Minimal date to select from.'
- },
- {
- name: 'maxDate',
- type: 'Date',
- description: 'Maximum date to select from.'
- },
- {
- name: 'firstDayOfWeek',
- type: 'FirstDayOfWeek (number from 0-6)',
- description: 'Accepts a number for first day of the week from 0 (Sunday) to 6 (Saturday).',
- defaultValue: '1'
- },
- {
- name: 'isDateBlocked',
- type: 'Function => boolean',
- description: 'Function that runs for each date and returns boolean whether date is disabled or not.',
- defaultValue: '() => false'
- },
- {
- name: 'displayFormat',
- type: 'string',
- description: 'String to format dates.',
- defaultValue: 'dd/MM/yyyy'
- },
- {
- name: 'locale',
- type: 'string',
- description: 'String to define the locale in ISO-639-1.',
- defaultValue: 'en-US'
- },
- {
- name: 'value',
- type: 'Date',
- description: 'Set the value of the input.'
- },
- {
- name: 'errorHandler',
- type: '(Function => void) | string',
- description: 'Text to be shown if error filling the input or fn to be trigger as a callback when error.'
- },
- {
- name: 'inputId',
- type: 'string',
- description: 'The id to be assigned to the input field.'
- },
- {
- name: 'disabled',
- type: 'boolean',
- description: 'Determines whether the datePicker is disabled or not.'
- }
- ];
- return ;
-};
diff --git a/src/components/Dimming/docs/Dimming.mdx b/src/components/Dimming/docs/Dimming.mdx
deleted file mode 100644
index 6c2b2de7a..000000000
--- a/src/components/Dimming/docs/Dimming.mdx
+++ /dev/null
@@ -1,25 +0,0 @@
----
-name: Dimming
-menu: Components
-route: /components/dimming
----
-
-import { Playground } from 'docz';
-import { ItemWrapper } from '../../../../docs/components/ItemWrapper';
-import { Dimming } from '../Dimming';
-import { DimmingFixedDimensions } from './DimmingFixedDimensions';
-
-# Dimming
-
-The Dimming is a dark blue transparent layer covering 100% of the screen’s width and height. It’s a building block to
-compose and emphasize a screen overlay. Here you will see it contained in a small box for demo purposes.
-
-
-
-
-
-### Usage
-
-```jsx
-
-```
diff --git a/src/components/Dimming/docs/Dimming.stories.tsx b/src/components/Dimming/docs/Dimming.stories.tsx
new file mode 100644
index 000000000..6ddcb4553
--- /dev/null
+++ b/src/components/Dimming/docs/Dimming.stories.tsx
@@ -0,0 +1,57 @@
+import React from 'react';
+import { Meta, StoryObj } from '@storybook/react';
+import { Dimming } from '../Dimming';
+
+const meta: Meta = {
+ title: 'Components/Dimming',
+ component: Dimming,
+ argTypes: {
+ style: {
+ table: {
+ disable: true
+ }
+ },
+ theme: {
+ table: {
+ disable: true
+ }
+ },
+ as: {
+ table: {
+ disable: true
+ }
+ },
+ forwardedAs: {
+ table: {
+ disable: true
+ }
+ },
+ ref: {
+ table: {
+ disable: true
+ }
+ }
+ },
+ decorators: [
+ Story => (
+ // use a workaround with `willChange: transform` to keep the fixed positioned element inside the container
+
+
+ text below
+
+ )
+ ],
+ parameters: {
+ docs: {
+ source: {
+ excludeDecorators: true
+ }
+ }
+ }
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {};
diff --git a/src/components/Dimming/docs/Dimming.storybook.mdx b/src/components/Dimming/docs/Dimming.storybook.mdx
new file mode 100644
index 000000000..8f7318f1e
--- /dev/null
+++ b/src/components/Dimming/docs/Dimming.storybook.mdx
@@ -0,0 +1,15 @@
+import { Meta, ArgTypes, Primary } from '@storybook/blocks';
+import * as DimmingStories from './Dimming.stories';
+
+
+
+# Dimming
+
+The Dimming is a dark blue transparent layer covering 100% of the screen’s width and height. It’s a building block to
+compose and emphasize a screen overlay. Here you will see it contained in a small box for demo purposes.
+
+
+
+### Properties
+
+
diff --git a/src/components/Dimming/docs/DimmingFixedDimensions.tsx b/src/components/Dimming/docs/DimmingFixedDimensions.tsx
deleted file mode 100644
index 742e41dfc..000000000
--- a/src/components/Dimming/docs/DimmingFixedDimensions.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import styled from 'styled-components';
-
-import { Dimming } from '../Dimming';
-
-// This container is needed or the dimming component would overtake the whole docs page and the user would be unable to
-// keep navigating.
-const DimmingFixedDimensions = styled(Dimming)`
- height: 15rem;
- position: static;
- width: 21rem;
- z-index: 0;
-`;
-
-export { DimmingFixedDimensions };
diff --git a/src/components/Divider/docs/Divider.mdx b/src/components/Divider/docs/Divider.mdx
deleted file mode 100644
index 57a215c00..000000000
--- a/src/components/Divider/docs/Divider.mdx
+++ /dev/null
@@ -1,101 +0,0 @@
----
-name: Divider
-menu: Components
-route: /components/divider
----
-
-import { Playground } from 'docz';
-import { ItemWrapper } from '../../../../docs/components/ItemWrapper';
-import { Divider } from '../Divider';
-import { WrappedHorizontalDivider, WrappedVerticalDivider, SectionPlaceholder } from './WrappedDivider';
-
-# Divider
-
-**Primary UI element for visually separating content**
-
-Renders a divider UI component: horizontal or vertical line that visually separates two pieces of data, content or UI.
-
-
-### Default Behaviour
-The horizontal divider takes up the full available width and the vertical divider takes up the full available height.
-
-The horizontal divider is rendered by default. Set **vertical** prop to `true` to change the divider orientation.
-
-
-### Divider vs Border
-The default color of Divider is **$border.primary** (#C6CDD4), however...
-
-**Divider is NOT a border, and should not be used as such. Please do not use this component as a border for elements.**
-
-Divider is naturally expected to have a certain offset from the elements it is 'dividing' or separating.
-
-
-### Style Props
-The Divider has the following design props:
-- **offset** - set the divider offset from the content it is separating (uses _mx_, _my_ styled system props)
-
-
-
-## Usage
-
-### Horizontal (with default offset)
-
-
-
-
-
-```jsx
-
-```
-
-
-### Horizontal (without offset)
-
-
-
-
-
-```jsx
-
-```
-
-
-### Vertical (with default offset)
-
-
-
-
-
-```jsx
-
-```
-
-
-### Vertical (without offset)
-
-
-
-
-
-```jsx
-
-```
-
-
-# Playground
-
-
- Section 1
-
- Section 2
-
-
-
- {/* We need the row flow to see vertical divider */}
-
- Section 1
-
- Section 2
-
-
-
diff --git a/src/components/Divider/docs/Divider.stories.tsx b/src/components/Divider/docs/Divider.stories.tsx
new file mode 100644
index 000000000..7ad30fc2e
--- /dev/null
+++ b/src/components/Divider/docs/Divider.stories.tsx
@@ -0,0 +1,41 @@
+import React from 'react';
+import { Meta, StoryObj } from '@storybook/react';
+import { Divider } from '../Divider';
+import { Box } from '../../Box/Box';
+import { Text } from '../../Text/Text';
+
+const meta: Meta = {
+ title: 'Components/Divider',
+ component: Divider,
+ argTypes: {
+ offset: {
+ description: 'Set margins from surrounding content in css units or Space scale',
+ control: {
+ type: 'text'
+ }
+ }
+ },
+ decorators: [
+ (Story, context) => (
+
+ One
+
+ Two
+
+ )
+ ]
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {};
+
+export const Vertical: Story = {
+ args: { vertical: true }
+};
+
+export const WithoutOffset: Story = {
+ args: { offset: 0 }
+};
diff --git a/src/components/Divider/docs/Divider.storybook.mdx b/src/components/Divider/docs/Divider.storybook.mdx
new file mode 100644
index 000000000..b44461b10
--- /dev/null
+++ b/src/components/Divider/docs/Divider.storybook.mdx
@@ -0,0 +1,39 @@
+import { Meta, ArgTypes, Primary, Stories, Unstyled } from '@storybook/blocks';
+import { Divider, InfoBanner } from '../../index';
+import * as DividerStories from './Divider.stories';
+
+
+
+# Divider
+
+**Primary UI element for visually separating content**
+
+Renders a divider UI component: horizontal or vertical line that visually separates two pieces of data, content or UI.
+
+
+
+### Properties
+
+
+
+## Default Behaviour
+
+The horizontal divider takes up the full available width and the vertical divider takes up the full available height.
+
+The horizontal divider is rendered by default. Set **vertical** prop to `true` to change the divider orientation.
+
+## Divider vs Border
+
+The default color of Divider is _$border.primary_ (#C6CDD4), however...
+
+
+
+
+
+Divider is naturally expected to have a certain offset from the elements it is 'dividing' or separating.
+
+
diff --git a/src/components/Divider/docs/WrappedDivider.tsx b/src/components/Divider/docs/WrappedDivider.tsx
deleted file mode 100644
index b8d1fbcd8..000000000
--- a/src/components/Divider/docs/WrappedDivider.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import { Divider } from '../Divider';
-import type { DividerOffset } from '../Divider';
-
-const DividerWrapper = styled.div`
- height: auto;
- display: flex;
- width: 100%;
-`;
-
-const DividerColumnWrapper = styled(DividerWrapper)`
- flex-direction: column;
-`;
-
-const DividerSideElement = styled.div`
- height: auto;
- padding: 4;
-`;
-
-const SectionPlaceholder = styled.div`
- flex: 1;
- height: '200px';
- border: 1px black solid;
- text-align: center;
- padding: 20px;
-`;
-
-const WrappedHorizontalDivider = (offset: DividerOffset): React.ReactElement => (
-
- Element 1
-
- Element 2
-
-);
-
-const WrappedVerticalDivider = (offset: DividerOffset): React.ReactElement => (
-
- Element 1
-
- Element 2
-
-);
-
-export { WrappedHorizontalDivider, WrappedVerticalDivider, SectionPlaceholder };
diff --git a/src/components/FilePicker/FilePicker.tsx b/src/components/FilePicker/FilePicker.tsx
index 61bf95522..5f65f7165 100644
--- a/src/components/FilePicker/FilePicker.tsx
+++ b/src/components/FilePicker/FilePicker.tsx
@@ -25,7 +25,7 @@ interface FilePickerProps extends MarginProps, ComponentPropsWithoutRef<'input'>
* What source to use for capturing image or video data.
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
*/
- capture?: string;
+ capture?: boolean | 'user' | 'environment';
/**
* Text to provide a clear description of what the user should upload
*/
@@ -40,7 +40,7 @@ interface FilePickerProps extends MarginProps, ComponentPropsWithoutRef<'input'>
*/
alwaysShowActionButton?: boolean;
/**
- * Whether or not the component should render an error state
+ * Whether the component should render an error state
*/
error?: boolean;
/**
diff --git a/src/components/FilePicker/docs/ControlledErrorFilePicker.tsx b/src/components/FilePicker/docs/ControlledErrorFilePicker.tsx
index 5224a2fc8..e5a696d71 100644
--- a/src/components/FilePicker/docs/ControlledErrorFilePicker.tsx
+++ b/src/components/FilePicker/docs/ControlledErrorFilePicker.tsx
@@ -5,34 +5,16 @@ import { HelperText } from '../../HelperText/HelperText';
const ControlledErrorFilePicker: FC = () => {
const [error, setError] = useState(false);
- const onError = file => {
- // eslint-disable-next-line no-console
- console.log('onError', file);
- setError(!!file);
- };
return (
{
- // eslint-disable-next-line no-console
- console.log('onChange', e);
- }}
- onFileChange={(eventFile, e) => {
- // eslint-disable-next-line no-console
- console.log('onFileChange', eventFile, e);
- try {
- if (eventFile.size > 0) {
- throw new Error('Oops! I need a file with no size');
- }
- } catch {
- onError(eventFile);
- }
+ onFileChange={() => {
+ setError(true);
}}
/>
{error && (
diff --git a/src/components/FilePicker/docs/FilePicker.mdx b/src/components/FilePicker/docs/FilePicker.mdx
deleted file mode 100644
index 1ef533327..000000000
--- a/src/components/FilePicker/docs/FilePicker.mdx
+++ /dev/null
@@ -1,115 +0,0 @@
----
-name: FilePicker
-menu: Components
-route: /components/file-picker
----
-
-import { Playground } from 'docz';
-import { StyledSystemLinks } from '../../../docs/StyledSystemLinks';
-import { FilePicker, Button, Box } from '../'
-import { ControlledErrorFilePicker } from './ControlledErrorFilePicker'
-import { FilePickerPropsTable } from './FilePickerPropsTable';
-
-
-# FilePicker
-
-This component it’s a trigger opening the native file uploader.
-This component uses default Web input type file check [Mozilla Input Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file)
-if you need to know more about the supported attributes and values
-
-## Properties
-
-
-
-
-
-## Appearance
-- **File title**: This provides a clear description of what the user should upload. If long, takes as many lines as needed extending the height of the component.
-- **Button label**: Describes the main action, it works better when short
-- It is recommended to place this component together with a helper text to provide additional help for what's expected. Helper text should only appear if the user open the file explorer and doesn't select anything.
-
-## Placement
-
-- They are mainly used in forms but can also appear in other places as a stand alone component, like item or user registration screens.
-- It should be placed with a minimum of 8px _("Spaces" value 1 for our default spaces values)_ margin on each side
-- It should be placed vertically aligned
-
-## Behaviour
-
-- The user may select 1 file at a time.
-- By default, any file format is accepted, but you can add parameters to validate a specific file format.
-- The action of clicking Browse file will trigger a browser-specific upload window.
-- Once the user selects the file, the browser-specific select window closes and the files will appear below the File title label.
-
-### Error
-Below you have an example of how you can properly show an error using the **HelperText**. You can try to submit any file to trigger the error
-and clean the input by canceling the selection to remove the error state.
-
-
-
-## Playground
-The example below will demostrate how to create compositions of `FilePicker`
-
-
-
- console.log('onChange', e)}
- onFileChange={(file, e) => console.log('onFileChange', file, e)}
- />
- console.log('onChange', e)}
- onFileChange={(file, e) => console.log('onFileChange', file, e)}
- alwaysShowActionButton
- mt={1}
- />
- console.log('onChange', e)}
- onFileChange={(file, e) => console.log('onFileChange', file, e)}
- mt={1}
- />
-
-
-
-In the real world you may need to deal with the `FilePicker` within a form that will handle the submission of the file. Below you will find a snippet
-that can help as example.
-
-**Tip:** The `FilePicker` exposes an additional callback of `onFileChange` which signature is `(file, event)`. The [File](https://developer.mozilla.org/es/docs/Web/API/File)
-and the standard input event. This is a convenient to use `file` instead of `e.target.elements.avatar.files[0]` check the console while using the example below.
-
-
-
-
-
-
diff --git a/src/components/FilePicker/docs/FilePicker.stories.tsx b/src/components/FilePicker/docs/FilePicker.stories.tsx
new file mode 100644
index 000000000..f57a6d3ee
--- /dev/null
+++ b/src/components/FilePicker/docs/FilePicker.stories.tsx
@@ -0,0 +1,51 @@
+import React from 'react';
+import { Meta, StoryObj } from '@storybook/react';
+import { FilePicker } from '../FilePicker';
+import { Box } from '../../Box/Box';
+
+const meta: Meta = {
+ title: 'Form Elements/FilePicker',
+ component: FilePicker,
+ argTypes: {
+ capture: {
+ options: ['user', 'environment'],
+ control: 'select'
+ }
+ },
+ args: {
+ name: 'avatar',
+ label: 'Picture of you',
+ buttonText: 'Browse'
+ }
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {};
+
+export const WithBrowserButtonAlwaysVisible: Story = {
+ args: {
+ alwaysShowActionButton: true
+ }
+};
+
+export const WithMultilineLabel: Story = {
+ args: {
+ label: 'A very long label which can stretch to more than one line without any issues'
+ },
+ decorators: [
+ Story => (
+
+
+
+ )
+ ]
+};
+
+export const AcceptingOnlyImages: Story = {
+ args: {
+ accept: 'image/*'
+ }
+};
diff --git a/src/components/FilePicker/docs/FilePicker.storybook.mdx b/src/components/FilePicker/docs/FilePicker.storybook.mdx
new file mode 100644
index 000000000..399e5483c
--- /dev/null
+++ b/src/components/FilePicker/docs/FilePicker.storybook.mdx
@@ -0,0 +1,76 @@
+import { Primary, Stories, ArgTypes, Meta } from '@storybook/blocks';
+import { ControlledErrorFilePicker } from './ControlledErrorFilePicker';
+import { StyledSystemLinks } from '../../../docs/StyledSystemLinks';
+import * as FilePickerStories from './FilePicker.stories';
+
+
+
+# FilePicker
+
+This component delivers an optimal user experience by utilizing core web technologies. It uses the [HTML filepicker](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file) for a lightweight and efficient approach to file uploading.
+
+
+
+## Properties
+
+
+
+
+
+## Appearance
+
+- **File title**: This provides a clear description of what the user should upload. If long, takes as many lines as needed extending the height of the component.
+- **Button label**: Describes the main action, it works better when short
+
+## Placement
+
+- They are mainly used in forms but can also appear in other places as a standalone component. In either case, prefer to have them inside `