Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
35 changes: 35 additions & 0 deletions pos-module-common-styling/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,41 @@ After installation, visit `/style-guide` on your instance. (Make sure you deploy
- Find the complete list of CSS variables you can override.


### Quick start with the `install` generator

The fastest way to wire up common-styling is the bundled `install` generator. It scaffolds a default layout that is already configured with the module, a starter overrides stylesheet, and ensures the required instance setting — covering the manual steps described in [Setup](#setup) below.

```bash
pos-cli generate run modules/common-styling/generators/install
```

This generates:

- `app/views/layouts/application.liquid` — a layout with `class="pos-app"` on `<html>`, the `init` partial in the `<head>`, your overrides stylesheet loaded after it, and the toast notifications container near the bottom of `<body>`.
- `app/assets/config-overrides.css` — a starter stylesheet (loaded after common-styling) where you can override CSS variables. See [Customizing CSS](#customizing-css).
- `app/config.yml` — ensures `escape_output_instead_of_sanitize: true` is set (merged into an existing config without touching your other settings).

After running it, deploy with `pos-cli deploy <env>` and set `layout: application` in your pages.

#### Options

| argument / option | default | description |
|-------------------|---------------|--------------------------------------------------------------------|
| `<layoutName>` | `application` | name of the layout file to generate |
| `--reset` | `true` | enable the [CSS reset](https://github.com/Platform-OS/pos-modules/blob/master/pos-module-common-styling/modules/common-styling/public/assets/style/pos-reset.css) |
| `--dark-mode` | `false` | enable [automatic dark mode](#automatic-dark-mode) (adds `pos-theme-darkEnabled`) |
| `--title` | `platformOS` | default `<title>` used by the layout |

```bash
# Generate a layout named "marketing" with the reset disabled and dark mode on
pos-cli generate run modules/common-styling/generators/install marketing --reset=false --dark-mode=true --title="My App"

# Show all available options
pos-cli generate run modules/common-styling/generators/install --generator-help
```

Prefer to wire things up by hand? Follow the manual steps below.

### Setup

1. **Install the module** using the [pos-cli](https://github.com/Platform-OS/pos-cli).
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import Generator from 'yeoman-generator';
import fs from 'fs';
import path from 'path';

const TRUE_VALUES = ['true', '1', 'yes', 'y'];
const toBool = (value, fallback) => {
if (value === undefined || value === null || value === '') return fallback;
if (typeof value === 'boolean') return value;
return TRUE_VALUES.includes(String(value).toLowerCase());
};

export default class extends Generator {
constructor(args, opts) {
super(args, opts);

this.description = 'Generate a default layout configured with common-styling';

this.argument('layoutName', {
type: String,
required: false,
default: 'application',
description: 'name of the layout to generate (default: application)'
});

this.option('reset', {
type: Boolean,
default: true,
description: 'enable the common-styling CSS reset'
});
this.option('dark-mode', {
type: Boolean,
default: false,
description: 'enable automatic dark mode based on system preference'
});
this.option('title', {
type: String,
default: 'platformOS',
description: 'default <title> used by the layout'
});

const layoutName = (this.options.layoutName || 'application').replace(/\.liquid$/, '');

this.props = {
layoutName: layoutName,
reset: toBool(this.options.reset, true),
darkMode: toBool(this.options['dark-mode'], false),
title: this.options.title || 'platformOS',
configCss: 'config-overrides.css'
};
}

writing() {
try {
this.fs.copyTpl(
this.templatePath('./views/layouts/application.liquid'),
this.destinationPath(`app/views/layouts/${this.props.layoutName}.liquid`),
this.props
);

this.fs.copyTpl(
this.templatePath('./assets/config-overrides.css'),
this.destinationPath(`app/assets/${this.props.configCss}`),
this.props
);
} catch (e) {
console.error(e);
}
}

// common-styling requires the instance to escape output instead of sanitizing it.
// Done in end() with plain fs (after the mem-fs commit) so we can update an
// existing app/config.yml in place without triggering Yeoman's overwrite prompt.
_ensureConfig() {
const configPath = this.destinationPath('app/config.yml');
const flag = 'escape_output_instead_of_sanitize: true';

if (!fs.existsSync(configPath)) {
fs.mkdirSync(path.dirname(configPath), { recursive: true });
fs.writeFileSync(configPath, `---\n${flag}\n---\n`);
return true;
}

const content = fs.readFileSync(configPath, 'utf8');
if (/escape_output_instead_of_sanitize\s*:/.test(content)) {
return false;
}

// Insert the flag right after the opening `---` front matter delimiter when
// present; otherwise wrap the file in a front matter block.
if (/^---\s*\n/.test(content)) {
fs.writeFileSync(configPath, content.replace(/^---\s*\n/, `---\n${flag}\n`));
} else {
fs.writeFileSync(configPath, `---\n${flag}\n---\n\n${content}`);
}
return true;
}

end() {
const configChanged = this._ensureConfig();

console.log(`Layout generated: app/views/layouts/${this.props.layoutName}.liquid`);
console.log(`Overrides stylesheet generated: app/assets/${this.props.configCss}`);
if (configChanged) {
console.log('Ensured escape_output_instead_of_sanitize: true in app/config.yml');
} else {
console.log('app/config.yml already escapes output — left untouched');
}
console.log(`\nDeploy with \`pos-cli deploy <env>\``);
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* common-styling overrides
* -------------------------
* Copy ONLY the variables you want to change from `pos-config.css` into the
* blocks below and redefine them here. This file is loaded after common-styling,
* so anything you set here takes precedence.
*
* Discover available variables and components at /style-guide.
*/

:root {
/* Example — give primary buttons a green theme:
--pos-color-button-primary-background: #008000;
--pos-color-button-primary-hover-background: #00a000;
*/
}

/* Dark mode overrides (only needed if your app supports dark mode):
:root {
--pos-color-dark-button-primary-background: #004d00;
}
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en" class="pos-app<% if (darkMode) { %> pos-theme-darkEnabled<% } %>">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes">
<title>{% if context.page.metadata.title %}{{ context.page.metadata.title }}{% else %}<%= title %>{% endif %}</title>

{% comment %} platformOS common-styling: loads the design system CSS/JS into the page head {% endcomment %}
{% render 'modules/common-styling/init'<% if (reset) { %>, reset: true<% } %> %}

{% comment %} Your overrides — must load AFTER common-styling so they take precedence {% endcomment %}
<link rel="stylesheet" href="{{ '<%= configCss %>' | asset_url }}">
</head>
<body>
{{ content_for_layout }}

{% comment %} Toast notifications — keep near the bottom of <body>. Reads the server-side flash. {% endcomment %}
{% liquid
function flash = 'modules/core/commands/session/get', key: 'sflash'
if context.location.pathname != flash.from or flash.force_clear
function _ = 'modules/core/commands/session/clear', key: 'sflash'
endif
render 'modules/common-styling/toasts', params: flash
%}
</body>
</html>
Loading
Loading