# Atlas Copco VT Lite Site Generator

Standalone Lite Site Generator package for Atlas Copco VT. This package contains the LSG component set, Storybook documentation, and themed AEM-ready CSS/JS outputs.

## Tech stack

- **React 18** + **TypeScript**
- **Storybook 7** with `@storybook/nextjs`
- **SCSS** + **Tailwind CSS** + **PostCSS**
- **Next.js 13** to preserve the existing Storybook/runtime foundation

## Getting started

```bash
# Install dependencies
npm install

# Run Storybook (default: http://localhost:6006)
npm run storybook

# Build static Storybook
npm run build-storybook
```

## Scripts

| Script              | Description                    |
|---------------------|--------------------------------|
| `npm run storybook` | Start Storybook dev server     |
| `npm run build-storybook` | Build static Storybook  |
| `npm run build:npm` | Build the component library plus all themed assets |
| `npm run build:themes:css` | Emit `theme-1.css`, `theme-2.css`, `theme-3.css` |
| `npm run build:themes:js` | Emit `theme-1.js`, `theme-2.js`, `theme-3.js` |
| `npm run dev`       | Start Next.js dev server       |
| `npm run build`     | Build Next.js app              |
| `npm run lint`      | Run ESLint                     |

## Project structure

```
.storybook/           # Storybook config, theme, preview
src/
  components/lsg/     # Shared base LSG React components, docs, and clientlib runtime
  themes/             # Theme component wrappers plus Theme 1 / 2 / 3 CSS and JS entry points
  stories/foundation/_components/  # Minimal Storybook layout helpers used by LSG docs
  utils/styles/       # Shared spacing/style primitives still used by LSG SCSS
public/               # Static assets
```

## Architecture layers

1. Base layer: `src/components/lsg/` contains the shared structural components and the common SCSS each theme builds from.
2. Theme layer: each folder under `src/themes/` exposes its own themed component set that wraps the base components and can add extra theme-specific styling on top.
3. Brand layer: the `--lsg-*` CSS custom properties define the brand contract for colours, fonts, radii, and sizes. Each brand/theme supplies its own values for that contract.

## How themes work

Themes are built as an extension model, not as separate rewrites of the component library.

### 1. Base components

The shared implementation lives under `src/components/lsg/`.

- This layer contains the React structure and the common SCSS for `LsgButton`, `LsgHeader`, `LsgFooter`, and the rest of the LSG set.
- Base components should own the shared markup, accessibility, interaction logic, and stable AEM-facing class names.
- Base SCSS should use the `--lsg-*` token contract instead of hardcoding a brand style.

This is the layer every theme builds on top of.

### 2. Theme components

Each theme has its own component entrypoint under `src/themes/<theme>/components.tsx`.

- Theme components are wrappers around the base components.
- The wrapper generation happens in `src/themes/createThemeComponents.tsx`.
- Each wrapper adds theme-specific classes such as `lsg-themed-component--theme-1` so a theme can target the base component with extra styling.

That means the theme can keep the shared functionality from the base component while still changing the presentation or adding a branded treatment.

Example flow:

1. `Theme1LsgButton` renders the shared `LsgButton`.
2. The wrapper adds the `lsg-themed-component--theme-1` class.
3. `src/themes/theme-1/components.scss` applies extra styles to the shared `.lsg-button` markup inside that theme wrapper.

### 3. Brand variables

The brand layer is the CSS variable contract.

- Tokens such as `--lsg-color-primary`, `--lsg-font-family-primary`, and `--lsg-radius-rounded` define the brand values.
- The default contract lives in `src/components/lsg/lsg-tokens.scss`.
- Each theme entry file overrides those same variables in its own `:root` block.

This keeps the API stable. Components always read the same variables, while each brand provides different values for them.

## Storybook theme behavior

Storybook switches themes at runtime.

- The toolbar is configured in `.storybook/preview.tsx` through `globalTypes.lsgTheme`.
- The `LSG_THEMES` object maps a theme name to a set of `--lsg-*` values.
- The `withLsgTheme` decorator turns the selected theme into a `:root` CSS block and injects it into the preview document.
- The decorator also sets `document.documentElement.dataset.lsgTheme = themeKey`.

That `data-lsg-theme` attribute is important because the theme SCSS can target either:

- the whole Storybook canvas through `:root[data-lsg-theme="theme-x"]`
- a specific themed wrapper through `.lsg-themed-component--theme-x`

So in Storybook you get both:

- brand token swapping for colours, typography, spacing, and radii
- theme-specific component styling layered on top of the shared components

## Production theme outputs

Each theme has its own CSS and JS bundle.

- `src/themes/theme-1/theme.scss`, `src/themes/theme-2/theme.scss`, and `src/themes/theme-3/theme.scss` import the shared LSG styles and their own theme component styles.
- Those files also override the `:root` token contract for that theme.
- `build:themes:css` emits one CSS file per theme.
- `build:themes:js` emits one JS file per theme for clientlib runtime behavior.

This is the AEM delivery model:

1. Shared component structure comes from the base implementation.
2. Theme CSS adds component-level extensions.
3. Theme variables apply the brand colours, fonts, and sizes.
4. Theme JS boots the runtime behavior for that theme.

## When to use each layer

- Use the base component layer when the change should apply to every theme.
- Use the theme component layer when a theme needs a distinct visual treatment on top of the shared component behavior.
- Use the token layer when the change is a brand value such as colour, typeface, size, or border radius.

As a rule, put structure and behavior in the base component first. Only move into `src/themes/` when the theme genuinely needs its own component styling on top of that shared core.

## Adding a new themed component

1. Add or update the shared component in `src/components/lsg/`.
2. Keep the base SCSS driven by `var(--lsg-*)` tokens.
3. Add theme-specific styling in `src/themes/<theme>/components.scss` if that theme needs more than token changes.
4. Export the theme wrapper from `src/themes/<theme>/components.tsx`.
5. If needed in Storybook, add or update the theme values in `.storybook/preview.tsx`.

## Adding components

1. Add a component under `src/components/lsg/<Name>/` and keep its styles as plain `.scss` so AEM-facing class names stay stable.
2. Add `*.stories.tsx` or MDX docs alongside that component in `src/components/lsg/`.
3. If a theme needs more than brand variables, add its component-level extensions under `src/themes/<theme>/components.scss` and expose a themed wrapper from `src/themes/<theme>/components.tsx`.
4. Use the root token contract from `src/components/lsg/lsg-tokens.scss` and prefer `var(--lsg-*)` values over hardcoded theme colours.

## Design tokens

- **Core colours:** `--lsg-color-primary`, `--lsg-color-secondary`, `--lsg-color-tertiary`, `--lsg-color-light`, `--lsg-color-dark`, `--lsg-color-black`, `--lsg-color-white`
- **Typography:** `--lsg-font-family-primary`, `--lsg-font-family-secondary`, plus `--lsg-size-*` scale tokens
- **Shape:** `--lsg-radius-square`, `--lsg-radius-rounded`, `--lsg-radius-pill`

Theme-specific overrides live under `src/themes/`, but they extend the shared base components instead of replacing the root `--lsg-*` contract.
