Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions app/src/main/kotlin/ee/ria/DigiDoc/ui/theme/FocusIndication.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright 2017 - 2026 Riigi Infosüsteemi Amet
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/

@file:Suppress("PackageName")

package ee.ria.DigiDoc.ui.theme

import androidx.compose.foundation.IndicationNodeFactory
import androidx.compose.foundation.interaction.FocusInteraction
import androidx.compose.foundation.interaction.InteractionSource
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.node.DelegatableNode
import androidx.compose.ui.node.DrawModifierNode
import androidx.compose.ui.node.invalidateDraw
import ee.ria.DigiDoc.ui.theme.Dimensions.MSCornerRadius
import kotlinx.coroutines.launch

data class FocusIndication(
private val color: Color,
private val alpha: Float = 1.0f,
) : IndicationNodeFactory {
override fun create(interactionSource: InteractionSource): DelegatableNode =
FocusIndicationNode(interactionSource, color.copy(alpha = alpha))
}

private class FocusIndicationNode(
private val interactionSource: InteractionSource,
private val color: Color,
) : Modifier.Node(),
DrawModifierNode {
private var isFocused = false

override fun onAttach() {
coroutineScope.launch {
interactionSource.interactions.collect { interaction ->
when (interaction) {
is FocusInteraction.Focus -> isFocused = true
is FocusInteraction.Unfocus -> isFocused = false
}
invalidateDraw()
}
}
}

override fun ContentDrawScope.draw() {
if (isFocused) {
drawRoundRect(
color = color,
size = size,
cornerRadius = CornerRadius(MSCornerRadius.toPx()),
)
}
drawContent()
}
}
57 changes: 55 additions & 2 deletions app/src/main/kotlin/ee/ria/DigiDoc/ui/theme/Theme.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,24 @@
package ee.ria.DigiDoc.ui.theme

import android.app.Activity
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ripple.RippleAlpha
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.LocalRippleConfiguration
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RippleConfiguration
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
Expand Down Expand Up @@ -120,15 +128,30 @@ fun RIADigiDocTheme(
dynamicColor: Boolean = false,
content: @Composable () -> Unit,
) {
val accessibilityFocusColor =
if (isSystemInDarkTheme()) {
LightColorScheme.primary
} else {
DarkColorScheme.primary
}

val accessibilityFocusAlpha =
RippleAlpha(
pressedAlpha = 0.1f,
focusedAlpha = 0.4f,
draggedAlpha = 0.16f,
hoveredAlpha = 0.08f,
)

val useDarkTheme = darkTheme ?: isSystemInDarkTheme()
val colorScheme =
when {
dynamicColor -> {
val context = LocalContext.current
if (useDarkTheme == true) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
if (useDarkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}

useDarkTheme == true -> DarkColorScheme
useDarkTheme -> DarkColorScheme
else -> LightColorScheme
}
val view = LocalView.current
Expand All @@ -147,6 +170,36 @@ fun RIADigiDocTheme(
MaterialTheme(
colorScheme = colorScheme,
typography = getTypography(),
content = {
AccessibilityFocusProvider(
focusColor = accessibilityFocusColor,
alpha = accessibilityFocusAlpha,
content = content,
)
},
)
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun AccessibilityFocusProvider(
focusColor: Color,
alpha: RippleAlpha,
content: @Composable () -> Unit,
) {
CompositionLocalProvider(
LocalIndication provides
remember(focusColor) {
FocusIndication(
color = focusColor,
alpha = alpha.focusedAlpha,
)
},
LocalRippleConfiguration provides
RippleConfiguration(
color = focusColor,
rippleAlpha = alpha,
),
content = content,
)
}
Loading