From fe7adaea8bc4a875a580c1e56abc58a58ed685ad Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Mon, 28 Sep 2026 16:59:48 +0200 Subject: [PATCH] fix(theme): time the theme's transitions with the names the token editor sets The editor writes --animation-quick and --animation-slow, while theme.css timed its buttons, links and inputs with --nldesign-animation-quick, which the editor never sets. overrides.css only maps the nldesign name onto the Nextcloud name, so the admin's speed never reached those transitions and the page ran two speeds. theme.css now reads --animation-quick, which overrides.css still feeds from the set's --nldesign-animation-quick when no override is saved. Fixes #697 --- css/systems/nldesign/theme.css | 16 ++-- .../Unit/MotionTokensReachTransitionsTest.php | 76 +++++++++++++++++++ 2 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 tests/Unit/MotionTokensReachTransitionsTest.php diff --git a/css/systems/nldesign/theme.css b/css/systems/nldesign/theme.css index 82f5f51f..029680f1 100644 --- a/css/systems/nldesign/theme.css +++ b/css/systems/nldesign/theme.css @@ -379,7 +379,7 @@ div[class*='login-box__wrapper'] > div { color: var(--nldesign-component-button-primary-action-color) !important; border-radius: var(--nldesign-component-button-border-radius) !important; box-shadow: none !important; - transition: background-color var(--nldesign-animation-quick) ease !important; + transition: background-color var(--animation-quick) ease !important; } #body-login .button-vue--vue-primary:hover, @@ -462,9 +462,9 @@ button:not(.action-button), border-radius: var(--nldesign-component-button-border-radius) !important; border-width: var(--nldesign-component-button-border-width) !important; transition: - background-color var(--nldesign-animation-quick) ease, - border-color var(--nldesign-animation-quick) ease, - color var(--nldesign-animation-quick) ease !important; + background-color var(--animation-quick) ease, + border-color var(--animation-quick) ease, + color var(--animation-quick) ease !important; } /* Primary buttons */ @@ -608,7 +608,7 @@ button.secondary:hover { a { color: var(--nldesign-component-link-color) !important; text-decoration: var(--nldesign-component-link-text-decoration) !important; - transition: color var(--nldesign-animation-quick) ease !important; + transition: color var(--animation-quick) ease !important; } a:hover { @@ -660,8 +660,8 @@ textarea { font-family: var(--nldesign-component-textbox-font-family) !important; font-size: var(--nldesign-component-textbox-font-size) !important; transition: - border-color var(--nldesign-animation-quick) ease, - box-shadow var(--nldesign-animation-quick) ease !important; + border-color var(--animation-quick) ease, + box-shadow var(--animation-quick) ease !important; } input[type='text']:hover, @@ -705,7 +705,7 @@ textarea:disabled { select { border-color: var(--nldesign-component-form-select-border-color) !important; border-radius: var(--nldesign-component-form-select-border-radius) !important; - transition: border-color var(--nldesign-animation-quick) ease !important; + transition: border-color var(--animation-quick) ease !important; } select:focus { diff --git a/tests/Unit/MotionTokensReachTransitionsTest.php b/tests/Unit/MotionTokensReachTransitionsTest.php new file mode 100644 index 00000000..21f7f841 --- /dev/null +++ b/tests/Unit/MotionTokensReachTransitionsTest.php @@ -0,0 +1,76 @@ + The property names, e.g. `--animation-quick`. + */ + private function motionVarsInTheme(): array { + $css = (string)file_get_contents(\dirname(__DIR__, 2) . '/css/systems/nldesign/theme.css'); + $this->assertNotSame('', $css, 'theme.css must be readable.'); + + preg_match_all('/(?:transition|animation)[a-z-]*\s*:([^;]*);/i', $css, $declarations); + $names = []; + foreach ($declarations[1] as $value) { + preg_match_all('/var\(\s*(--[A-Za-z0-9_-]+)/', $value, $vars); + foreach ($vars[1] as $name) { + $names[$name] = true; + } + } + + return array_keys($names); + }//end motionVarsInTheme() + + /** + * Every duration theme.css reads is one the token editor can set. + */ + public function testEveryThemeTransitionReadsAnEditableMotionToken(): void { + $names = $this->motionVarsInTheme(); + $this->assertNotEmpty($names, 'theme.css is expected to time its transitions with a token.'); + + foreach ($names as $name) { + $this->assertTrue( + TokenRegistry::isEditable(tokenName: $name), + $name . ' times a transition in theme.css, but the token editor cannot set it.' + ); + } + }//end testEveryThemeTransitionReadsAnEditableMotionToken() + + /** + * The set's own speed still reaches the Nextcloud names the theme now reads. + */ + public function testTheSetSpeedStillFeedsTheNextcloudNames(): void { + $overrides = (string)file_get_contents(\dirname(__DIR__, 2) . '/css/systems/nldesign/overrides.css'); + + $this->assertMatchesRegularExpression('/--animation-quick:\s*var\(--nldesign-animation-quick\)/', $overrides); + $this->assertMatchesRegularExpression('/--animation-slow:\s*var\(--nldesign-animation-slow\)/', $overrides); + }//end testTheSetSpeedStillFeedsTheNextcloudNames() +}//end class