Webpack + Customizable Semantic UI 2.x (LESS)
Author Artem Butusov · Published on September 11th, 2016
Contents
The goal: Get configurable Semantic UI without requirement to copy/paste all Semantic UI source code, ideally a way to enable/disable any components and override theme styles.
Let’s say we have application folder structure:
- src/index.jsx
- package.json
- node_modules
Assumptions
Let’s assume that we would like to put all Semantic UI related overrides somewhere in project source folder, for example, src/semantic.
src/semantic/theme.config- theme configuration, we could define what is the default theme for each component.src/semantic/semantic.less- main less include file, we could define here what css components we want to enable.src/semantic/semantic.js- main js include file, we could define here what js components we want to enable.src/semantic/site- site theme, structure should match with http://learnsemantic.com/developing/customizing.html
Fix Semantic UI
Unfortunately, but Semantic UI is not designed to be easily included via webpack.
We need to apply some fixes on Semantic UI less sources to make it work.
We can do that in automatic way after each npm install.
./semantic-fix.js:
var fs = require('fs');
// relocate default config
fs.writeFileSync(
'node_modules/semantic-ui-less/theme.config',
"@import '../../src/semantic/theme.config';\n",
'utf8'
);
// fix well known bug with default distribution
fixFontPath('node_modules/semantic-ui-less/themes/default/globals/site.variables');
fixFontPath('node_modules/semantic-ui-less/themes/flat/globals/site.variables');
fixFontPath('node_modules/semantic-ui-less/themes/material/globals/site.variables');
function fixFontPath(filename) {
var content = fs.readFileSync(filename, 'utf8');
var newContent = content.replace(
"@fontPath : '../../themes/",
"@fontPath : '../../../themes/"
);
fs.writeFileSync(filename, newContent, 'utf8');
}
package.json:
...
"scripts": {
...
"postinstall": "node semantic-fix.js",
...
}
...
Install
npm install --save semantic-ui-less && node semantic-fix.js
semantic-ui package has more features, but it runs gulp install automatically so it is not suitable (for me at least).
Copy semantic.less
Copy node_modules/semantic-ui-less/semantic.less into src/semantic/semantic.less.
Fix all imports to begin with @import ~semantic-ui-less/.
Create semantic.js
Create src/semantic/semantic.js:
import 'semantic-ui-less/definitions/globals/site';
import 'semantic-ui-less/definitions/behaviors/api';
import 'semantic-ui-less/definitions/behaviors/colorize';
import 'semantic-ui-less/definitions/behaviors/form';
import 'semantic-ui-less/definitions/behaviors/state';
import 'semantic-ui-less/definitions/behaviors/visibility';
import 'semantic-ui-less/definitions/behaviors/visit';
import 'semantic-ui-less/definitions/modules/accordion';
import 'semantic-ui-less/definitions/modules/checkbox';
import 'semantic-ui-less/definitions/modules/dimmer';
import 'semantic-ui-less/definitions/modules/dropdown';
import 'semantic-ui-less/definitions/modules/embed';
import 'semantic-ui-less/definitions/modules/modal';
import 'semantic-ui-less/definitions/modules/nag';
import 'semantic-ui-less/definitions/modules/popup';
import 'semantic-ui-less/definitions/modules/progress';
import 'semantic-ui-less/definitions/modules/rating';
import 'semantic-ui-less/definitions/modules/search';
import 'semantic-ui-less/definitions/modules/shape';
import 'semantic-ui-less/definitions/modules/sidebar';
import 'semantic-ui-less/definitions/modules/sticky';
import 'semantic-ui-less/definitions/modules/tab';
import 'semantic-ui-less/definitions/modules/transition';
// import 'semantic-ui-less/definitions/modules/video';
Copy theme.config
Copy node_modules/semantic-ui-less/theme.config.example into src/semantic/theme.config.
Set variable @siteFolder : '../../src/semantic/site';.
Fix theme import like @import "~semantic-ui-less/theme.less";.
Test
You could create test override to check if configuration works well. Create src/semantic/site/elements/button.variables and override @backgroundColor to any color.
And something like that could help you to test:
<button className="ui button">Button with custom background</button>
Autoprefixer
Semantic UI comes with autoprefixer configuration. It is included in semantic-ui but not in semantic-ui-less. It could be loaded in webpack with:
var LessPluginAutoPrefix = require('less-plugin-autoprefix');
// that could be possible if semantic-ui will not run intstall
// var autoprefixerBrowsers = require('semantic-ui/tasks/config/tasks').settings.prefix.browsers;
// workaround until (hardcoded value from file behind)
var autoprefixerBrowsers = ['last 2 versions', '> 1%', 'opera 12.1', 'bb 10', 'android 4'];
module.exports = {
module: {
loaders: [
{ test: /\.less$/, loader: ... }
]
},
lessLoader: {
lessPlugins: [
new LessPluginAutoPrefix({ browsers: autoprefixerBrowsers })
]
}
};
Import
Put code below somewhere in main entry point to import css and javascript part of Semantic UI.
import './semantic/semantic';
import './semantic/semantic.less';