Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.atls.hyperion.ui.fragments.datepicker.stories.DateRangePickerStory
import com.atls.hyperion.ui.primitives.stories.LinkStory
import com.atls.hyperion.ui.primitives.stories.TextStory
import com.atls.hyperion.ui.theme.Theme
import com.atls.hyperion.ui.theme.tokens.elevation.stories.ElevationStory

@Composable
fun App() {
Expand All @@ -41,6 +42,7 @@ fun App() {
DatePickerStory(),
DateRangePickerStory(),
DividerStory(),
ElevationStory(),
InputStory(),
PaginationStory(),
PlaceholderStory(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.atls.hyperion.ui.primitives

import androidx.compose.foundation.background
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.dropShadow
import androidx.compose.ui.draw.innerShadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.shadow.Shadow
import androidx.compose.ui.unit.DpOffset
import com.atls.hyperion.ui.theme.tokens.elevation.Elevation
import com.atls.hyperion.ui.theme.tokens.elevation.ShadowType

fun Modifier.elevation(
elevation: Elevation,
backgroundColor: Color,
shape: Shape = RectangleShape
): Modifier {
val withDropShadows = elevation.shadows.fold(this) { modifier, shadow ->
if (shadow.type == ShadowType.Drop) {
modifier.dropShadow(
shape = shape,
shadow = shadow.toComposeShadow()
)
} else {
modifier
}
}

val withBackground = withDropShadows.background(backgroundColor, shape)
Comment thread
TorinAsakura marked this conversation as resolved.

return elevation.shadows.fold(withBackground) { modifier, shadow ->
if (shadow.type == ShadowType.Inner) {
modifier.innerShadow(
shape = shape,
shadow = shadow.toComposeShadow()
)
} else {
modifier
}
}
}

private fun com.atls.hyperion.ui.theme.tokens.elevation.Shadow.toComposeShadow() = Shadow(
radius = blur,
spread = spread,
offset = DpOffset(offsetX, offsetY),
color = color
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import com.atls.hyperion.ui.theme.tokens.borders.Borders
import com.atls.hyperion.ui.theme.tokens.colors.Colors
import com.atls.hyperion.ui.theme.tokens.colors.darkColors
import com.atls.hyperion.ui.theme.tokens.colors.lightColors
import com.atls.hyperion.ui.theme.tokens.elevation.Elevations
import com.atls.hyperion.ui.theme.typography.TextStyles
import com.atls.hyperion.ui.theme.typography.fontFamilies.ScienceGothicFontFamily

val LocalHyperionColors = staticCompositionLocalOf { lightColors }
val LocalHyperionBorders = staticCompositionLocalOf { Borders(lightColors) }
val LocalHyperionElevations = staticCompositionLocalOf { Elevations(lightColors) }
val LocalHyperionTypography = staticCompositionLocalOf { TextStyles(fontFamily = FontFamily.Default) }

@Composable
Expand All @@ -22,11 +24,13 @@ fun Theme(
content: @Composable () -> Unit
) {
val borders = Borders(colors)
val elevations = Elevations(colors)
val typography = TextStyles(fontFamily = ScienceGothicFontFamily())

CompositionLocalProvider(
LocalHyperionColors provides colors,
LocalHyperionBorders provides borders,
LocalHyperionElevations provides elevations,
LocalHyperionTypography provides typography
) {
content()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ val darkColors = Colors(
hover = Color(0xFF7AA7FF),
pressed = Color(0xFF3F74FF),
disabled = Color(0xFF5F8FFF),
subtle = Color(0xFF394A6B)
subtle = Color(0x4D5F8FFF)
),
surface = SurfaceColors(
base = Color(0xFF111111),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ val lightColors = Colors(
hover = Color(0xFF1643A3),
pressed = Color(0xFF12357F),
disabled = Color(0x401E56C7),
subtle = Color(0xFF6B86C8)
subtle = Color(0x401E56C7)
),
surface = SurfaceColors(
base = Color(0xFFF8F9FF),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.atls.hyperion.ui.theme.tokens.elevation

import androidx.compose.ui.unit.dp

object ShadowBlur {
val xs5 = 1.dp
val xs4 = 2.dp
val xs3 = 3.dp
val xs2 = 4.dp
val xs = 5.dp
val sm = 6.dp
val md = 8.dp
val lg = 12.dp
val xl = 14.dp
val xl2 = 16.dp
val xl3 = 20.dp
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package com.atls.hyperion.ui.theme.tokens.elevation

import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import com.atls.hyperion.ui.theme.tokens.colors.Colors

class Elevations(colors: Colors) {
val xs: PressableElevationStates = Xs(colors.elevation.xs)
val sm: PressableElevationStates = Sm(colors.elevation.sm)
val md: PressableElevationStates = Md(colors.elevation.md)
val lg: PressableElevationStates = Lg(colors.elevation.lg)
val modal: ElevationStates = Modal(colors.elevation.md)

private class Xs(color: Color) : PressableElevationStates {
override val default = elevation(
drop(color, offsetY = ShadowOffset.xs, blur = ShadowBlur.xs4)
)
override val pressed = elevation(
inner(color, offsetY = ShadowOffset.xs, blur = ShadowBlur.xs5),
drop(
color,
offsetY = ShadowOffset.xs,
blur = ShadowBlur.xs5,
spread = ShadowSpread.negativeXs
)
)
override val disabled = elevation(
drop(color, offsetY = ShadowOffset.xs, blur = ShadowBlur.xs5)
)
}

private class Sm(color: Color) : PressableElevationStates {
override val default = elevation(
drop(color, offsetY = ShadowOffset.sm, blur = ShadowBlur.sm)
)
override val pressed = elevation(
inner(color, offsetY = ShadowOffset.xs, blur = ShadowBlur.xs4),
drop(
color,
offsetY = ShadowOffset.xs,
blur = ShadowBlur.xs3,
spread = ShadowSpread.negativeSm
)
)
override val disabled = elevation(
drop(color, offsetY = ShadowOffset.xs, blur = ShadowBlur.xs4)
)
}

private class Md(color: Color) : PressableElevationStates {
override val default = elevation(
drop(color, offsetY = ShadowOffset.lg, blur = ShadowBlur.lg)
)
override val pressed = elevation(
inner(color, offsetY = ShadowOffset.xs, blur = ShadowBlur.xs3),
drop(
color,
offsetY = ShadowOffset.sm,
blur = ShadowBlur.sm,
spread = ShadowSpread.negativeXs
)
)
override val disabled = elevation(
drop(color, offsetY = ShadowOffset.sm, blur = ShadowBlur.xs)
)
}

private class Lg(color: Color) : PressableElevationStates {
override val default = elevation(
drop(
color,
offsetY = ShadowOffset.xl,
blur = ShadowBlur.lg,
spread = ShadowSpread.negativeLg
)
)
override val pressed = elevation(
inner(color, offsetY = ShadowOffset.sm, blur = ShadowBlur.xs2),
drop(
color,
offsetY = ShadowOffset.md,
blur = ShadowBlur.md,
spread = ShadowSpread.negativeLg
)
)
override val disabled = elevation(
drop(
color,
offsetY = ShadowOffset.md,
blur = ShadowBlur.sm,
spread = ShadowSpread.negativeMd
)
)
}

private class Modal(color: Color) : ElevationStates {
override val default = elevation(
drop(
color,
offsetY = ShadowOffset.xl3,
blur = ShadowBlur.xl3,
spread = ShadowSpread.negativeSm
)
)
}
}

private fun elevation(vararg shadows: Shadow) = Elevation(shadows.toList())

private fun drop(
color: Color,
offsetX: Dp = ShadowOffset.none,
offsetY: Dp,
blur: Dp,
spread: Dp = ShadowSpread.none
) = Shadow(
type = ShadowType.Drop,
offsetX = offsetX,
offsetY = offsetY,
blur = blur,
spread = spread,
color = color
)

private fun inner(
color: Color,
offsetY: Dp,
blur: Dp
) = Shadow(
type = ShadowType.Inner,
offsetX = ShadowOffset.none,
offsetY = offsetY,
blur = blur,
spread = ShadowSpread.none,
color = color
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.atls.hyperion.ui.theme.tokens.elevation

import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp

data class Elevation(
val shadows: List<Shadow>
Comment thread
TorinAsakura marked this conversation as resolved.
)

@Immutable
data class Shadow(
val type: ShadowType,
val offsetX: Dp,
val offsetY: Dp,
val blur: Dp,
val spread: Dp,
val color: Color
)

enum class ShadowType {
Drop,
Inner
}

interface ElevationStates {
val default: Elevation
}

interface PressableElevationStates : ElevationStates {
val pressed: Elevation
val disabled: Elevation
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.atls.hyperion.ui.theme.tokens.elevation

import androidx.compose.ui.unit.dp

object ShadowOffset {
val none = 0.dp
val xs = 1.dp
val sm = 2.dp
val md = 3.dp
val lg = 4.dp
val xl = 6.dp
val xl2 = 7.dp
val xl3 = 12.dp
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.atls.hyperion.ui.theme.tokens.elevation

import androidx.compose.ui.unit.dp

object ShadowSpread {
val negativeLg = (-4).dp
val negativeMd = (-3).dp
val negativeSm = (-2).dp
val negativeXs = (-1).dp
val none = 0.dp
val xs = 1.dp
}
Loading
Loading