diff --git a/webapp/packages/core-theming/src/ThemeService.ts b/webapp/packages/core-theming/src/ThemeService.ts index b1813cdc61..786f3609c9 100644 --- a/webapp/packages/core-theming/src/ThemeService.ts +++ b/webapp/packages/core-theming/src/ThemeService.ts @@ -18,6 +18,7 @@ import './styles/main/fonts.pure.css'; // TODO: important to keep normalize first import './styles/main/normalize.pure.css'; import './styles/utilities/typography.css'; +import './styles/utilities/ripple.css'; import './styles/UiIconButton.css'; import './styles/UiSpinner.css'; import './styles/UiInput.css'; diff --git a/webapp/packages/core-theming/src/styles/_color.scss b/webapp/packages/core-theming/src/styles/_color.scss index 7f266527e1..95a87c4b84 100644 --- a/webapp/packages/core-theming/src/styles/_color.scss +++ b/webapp/packages/core-theming/src/styles/_color.scss @@ -91,113 +91,6 @@ background-color: var(--theme-#{$color-name}); } } - - // Ripple effect classes (hover/focus/active feedback) - &.theme-ripple, - .theme-ripple { - position: relative; - - &::before { - position: absolute; - content: ''; - opacity: 0; - top: 0; - left: 0; - width: 100%; - height: 100%; - overflow: hidden; - background-color: currentColor; - border-radius: inherit; - pointer-events: none; - transition: opacity 150ms linear; - } - - &:hover::before { - opacity: 0.04; - } - - &:focus::before { - opacity: 0.1; - } - - &:active::before { - opacity: 0.1; - } - - &[aria-expanded='true']::before { - opacity: 0.14; - } - } - - &.theme-ripple-selectable, - .theme-ripple-selectable { - &[aria-selected='true']::before { - opacity: 0.14; - } - } - - &.theme-ripple-background, - .theme-ripple-background { - background-color: var(--theme-background); - color: var(--theme-text-hint-on-light); - - &.theme-ripple-selectable { - &:hover { - color: var(--theme-text-primary-on-light); - } - - &[aria-selected='true'] { - background-color: var(--theme-surface); - color: var(--theme-text-primary-on-light); - - &::before { - opacity: 0 !important; - } - } - } - } - - &.theme-ripple-secondary, - .theme-ripple-secondary { - background-color: var(--theme-secondary); - color: var(--theme-text-hint-on-light); - - &.theme-ripple-selectable { - &:hover { - color: var(--theme-text-primary-on-light); - } - - &[aria-selected='true'] { - background-color: var(--theme-surface); - color: var(--theme-text-primary-on-light); - - &::before { - opacity: 0 !important; - } - } - } - } - - &.theme-ripple-surface, - .theme-ripple-surface { - background-color: var(--theme-surface); - color: var(--theme-text-hint-on-light); - - &.theme-ripple-selectable { - &:hover { - color: var(--theme-text-primary-on-light); - } - - &[aria-selected='true'] { - background-color: var(--theme-surface); - color: var(--theme-text-primary-on-light); - - &::before { - opacity: 0 !important; - } - } - } - } } @layer components { diff --git a/webapp/packages/core-theming/src/styles/utilities/ripple.css b/webapp/packages/core-theming/src/styles/utilities/ripple.css new file mode 100644 index 0000000000..79bf027fa1 --- /dev/null +++ b/webapp/packages/core-theming/src/styles/utilities/ripple.css @@ -0,0 +1,50 @@ +/** + * Ripple Effect Utilities + * + * Provides hover/focus/active feedback using a pseudo-element overlay. + * Uses currentColor so it adapts to the parent's text color. + */ + +@layer components { + /* Base ripple effect */ + .theme-ripple { + position: relative; + + &::before { + position: absolute; + content: ''; + opacity: 0; + top: 0; + left: 0; + width: 100%; + height: 100%; + overflow: hidden; + background-color: currentColor; + border-radius: inherit; + pointer-events: none; + transition: opacity 150ms linear; + } + + &:hover::before { + opacity: 0.04; + } + + &:focus::before { + opacity: 0.1; + } + + &:active::before { + opacity: 0.1; + } + + &[aria-expanded='true']::before { + opacity: 0.14; + } + } + + .theme-ripple-selectable { + &[aria-selected='true']::before { + opacity: 0.14; + } + } +}