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

Storybook: enhance story making #2130

Merged
merged 63 commits into from
Jul 21, 2023
Merged
Show file tree
Hide file tree
Changes from 62 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
a5db061
`npx storybook upgrade`
louismaximepiton Jun 23, 2023
effb6de
.
louismaximepiton Jul 3, 2023
b04bc51
?
louismaximepiton Jul 3, 2023
8b12f5e
?
louismaximepiton Jul 3, 2023
5044176
.
louismaximepiton Jul 3, 2023
2c8db60
.
louismaximepiton Jul 3, 2023
d0dbe2b
remove useless addon
louismaximepiton Jul 5, 2023
f64e9fc
Remove actions
louismaximepiton Jul 5, 2023
a948958
Remove useless packages
louismaximepiton Jul 5, 2023
94956c4
Merge branch 'main' into main-lmp-bump-storybook-7
julien-deramond Jul 6, 2023
1c0ec46
update to last storybook
louismaximepiton Jul 6, 2023
ed6b209
Add docs tab ?
louismaximepiton Jul 7, 2023
04e351d
?
louismaximepiton Jul 7, 2023
9b1e8b1
.
louismaximepiton Jul 7, 2023
3d952be
Remove unused ?
louismaximepiton Jul 7, 2023
1b92725
.
louismaximepiton Jul 7, 2023
1082390
Merge branch 'main' into main-lmp-bump-storybook-7
julien-deramond Jul 11, 2023
c46c137
First tests
louismaximepiton Jul 6, 2023
d00d712
.
louismaximepiton Jul 6, 2023
0f2aba0
.
louismaximepiton Jul 6, 2023
be82698
Auto add js
louismaximepiton Jul 6, 2023
d4b8adf
.
louismaximepiton Jul 6, 2023
2658809
.
louismaximepiton Jul 6, 2023
80b0017
.
louismaximepiton Jul 6, 2023
9f60654
Working story generation
louismaximepiton Jul 7, 2023
3b717ae
Solution for Toasts
louismaximepiton Jul 7, 2023
0322354
.
louismaximepiton Jul 7, 2023
a13f416
.
louismaximepiton Jul 7, 2023
da260bd
Toasts and Alerts comeback ?
louismaximepiton Jul 7, 2023
8a2a288
.
louismaximepiton Jul 7, 2023
72434fd
.
louismaximepiton Jul 7, 2023
5b7f523
Less console error ?
louismaximepiton Jul 10, 2023
3a10e1a
Add Form variants
louismaximepiton Jul 10, 2023
a96fa13
Better js
louismaximepiton Jul 10, 2023
e6ed520
Remove link redirect ?
louismaximepiton Jul 10, 2023
e657dc1
.
louismaximepiton Jul 10, 2023
0c2d21a
Script change
louismaximepiton Jul 10, 2023
55203f2
.
louismaximepiton Jul 10, 2023
ac42837
Adding CSS
louismaximepiton Jul 10, 2023
7f31bdf
.
louismaximepiton Jul 10, 2023
6c6f3bd
.
louismaximepiton Jul 10, 2023
3f9bf00
.
louismaximepiton Jul 10, 2023
1bfa597
.
louismaximepiton Jul 10, 2023
9f5d5eb
Optimize
louismaximepiton Jul 10, 2023
28e334c
.
louismaximepiton Jul 10, 2023
d3e5824
.
louismaximepiton Jul 10, 2023
d41146f
Add comments
louismaximepiton Jul 10, 2023
f5b2ac7
.
louismaximepiton Jul 11, 2023
a5076a4
.
louismaximepiton Jul 11, 2023
f294dc3
.
louismaximepiton Jul 11, 2023
2942215
.
louismaximepiton Jul 11, 2023
ab02989
.
louismaximepiton Jul 11, 2023
3352fd4
Class list on parent element instead of root
louismaximepiton Jul 11, 2023
b8c5d49
Test to get only one listener
louismaximepiton Jul 11, 2023
7b15714
.
louismaximepiton Jul 11, 2023
7b2bde5
Fix carousels
louismaximepiton Jul 11, 2023
5045b85
Add tooltips/popovers on forms
louismaximepiton Jul 12, 2023
08fdf9a
Merge branch 'main' into main-lmp-add-js-storybook
julien-deramond Jul 21, 2023
8df0129
Update .storybook/preview-head.html
julien-deramond Jul 21, 2023
4cbf53e
Update site/assets/js/snippets.js
julien-deramond Jul 21, 2023
4ff8fd9
.
louismaximepiton Jul 21, 2023
ae43a3e
.
louismaximepiton Jul 21, 2023
84bc74a
Update stories/create-stories-from-doc.js
julien-deramond Jul 21, 2023
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
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ _Note: Please transform `- [ ]` into `- (NA)` in the description when things are
### Checklist (for Core Team only)

- [ ] My change introduces changes to the migration guide
- [ ] My new component is added in Storybook
- [ ] My new component is well displayed in [Storybook](https://deploy-preview-{your_pr_number}--boosted.netlify.app/storybook)
julien-deramond marked this conversation as resolved.
Show resolved Hide resolved
- [ ] My new component is compatible with RTL
- [ ] Manually run [BrowserStack tests](https://github.com/Orange-OpenSource/Orange-Boosted-Bootstrap/actions/workflows/browserstack.yml)
- [ ] Manually test browser compatibility with BrowserStack (Chrome >= 60, Firefox >= 60 (+ ESR), Edge, Safari >= 12, iOS Safari, Chrome & Firefox on Android)
Expand Down
6 changes: 6 additions & 0 deletions .storybook/preview-head.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,9 @@

<!-- Boosted CSS -->
<link href="https://cdn.jsdelivr.net/npm/boosted/dist/css/boosted.min.css" rel="stylesheet" crossorigin="anonymous">

<!-- Boosted site CSS -->
<link href="https://boosted.orange.com/docs/5.3/assets/css/docs.css" rel="stylesheet" crossorigin="anonymous">

<!-- Boosted Js: Use of defer because it allows to load only once the bundle (Storybook issue) -->
<script src="https://cdn.jsdelivr.net/npm/boosted/dist/js/boosted.bundle.min.js" crossorigin="anonymous" defer></script>
64 changes: 37 additions & 27 deletions site/assets/js/snippets.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,44 @@
(() => {
'use strict'

// Boosted mod: Try not using `const` at the first layer in this file, otherwise Storybook will fail to render some examples.

// storybook-start overview
// --------
// Tooltips
// --------
// Instantiate all tooltips in a docs or StackBlitz
// storybook-start tooltips
document.querySelectorAll('[data-bs-toggle="tooltip"]')
.forEach(tooltip => {
new boosted.Tooltip(tooltip)
})
// storybook-end tooltips

// --------
// Popovers
// --------
// Instantiate all popovers in docs or StackBlitz
// storybook-start popovers
document.querySelectorAll('[data-bs-toggle="popover"]')
.forEach(popover => {
new boosted.Popover(popover)
})
// storybook-end popovers
// storybook-end overview

// -------------------------------
// Toasts
// -------------------------------
// Used by 'Placement' example in docs or StackBlitz
const toastPlacement = document.getElementById('toastPlacement')
if (toastPlacement) {
// storybook-start toasts
if (document.getElementById('toastPlacement')) {
document.getElementById('selectToastPlacement').addEventListener('change', function () {
if (!toastPlacement.dataset.originalClass) {
toastPlacement.dataset.originalClass = toastPlacement.className
if (!document.getElementById('toastPlacement').dataset.originalClass) {
document.getElementById('toastPlacement').dataset.originalClass = document.getElementById('toastPlacement').className
}

toastPlacement.className = `${toastPlacement.dataset.originalClass} ${this.value}`
document.getElementById('toastPlacement').className = `${document.getElementById('toastPlacement').dataset.originalClass} ${this.value}`
})
}

Expand All @@ -61,26 +69,23 @@

// Instantiate all toasts in docs pages only
// js-docs-start live-toast
const toastTrigger = document.getElementById('liveToastBtn')
const toastLiveExample = document.getElementById('liveToast')

if (toastTrigger) {
const toastBoosted = boosted.Toast.getOrCreateInstance(toastLiveExample)
toastTrigger.addEventListener('click', () => {
toastBoosted.show()
if (document.getElementById('liveToastBtn')) {
document.getElementById('liveToastBtn').addEventListener('click', () => {
boosted.Toast.getOrCreateInstance(document.getElementById('liveToast')).show()
})
}
// js-docs-end live-toast
// storybook-end toasts

// -------------------------------
// Alerts
// -------------------------------
// Used in 'Show live alert' example in docs or StackBlitz

// Boosted mod: adapted innerHTML to have the icon and so added a parameter within `appendAlert()` and a tooltip on `.btn-close`
// storybook-start alerts
// js-docs-start live-alert
const alertPlaceholder = document.getElementById('liveAlertPlaceholder')
const appendAlert = (message, type, typeVisuallyHidden) => {
function appendAlert(message, type, typeVisuallyHidden) {
const wrapper = document.createElement('div')
wrapper.innerHTML = [
`<div class="alert alert-${type} alert-dismissible" role="alert">`,
Expand All @@ -94,7 +99,7 @@
'</div>'
].join('')

alertPlaceholder.append(wrapper)
document.getElementById('liveAlertPlaceholder').append(wrapper)

// Create `.btn-close` tooltip after `innerHTML` has been modified
const btnClose = wrapper.querySelector('.btn-close')
Expand All @@ -104,33 +109,37 @@
})
}

const alertTrigger = document.getElementById('liveAlertBtn')
if (alertTrigger) {
alertTrigger.addEventListener('click', () => {
if (document.getElementById('liveAlertBtn')) {
document.getElementById('liveAlertBtn').addEventListener('click', () => {
appendAlert('Nice, you triggered this alert message!', 'success', 'Success')
})
}
// js-docs-end live-alert
// storybook-end alerts

// --------
// Carousels
// --------
// Instantiate all non-autoplaying carousels in docs or StackBlitz
// storybook-start carousel
document.querySelectorAll('.carousel:not([data-bs-ride="carousel"])')
.forEach(carousel => {
boosted.Carousel.getOrCreateInstance(carousel)
})
// storybook-end carousel

// -------------------------------
// Checks & Radios
// -------------------------------
// Indeterminate checkbox example in docs and StackBlitz
// storybook-start checksradios
document.querySelectorAll('.bd-example-indeterminate [type="checkbox"]')
.forEach(checkbox => {
if (checkbox.id.includes('Indeterminate')) {
checkbox.indeterminate = true
}
})
// storybook-end checksradios

// -------------------------------
// Links
Expand All @@ -147,10 +156,10 @@
// Modal
// -------------------------------
// Modal 'Varying modal content' example in docs and StackBlitz
// storybook-start modal
// js-docs-start varying-modal-content
const exampleModal = document.getElementById('exampleModal')
if (exampleModal) {
exampleModal.addEventListener('show.bs.modal', event => {
if (document.getElementById('exampleModal')) {
document.getElementById('exampleModal').addEventListener('show.bs.modal', event => {
// Button that triggered the modal
const button = event.relatedTarget
// Extract info from data-bs-* attributes
Expand All @@ -159,25 +168,26 @@
// and then do the updating in a callback.

// Update the modal's content.
const modalTitle = exampleModal.querySelector('.modal-title')
const modalBodyInput = exampleModal.querySelector('.modal-body input')
const modalTitle = document.getElementById('exampleModal').querySelector('.modal-title')
const modalBodyInput = document.getElementById('exampleModal').querySelector('.modal-body input')

modalTitle.textContent = `New message to ${recipient}`
modalBodyInput.value = recipient
})
}
// js-docs-end varying-modal-content
// storybook-end modal

// -------------------------------
// Offcanvas
// -------------------------------
// 'Offcanvas components' example in docs only
const myOffcanvas = document.querySelectorAll('.bd-example-offcanvas .offcanvas')
if (myOffcanvas) {
myOffcanvas.forEach(offcanvas => {
// storybook-start offcanvas
document.querySelectorAll('.bd-example-offcanvas .offcanvas')
.forEach(offcanvas => {
offcanvas.addEventListener('show.bs.offcanvas', event => {
event.preventDefault()
}, false)
})
}
// storybook-end offcanvas
})()
70 changes: 22 additions & 48 deletions stories/create-stories-from-doc.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
'use strict'

const fs = require('node:fs')
const path = require('node:path')
const puppeteer = require('puppeteer') // eslint-disable-line import/no-extraneous-dependencies

const version = '5.3'
julien-deramond marked this conversation as resolved.
Show resolved Hide resolved

function createDirectoryIfNeeded(path) {
if (!fs.existsSync(path)) {
fs.mkdirSync(path, 0o766, error => {
Expand Down Expand Up @@ -37,46 +40,15 @@ const convertToKebabCase = string => {
.toLowerCase()
}

// TODO: build this list automatically from docs
const files = [
['Accordion', '../_site/docs/5.3/components/accordion/index.html'],
['Alerts', '../_site/docs/5.3/components/alerts/index.html'],
['BackToTop', '../_site/docs/5.3/components/back-to-top/index.html'],
['Badge', '../_site/docs/5.3/components/badge/index.html'],
['Breadcrumb', '../_site/docs/5.3/components/breadcrumb/index.html'],
['ButtonGroup', '../_site/docs/5.3/components/button-group/index.html'],
['Buttons', '../_site/docs/5.3/components/buttons/index.html'],
['Card', '../_site/docs/5.3/components/card/index.html'],
['Carousel', '../_site/docs/5.3/components/carousel/index.html'],
['CloseButton', '../_site/docs/5.3/components/close-button/index.html'],
['Collapse', '../_site/docs/5.3/components/collapse/index.html'],
['Dropdowns', '../_site/docs/5.3/components/dropdowns/index.html'],
['Footer', '../_site/docs/5.3/components/footer/index.html'],
['ListGroup', '../_site/docs/5.3/components/list-group/index.html'],
['Modal', '../_site/docs/5.3/components/modal/index.html'],
['Navbar', '../_site/docs/5.3/components/navbar/index.html'],
['NavsTabs', '../_site/docs/5.3/components/navs-tabs/index.html'],
['OffCanvas', '../_site/docs/5.3/components/offcanvas/index.html'],
['OrangeNavbar', '../_site/docs/5.3/components/orange-navbar/index.html'],
['Pagination', '../_site/docs/5.3/components/pagination/index.html'],
['Placeholders', '../_site/docs/5.3/components/placeholders/index.html'],
['Popovers', '../_site/docs/5.3/components/popovers/index.html'],
['Progress', '../_site/docs/5.3/components/progress/index.html'],
['Scrollspy', '../_site/docs/5.3/components/scrollspy/index.html'],
['Spinners', '../_site/docs/5.3/components/spinners/index.html'],
['SteppedProcess', '../_site/docs/5.3/components/stepped-process/index.html'],
['Sticker', '../_site/docs/5.3/components/sticker/index.html'],
['Tags', '../_site/docs/5.3/components/tags/index.html'],
['TitleBars', '../_site/docs/5.3/components/title-bars/index.html'],
['Toasts', '../_site/docs/5.3/components/toasts/index.html'],
// Note: we need to use `var` instead of `const` to avoid `redeclaration of const tooltipTriggerList` message
['Tooltips',
'../_site/docs/5.3/components/tooltips/index.html',
'var tooltipTriggerList = [].slice.call(document.querySelectorAll(\'[data-bs-toggle="tooltip"]\'));\
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {\
return new boosted.Tooltip(tooltipTriggerEl);\
})']
]
const toPascalCase = str => {
return (str.match(/[\dA-Za-z]+/g) || []).map(w => `${w.charAt(0).toUpperCase()}${w.slice(1)}`).join('')
}

// Get all stories that might be displayed
const files = fs.readdirSync(path.resolve(__dirname, `../site/content/docs/${version}/components/`)).map(fileName => [toPascalCase(fileName.replace('.md', '')), 'components'])
.concat(fs.readdirSync(path.resolve(__dirname, `../site/content/docs/${version}/forms/`)).map(fileName => [toPascalCase(fileName.replace('.md', '')), 'forms']))
.concat([['Tables', 'content']]) // Manual adding
const snippets = fs.readFileSync(path.resolve(__dirname, '../site/assets/js/snippets.js'), { encoding: 'utf8' })

const outputDirectory = `${__dirname}/auto`
createDirectoryIfNeeded(outputDirectory);
Expand All @@ -95,17 +67,18 @@ createDirectoryIfNeeded(outputDirectory);
// 'Error: Execution context was destroyed, most likely because of a navigation.':
await Promise.all([
page.waitForNavigation(),
page.goto(`file://${__dirname}/${file[1]}`),
page.goto(`file://${__dirname}/../_site/docs/${version}/${file[1]}/${convertToKebabCase(file[0])}/index.html`),
page.waitForNavigation()
])

// Getting examples content and classes
const e = await page.evaluate(() =>
Array.from(document.querySelectorAll('.bd-example'), e => e.innerHTML) // eslint-disable-line no-undef
Array.from(document.querySelectorAll('.bd-example'), e => [e.innerHTML, e.classList]) // eslint-disable-line no-undef
)

let index = 0
let mdxContent = ''
for (let example of e) {
for (const example of e) {
const outputFileDirectory = `${outputDirectory}/${file[0]}`
const outputFile = `${outputFileDirectory}/${file[0]}_${index}.stories.js`

Expand All @@ -115,18 +88,19 @@ createDirectoryIfNeeded(outputDirectory);
mdxContent += `<Canvas>\n<Story id="components-${file[0].toLowerCase()}--${convertToKebabCase(file[0])}-${index}"/>\n</Canvas>\n\n`

// Automatically remove HTML comments that would break the story
example = example.replace(/<!--[\S\s]*?-->/gm, '')
example[0] = `<div class="${Object.values(example[1]).join(' ')} m-0 border-0">${example[0].replace(/<!--[\S\s]*?-->/gm, '').replaceAll('`', '\\`').replaceAll('${', '\\${')}</div>`

// Insert some specific JavaScript
example += '<script src="https://cdn.jsdelivr.net/npm/boosted/dist/js/boosted.bundle.min.js" crossorigin="anonymous"></script>'
if (file[2]) {
example += `<script type="text/javascript">${file[2]}</script>`
example[0] += '\n<script type="text/javascript">\n /* global boosted: false */\n document.querySelectorAll(\'[href]\').forEach(link => {link.addEventListener(\'click\', event => {event.preventDefault()})})\n</script>' // Remove links behavior
if (new RegExp(`// storybook-start ${file[0]}\n`, 'si').test(snippets)) {
const re = new RegExp(`// storybook-start ${file[0]}\n.*// storybook-end ${file[0]}\n`, 'gsi') // RegExp to get all used code in `snippets.js`
example[0] += `\n<script type="text/javascript">\n ${snippets.match(re)[0].replaceAll('`', '\\`').replaceAll('${', '\\${')}</script>` // Replace backticks and variables in js snippets
julien-deramond marked this conversation as resolved.
Show resolved Hide resolved
}

createDirectoryIfNeeded(outputFileDirectory)

try {
fs.writeFileSync(outputFile, createTemplate(file[0], index, example))
fs.writeFileSync(outputFile, createTemplate(file[0], index, example[0]))
} catch (error) {
throw new Error(error)
}
Expand Down