An opinionated component-based base theme with built-in support for StorybookJS 6, Bootstrap 4.6.0 (Bootstrap 5.x is work in progress on the main Radix theme), BrowserSync, leveraging laravel-mix, webpack and CriticalCSS. With some heavy usage of theme overrides and theme hook suggestions out of the box.
Prerequisites
- Node:
^14.15.0
- Yarn:
^1.22.4
or preferably higher
Getting Started
- Download the theme
composer require drupal/bootstrap_storybook
- Enable the theme:
drush theme:enable bootstrap_storybook
(Don't set it as the default theme) - To create a subtheme
drush --include="web/themes/contrib/bootstrap_storybook" bootstrap_storybook:create SUBTHEMENAME
When creating the subtheme, if you're using ddev, Lando, Docksal, etc. consider the fact that the "web" directory is set as the docroot by default, so you have to omit the "web/" part of the path, also note that Drush should be used locally and defined in the project and it will fail with Drush v8 or a global Drush. - Go to the theme directory
cd web/themes/custom/SUBTHEMENAME
- Run
npm install --legacy-peer-deps
(npm 7: When to use `--force` and `--legacy-peer-deps`) - Copy the config.example.js to config.js in the config directory of your subtheme:
cp config/config.example.js config/config.js
- Update proxy variable to your localhost address in
config/config.js
- Make sure to build the theme first:
npm run build
- Go back to your Drupal root directory, Install components module and enable it:
composer require 'drupal/components'
and thendrush en components -y
- Enable and set the default theme
drush then SUBTHEMENAME -y; drush config-set system.theme default SUBTHEMENAME -y
- Clear the cache and you're good to go:
drush cr
this file is .gitignored by default to avoid overrides
You may use
yarn
instead ofnpm
commands
Main Commands
npm run watch
runs Drupal only asset watch and browserSyncnpm run storybook
starts Storybooknpm run build-storybook
StorybookJS static buildnpm run crazy
Crazy mode ? (recommended for development): To compile & watch Storybook & Drupal assets, running browserSync in parallelnpm run production
?compiles for production, ❇️ also compiles the critical CSS files, but you have to make sure to define the necessary libraries and make sure it loads in the header as a critically needed style, include each CSS file in its proper twig file. Check the documentation on how to edit yourwebpack.mix.js
to create different critical CSS files for different pathsnpm run production:no-critical
?compiles for production, with no critical CSS file generation (faster compiling)
Recommendations / HOW To
- The base theme is not meant to be used as a starterkit, make sure to create child theme first before you proceed
- In case you don't want to use StorybookJS, you can just ignore it and use the theme as is
- The theme comes with some helper variables/mixins out of the box, use them wisely!
- it's a best practice to keep anything Drupal related to Drupal and make things as generic as possible for components, so build folders and new components
- We are taking advantage of hook_library_info_build to build each component assets and have it ready automatically as long as the asset names are identical, so for example check
src/components/block
and its template filetemplates/block/block.html.twig
There's already a{{ attach_library('bootstrap_storybook/block') }}
included without it being shown inbootstrap_storybook.libraries.yml
file, you can assume each comoponent will have its library created out of the box - Images and Icons should be in
src
folder, it will be copied to assets automatically on asset watch/compile. There's no image optimization just to be safe, do it yourself or ask your server to optimize your images! - Given all the above explanation, you should not edit/touch anything in the
assets
directory, we do not gitignore theassets
directory by default, but you probably should do it yourself. all changes must be done insrc
directory only - After creating any new components, you have to clear cache to make sure the library of it would be in effect
Critical CSS
Note that the critical-css file is only being generated by running the production command, it will build and save the asset into the `assets/css/critical/PATH_critical.min.css`, we currently only use the front path out of box, so it's named: front_critical.min.css
which should get defined via a library in `SUBTHEMENAME.libraries.yml` and loaded in the <head>
area of a twig file like so: (also see inline_css documentation)
{% block critical %}
<style type="text/css">
{{ source('@critical/node-navigation_critical.min.css') }}
</style>
{% endblock %}
In case you need more specific path-based critical css files besides your front, you may add more paths to webpack.mix.js
in the urls array section, f.x:
urls: [
{ src: proxy.proxy + '/', dest: './assets/css/critical/front_critical.min.css' },
{ src: proxy.proxy + '/blog', dest: './assets/css/critical/blog_critical.min.css' },
],
StorybookJS and Drupal
This theme supports jQuery and Drupal.behaviors
out of the box to play nicely with StorybookJS (example button.stories.js), the jQuery library is forced into Storybook against its will ¯\_(ツ)_/¯ , you can remove it in .storybook/config.js
and go ahead and write down your ES6, but in case you need it, make sure that your jQuery is wrapped around $(document).ready
or window.onload
to be testable in StorybookJS environment
Also, the bootstrap SCSS files are directly included in the StorybookJS, so you can just play around your bootstrap partial @import
in the theme's src/sass/main.style.scss
and be assured that it's being reflected in StorybookJS as well.
5.x Roadmap
- Integrate Bootstrap 5.x
- Linter integration
- Documentation & best practices
- A set of pre-defined components under
library
with StorybookJS demo - Integrate Yeoman for component creation
- More isolation of Bootstrap from the Drupal subtheme
Credits & Inspirations
- Initial idea for StorybookJS integration: Albert Skibinski
- Theme structure and initial base from the amazing Radix theme
- FourKitchens for their great work on the new emulsify