Skip to content

Commit

Permalink
Merge pull request #45 from mori-atsushi/button
Browse files Browse the repository at this point in the history
Add Button
  • Loading branch information
mori-atsushi authored Nov 23, 2023
2 parents 2de82d4 + 3d0a79e commit d5874ec
Show file tree
Hide file tree
Showing 17 changed files with 363 additions and 9 deletions.
8 changes: 8 additions & 0 deletions .idea/artifacts/compose_stylesheet_button_desktop.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 52 additions & 0 deletions component/compose-stylesheet-button/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.compose.multiplatform)
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.maven.publish)
}

kotlin {
androidTarget {
publishLibraryVariants("release")
}
jvm("desktop")
iosX64("uikitX64")
iosArm64("uikitArm64")
iosSimulatorArm64("uikitSimArm64")
macosX64()
macosArm64()

sourceSets {
val commonMain by getting {
dependencies {
implementation(compose.foundation)
implementation(project(":compose-stylesheet-core"))
}
}

val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}

all {
languageSettings.optIn(
"com.moriatsushi.compose.stylesheet.component.StyleSheetComponentApi",
)
}
}
}

android {
namespace = "com.moriatsushi.compose.stylesheet.button"
compileSdk = 34
defaultConfig {
minSdk = 21
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}
4 changes: 4 additions & 0 deletions component/compose-stylesheet-button/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
POM_ARTIFACT_ID=compose-stylesheet-button
POM_NAME=Compose StyleSheet
POM_DESCRIPTION=A flexible UI component library for Jetpack Compose
POM_PACKAGING=aar
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.moriatsushi.compose.stylesheet.button

import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.semantics
import com.moriatsushi.compose.stylesheet.StyleSheet
import com.moriatsushi.compose.stylesheet.component.Component
import com.moriatsushi.compose.stylesheet.component.componentCommonStyle
import com.moriatsushi.compose.stylesheet.content.ProvideContentStyle
import com.moriatsushi.compose.stylesheet.tag.TagModifier

/**
* A button component.
*/
@Composable
fun Button(
onClick: () -> Unit,
modifier: Modifier = Modifier,
tags: TagModifier<ButtonStyle> = TagModifier(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
buttonStyle: ButtonStyle = ButtonStyle.Default,
content: @Composable RowScope.() -> Unit,
) {
val localStyle = StyleSheet.getStyle(button, tags)
val mergedStyle = ButtonStyle {
this += localStyle
this += buttonStyle
}
val isPressed by interactionSource.collectIsPressedAsState()
val stateStyle = mergedStyle.getStyleForState(isPressed = isPressed)

Row(
modifier = modifier
.semantics { role = Role.Button }
.clickable(
interactionSource = interactionSource,
indication = null,
onClick = onClick,
)
.componentCommonStyle(stateStyle.commonStyle),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
) {
ProvideContentStyle(contentStyle = stateStyle.contentStyle) {
content()
}
}
}

/**
* An object for [Button].
*/
object Button

/**
* A symbol for [Button].
*/
val button = Component(
name = "Button",
defaultStyle = ButtonStyle.Default,
createBuilder = ::ButtonStyleBuilder,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.moriatsushi.compose.stylesheet.button

import androidx.compose.runtime.Immutable
import com.moriatsushi.compose.stylesheet.component.ComponentCommonStyle
import com.moriatsushi.compose.stylesheet.component.ComponentStyle
import com.moriatsushi.compose.stylesheet.content.ContentStyle

/**
* A style for each [Button] state, such as pressed, focused, etc.
*/
@Immutable
sealed interface ButtonStateStyle : ComponentStyle {
val contentStyle: ContentStyle

companion object {
/**
* Constant for a default [ButtonStateStyle].
*/
val Default: ButtonStateStyle = ButtonStateStyle()
}
}

internal fun ButtonStateStyle(builder: ButtonStateStyleBuilder.() -> Unit): ButtonStateStyle =
ButtonStateStyleBuilder().apply(builder).build()

internal fun ButtonStateStyle(
commonStyle: ComponentCommonStyle = ComponentCommonStyle.Default,
contentStyle: ContentStyle = ContentStyle.Default,
): ButtonStateStyle = ButtonStateStyleImpl(
commonStyle = commonStyle,
contentStyle = contentStyle,
)

@Immutable
private data class ButtonStateStyleImpl(
override val commonStyle: ComponentCommonStyle = ComponentCommonStyle.Default,
override val contentStyle: ContentStyle = ContentStyle.Default,
) : ButtonStateStyle
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.moriatsushi.compose.stylesheet.button

import com.moriatsushi.compose.stylesheet.StyleSheetBuilderMarker
import com.moriatsushi.compose.stylesheet.component.ComponentStyleBuilder
import com.moriatsushi.compose.stylesheet.content.ContentStyleBuilder

/**
* A builder for [ButtonStateStyle].
*/
@StyleSheetBuilderMarker
class ButtonStateStyleBuilder internal constructor() : ComponentStyleBuilder<ButtonStateStyle>() {
/**
* A content style.
*/
val content: ContentStyleBuilder = ContentStyleBuilder()

/**
* Defines content styles.
*/
fun content(builder: ContentStyleBuilder.() -> Unit) {
content.builder()
}

override fun plusAssign(other: ButtonStateStyle) {
this += other.commonStyle
content += other.contentStyle
}

override fun build(): ButtonStateStyle = ButtonStateStyle(
commonStyle = buildCommonStyle(),
contentStyle = content.build(),
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.moriatsushi.compose.stylesheet.button

import androidx.compose.runtime.Immutable
import com.moriatsushi.compose.stylesheet.component.ComponentCommonStyle
import com.moriatsushi.compose.stylesheet.component.ComponentStyle
import com.moriatsushi.compose.stylesheet.content.ContentStyle

/**
* A style for [Button].
*/
@Immutable
sealed interface ButtonStyle : ComponentStyle {
val contentStyle: ContentStyle
val pressedStyle: ButtonStateStyle

companion object {
/**
* Constant for a default [ButtonStyle].
*/
val Default: ButtonStyle = ButtonStyle()
}
}

/**
* Creates a [ButtonStyle] using the [builder].
*/
fun ButtonStyle(builder: ButtonStyleBuilder.() -> Unit): ButtonStyle =
ButtonStyleBuilder().apply(builder).build()

internal fun ButtonStyle(
commonStyle: ComponentCommonStyle = ComponentCommonStyle.Default,
contentStyle: ContentStyle = ContentStyle.Default,
pressedStyle: ButtonStateStyle = ButtonStateStyle.Default,
): ButtonStyle = ButtonStyleImpl(
commonStyle = commonStyle,
contentStyle = contentStyle,
pressedStyle = pressedStyle,
)

internal fun ButtonStyle.getStyleForState(
isPressed: Boolean,
): ButtonStateStyle {
val buttonStyle = this
return ButtonStateStyle {
this += buttonStyle.commonStyle
content += buttonStyle.contentStyle

if (isPressed) {
this += buttonStyle.pressedStyle
}
}
}

@Immutable
private data class ButtonStyleImpl(
override val commonStyle: ComponentCommonStyle,
override val contentStyle: ContentStyle,
override val pressedStyle: ButtonStateStyle,
) : ButtonStyle
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.moriatsushi.compose.stylesheet.button

import com.moriatsushi.compose.stylesheet.StyleSheetBuilderMarker
import com.moriatsushi.compose.stylesheet.component.ComponentStyleBuilder
import com.moriatsushi.compose.stylesheet.content.ContentStyleBuilder

/**
* A builder for [ButtonStyle].
*/
@StyleSheetBuilderMarker
class ButtonStyleBuilder internal constructor() : ComponentStyleBuilder<ButtonStyle>() {
private val pressedStyleBuilder = ButtonStateStyleBuilder()

/**
* A content style.
*/
val content: ContentStyleBuilder = ContentStyleBuilder()

/**
* Defines content styles.
*/
fun content(builder: ContentStyleBuilder.() -> Unit) {
content.builder()
}

/**
* Defines pressed styles.
*/
fun pressed(builder: ButtonStateStyleBuilder.() -> Unit) {
pressedStyleBuilder.builder()
}

override fun plusAssign(other: ButtonStyle) {
this += other.commonStyle
content += other.contentStyle
pressedStyleBuilder += other.pressedStyle
}

override fun build(): ButtonStyle = ButtonStyle(
commonStyle = buildCommonStyle(),
contentStyle = content.build(),
pressedStyle = pressedStyleBuilder.build(),
)
}
1 change: 1 addition & 0 deletions compose-stylesheet-theme/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ kotlin {
dependencies {
implementation(compose.foundation)
implementation(project(":compose-stylesheet-core"))
api(project(":component:compose-stylesheet-button"))
api(project(":component:compose-stylesheet-text"))
api(project(":component:compose-stylesheet-surface"))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ object Colors {
val black = Token("color.black", Color(0xFF000000))
val white = Token("color.white", Color(0xFFFFFFFF))

val gray50 = Token("color.gray100", Color(0xFFF7F8F9))
val gray100 = Token("color.gray200", Color(0xFFECEEEf))
val gray200 = Token("color.gray300", Color(0xFFD4D6D9))
val gray300 = Token("color.gray400", Color(0xFFABD1B6))
val gray400 = Token("color.gray500", Color(0xFF888C91))
val gray500 = Token("color.gray600", Color(0xFF61656A))
val gray600 = Token("color.gray700", Color(0xFF3F4349))
val gray700 = Token("color.gray800", Color(0xFF2D3135))
val gray800 = Token("color.gray900", Color(0xFF1A1C1F))
val gray50 = Token("color.gray50", Color(0xFFF7F8F9))
val gray100 = Token("color.gray100", Color(0xFFECEEEf))
val gray200 = Token("color.gray200", Color(0xFFD4D6D9))
val gray300 = Token("color.gray300", Color(0xFFADB1B6))
val gray400 = Token("color.gray400", Color(0xFF888C91))
val gray500 = Token("color.gray500", Color(0xFF61656A))
val gray600 = Token("color.gray600", Color(0xFF3F4349))
val gray700 = Token("color.gray700", Color(0xFF2D3135))
val gray800 = Token("color.gray800", Color(0xFF1A1C1F))
val gray900 = Token("color.gray900", Color(0xFF090A0C))

val semantic: SemanticColors = SemanticColors()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.moriatsushi.compose.stylesheet.StyleSheet
import com.moriatsushi.compose.stylesheet.theme.button.buttonStyleSheet
import com.moriatsushi.compose.stylesheet.theme.surface.surfaceStyleSheet

/**
Expand All @@ -20,11 +21,15 @@ fun themeStyleSheet(
Colors.semantic.onBackground += if (useDarkMode) Colors.white else Colors.gray900
Colors.semantic.primarySurface += if (useDarkMode) Colors.gray800 else Colors.gray100
Colors.semantic.onPrimarySurface += Colors.semantic.onBackground
Colors.semantic.inverseSurface += if (useDarkMode) Colors.white else Colors.gray900
Colors.semantic.inverseSurfacePressed += if (useDarkMode) Colors.gray300 else Colors.gray600
Colors.semantic.onInverseSurface += if (useDarkMode) Colors.gray900 else Colors.white

content {
color += Colors.semantic.onBackground
}

this += buttonStyleSheet
this += surfaceStyleSheet
}
}
Loading

0 comments on commit d5874ec

Please sign in to comment.