Keyboard Key

Keyboard Key

Subscribe for Live Previews, in your browser

$3 / month

Code

import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.dropShadow
import androidx.compose.ui.draw.innerShadow
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Color.Companion.Transparent
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.PointerIcon
import androidx.compose.ui.input.pointer.pointerHoverIcon
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.util.lerp
import theme.Colors


@Composable
fun KeyboardButtonImpl(modifier: Modifier = Modifier) {
    Box(
        modifier.fillMaxSize().background(color = Colors.Zinc200),
        contentAlignment = Alignment.Center,
    ) {
        KeyboardButton(
            modifier = Modifier,
            onClick = {

            },
        ) {
            Text(
                "hello",
                color = Colors.Zinc950,
                fontSize = 16.sp,
                fontFamily = FontFamily.Monospace,
                fontWeight = FontWeight.SemiBold,
            )
        }
    }
}

@Composable
fun KeyboardButton(
    modifier: Modifier = Modifier,
    onClick: () -> Unit,
    mid: Color = Colors.Orange500,
    light: Color = Colors.Orange400,
    lightest: Color = Colors.Orange300,
    content: @Composable RowScope.() -> Unit,
) {

    var isPressed by remember { mutableStateOf(false) }

    val touch by animateFloatAsState(
        targetValue = if (isPressed) 1f else 0f,
        animationSpec = spring(
            stiffness = Spring.StiffnessHigh
        )
    )

    var x = remember { .3f }
    Row(
        modifier = modifier
            .pointerInput(Unit) {
                detectTapGestures(
                    onPress = {
                        isPressed = true
                        tryAwaitRelease()
                        isPressed = false
                    },
                    onTap = { onClick() },
                )
            }
            .pointerHoverIcon(PointerIcon.Hand)
            .padding(2.dp)
            .background(
                color = Colors.Neutral950,
                shape = RoundedCornerShape(8.dp)
            )
            .dropShadow(
                shape = RoundedCornerShape(8.dp)
            ) {
                color = Colors.Black.copy(alpha = .4f)
                radius = lerp(8f, 2f, touch)
                offset = androidx.compose.ui.geometry.lerp(Offset(5f, 5f), Offset(0f, 0f), touch)
            }
            .padding(1.dp)
            .graphicsLayer {
                val scale = lerp(1f, .97f, touch)
                scaleX = scale
                scaleY = scale
            }
            .background(
                brush = Brush.sweepGradient(
                    Pair(0.125f * 0, mid),

                    Pair(0.125f * (1 - x), mid),
                    Pair(0.125f * 1, light),
                    Pair(0.125f * (1 + x), mid),

                    Pair(0.125f * 2, mid),

                    Pair(0.125f * (3 - x), mid),
                    Pair(0.125f * 3, light),
                    Pair(0.125f * (3 + x), mid),

                    Pair(0.125f * 4, mid),

                    Pair(0.125f * (5 - x), mid),
                    Pair(0.125f * 5, light),
                    Pair(0.125f * (5 + x), mid),

                    Pair(0.125f * 6, mid),

                    Pair(0.125f * (7 - x), mid),
                    Pair(0.125f * 7, light),
                    Pair(0.125f * (7 + x), mid),

                    Pair(1f, mid),
                ),
                shape = RoundedCornerShape(7.dp)
            )
            .innerShadow(
                shape = RoundedCornerShape(7.dp)
            ) {
                color = Colors.Black.copy(alpha = lerp(0f, .6f, touch))
                radius = lerp(0f, 20f, touch)
                offset = Offset(-5f, -5f)
                spread = 3f
            }
            .padding(4.dp)
            .dropShadow(
                shape = RoundedCornerShape(6.dp)
            ) {
                brush = Brush.verticalGradient(
                    colors = listOf(
                        Colors.Transparent,
                        Colors.Black.copy(alpha = .4f)
                    )
                )
                radius = 10f
            }
            .background(
                color = mid,
                shape = RoundedCornerShape(6.dp)
            )
            .background(
                brush = Brush.linearGradient(
                    colors = listOf(
                        lightest.copy(alpha = lerp(1f, .2f, touch)),
                        mid.copy(alpha = lerp(1f, .2f, touch)),
                    )
                ),
                shape = RoundedCornerShape(6.dp)
            )
            .innerShadow(
                shape = RoundedCornerShape(6.dp)
            ) {
                brush = Brush.verticalGradient(
                    colors = listOf(
                        Colors.Orange100.copy(alpha = lerp(1f, .6f, touch)),
                        Transparent,
                    )
                )
                radius = 4f
                spread = 2f

            }
            .padding(horizontal = 16.dp, vertical = 16.dp)
    ) {
        content()
    }

}
Mastodon