Add BMAD commands, skills, and module files from piSetup
This commit is contained in:
@@ -0,0 +1,402 @@
|
||||
---
|
||||
name: oro-frontend-dev
|
||||
description: OroCommerce frontend development reference covering storefront themes, back-office themes, layouts, SCSS, JavaScript architecture (Chaplin/Backbone), page components, templates, and asset management. Use when customizing the storefront UI, modifying admin templates, writing JS components, or styling OroCommerce pages.
|
||||
---
|
||||
|
||||
# OroCommerce Frontend Developer
|
||||
|
||||
Reference for frontend/UI development on OroCommerce.
|
||||
Full docs: https://doc.oroinc.com/frontend/
|
||||
|
||||
## Two Theme Systems
|
||||
|
||||
OroCommerce has two separate theme architectures:
|
||||
|
||||
| Area | Framework | Templates | JS | Docs |
|
||||
|---|---|---|---|---|
|
||||
| Storefront | OroLayouts (SEO-friendly, no SPA) | Layout YAML + Twig blocks | Chaplin/Backbone | https://doc.oroinc.com/frontend/storefront/ |
|
||||
| Back-office | Placeholders (SPA-like, Twig+Underscore) | Twig extends @OroUI | Chaplin/Backbone | https://doc.oroinc.com/frontend/back-office/ |
|
||||
|
||||
Themes are NOT interchangeable between storefront and back-office.
|
||||
|
||||
## Storefront Theming
|
||||
|
||||
### Theme Structure
|
||||
|
||||
```
|
||||
Resources/views/layouts/{theme_name}/
|
||||
theme.yml # theme definition (label, parent, icon)
|
||||
config/
|
||||
assets.yml # SCSS entry points
|
||||
jsmodules.yml # JS module registration
|
||||
datagrids.yml # frontend datagrid configs
|
||||
templates/ # Twig block templates
|
||||
page/ # per-page layout overrides
|
||||
```
|
||||
|
||||
### theme.yml
|
||||
|
||||
Basic:
|
||||
```yaml
|
||||
label: 'My Custom Theme'
|
||||
parent: default
|
||||
icon: bundles/mybundle/images/theme-icon.png
|
||||
groups: [commerce]
|
||||
rtl_support: true
|
||||
```
|
||||
|
||||
Full configuration with admin-selectable options:
|
||||
```yaml
|
||||
label: 'Acme Theme'
|
||||
parent: default
|
||||
groups: [commerce]
|
||||
rtl_support: true
|
||||
|
||||
configuration:
|
||||
sections:
|
||||
header:
|
||||
label: Header
|
||||
options:
|
||||
promotional_content:
|
||||
label: oro_frontend.theme.default.configuration.header.promotional_content.label
|
||||
type: content_block_selector
|
||||
options:
|
||||
required: false
|
||||
standalone_main_menu:
|
||||
label: oro_frontend.theme.default.configuration.header.standalone_main_menu.label
|
||||
type: checkbox
|
||||
default: checked
|
||||
previews:
|
||||
checked: 'bundles/orofrontend/images/previews/menu-standalone.png'
|
||||
unchecked: 'bundles/orofrontend/images/previews/menu-hamburger.png'
|
||||
product_listing:
|
||||
label: 'oro.product.theme.default.configuration.product_listing.label'
|
||||
options:
|
||||
filters_position:
|
||||
label: 'oro.product.theme.default.configuration.product_listing.filters_position.label'
|
||||
type: radio
|
||||
default: sidebar
|
||||
values:
|
||||
top: 'oro.product.theme.default.configuration.product_listing.filters_position.values.top'
|
||||
sidebar: 'oro.product.theme.default.configuration.product_listing.filters_position.values.sidebar'
|
||||
```
|
||||
|
||||
Configuration option types: `content_block_selector`, `menu_selector`, `checkbox`, `radio`, `select`.
|
||||
|
||||
### Layout Updates
|
||||
|
||||
Layout updates are YAML files that modify page structure:
|
||||
|
||||
```yaml
|
||||
layout:
|
||||
actions:
|
||||
- '@setBlockTheme':
|
||||
id: page_container
|
||||
themes: '@MyBundle/layouts/my_theme/page/layout.html.twig'
|
||||
- '@add':
|
||||
id: my_custom_block
|
||||
parentId: page_content
|
||||
blockType: text
|
||||
options:
|
||||
text: '=data["locale"].getLanguage()'
|
||||
- '@remove':
|
||||
id: unwanted_block
|
||||
- '@move':
|
||||
id: existing_block
|
||||
parentId: new_parent
|
||||
```
|
||||
|
||||
Place layout updates in route-specific directories to target individual pages:
|
||||
```
|
||||
Resources/views/layouts/{theme}/
|
||||
layout.yml # global layout (all pages)
|
||||
oro_frontend_root/frontend_root.yml # homepage
|
||||
oro_product_frontend_product_index/product_index.yml # PLP
|
||||
oro_product_frontend_product_view/product_view.yml # PDP
|
||||
oro_checkout_frontend_checkout/checkout.yml # checkout
|
||||
```
|
||||
|
||||
### Block Types
|
||||
|
||||
| blockType | Purpose |
|
||||
|---|---|
|
||||
| `container` | Wraps child blocks with a div |
|
||||
| `text` | Static text or expression |
|
||||
| `block` | Custom Twig-rendered block |
|
||||
| `content_block` | References admin-managed content block by `alias` |
|
||||
| `menu` | Renders a navigation menu |
|
||||
|
||||
### Layout Data Expressions
|
||||
|
||||
Access data providers and context variables in YAML options:
|
||||
|
||||
```yaml
|
||||
options:
|
||||
vars:
|
||||
# Data provider methods (registered via layout_data_provider tag)
|
||||
topCategories: '=data["category_provider"].getRootCategoriesWithSlugs()'
|
||||
featuredCount: '=data["product_provider"].getFeaturedProductCount()'
|
||||
ctaLinks: '=data["cta_link_provider"].getLinks(data["menu"].getMenu("commerce_main_menu"))'
|
||||
|
||||
# Context variables (route params, request attributes)
|
||||
category: '=data["category_provider"].getCategoryById(context["category_id"])'
|
||||
```
|
||||
|
||||
### @addTree Action
|
||||
|
||||
Add multiple blocks at once:
|
||||
|
||||
```yaml
|
||||
- '@addTree':
|
||||
items:
|
||||
footer_menu:
|
||||
blockType: menu
|
||||
options:
|
||||
item: '=data["menu"].getMenu("commerce_footer_links")'
|
||||
depth: 2
|
||||
tree:
|
||||
page_footer_base:
|
||||
footer_menu: ~
|
||||
```
|
||||
|
||||
### @setBlockTheme with Multiple Files
|
||||
|
||||
```yaml
|
||||
- '@setBlockTheme':
|
||||
themes:
|
||||
- 'templates/layout.html.twig'
|
||||
- 'templates/page-footer/footer_branding.html.twig'
|
||||
- 'templates/navigation/sidebar_menu.html.twig'
|
||||
```
|
||||
|
||||
### Twig Block Naming Convention
|
||||
|
||||
Block names in layout Twig templates follow: `_{blockId}_widget`
|
||||
|
||||
```twig
|
||||
{% block _my_custom_block_widget %}
|
||||
<div {{ block('block_attributes') }}>
|
||||
{{ block_widget(block) }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
```
|
||||
|
||||
### SCSS / Stylesheets
|
||||
|
||||
Register SCSS in `config/assets.yml`:
|
||||
|
||||
```yaml
|
||||
styles:
|
||||
inputs:
|
||||
- 'bundles/acmetheme/scss/styles.scss'
|
||||
output: 'css/styles.css'
|
||||
```
|
||||
|
||||
Recommended SCSS directory organization:
|
||||
|
||||
```
|
||||
scss/
|
||||
styles.scss # main entry point (@import all)
|
||||
variables/
|
||||
_colors.scss # color palette as Sass maps
|
||||
_typography.scss
|
||||
_mixins.scss
|
||||
components/
|
||||
_product-cards.scss
|
||||
_buttons.scss
|
||||
layout/
|
||||
_page-header.scss
|
||||
_page-footer.scss
|
||||
_product-view.scss
|
||||
_product-index.scss
|
||||
_checkout.scss
|
||||
navigation/
|
||||
_sidebar.scss
|
||||
_topbar.scss
|
||||
```
|
||||
|
||||
Color palette using Sass maps (Oro pattern):
|
||||
|
||||
```scss
|
||||
@use 'sass:map';
|
||||
|
||||
$theme-color-palette: (
|
||||
'brand': (
|
||||
'primary': #424242,
|
||||
'secondary': #A89571,
|
||||
),
|
||||
'semantic': (
|
||||
'success': #005E1F,
|
||||
'error': #D32F2F,
|
||||
)
|
||||
) !default;
|
||||
|
||||
$color-palette: map.deep-merge($color-palette, $theme-color-palette);
|
||||
```
|
||||
|
||||
Access via `get-var-color('brand', 'primary')`. Build: `php bin/console oro:assets:build`.
|
||||
|
||||
### SVG Icons
|
||||
|
||||
Custom icons go in the theme's icons directory. Register via theme config.
|
||||
|
||||
## Back-Office Theming
|
||||
|
||||
### Twig Template Overrides
|
||||
|
||||
Override admin templates by mirroring directory structure under `Resources/views/`.
|
||||
|
||||
Common base templates to extend:
|
||||
- `@OroUI/actions/index.html.twig` -- list/grid pages
|
||||
- `@OroUI/actions/view.html.twig` -- detail/view pages
|
||||
- `@OroUI/actions/update.html.twig` -- create/edit form pages
|
||||
|
||||
Use Oro UI macros for consistent rendering:
|
||||
|
||||
```twig
|
||||
{% import '@OroUI/macros.html.twig' as UI %}
|
||||
{{ UI.renderProperty('Label', value) }}
|
||||
{{ UI.renderHtmlProperty('HTML Label', htmlValue) }}
|
||||
```
|
||||
|
||||
### Placeholders
|
||||
|
||||
Inject content into predefined back-office page regions.
|
||||
|
||||
```yaml
|
||||
# Resources/config/oro/placeholders.yml
|
||||
placeholders:
|
||||
oro_view_additional_data:
|
||||
items:
|
||||
my_custom_section:
|
||||
order: 50
|
||||
template: '@AcmeExample/Placeholder/section.html.twig'
|
||||
applicable: '@acme.placeholder_filter->isApplicable'
|
||||
```
|
||||
|
||||
Common placeholder targets:
|
||||
- `oro_view_additional_data` -- entity view page extra sections
|
||||
- `oro_widget_side_bar` -- sidebar widgets
|
||||
- `oro_title_before` / `oro_title_after` -- title area
|
||||
|
||||
Conditional rendering via `applicable` filter (service method returning bool).
|
||||
Placeholders are back-office only; use Layout Updates for storefront.
|
||||
|
||||
### SCSS
|
||||
|
||||
Override admin SCSS variables or add new stylesheets via theme settings.
|
||||
|
||||
## JavaScript Architecture
|
||||
|
||||
Built on Chaplin.js (extends Backbone.js). Key concepts:
|
||||
|
||||
### Page Components
|
||||
|
||||
The primary extension mechanism. Define in HTML via data attributes:
|
||||
|
||||
```html
|
||||
<div data-page-component-module="mybundle/js/app/components/my-component"
|
||||
data-page-component-options="{{ options|json_encode }}">
|
||||
</div>
|
||||
```
|
||||
|
||||
Component lifecycle: created on `page:update`, disposed on page change.
|
||||
|
||||
### JS Module Registration
|
||||
|
||||
Register modules in `Resources/config/jsmodules.yml`:
|
||||
|
||||
```yaml
|
||||
dynamic-imports:
|
||||
mybundle:
|
||||
- mybundle/js/app/components/my-component
|
||||
|
||||
aliases:
|
||||
jquery$: oroui/js/extend/jquery
|
||||
|
||||
# Override an existing module with custom implementation
|
||||
map:
|
||||
'*':
|
||||
'orofrontend/js/app/datafilter/frontend-multiselect-decorator': 'acmetheme/js/custom-multiselect-decorator'
|
||||
```
|
||||
|
||||
### App Modules
|
||||
|
||||
Execute code at application startup (auto-initialized on every page):
|
||||
|
||||
```yaml
|
||||
app-modules:
|
||||
- acmetheme/js/app/modules/inventory-checker
|
||||
- acmetheme/js/app/modules/checkout-shipping-options
|
||||
```
|
||||
|
||||
### AMD Module Pattern
|
||||
|
||||
Oro's JS uses AMD `define()` with the `oroui/js/mediator` for cross-component communication:
|
||||
|
||||
```javascript
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
const mediator = require('oroui/js/mediator');
|
||||
const $ = require('jquery');
|
||||
|
||||
class MyComponent {
|
||||
constructor() {
|
||||
$(document).ready(() => {
|
||||
mediator.on('checkout:shipping-method:rendered', this.onShippingRendered);
|
||||
});
|
||||
}
|
||||
|
||||
onShippingRendered() {
|
||||
// DOM manipulation after Oro renders shipping methods
|
||||
}
|
||||
}
|
||||
|
||||
new MyComponent();
|
||||
return MyComponent;
|
||||
});
|
||||
```
|
||||
|
||||
Key mediator events: `checkout:shipping-method:rendered`, `filters-manager:after-applying-state`, `page:update`, `page:afterChange`.
|
||||
|
||||
### Page Events
|
||||
|
||||
System events during page lifecycle:
|
||||
1. `page:beforeChange`
|
||||
2. `page:request`
|
||||
3. `page:update` -- content is updated, init components
|
||||
4. `page:afterChange` -- all components initialized
|
||||
|
||||
### File Naming Convention
|
||||
|
||||
```
|
||||
js/app/
|
||||
components/ # PageComponent implementations
|
||||
controllers/ # Chaplin controllers (rare -- PageController handles all)
|
||||
models/ # Backbone models and collections
|
||||
views/ # Backbone views
|
||||
modules/ # App modules (startup code)
|
||||
templates/ # Underscore.js templates (*.html)
|
||||
```
|
||||
|
||||
## Asset Build
|
||||
|
||||
```bash
|
||||
php bin/console oro:assets:build # build all themes
|
||||
php bin/console oro:assets:build --watch # watch mode for dev
|
||||
php bin/console assets:install # symlink public assets
|
||||
```
|
||||
|
||||
Requires Node.js >= 22 and NPM > 10.
|
||||
|
||||
## RTL Support
|
||||
|
||||
Enable Right-to-Left UI via theme configuration.
|
||||
See: https://doc.oroinc.com/frontend/rtl-support/
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- Storefront how-to guides: https://doc.oroinc.com/frontend/storefront/how-to/
|
||||
- JS modularity deep-dive: https://doc.oroinc.com/frontend/javascript/javascript-modularity/
|
||||
- Storefront design/style guide (Figma): https://doc.oroinc.com/frontend/storefront-style-guide/
|
||||
Reference in New Issue
Block a user