Skip to content

Commit 42b28bf

Browse files
committed
[TASK] Introduce stateful color tokens for better theming flexibility
This change introduces dedicated state-specific color tokens (e.g., `--typo3-state-primary-*`) that reference the base color tokens instead of directly assigning color values to state properties. This separation allows for easier color scheme adjustments and better maintainability. Additionally, this introduces tinting for neutral colors to provide an even color distribution across the interface. For the modern theme, this results in a blueish tint based on the theme's primary color definition. Note: Color assignments still require manual picking and adjustments. This change focuses on establishing better token architecture for future theming improvements. Resolves: #108208 Releases: main Change-Id: I21cac7d80c9993e237ba5261235cd5d496c0af5b Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/91756 Reviewed-by: Benjamin Kott <benjamin.kott@outlook.com> Reviewed-by: Andreas Kienast <akienast@scripting-base.de> Tested-by: core-ci <typo3@b13.com> Tested-by: Benjamin Franzke <ben@bnf.dev> Tested-by: Andreas Kienast <akienast@scripting-base.de> Reviewed-by: Benjamin Franzke <ben@bnf.dev> Tested-by: Benjamin Kott <benjamin.kott@outlook.com>
1 parent 7e6a25c commit 42b28bf

File tree

10 files changed

+475
-114
lines changed

10 files changed

+475
-114
lines changed

Build/Sources/Sass/component/_root.scss

Lines changed: 108 additions & 89 deletions
Large diffs are not rendered by default.

Build/Sources/Sass/component/scaffold/_topbar.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
--topbar-item-color-state: initial;
1414
--topbar-item-bg-state: initial;
1515
--topbar-item-border-color-state: initial;
16-
--topbar-workspace-bg: light-dark(var(--token-color-blue-20), var(--token-color-blue-80));
16+
--topbar-workspace-bg: light-dark(var(--token-color-primary-20), var(--token-color-primary-80));
1717
// Internal state definitions
1818
--topbar-item-hover-color: var(--typo3-scaffold-header-color);
1919
--topbar-item-hover-bg: color-mix(in srgb, var(--topbar-item-bg), var(--topbar-item-color) 5%);

Build/Sources/Sass/module/_page.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
--pagemodule-grid-inner-spacing: 1rem;
99
--pagemodule-grid-cell-header-size: 1em;
1010
--pagemodule-grid-cell-border-radius: calc(var(--pagemodule-grid-border-radius) - 3px);
11-
--pagemodule-grid-cell-bg: color-mix(in srgb, var(--module-bg), currentColor 5%);
11+
--pagemodule-grid-cell-bg: var(--typo3-surface-container-base);
1212
--pagemodule-grid-cell-restricted-bg: var(--typo3-surface-container-warning);
1313
--pagemodule-grid-column-unused-bg: var(--typo3-surface-container-warning);
1414
--pagemodule-element-spacing: 1rem;

Build/Sources/Sass/variables/_main.scss

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,18 @@
1111
// TYPO3
1212
// =====
1313
//
14-
$natural-base: #000;
14+
$neutral-base: #000;
1515
$neutral-shades: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100);
16+
$state-colors: (
17+
'primary': #205eb5,
18+
'secondary': #737373,
19+
'info': #abdced,
20+
'success': #247554,
21+
'warning': #fc3,
22+
'danger': #d13a2e,
23+
'notice': #737373,
24+
);
25+
$state-shades: (1, 2, 3, 4, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 96, 97, 98, 99);
1626
$base-colors: (
1727
'blue': #205eb5,
1828
'purple': #5e4db2,

typo3/sysext/backend/Resources/Public/Css/backend.css

Lines changed: 20 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

typo3/sysext/styleguide/Classes/Controller/StylesController.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ final class StylesController
4040
private array $allowedActions = [
4141
'stylesOverview',
4242
'colorTokens',
43+
'accentAndState',
4344
'icons',
4445
'shadows',
4546
'surfaces',
@@ -61,6 +62,7 @@ public function handleRequest(ServerRequestInterface $request): ResponseInterfac
6162
// Actions from styles navigation
6263
return match ($queryAction) {
6364
'colorTokens' => $this->renderColorTokensView($request),
65+
'accentAndState' => $this->renderAccentAndStateView($request),
6466
'icons' => $this->renderIconsView($request),
6567
'shadows' => $this->renderShadowsView($request),
6668
'surfaces' => $this->renderSurfacesView($request),
@@ -90,12 +92,29 @@ private function renderColorTokensView(ServerRequestInterface $request): Respons
9092
'routeIdentifier' => 'styleguide_styles',
9193
'neutralColors' => ['neutral'],
9294
'neutralSteps' => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100],
93-
'accentColors' => ['blue', 'purple', 'teal', 'green', 'magenta', 'yellow', 'orange', 'red'],
94-
'accentSteps' => [10, 20, 30, 40, 50, 60, 70, 80, 90],
95+
'stateColors' => ['primary', 'secondary', 'info', 'success', 'warning', 'danger', 'notice'],
96+
'stateSteps' => [1, 2, 3, 4, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 96, 97, 98, 99],
97+
'baseColors' => ['blue', 'purple', 'teal', 'green', 'magenta', 'yellow', 'orange', 'red'],
98+
'baseSteps' => [10, 20, 30, 40, 50, 60, 70, 80, 90],
9599
]);
96100
return $view->renderResponse('Backend/Styles/ColorTokens');
97101
}
98102

103+
private function renderAccentAndStateView(ServerRequestInterface $request): ResponseInterface
104+
{
105+
$view = $this->createModuleTemplate($request, 'accentAndState');
106+
$view->assignMultiple([
107+
'actions' => $this->allowedActions,
108+
'currentAction' => 'accentAndState',
109+
'routeIdentifier' => 'styleguide_styles',
110+
'accentColors' => ['primary', 'secondary'],
111+
'stateColors' => ['default', 'info', 'success', 'warning', 'danger', 'notice'],
112+
'stateVariants' => ['default', 'hover', 'focus', 'disabled'],
113+
'stateProperties' => ['color', 'bg', 'border-color'],
114+
]);
115+
return $view->renderResponse('Backend/Styles/AccentAndState');
116+
}
117+
99118
private function renderIconsView(ServerRequestInterface $request): ResponseInterface
100119
{
101120
$iconRegistry = GeneralUtility::makeInstance(IconRegistry::class);

typo3/sysext/styleguide/Resources/Private/Language/locallang.xlf

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@
114114
<trans-unit id="action.colorTokens.description">
115115
<source>Predefined color values and design tokens used throughout the TYPO3 backend interface.</source>
116116
</trans-unit>
117+
<trans-unit id="action.accentAndState">
118+
<source>Accent and State</source>
119+
</trans-unit>
120+
<trans-unit id="action.accentAndState.description">
121+
<source>Stateful color variants for interactive elements including accent colors and semantic states.</source>
122+
</trans-unit>
117123
<trans-unit id="action.componentsOverview">
118124
<source>Components overview</source>
119125
</trans-unit>
@@ -1045,6 +1051,14 @@
10451051
<source><![CDATA[Surfaces used in the TYPO3 Backend, for <strong>internal usage only</strong>.]]></source>
10461052
</trans-unit>
10471053

1054+
<!-- Styles: Accent and State -->
1055+
<trans-unit id="styles.accentAndState.headline">
1056+
<source>Accent and State</source>
1057+
</trans-unit>
1058+
<trans-unit id="styles.accentAndState.introtext">
1059+
<source><![CDATA[Stateful color variants used for interactive elements in the TYPO3 Backend, for <strong>internal usage only</strong>. These include accent colors (primary, secondary) and semantic state colors (info, success, warning, danger, notice) with their respective default, hover, focus, and disabled variants.]]></source>
1060+
</trans-unit>
1061+
10481062
<!-- Styles: Icons -->
10491063
<trans-unit id="styles.icons.headline">
10501064
<source>Icons</source>
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
<html
2+
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
3+
xmlns:sg="http://typo3.org/ns/TYPO3/CMS/Styleguide/ViewHelpers"
4+
data-namespace-typo3-fluid="true"
5+
>
6+
7+
<f:layout name="Module" />
8+
9+
<f:section name="Content">
10+
11+
<f:render
12+
partial="Backend/Navigation"
13+
arguments="{
14+
currentAction: currentAction,
15+
actions: actions,
16+
route: routeIdentifier
17+
}"
18+
/>
19+
20+
<div class="styleguide-content">
21+
<h1><f:translate key="styles.accentAndState.headline" domain="styleguide.messages" /></h1>
22+
<p>
23+
<f:sanitize.html><f:translate key="styles.accentAndState.introtext" domain="styleguide.messages" /></f:sanitize.html>
24+
</p>
25+
26+
<f:asset.css identifier="styleguide-states-demo">
27+
.state-tokens-grid {
28+
display: grid;
29+
gap: 1rem;
30+
}
31+
32+
.state-token-section h3 {
33+
margin-top: 0;
34+
margin-bottom: 1rem;
35+
text-transform: capitalize;
36+
}
37+
38+
.state-variants-grid {
39+
display: grid;
40+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
41+
gap: 1rem;
42+
}
43+
44+
.state-variant-header {
45+
font-weight: 600;
46+
font-size: 0.6875rem;
47+
text-transform: capitalize;
48+
margin-bottom: 0.5rem;
49+
}
50+
51+
.state-variant-demo {
52+
padding: 1rem;
53+
border-radius: calc(var(--typo3-component-border-radius) * 0.5);
54+
margin-bottom: 0.75rem;
55+
text-align: center;
56+
font-weight: 500;
57+
}
58+
59+
.state-property-list {
60+
display: flex;
61+
flex-direction: column;
62+
gap: 0.25rem;
63+
font-size: 0.6875rem;
64+
font-family: var(--typo3-font-family-monospace);
65+
}
66+
67+
.state-property-item {
68+
display: flex;
69+
gap: 0.5rem;
70+
padding: 0.25rem 0;
71+
align-items: center;
72+
color: var(--typo3-text-color-base);
73+
font-weight: 600;
74+
}
75+
76+
.state-property-color-tile {
77+
width: 1rem;
78+
height: 1rem;
79+
border-radius: 0.125rem;
80+
flex-shrink: 0;
81+
}
82+
</f:asset.css>
83+
84+
<sg:colorScheme>
85+
<div class="state-tokens-grid">
86+
<h2>Accent Colors</h2>
87+
<f:for each="{accentColors}" as="color">
88+
<div class="state-token-section">
89+
<h3>{color}</h3>
90+
<div class="state-variants-grid">
91+
<f:for each="{stateVariants}" as="variant">
92+
<div>
93+
<div class="state-variant-header">{variant}</div>
94+
<f:if condition="{variant} == 'default'">
95+
<f:then>
96+
<div class="state-variant-demo" style="
97+
color: var(--typo3-state-{color}-color);
98+
background: var(--typo3-state-{color}-bg);
99+
border: 2px solid var(--typo3-state-{color}-border-color);
100+
">
101+
Sample Text
102+
</div>
103+
<div class="state-property-list">
104+
<div class="state-property-item">
105+
<span class="state-property-color-tile" style="background: var(--typo3-state-{color}-color);"></span>
106+
--typo3-state-{color}-color
107+
</div>
108+
<div class="state-property-item">
109+
<span class="state-property-color-tile" style="background: var(--typo3-state-{color}-bg);"></span>
110+
--typo3-state-{color}-bg
111+
</div>
112+
<div class="state-property-item">
113+
<span class="state-property-color-tile" style="background: var(--typo3-state-{color}-border-color);"></span>
114+
--typo3-state-{color}-border-color
115+
</div>
116+
</div>
117+
</f:then>
118+
<f:else>
119+
<div class="state-variant-demo" style="
120+
color: var(--typo3-state-{color}-{variant}-color);
121+
background: var(--typo3-state-{color}-{variant}-bg);
122+
border: 2px solid var(--typo3-state-{color}-{variant}-border-color);
123+
">
124+
Sample Text
125+
</div>
126+
<div class="state-property-list">
127+
<div class="state-property-item">
128+
<span class="state-property-color-tile" style="background: var(--typo3-state-{color}-{variant}-color);"></span>
129+
--typo3-state-{color}-{variant}-color
130+
</div>
131+
<div class="state-property-item">
132+
<span class="state-property-color-tile" style="background: var(--typo3-state-{color}-{variant}-bg);"></span>
133+
--typo3-state-{color}-{variant}-bg
134+
</div>
135+
<div class="state-property-item">
136+
<span class="state-property-color-tile" style="background: var(--typo3-state-{color}-{variant}-border-color);"></span>
137+
--typo3-state-{color}-{variant}-border-color
138+
</div>
139+
</div>
140+
</f:else>
141+
</f:if>
142+
</div>
143+
</f:for>
144+
</div>
145+
</div>
146+
</f:for>
147+
148+
<h2>State Colors</h2>
149+
<f:for each="{stateColors}" as="color">
150+
<div class="state-token-section">
151+
<h3>{color}</h3>
152+
<div class="state-variants-grid">
153+
<f:for each="{stateVariants}" as="variant">
154+
<div>
155+
<div class="state-variant-header">{variant}</div>
156+
<f:if condition="{variant} == 'default'">
157+
<f:then>
158+
<div class="state-variant-demo" style="
159+
color: var(--typo3-state-{color}-color);
160+
background: var(--typo3-state-{color}-bg);
161+
border: 2px solid var(--typo3-state-{color}-border-color);
162+
">
163+
Sample Text
164+
</div>
165+
<div class="state-property-list">
166+
<div class="state-property-item">
167+
<span class="state-property-color-tile" style="background: var(--typo3-state-{color}-color);"></span>
168+
--typo3-state-{color}-color
169+
</div>
170+
<div class="state-property-item">
171+
<span class="state-property-color-tile" style="background: var(--typo3-state-{color}-bg);"></span>
172+
--typo3-state-{color}-bg
173+
</div>
174+
<div class="state-property-item">
175+
<span class="state-property-color-tile" style="background: var(--typo3-state-{color}-border-color);"></span>
176+
--typo3-state-{color}-border-color
177+
</div>
178+
</div>
179+
</f:then>
180+
<f:else>
181+
<div class="state-variant-demo" style="
182+
color: var(--typo3-state-{color}-{variant}-color);
183+
background: var(--typo3-state-{color}-{variant}-bg);
184+
border: 2px solid var(--typo3-state-{color}-{variant}-border-color);
185+
">
186+
Sample Text
187+
</div>
188+
<div class="state-property-list">
189+
<div class="state-property-item">
190+
<span class="state-property-color-tile" style="background: var(--typo3-state-{color}-{variant}-color);"></span>
191+
--typo3-state-{color}-{variant}-color
192+
</div>
193+
<div class="state-property-item">
194+
<span class="state-property-color-tile" style="background: var(--typo3-state-{color}-{variant}-bg);"></span>
195+
--typo3-state-{color}-{variant}-bg
196+
</div>
197+
<div class="state-property-item">
198+
<span class="state-property-color-tile" style="background: var(--typo3-state-{color}-{variant}-border-color);"></span>
199+
--typo3-state-{color}-{variant}-border-color
200+
</div>
201+
</div>
202+
</f:else>
203+
</f:if>
204+
</div>
205+
</f:for>
206+
</div>
207+
</div>
208+
</f:for>
209+
</div>
210+
</sg:colorScheme>
211+
</div>
212+
213+
</f:section>
214+
215+
</html>

0 commit comments

Comments
 (0)