With themes it is possible to add custom SCSS variables through the theme.json config fields. Since there is no theme.json in regular plugins you can use a subscriber class to add custom SCSS variables.
Before you start adding your subscriber you should provide a fallback value for your custom SCSS variable in your plugin base.scss
:
// ScssPlugin/src/Resources/app/storefront/src/scss/base.scss
// The value will be overwritten by the subscriber when the plugin is installed and activated
$sass-plugin-header-bg-color: #ffcc00 !default;
.header-main {
background-color: $sass-plugin-header-bg-color;
}
You can add a new subscriber according to the plugin subscriber documentation. In this example we name the subscriber ThemeVariableSubscriber.php
". The subscriber listens to the ThemeCompilerEnrichScssVariablesEvent
.
// ScssPlugin/src/Subscriber/ThemeVariablesSubscriber.php
namespace ScssPlugin\Subscriber;
use Shopware\Storefront\Event\ThemeCompilerEnrichScssVariablesEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class ThemeVariablesSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
ThemeCompilerEnrichScssVariablesEvent::class => 'onAddVariables'
];
}
public function onAddVariables(ThemeCompilerEnrichScssVariablesEvent $event)
{
// Will render: $sass-plugin-name-font: "Helvetica Neue", Arial, sans-serif;
$event->addVariable('sass-plugin-name-font', '"Helvetica Neue", Arial, sans-serif');
// Will render: $sass-plugin-name-color: #ffcc59;
$event->addVariable('sass-plugin-name-color', '#ffcc59');
// Will render: $sass-plugin-name-special: 'My special string';
$event->addVariable('sass-plugin-name-special', 'My special string', true);
}
}
The ThemeCompilerEnrichScssVariablesEvent
provides the addVariable()
method which takes the following parameters:
$name:
(string)$
will be added automatically. We also recommend prefixing your variable name with your plugin's or company's name to prevent naming conflicts.$value:
(string)$sanitize
(bool - optional)Inside your ThemeVariablesSubscriber.php
you can also read values from the plugin configuration and assign those to a SCSS variable. This makes it also possible to have different values for each sales channel. Depending on the selected sales channel inside the plugin configuration in the administration.
First of all lets add a new plugin configuration field according to the plugin configuration documentation:
<!-- ScssPlugin/src/Resources/config/config.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/shopware/platform/master/src/Core/System/SystemConfig/Schema/config.xsd">
<card>
<title>Example configuration</title>
<input-field>
<name>exampleColor</name>
<label>Example color field</label>
</input-field>
</card>
</config>
To be able to read this config you have to add the SystemConfigService
to your subscriber:
// ScssPlugin/src/Subscriber/ThemeVariablesSubscriber.php
namespace ScssPlugin\Subscriber;
// ...
use Shopware\Core\System\SystemConfig\SystemConfigService;
class ThemeVariablesSubscriber implements EventSubscriberInterface
{
/**
* @var SystemConfigService
*/
protected $systemConfig;
// add the `SystemConfigService` to your constructor
public function __construct(SystemConfigService $systemConfig)
{
$this->systemConfig = $systemConfig;
}
// ...
public function onAddVariables(ThemeCompilerEnrichScssVariablesEvent $event)
{
/** @var string $configExampleField */
$configExampleField = $this->systemConfig->get('ScssPlugin.config.exampleColor', $event->getSalesChannelId());
// pass the value from `exampleColor` to `addVariable`
$event->addVariable('sass-plugin-example-color', $configExampleField);
}
}
SystemConfigService
provides a get()
method where you can access the configuration structure in the first parameter with a dot notation syntax like MyPluginName.config.fieldName
. The second parameter is the sales channel id. With this id the config fields can be accessed for each sales channel.getSalesChannelId()
of the ThemeCompilerEnrichScssVariablesEvent
.Adding config fields via $event->addVariable()
individually for every field may be a bit cumbersome in some cases. You could also loop over all config fields and call addVariable()
for each config field. But this depends on your use case.
// ScssPlugin/src/Subscriber/ThemeVariablesSubscriber.php
namespace ScssPlugin\Subscriber;
// ...
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
class ThemeVariablesSubscriber implements EventSubscriberInterface
{
// ...
public function onAddVariables(ThemeCompilerEnrichScssVariablesEvent $event)
{
$configFields = $this->systemConfig->get('ScssPlugin.config', $event->getSalesChannelId());
foreach($configFields as $key => $value) {
// Convert `customVariableName` to `custom-variable-name`
$variableName = str_replace('_', '-', (new CamelCaseToSnakeCaseNameConverter())->normalize($key));
$event->addVariable($variableName, $value);
}
}
}
To avoid camelCase variable names when reading from the config.xml
we recommend to use the CamelCaseToSnakeCaseNameConverter
to format the variable before adding it.