First of all you need to decide who will be your target consumers based on the following:
- 
They have the same environment(webpack config, babel config) setup as you where you built your design system(this is mostly possible if you use monorepos/same configs where all the teams share the same environment).
 - 
They don't have the same environment which is the case when you work in bigger teams and you want to distribute your design system as any other npm package which is already built and can be used directly.
 
If your use case falls under case no. 1 then you can just compile the source babel src -d build and leave the bundling to the consumer projects tools(webpack/rollup)
design-system
  src
    Button
      Button.js
      index.js
    Text
      Text.js
      index.js
  build
    Button
      Button.js
      index.js
    Text
      Text.js
      index.js
  Button.js // this is a re-export from build
    export default from './build/Button'
and then in your consumer projects
// app.js
import Button from 'design-system/Button'
if your use case falls under case no. 2 then you need to be careful about many things so that your consumer don't end up importing unnecessary things.
Let me start with what tool to use:
- You can use webpack/rollup.
 
- Choose rollup if you want to generate 
commonjsandesmoduleversion of your components. - Choose webpack if you don't care about 
esmoduleand don't want to invest in understanding rollup(P.S it's simple enough and it's worth investing time in it everything is plugins. esp when you're building libraries). 
Let's understand this with an example. Assume this is your source code directory structure
design-system
  src
    Button
      Button.js
      index.js
    Text
      Text.js
      index.js
Your webpack config will look something like this
module.exports = {
  entry: [
    './src/Button/index.js',
    './src/Text/index.js',
  ]
  
  output: {
    libraryTarget: 'commonjs',
    path: path.resolve(__dirname, './build'),
    filename: '[name].js',
  },
  
  externals: Object.keys(peerDependencies).reduce((acc,peerDependency)=> {...acc, [peerDependency]: peerDependency}, {})
}
if you want your css files to be extracted out in a seaprate file per JS file you can use mini-css-extract-plugin
After you run this you'll have something like this
design-system
  src
    Button
      Button.js
      index.js
    Text
      Text.js
      index.js
  build
    Button.js
    Text.js
Once you publish this you can't have main field in your package.json  as there's no single entry point and all your users have to do this
import Button from 'design-system/build/Button'
which is kind of bad DX and looks weird as well.
This can be solved in multiple ways:
1. You can have a top level index.js which is nothing but re-exports of all your components(this can generated using a simple script as part of your build process)
design-system
  src
    Button
      Button.js
      index.js
    Text
      Text.js
      index.js
  build
    Button.js
    Text.js
  index.js
    export { default as Button } from './build/Button'
    export { default as Text } from './build/Text'
- So now your consumers can do like this
 
import { Button, Text } from 'design-system'
- But still this will make your imports ugly since everything is being imported from 
design-systemin one line and everything is named import. Imagine importing 10 components in single line. - Plus most commonly people will think that you can't have tree shaking since webpack knows everything is a named import from 
design-system/index.jsso it can't statically analyze what to tree shake.- But this can be solved by setting 
side-effects: falsein yourdesign-system/package.jsonso webpack knows this can be tree-shaken and it doesn't has any side-effects. But this needs a gaurantee that your consumer tools should usewebpackas their bundling tool. 
 - But this can be solved by setting 
 
2. You can have individual components at the root Button.js and re-export Button from build/Button.js
- This is pretty neat
 
design-system
  src
    Button
      Button.js
      index.js
    Text
      Text.js
      index.js
  build
    Button.js
    Text.js
  Button.js
    export default from './build/Button'
  Text.js
    export default from './build/Text'
- So now your consumers can import like this
 
import Button from 'design-system/Button'
import Text from 'design-system/Text'
If you want to target commonjs and esmodule then you can do that with rollup
const config = fs
  .readdirSync('src')
  .map((component) => ({
    input: `src/${component}/index.js`,
    external: Object.keys(peerDependencies),
    plugins: [
      babel({
        exclude: 'node_modules/**',
        runtimeHelpers: true,
        externalHelpers: true,
      }),
      commonjs(),
      json(),
    ],
    output: [{
      file: `cjs/${component}.js`,
      format: 'cjs',
    }, {
      file: `${component}.js`,
      format: 'esm',
    }],
  }));
export default config
So after you run rollup you'll have somthing like this
design-system
  src
    Button
      Button.js
      index.js
    Text
      Text.js
      index.js
  cjs
    Button.js
    Text.js
  Button.js
  Text.js
Now the obvious question to ask is why cjs as a separate folder and esm at the root level. This is not the only way to do it. But the idea here is that if your majority of the consumers are mostly concerned with the esm version then the DX becomes simpler for them.
import Button from 'design-system/Button'
and the ones(minority/legacy codebase) who are concerned about cjs they can do like this
import Button from 'design-system/cjs/Button'
So there are multiple ways of doing things depends what fits your use case. We use a good mix and match of all the above mentioned things based on use cases. Also if you look at Leaf-UI we just transpile the source and leave the bundling to the consumers. You can read the script for re-exporting here.
Now let me answer your questions one by one.
- We use 
styled-componentsand we don't extract css out in a separate file. - If you use 
mini-css-extract-pluginyou can re-export it from your Button component and refer it in your consumer component directly 
import Button, { buttonStyles } from 'design-system/Button' 
- Bundle per component. Helps to separate out concerns when importing components(default and named imports).
 
- For individual component bundles refer this webpack config
 - If you follow re-export on the root from 
index.js/individualButton.jsre-exports your command+click problem will be solved. 
4. I have a component folder where I keep all the components. You import them as - import { Button } from 'my-design-system'. The entry point is 'src/index.js' where I import all the components from component folder and export them
- 
Question: Possible to achieve import Button from 'my-design-system/Button' with current project structure
- You can refer the whole process as mentioned above for this.
 
 - 
Question:
libraryTargetin Webpack is 'commonjs2'. What you use?commonjs. It's a minute difference shouldn't matter much. Read here about it more.
 - 
Question: Is it good practice to refer output path in Webpack from build folder?
- Need more details about this. Can you elaborate?
 
 
Still a great gist for outlining the basics. I was actually looking for different approaches with CSS bundling, but found this anyway quite useful.