locomotivemtl / locomotive-boilerplate

🚂 Front-end boilerplate for projects by Locomotive.
https://locomotivemtl-boilerplate.vercel.app/
MIT License
458 stars 71 forks source link

Add custom grid helper based on CSS custom properties #112

Closed lucasvallenet closed 1 year ago

lucasvallenet commented 2 years ago

Grid Helper is often used in our projects to make sure the layout is aligned with the design. Here is a fully customizable version with no CSS dependencies appart from the base CSS Variables located at /assets/styles/elements/_page.scss. It allows us to customize grid gutters, columns and margins with CSS only.

Use: After the <body> tag write the following line:

<div data-module-grid-helper></div>

You can hardcode values directly in the html:

<div 
    data-module-grid-helper
    style="--grid-columns: 8; --grid-gutter: 20px;"
></div>

Or use the CSS in /assets/styles/elements/_page.scss:

:root {

    // Grid
    --grid-columns      : 4; // Number of columns
    --grid-gutter       : #{rem(10px)}; // Gutter size
    --grid-gutter-half  : calc(0.5 * var(--grid-gutter)); // Half gutter size often use in CSS
    --grid-margin       : 0px; // Grid horizontal margin

    // Update any of these vars for a responsive grid-helper
    @media (min-width: $from-small) {
        --grid-columns  : 12;
        --grid-gutter   : #{rem(16px)};
        --grid-margin   : #{rem(20px)};
    }
}

Press CTRL + G to toggle the grid helper.

devenini commented 2 years ago

I like the idea. However I'm not a fan of having this in the boilerplate without having an environment variables setup to make sure that these types of modules are not included on a live production. Like a "debug/development" global variable.

lucasvallenet commented 2 years ago

We could use the env.process.NODE_ENV that return development on watch and production on build, but I can't get around the ES6 synthax to conditionally import/export the component. Any idea @mcaskill ?

mcaskill commented 2 years ago

Hrm. We would need to update the build/tasks/styles.js and implement a feature similar to the Webpack sass-loader's additionaldata option. Not sure how that feature works though.

Based on @webpack/sass-loader's additionaldata option, we would need to change build/tasks/styles.js to use Sass' data option instead of the file option (importing the entry file's contents and concatenating with a Sass variable that would contain the environment variable):

let content = await readFile(infile);

let result = await sassRender(Object.assign({}, sassOptions, {
    data: `$env: ${process.env.NODE_ENV};\n${content}`,
    outFile: outfile,
}));
@if ($env == 'development') {
      :root {
          // Grid
          // …
      }
}

Alternatively, we could try node-sass' experimental functions option to create a custom env function to access the desired environment variable:

let result = await sassRender(Object.assign({}, sassOptions, {
    file: infile,
    outFile: outfile,
    functions: {
        'env($name: NODE_ENV)': function (name) {
            name = name.getValue();
            if (typeof process.env[name] === 'string') {
                return new sass.types.String(process.env[name]);
            }

            return sass.types.Null.NULL;
        }
        // or
        'env()': function () {
            return new sass.types.String(process.env.NODE_ENV || 'production');
        }
    },
}));
@if (env() == 'development') {
      :root {
          // Grid
          // …
      }
}
lucasvallenet commented 2 years ago

@mcaskill the main issue here is not css but javascript.

We'd like to import the component only on development, unfortunatly this is not doable:

if(process.env.NODE_ENV === 'development') {
    export { default as GridHelper } from './modules/GridHelper';
}

Could we bundle a development file for js utilities we use for development only, like vendors ? And then find a way to only include it on development environment in the frontend like so:

app.js

if(process.env.NODE_ENV === 'development') {
    const devScript = document.createElement('script');
    devScript.setAttribute('src', '/assets/scripts/development.js');
    document.body.appendChild(devScript);
}
mcaskill commented 2 years ago

Thanks, I better understand the situation. There must be a way with BrowserSync to inject additional <script> elements into a page, like it does (I presume) for its live-reloading. Maybe using their rewriteRules option or some plugin. I'd prefer if our development tools be a separate JS entry file to avoid polluting the project's primary entry file.

Jerek0 commented 2 years ago

We could remove the import in modules.js and the grid helper markup by default and use it cautiously only when we need for now? That would allow us to merge this PR and we could tackle the development-only scripts concept in a new PR?

mcaskill commented 1 year ago

Outcome from meeting on 2022-10-05

cloudflare-pages[bot] commented 1 year ago

Deploying with  Cloudflare Pages  Cloudflare Pages

Latest commit: eead1d2
Status: ✅  Deploy successful!
Preview URL: https://af167013.locomotive-boilerplate.pages.dev
Branch Preview URL: https://feature-grid-helper.locomotive-boilerplate.pages.dev

View logs

arnvvd commented 1 year ago

Updates

function init() { /**