AppBar Impl (#315)
This commit is contained in:
Родитель
b14bc57486
Коммит
6c7af89368
|
@ -28,6 +28,7 @@
|
|||
|
||||
<!-- Demo activities -->
|
||||
<activity android:name="com.microsoft.fluentuidemo.demos.ActionBarLayoutActivity" />
|
||||
<activity android:name="com.microsoft.fluentuidemo.demos.V2AppBarLayoutActivity" />
|
||||
<activity android:name="com.microsoft.fluentuidemo.demos.AppBarLayoutActivity" />
|
||||
<activity android:name="com.microsoft.fluentuidemo.demos.AvatarViewActivity" />
|
||||
<activity android:name="com.microsoft.fluentuidemo.demos.AvatarGroupViewActivity" />
|
||||
|
|
|
@ -11,6 +11,7 @@ import kotlin.reflect.KClass
|
|||
|
||||
const val ACTION_BAR_LAYOUT = "ActionBarLayout"
|
||||
const val APP_BAR_LAYOUT = "AppBarLayout"
|
||||
const val V2APP_BAR_LAYOUT = "V2 AppBarLayout"
|
||||
const val AVATAR_VIEW = "AvatarView"
|
||||
const val AVATAR_GROUP_VIEW = "AvatarGroupView"
|
||||
const val BASIC_INPUTS = "Basic Inputs"
|
||||
|
@ -50,6 +51,7 @@ const val TOOLTIP = "Tooltip"
|
|||
const val TYPOGRAPHY = "Typography"
|
||||
|
||||
val DEMOS = arrayListOf(
|
||||
Demo(V2APP_BAR_LAYOUT, V2AppBarLayoutActivity::class),
|
||||
Demo(V2AVATAR, V2AvatarActivity::class),
|
||||
Demo(V2AVATAR_CAROUSEL, V2AvatarCarouselActivity::class),
|
||||
Demo(V2AVATAR_GROUP, V2AvatarGroupActivity::class),
|
||||
|
|
|
@ -0,0 +1,352 @@
|
|||
package com.microsoft.fluentuidemo.demos
|
||||
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.compose.animation.core.LinearEasing
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.gestures.detectDragGestures
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Email
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.microsoft.fluentui.icons.ListItemIcons
|
||||
import com.microsoft.fluentui.icons.SearchBarIcons
|
||||
import com.microsoft.fluentui.icons.listitemicons.Chevron
|
||||
import com.microsoft.fluentui.icons.searchbaricons.Arrowback
|
||||
import com.microsoft.fluentui.theme.FluentTheme
|
||||
import com.microsoft.fluentui.theme.ThemeMode
|
||||
import com.microsoft.fluentui.theme.token.AliasTokens
|
||||
import com.microsoft.fluentui.theme.token.FluentColor
|
||||
import com.microsoft.fluentui.theme.token.FluentIcon
|
||||
import com.microsoft.fluentui.theme.token.FluentStyle
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.AppBarSize
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.AvatarSize
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.AvatarStatus
|
||||
import com.microsoft.fluentui.tokenized.AppBar
|
||||
import com.microsoft.fluentui.tokenized.SearchBar
|
||||
import com.microsoft.fluentui.tokenized.controls.ToggleSwitch
|
||||
import com.microsoft.fluentui.tokenized.listitem.ChevronOrientation
|
||||
import com.microsoft.fluentui.tokenized.listitem.ListItem
|
||||
import com.microsoft.fluentui.tokenized.persona.Avatar
|
||||
import com.microsoft.fluentui.tokenized.persona.Person
|
||||
import com.microsoft.fluentui.tokenized.segmentedcontrols.PillBar
|
||||
import com.microsoft.fluentui.tokenized.segmentedcontrols.PillMetaData
|
||||
import com.microsoft.fluentuidemo.DemoActivity
|
||||
import com.microsoft.fluentuidemo.R
|
||||
import kotlin.math.max
|
||||
|
||||
class V2AppBarLayoutActivity : DemoActivity() {
|
||||
override val contentLayoutId: Int
|
||||
get() = R.layout.v2_activity_compose
|
||||
override val contentNeedsScrollableContainer: Boolean
|
||||
get() = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val composeHere = findViewById<ComposeView>(R.id.compose_here)
|
||||
val context = this
|
||||
|
||||
composeHere.setContent {
|
||||
FluentTheme {
|
||||
var style: FluentStyle by rememberSaveable { mutableStateOf(FluentStyle.Neutral) }
|
||||
var appBarSize: AppBarSize by rememberSaveable { mutableStateOf(AppBarSize.Small) }
|
||||
var searchMode: Boolean by rememberSaveable { mutableStateOf(false) }
|
||||
var subtitle: String? by rememberSaveable { mutableStateOf("Subtitle") }
|
||||
var enableSearchBar: Boolean by rememberSaveable { mutableStateOf(false) }
|
||||
var enableButtonBar: Boolean by rememberSaveable { mutableStateOf(false) }
|
||||
var yAxisDelta: Float by rememberSaveable { mutableStateOf(1.0F) }
|
||||
|
||||
Column(modifier = Modifier.pointerInput(Unit) {
|
||||
detectDragGestures { _, distance ->
|
||||
if (searchMode)
|
||||
yAxisDelta = 0F
|
||||
else
|
||||
yAxisDelta = max(0F, distance.y + 10F) / 20F
|
||||
}
|
||||
}) {
|
||||
ListItem.SectionHeader(
|
||||
title = LocalContext.current.resources.getString(R.string.app_modifiable_parameters),
|
||||
enableChevron = true,
|
||||
enableContentOpenCloseTransition = true,
|
||||
chevronOrientation = ChevronOrientation(90f, 0f),
|
||||
) {
|
||||
Column {
|
||||
PillBar(
|
||||
mutableListOf(
|
||||
PillMetaData(
|
||||
text = LocalContext.current.resources.getString(R.string.fluentui_large),
|
||||
onClick = { appBarSize = AppBarSize.Large },
|
||||
selected = appBarSize == AppBarSize.Large
|
||||
),
|
||||
PillMetaData(
|
||||
text = LocalContext.current.resources.getString(R.string.fluentui_medium),
|
||||
onClick = { appBarSize = AppBarSize.Medium },
|
||||
selected = appBarSize == AppBarSize.Medium
|
||||
),
|
||||
PillMetaData(
|
||||
text = LocalContext.current.resources.getString(R.string.fluentui_small),
|
||||
onClick = { appBarSize = AppBarSize.Small },
|
||||
selected = appBarSize == AppBarSize.Small
|
||||
),
|
||||
PillMetaData(
|
||||
text = LocalContext.current.resources.getString(R.string.fluentui_search),
|
||||
onClick = { searchMode = !searchMode },
|
||||
selected = searchMode
|
||||
)
|
||||
), style = style,
|
||||
showBackground = true
|
||||
)
|
||||
|
||||
var subtitleText =
|
||||
LocalContext.current.resources.getString(R.string.app_bar_subtitle)
|
||||
ListItem.Item(
|
||||
text = subtitleText,
|
||||
subText = if (subtitle.isNullOrBlank())
|
||||
LocalContext.current.resources.getString(R.string.fluentui_disabled)
|
||||
else
|
||||
LocalContext.current.resources.getString(R.string.fluentui_enabled),
|
||||
trailingAccessoryView = {
|
||||
ToggleSwitch(
|
||||
onValueChange = {
|
||||
subtitle =
|
||||
if (subtitle.isNullOrBlank())
|
||||
subtitleText
|
||||
else
|
||||
null
|
||||
},
|
||||
checkedState = !subtitle.isNullOrBlank()
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
ListItem.Item(
|
||||
text = LocalContext.current.resources.getString(R.string.app_bar_style),
|
||||
subText = if (style == FluentStyle.Neutral)
|
||||
LocalContext.current.resources.getString(R.string.fluentui_neutral)
|
||||
else
|
||||
LocalContext.current.resources.getString(R.string.fluentui_brand),
|
||||
trailingAccessoryView = {
|
||||
ToggleSwitch(
|
||||
onValueChange = {
|
||||
style =
|
||||
if (style == FluentStyle.Neutral)
|
||||
FluentStyle.Brand
|
||||
else
|
||||
FluentStyle.Neutral
|
||||
},
|
||||
checkedState = style == FluentStyle.Brand
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
ListItem.Item(
|
||||
text = LocalContext.current.resources.getString(R.string.buttonbar),
|
||||
subText = if (enableButtonBar)
|
||||
LocalContext.current.resources.getString(R.string.fluentui_enabled)
|
||||
else
|
||||
LocalContext.current.resources.getString(R.string.fluentui_disabled),
|
||||
trailingAccessoryView = {
|
||||
ToggleSwitch(
|
||||
onValueChange = {
|
||||
enableButtonBar = !enableButtonBar
|
||||
},
|
||||
checkedState = enableButtonBar
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
ListItem.Item(
|
||||
text = LocalContext.current.resources.getString(R.string.searchbar),
|
||||
subText = if (enableSearchBar)
|
||||
LocalContext.current.resources.getString(R.string.fluentui_enabled)
|
||||
else
|
||||
LocalContext.current.resources.getString(R.string.fluentui_disabled),
|
||||
trailingAccessoryView = {
|
||||
enableSearchBar = enableSearchBar || searchMode
|
||||
ToggleSwitch(
|
||||
onValueChange = {
|
||||
enableSearchBar = !enableSearchBar
|
||||
},
|
||||
checkedState = enableSearchBar,
|
||||
enabledSwitch = !searchMode
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val buttonBarList = mutableListOf<PillMetaData>()
|
||||
for (idx in 1..6) {
|
||||
buttonBarList.add(
|
||||
PillMetaData(
|
||||
"Button $idx",
|
||||
{
|
||||
Toast.makeText(
|
||||
context,
|
||||
"Button $idx pressed",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val appTitleDelta: Float by animateFloatAsState(
|
||||
if (searchMode) 0F else 1F,
|
||||
animationSpec = tween(durationMillis = 150, easing = LinearEasing)
|
||||
)
|
||||
|
||||
val yAxisDeltaCoerced = yAxisDelta.coerceIn(0F, 1F)
|
||||
|
||||
val accessoryDelta: Float by animateFloatAsState(yAxisDeltaCoerced)
|
||||
val rightIconColor: Color = if (style == FluentStyle.Neutral)
|
||||
FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground2].value(
|
||||
FluentTheme.themeMode
|
||||
)
|
||||
else
|
||||
FluentColor(
|
||||
light = FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.ForegroundOnColor].value(
|
||||
ThemeMode.Light
|
||||
),
|
||||
dark = FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground2].value(
|
||||
ThemeMode.Dark
|
||||
)
|
||||
).value(FluentTheme.themeMode)
|
||||
|
||||
AppBar(
|
||||
title = "Fluent UI Demo",
|
||||
navigationIcon = FluentIcon(
|
||||
SearchBarIcons.Arrowback,
|
||||
contentDescription = "Navigate Back",
|
||||
onClick = {
|
||||
Toast.makeText(
|
||||
context,
|
||||
"Navigation Icon pressed",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
),
|
||||
subTitle = subtitle,
|
||||
logo = {
|
||||
Avatar(
|
||||
Person(
|
||||
"Allan",
|
||||
"Munger",
|
||||
status = AvatarStatus.DND,
|
||||
isActive = true
|
||||
),
|
||||
enablePresence = true,
|
||||
size = AvatarSize.Size32
|
||||
)
|
||||
},
|
||||
postTitleIcon = FluentIcon(
|
||||
ListItemIcons.Chevron,
|
||||
contentDescription = LocalContext.current.resources.getString(R.string.fluentui_chevron),
|
||||
onClick = {
|
||||
Toast.makeText(context, "Title Icon pressed", Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
),
|
||||
postSubtitleIcon = FluentIcon(
|
||||
ListItemIcons.Chevron,
|
||||
contentDescription = LocalContext.current.resources.getString(R.string.fluentui_chevron),
|
||||
onClick = {
|
||||
Toast.makeText(context, "Subtitle Icon pressed", Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
),
|
||||
appBarSize = appBarSize,
|
||||
style = style,
|
||||
searchMode = searchMode,
|
||||
searchBar = if (enableSearchBar) {
|
||||
{
|
||||
SearchBar(
|
||||
onValueChange = { _, _ -> },
|
||||
modifier = Modifier.onFocusChanged { focusState ->
|
||||
when {
|
||||
focusState.isFocused -> {
|
||||
searchMode = true
|
||||
}
|
||||
}
|
||||
},
|
||||
style = style,
|
||||
navigationIconCallback = { searchMode = false }
|
||||
)
|
||||
}
|
||||
} else null,
|
||||
bottomBar = if (enableButtonBar) {
|
||||
{ PillBar(metadataList = buttonBarList, style = style) }
|
||||
} else null,
|
||||
appTitleDelta = appTitleDelta,
|
||||
accessoryDelta = accessoryDelta,
|
||||
rightAccessoryView = {
|
||||
Box(
|
||||
Modifier
|
||||
.size(44.dp)
|
||||
.clickable(
|
||||
onClick = {
|
||||
Toast
|
||||
.makeText(
|
||||
context,
|
||||
"Navigation Icon 1 Pressed",
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
.show()
|
||||
}
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
Icons.Filled.Add,
|
||||
"Add",
|
||||
tint = rightIconColor
|
||||
)
|
||||
}
|
||||
|
||||
Box(
|
||||
Modifier
|
||||
.size(44.dp)
|
||||
.clickable(
|
||||
onClick = {
|
||||
Toast
|
||||
.makeText(
|
||||
context,
|
||||
"Navigation Icon 2 Pressed",
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
.show()
|
||||
}
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
Icons.Filled.Email,
|
||||
"E-mail",
|
||||
tint = rightIconColor
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
~ Licensed under the MIT License.
|
||||
-->
|
||||
|
||||
<resources xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:ignore="MissingTranslation">
|
||||
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
|
||||
|
||||
<!--App-->
|
||||
<string name="app_name">Fluent UI Demo</string>
|
||||
|
@ -35,8 +33,12 @@
|
|||
<string name="actionbar_position_heading">ActionBar Position</string>
|
||||
|
||||
<!--AppBar-->
|
||||
<string name="app_bar_style">AppBar Style</string>
|
||||
<string name="app_bar_subtitle">Subtitle</string>
|
||||
|
||||
<!-- Text that shows the action performed to the user -->
|
||||
<string name="app_bar_layout_navigation_icon_clicked">Navigation icon clicked.</string>
|
||||
|
||||
<!-- Icon labels -->
|
||||
<string name="app_bar_layout_menu_flag">Flag</string>
|
||||
<string name="app_bar_layout_menu_settings">Settings</string>
|
||||
|
@ -127,7 +129,7 @@
|
|||
<string name="bottom_sheet_dialog_button">Show</string>
|
||||
<string name="drawer_content_desc_collapse_state">Expand</string>
|
||||
<string name="drawer_content_desc_expand_state">Minimize</string>
|
||||
<string name="large_scrollable_text" translatable="false" >Large demo Text line for showing scroll behaviour of a content. Use inside a Scrollview \n
|
||||
<string name="large_scrollable_text" translatable="false">Large demo Text line for showing scroll behaviour of a content. Use inside a Scrollview \n
|
||||
Large demo Text line for showing scroll behaviour of a content. Use inside a Scrollview \n
|
||||
Large demo Text line for showing scroll behaviour of a content. Use inside a Scrollview \n
|
||||
Large demo Text line for showing scroll behaviour of a content. Use inside a Scrollview \n
|
||||
|
@ -296,6 +298,7 @@
|
|||
<!--Button-->
|
||||
<!-- text for buttons -->
|
||||
<string name="button">Button</string>
|
||||
<string name="buttonbar">ButtonBar</string>
|
||||
<string name="button_disabled">Disabled Button</string>
|
||||
<string name="button_borderless">Borderless Button</string>
|
||||
<string name="button_borderless_disabled">Borderless Disabled Button</string>
|
||||
|
@ -587,6 +590,7 @@
|
|||
Ut enim ad minim veniam.</string>
|
||||
|
||||
<!--SearchBar-->
|
||||
<string name="searchbar">SearchBar</string>
|
||||
<!-- name of the icon-->
|
||||
<string name="searchbar_microphone_callback">Microphone Callback</string>
|
||||
<!-- UI Text label -->
|
||||
|
|
|
@ -15,6 +15,7 @@ interface ControlToken
|
|||
class ControlTokens {
|
||||
|
||||
enum class ControlType {
|
||||
AppBar,
|
||||
Avatar,
|
||||
AvatarCarousel,
|
||||
AvatarGroup,
|
||||
|
@ -44,6 +45,7 @@ class ControlTokens {
|
|||
val tokens: TokenSet<ControlType, ControlToken> by lazy {
|
||||
TokenSet { token ->
|
||||
when (token) {
|
||||
ControlType.AppBar -> AppBarTokens()
|
||||
ControlType.Avatar -> AvatarTokens()
|
||||
ControlType.AvatarCarousel -> AvatarCarouselTokens()
|
||||
ControlType.AvatarGroup -> AvatarGroupTokens()
|
||||
|
|
|
@ -2,14 +2,15 @@ package com.microsoft.fluentui.theme.token
|
|||
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.microsoft.fluentui.theme.ThemeMode
|
||||
|
||||
data class Icon(
|
||||
data class FluentIcon(
|
||||
val light: ImageVector = ImageVector.Builder("", 0.dp, 0.dp, 0F, 0F).build(),
|
||||
val dark: ImageVector = ImageVector.Builder("", 0.dp, 0.dp, 0F, 0F).build(),
|
||||
val dark: ImageVector = light,
|
||||
val contentDescription: String = "",
|
||||
val onClick: (() -> Unit)? = null
|
||||
) {
|
||||
@Composable
|
||||
fun value(themeMode: ThemeMode = com.microsoft.fluentui.theme.FluentTheme.themeMode): ImageVector {
|
||||
|
@ -17,7 +18,11 @@ data class Icon(
|
|||
ThemeMode.Light -> light
|
||||
ThemeMode.Dark -> dark
|
||||
ThemeMode.Auto -> if (isSystemInDarkTheme()) dark else light
|
||||
else -> ImageVector.Builder("", 0.dp, 0.dp, 0F, 0F).build()
|
||||
}
|
||||
}
|
||||
|
||||
fun isIconAvailable(): Boolean {
|
||||
return (this.light.defaultWidth > 0.dp && this.light.defaultHeight > 0.dp) ||
|
||||
(this.dark.defaultWidth > 0.dp && this.dark.defaultHeight > 0.dp)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
package com.microsoft.fluentui.theme.token.controlTokens
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.microsoft.fluentui.theme.FluentTheme
|
||||
import com.microsoft.fluentui.theme.ThemeMode
|
||||
import com.microsoft.fluentui.theme.token.*
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
enum class AppBarSize {
|
||||
Large,
|
||||
Medium,
|
||||
Small
|
||||
}
|
||||
|
||||
data class AppBarInfo(
|
||||
val style: FluentStyle = FluentStyle.Neutral,
|
||||
val appBarSize: AppBarSize = AppBarSize.Medium
|
||||
) : ControlInfo
|
||||
|
||||
@Parcelize
|
||||
open class AppBarTokens : ControlToken, Parcelable {
|
||||
|
||||
@Composable
|
||||
open fun backgroundColor(info: AppBarInfo): Color {
|
||||
return when (info.style) {
|
||||
FluentStyle.Neutral ->
|
||||
FluentTheme.aliasTokens.neutralBackgroundColor[AliasTokens.NeutralBackgroundColorTokens.Background3].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
)
|
||||
FluentStyle.Brand ->
|
||||
FluentColor(
|
||||
light = FluentTheme.aliasTokens.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackground1].value(
|
||||
ThemeMode.Light
|
||||
),
|
||||
dark = FluentTheme.aliasTokens.neutralBackgroundColor[AliasTokens.NeutralBackgroundColorTokens.Background3].value(
|
||||
ThemeMode.Dark
|
||||
)
|
||||
).value(themeMode = FluentTheme.themeMode)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
open fun navigationIconColor(info: AppBarInfo): Color {
|
||||
return when (info.style) {
|
||||
FluentStyle.Neutral ->
|
||||
FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground2].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
)
|
||||
FluentStyle.Brand ->
|
||||
FluentColor(
|
||||
light = FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.ForegroundOnColor].value(
|
||||
ThemeMode.Light
|
||||
),
|
||||
dark = FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground2].value(
|
||||
ThemeMode.Dark
|
||||
)
|
||||
).value(themeMode = FluentTheme.themeMode)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
open fun titleIconColor(info: AppBarInfo): Color {
|
||||
return when (info.style) {
|
||||
FluentStyle.Neutral ->
|
||||
FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground1].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
)
|
||||
FluentStyle.Brand ->
|
||||
FluentColor(
|
||||
light = FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.ForegroundOnColor].value(
|
||||
ThemeMode.Light
|
||||
),
|
||||
dark = FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground1].value(
|
||||
ThemeMode.Dark
|
||||
)
|
||||
).value(themeMode = FluentTheme.themeMode)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
open fun subtitleIconColor(info: AppBarInfo): Color {
|
||||
return when (info.style) {
|
||||
FluentStyle.Neutral ->
|
||||
FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground2].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
)
|
||||
FluentStyle.Brand ->
|
||||
FluentColor(
|
||||
light = FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.ForegroundOnColor].value(
|
||||
ThemeMode.Light
|
||||
),
|
||||
dark = FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground2].value(
|
||||
ThemeMode.Dark
|
||||
)
|
||||
).value(themeMode = FluentTheme.themeMode)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
open fun titleTextColor(info: AppBarInfo): Color {
|
||||
return when (info.style) {
|
||||
FluentStyle.Neutral ->
|
||||
FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground1].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
)
|
||||
FluentStyle.Brand ->
|
||||
FluentColor(
|
||||
light = FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.ForegroundOnColor].value(
|
||||
ThemeMode.Light
|
||||
),
|
||||
dark = FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground1].value(
|
||||
ThemeMode.Dark
|
||||
)
|
||||
).value(themeMode = FluentTheme.themeMode)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
open fun subtitleTextColor(info: AppBarInfo): Color {
|
||||
return when (info.style) {
|
||||
FluentStyle.Neutral ->
|
||||
FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground2].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
)
|
||||
FluentStyle.Brand ->
|
||||
FluentColor(
|
||||
light = FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.ForegroundOnColor].value(
|
||||
ThemeMode.Light
|
||||
),
|
||||
dark = FluentTheme.aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground2].value(
|
||||
ThemeMode.Dark
|
||||
)
|
||||
).value(themeMode = FluentTheme.themeMode)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
open fun titleTypography(info: AppBarInfo): FontInfo {
|
||||
return when (info.appBarSize) {
|
||||
AppBarSize.Large -> FluentTheme.aliasTokens.typography[AliasTokens.TypographyTokens.Title1]
|
||||
AppBarSize.Medium -> FluentTheme.aliasTokens.typography[AliasTokens.TypographyTokens.Title2]
|
||||
AppBarSize.Small -> FluentTheme.aliasTokens.typography[AliasTokens.TypographyTokens.Body1Strong]
|
||||
else -> FontInfo(fontSize = FontSize(0.sp, 0.sp))
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
open fun subtitleTypography(info: AppBarInfo): FontInfo {
|
||||
return FluentTheme.aliasTokens.typography[AliasTokens.TypographyTokens.Caption1]
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun leftIconSize(info: AppBarInfo): Dp {
|
||||
return GlobalTokens.iconSize(GlobalTokens.IconSizeTokens.Medium)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun titleIconSize(info: AppBarInfo): Dp {
|
||||
return when (info.appBarSize) {
|
||||
AppBarSize.Small -> GlobalTokens.iconSize(GlobalTokens.IconSizeTokens.XSmall)
|
||||
else -> 0.dp
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun subtitleIconSize(info: AppBarInfo): Dp {
|
||||
return when (info.appBarSize) {
|
||||
AppBarSize.Small -> GlobalTokens.iconSize(GlobalTokens.IconSizeTokens.XXSmall)
|
||||
AppBarSize.Medium -> GlobalTokens.iconSize(GlobalTokens.IconSizeTokens.XXSmall)
|
||||
else -> 0.dp
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
open fun navigationIconPadding(info: AppBarInfo): PaddingValues {
|
||||
return when (info.appBarSize) {
|
||||
AppBarSize.Large -> PaddingValues()
|
||||
AppBarSize.Medium -> PaddingValues(16.dp)
|
||||
AppBarSize.Small -> PaddingValues(16.dp)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
open fun textPadding(info: AppBarInfo): PaddingValues {
|
||||
return when (info.appBarSize) {
|
||||
AppBarSize.Large -> PaddingValues(start = 12.dp)
|
||||
AppBarSize.Medium -> PaddingValues()
|
||||
AppBarSize.Small -> PaddingValues(start = 8.dp)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
open fun height(info: AppBarInfo): Dp {
|
||||
return 40.dp
|
||||
}
|
||||
}
|
|
@ -351,36 +351,36 @@ open class AvatarTokens(private val activityRingToken: ActivityRingsToken = Acti
|
|||
}
|
||||
|
||||
@Composable
|
||||
open fun presenceIcon(avatarInfo: AvatarInfo): Icon {
|
||||
open fun presenceIcon(avatarInfo: AvatarInfo): FluentIcon {
|
||||
return when (avatarInfo.status) {
|
||||
AvatarStatus.Available ->
|
||||
when (avatarInfo.size) {
|
||||
AvatarSize.Size16 -> Icon()
|
||||
AvatarSize.Size20 -> Icon(
|
||||
AvatarSize.Size16 -> FluentIcon()
|
||||
AvatarSize.Size20 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Availableoof.Small.Light else AvatarIcons.Presence.Available.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Availableoof.Small.Dark else AvatarIcons.Presence.Available.Small.Dark
|
||||
)
|
||||
AvatarSize.Size24 -> Icon(
|
||||
AvatarSize.Size24 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Availableoof.Small.Light else AvatarIcons.Presence.Available.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Availableoof.Small.Dark else AvatarIcons.Presence.Available.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size32 -> Icon(
|
||||
AvatarSize.Size32 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Availableoof.Small.Light else AvatarIcons.Presence.Available.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Availableoof.Small.Dark else AvatarIcons.Presence.Available.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size40 -> Icon(
|
||||
AvatarSize.Size40 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Availableoof.Medium.Light else AvatarIcons.Presence.Available.Medium.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Availableoof.Medium.Dark else AvatarIcons.Presence.Available.Medium.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size56 -> Icon(
|
||||
AvatarSize.Size56 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Availableoof.Medium.Light else AvatarIcons.Presence.Available.Medium.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Availableoof.Medium.Dark else AvatarIcons.Presence.Available.Medium.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size72 -> Icon(
|
||||
AvatarSize.Size72 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Availableoof.Large.Light else AvatarIcons.Presence.Available.Large.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Availableoof.Large.Dark else AvatarIcons.Presence.Available.Large.Dark
|
||||
)
|
||||
|
@ -388,33 +388,33 @@ open class AvatarTokens(private val activityRingToken: ActivityRingsToken = Acti
|
|||
|
||||
AvatarStatus.Busy ->
|
||||
when (avatarInfo.size) {
|
||||
AvatarSize.Size16 -> Icon()
|
||||
AvatarSize.Size20 -> Icon(
|
||||
AvatarSize.Size16 -> FluentIcon()
|
||||
AvatarSize.Size20 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Busyoof.Small.Light else AvatarIcons.Presence.Busy.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Busyoof.Small.Dark else AvatarIcons.Presence.Busy.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size24 -> Icon(
|
||||
AvatarSize.Size24 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Busyoof.Small.Light else AvatarIcons.Presence.Busy.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Busyoof.Small.Dark else AvatarIcons.Presence.Busy.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size32 -> Icon(
|
||||
AvatarSize.Size32 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Busyoof.Small.Light else AvatarIcons.Presence.Busy.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Busyoof.Small.Dark else AvatarIcons.Presence.Busy.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size40 -> Icon(
|
||||
AvatarSize.Size40 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Busyoof.Medium.Light else AvatarIcons.Presence.Busy.Medium.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Busyoof.Medium.Dark else AvatarIcons.Presence.Busy.Medium.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size56 -> Icon(
|
||||
AvatarSize.Size56 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Busyoof.Medium.Light else AvatarIcons.Presence.Busy.Medium.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Busyoof.Medium.Dark else AvatarIcons.Presence.Busy.Medium.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size72 -> Icon(
|
||||
AvatarSize.Size72 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Busyoof.Large.Light else AvatarIcons.Presence.Busy.Large.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Busyoof.Large.Dark else AvatarIcons.Presence.Busy.Large.Dark
|
||||
)
|
||||
|
@ -422,33 +422,33 @@ open class AvatarTokens(private val activityRingToken: ActivityRingsToken = Acti
|
|||
|
||||
AvatarStatus.Away ->
|
||||
when (avatarInfo.size) {
|
||||
AvatarSize.Size16 -> Icon()
|
||||
AvatarSize.Size20 -> Icon(
|
||||
AvatarSize.Size16 -> FluentIcon()
|
||||
AvatarSize.Size20 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Awayoof.Small.Light else AvatarIcons.Presence.Away.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Awayoof.Small.Dark else AvatarIcons.Presence.Away.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size24 -> Icon(
|
||||
AvatarSize.Size24 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Awayoof.Small.Light else AvatarIcons.Presence.Away.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Awayoof.Small.Dark else AvatarIcons.Presence.Away.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size32 -> Icon(
|
||||
AvatarSize.Size32 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Awayoof.Small.Light else AvatarIcons.Presence.Away.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Awayoof.Small.Dark else AvatarIcons.Presence.Away.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size40 -> Icon(
|
||||
AvatarSize.Size40 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Awayoof.Medium.Light else AvatarIcons.Presence.Away.Medium.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Awayoof.Medium.Dark else AvatarIcons.Presence.Away.Medium.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size56 -> Icon(
|
||||
AvatarSize.Size56 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Awayoof.Medium.Light else AvatarIcons.Presence.Away.Medium.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Awayoof.Medium.Dark else AvatarIcons.Presence.Away.Medium.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size72 -> Icon(
|
||||
AvatarSize.Size72 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Awayoof.Large.Light else AvatarIcons.Presence.Away.Large.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Awayoof.Large.Dark else AvatarIcons.Presence.Away.Large.Dark
|
||||
)
|
||||
|
@ -456,33 +456,33 @@ open class AvatarTokens(private val activityRingToken: ActivityRingsToken = Acti
|
|||
|
||||
AvatarStatus.DND ->
|
||||
when (avatarInfo.size) {
|
||||
AvatarSize.Size16 -> Icon()
|
||||
AvatarSize.Size20 -> Icon(
|
||||
AvatarSize.Size16 -> FluentIcon()
|
||||
AvatarSize.Size20 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Dndoof.Small.Light else AvatarIcons.Presence.Dnd.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Dndoof.Small.Dark else AvatarIcons.Presence.Dnd.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size24 -> Icon(
|
||||
AvatarSize.Size24 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Dndoof.Small.Light else AvatarIcons.Presence.Dnd.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Dndoof.Small.Dark else AvatarIcons.Presence.Dnd.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size32 -> Icon(
|
||||
AvatarSize.Size32 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Dndoof.Small.Light else AvatarIcons.Presence.Dnd.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Dndoof.Small.Dark else AvatarIcons.Presence.Dnd.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size40 -> Icon(
|
||||
AvatarSize.Size40 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Dndoof.Medium.Light else AvatarIcons.Presence.Dnd.Medium.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Dndoof.Medium.Dark else AvatarIcons.Presence.Dnd.Medium.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size56 -> Icon(
|
||||
AvatarSize.Size56 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Dndoof.Medium.Light else AvatarIcons.Presence.Dnd.Medium.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Dndoof.Medium.Dark else AvatarIcons.Presence.Dnd.Medium.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size72 -> Icon(
|
||||
AvatarSize.Size72 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Dndoof.Large.Light else AvatarIcons.Presence.Dnd.Large.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Dndoof.Large.Dark else AvatarIcons.Presence.Dnd.Large.Dark
|
||||
)
|
||||
|
@ -490,33 +490,33 @@ open class AvatarTokens(private val activityRingToken: ActivityRingsToken = Acti
|
|||
|
||||
AvatarStatus.Unknown ->
|
||||
when (avatarInfo.size) {
|
||||
AvatarSize.Size16 -> Icon()
|
||||
AvatarSize.Size20 -> Icon(
|
||||
AvatarSize.Size16 -> FluentIcon()
|
||||
AvatarSize.Size20 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Light else AvatarIcons.Presence.Unknown.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Dark else AvatarIcons.Presence.Unknown.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size24 -> Icon(
|
||||
AvatarSize.Size24 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Light else AvatarIcons.Presence.Unknown.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Dark else AvatarIcons.Presence.Unknown.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size32 -> Icon(
|
||||
AvatarSize.Size32 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Light else AvatarIcons.Presence.Unknown.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Dark else AvatarIcons.Presence.Unknown.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size40 -> Icon(
|
||||
AvatarSize.Size40 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Medium.Light else AvatarIcons.Presence.Unknown.Medium.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Medium.Dark else AvatarIcons.Presence.Unknown.Medium.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size56 -> Icon(
|
||||
AvatarSize.Size56 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Medium.Light else AvatarIcons.Presence.Unknown.Medium.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Medium.Dark else AvatarIcons.Presence.Unknown.Medium.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size72 -> Icon(
|
||||
AvatarSize.Size72 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Large.Light else AvatarIcons.Presence.Unknown.Large.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Large.Dark else AvatarIcons.Presence.Unknown.Large.Dark
|
||||
)
|
||||
|
@ -524,33 +524,33 @@ open class AvatarTokens(private val activityRingToken: ActivityRingsToken = Acti
|
|||
|
||||
AvatarStatus.Blocked ->
|
||||
when (avatarInfo.size) {
|
||||
AvatarSize.Size16 -> Icon()
|
||||
AvatarSize.Size20 -> Icon(
|
||||
AvatarSize.Size16 -> FluentIcon()
|
||||
AvatarSize.Size20 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Light else AvatarIcons.Presence.Blocked.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Dark else AvatarIcons.Presence.Blocked.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size24 -> Icon(
|
||||
AvatarSize.Size24 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Light else AvatarIcons.Presence.Blocked.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Dark else AvatarIcons.Presence.Blocked.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size32 -> Icon(
|
||||
AvatarSize.Size32 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Light else AvatarIcons.Presence.Blocked.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Dark else AvatarIcons.Presence.Blocked.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size40 -> Icon(
|
||||
AvatarSize.Size40 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Medium.Light else AvatarIcons.Presence.Blocked.Medium.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Medium.Dark else AvatarIcons.Presence.Blocked.Medium.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size56 -> Icon(
|
||||
AvatarSize.Size56 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Medium.Light else AvatarIcons.Presence.Blocked.Medium.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Medium.Dark else AvatarIcons.Presence.Blocked.Medium.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size72 -> Icon(
|
||||
AvatarSize.Size72 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Large.Light else AvatarIcons.Presence.Blocked.Large.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Large.Dark else AvatarIcons.Presence.Blocked.Large.Dark
|
||||
)
|
||||
|
@ -558,33 +558,33 @@ open class AvatarTokens(private val activityRingToken: ActivityRingsToken = Acti
|
|||
|
||||
AvatarStatus.Offline ->
|
||||
when (avatarInfo.size) {
|
||||
AvatarSize.Size16 -> Icon()
|
||||
AvatarSize.Size20 -> Icon(
|
||||
AvatarSize.Size16 -> FluentIcon()
|
||||
AvatarSize.Size20 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Light else AvatarIcons.Presence.Offline.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Dark else AvatarIcons.Presence.Offline.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size24 -> Icon(
|
||||
AvatarSize.Size24 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Light else AvatarIcons.Presence.Offline.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Dark else AvatarIcons.Presence.Offline.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size32 -> Icon(
|
||||
AvatarSize.Size32 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Light else AvatarIcons.Presence.Offline.Small.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Small.Dark else AvatarIcons.Presence.Offline.Small.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size40 -> Icon(
|
||||
AvatarSize.Size40 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Medium.Light else AvatarIcons.Presence.Offline.Medium.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Medium.Dark else AvatarIcons.Presence.Offline.Medium.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size56 -> Icon(
|
||||
AvatarSize.Size56 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Medium.Light else AvatarIcons.Presence.Offline.Medium.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Medium.Dark else AvatarIcons.Presence.Offline.Medium.Dark
|
||||
)
|
||||
|
||||
AvatarSize.Size72 -> Icon(
|
||||
AvatarSize.Size72 -> FluentIcon(
|
||||
light = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Large.Light else AvatarIcons.Presence.Offline.Large.Light,
|
||||
dark = if (avatarInfo.isOOO) AvatarIcons.Presence.Oof.Large.Dark else AvatarIcons.Presence.Offline.Large.Dark
|
||||
)
|
||||
|
|
|
@ -134,8 +134,8 @@ open class SearchBarTokens : ControlToken, Parcelable {
|
|||
}
|
||||
|
||||
@Composable
|
||||
open fun padding(searchBarInfo: SearchBarInfo): PaddingValues {
|
||||
return PaddingValues(GlobalTokens.size(GlobalTokens.SizeTokens.Size80))
|
||||
open fun searchBarPadding(info: SearchBarInfo): PaddingValues {
|
||||
return PaddingValues(horizontal = GlobalTokens.size(GlobalTokens.SizeTokens.Size80))
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
@ -30,4 +30,8 @@
|
|||
<string name="fluentui_brand">Brand</string>
|
||||
<!--name of the icon -->
|
||||
<string name="fluentui_chevron">Chevron</string>
|
||||
<string name="fluentui_large">Large</string>
|
||||
<string name="fluentui_medium">Medium</string>
|
||||
<string name="fluentui_small">Small</string>
|
||||
<string name="fluentui_subtitle">Subtitle</string>
|
||||
</resources>
|
|
@ -27,7 +27,7 @@ import androidx.compose.ui.unit.DpOffset
|
|||
import com.microsoft.fluentui.theme.FluentTheme
|
||||
import com.microsoft.fluentui.theme.FluentTheme.themeMode
|
||||
import com.microsoft.fluentui.theme.token.ControlTokens
|
||||
import com.microsoft.fluentui.theme.token.Icon
|
||||
import com.microsoft.fluentui.theme.token.FluentIcon
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.AvatarInfo
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.AvatarSize
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.AvatarTokens
|
||||
|
@ -145,7 +145,7 @@ fun Avatar(
|
|||
|
||||
if (enablePresence) {
|
||||
val presenceOffset: DpOffset = getAvatarTokens().presenceOffset(getAvatarInfo())
|
||||
val image: Icon = getAvatarTokens().presenceIcon(getAvatarInfo())
|
||||
val image: FluentIcon = getAvatarTokens().presenceIcon(getAvatarInfo())
|
||||
Image(
|
||||
image.value(themeMode),
|
||||
null,
|
||||
|
|
|
@ -0,0 +1,299 @@
|
|||
package com.microsoft.fluentui.tokenized
|
||||
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.scale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.text.ExperimentalTextApi
|
||||
import androidx.compose.ui.text.PlatformTextStyle
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.microsoft.fluentui.core.R
|
||||
import com.microsoft.fluentui.icons.ListItemIcons
|
||||
import com.microsoft.fluentui.icons.SearchBarIcons
|
||||
import com.microsoft.fluentui.icons.listitemicons.Chevron
|
||||
import com.microsoft.fluentui.icons.searchbaricons.Arrowback
|
||||
import com.microsoft.fluentui.theme.FluentTheme
|
||||
import com.microsoft.fluentui.theme.FluentTheme.themeMode
|
||||
import com.microsoft.fluentui.theme.token.ControlTokens
|
||||
import com.microsoft.fluentui.theme.token.FluentIcon
|
||||
import com.microsoft.fluentui.theme.token.FluentStyle
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.AppBarInfo
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.AppBarSize
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.AppBarTokens
|
||||
|
||||
private val LocalAppBarTokens = compositionLocalOf { AppBarTokens() }
|
||||
private val LocalAppBarInfo = compositionLocalOf { AppBarInfo(FluentStyle.Neutral) }
|
||||
|
||||
/**
|
||||
* An app bar appears at the top of an app screen, below the status bar,
|
||||
* and enables navigation through a series of hierarchical screens.
|
||||
* When a new screen is displayed, a back button, often labeled with the title of
|
||||
* the previous screen, appears on the left side of the bar. Sometimes, the right side
|
||||
* of a navigation bar contains a control, like an Edit or a Done button,
|
||||
* for managing the content within the active view. In a split view,
|
||||
* a navigation bar may appear in a single pane of the split view.
|
||||
* Navigation bars are translucent, may have a background tint, and can be configured
|
||||
* to hide when the keyboard is onscreen, a gesture occurs, or a view resizes.
|
||||
*
|
||||
* @param title Title Of the current page
|
||||
* @param modifier Optional Modifier for updating appbar
|
||||
* @param appBarSize Enum to define App Bar Size. Default: [AppBarSize.Medium]
|
||||
* @param style Fluent Style of AppBar. Default: [FluentStyle.Neutral]
|
||||
* @param subTitle Subtitle to be displayed. Default: [null]
|
||||
* @param logo Composable to be placed at left of Title. Guideline is to not increase a size of 32x32. Default: [null]
|
||||
* @param searchMode Boolean to enable/disable searchMode. Default: [false]
|
||||
* @param navigationIcon Navigate Back Icon to be placed at extreme left. Default: [SearchBarIcons.Arrowback]
|
||||
* @param postTitleIcon Icon to be placed after title making the title clickable. Default: Empty [FluentIcon]
|
||||
* @param preSubtitleIcon Icon to be placed before subtitle. Default: Empty [FluentIcon]
|
||||
* @param postSubtitleIcon Icon to be placed after subtitle. Default: [ListItemIcons.Chevron]
|
||||
* @param rightAccessoryView Row Placeholder to be placed at right on AppTitle. Default: [null]
|
||||
* @param searchBar Composable to be placed as searchbar below appTitle. Default: [null]
|
||||
* @param bottomBar Composable to Be placed below appTitle. Displayed if searchbar is not provided or when in searchmode. Default: [null]
|
||||
* @param appTitleDelta Ratio of opening of appTitle. Used for Shychrome and other animations. Default: [1.0F]
|
||||
* @param accessoryDelta Ratio of opening of accessory View. Used for Shychrome and other animations. Default: [1.0F]
|
||||
* @param appBarTokens Optional Tokens for App Bar to customize it. Default: [null]
|
||||
*/
|
||||
@OptIn(ExperimentalTextApi::class)
|
||||
@Composable
|
||||
fun AppBar(
|
||||
title: String,
|
||||
modifier: Modifier = Modifier,
|
||||
appBarSize: AppBarSize = AppBarSize.Medium,
|
||||
style: FluentStyle = FluentStyle.Neutral,
|
||||
subTitle: String? = null,
|
||||
logo: @Composable (() -> Unit)? = null,
|
||||
searchMode: Boolean = false,
|
||||
navigationIcon: FluentIcon = FluentIcon(SearchBarIcons.Arrowback),
|
||||
postTitleIcon: FluentIcon = FluentIcon(),
|
||||
preSubtitleIcon: FluentIcon = FluentIcon(),
|
||||
postSubtitleIcon: FluentIcon = FluentIcon(
|
||||
ListItemIcons.Chevron,
|
||||
contentDescription = LocalContext.current.resources.getString(R.string.fluentui_chevron)
|
||||
),
|
||||
rightAccessoryView: @Composable (RowScope.() -> Unit)? = null,
|
||||
searchBar: @Composable (RowScope.() -> Unit)? = null,
|
||||
bottomBar: @Composable (RowScope.() -> Unit)? = null,
|
||||
appTitleDelta: Float = 1.0F,
|
||||
accessoryDelta: Float = 1.0F,
|
||||
appBarTokens: AppBarTokens? = null
|
||||
) {
|
||||
val token = appBarTokens
|
||||
?: FluentTheme.controlTokens.tokens[ControlTokens.ControlType.AppBar] as AppBarTokens
|
||||
|
||||
CompositionLocalProvider(
|
||||
LocalAppBarTokens provides token,
|
||||
LocalAppBarInfo provides AppBarInfo(style, appBarSize)
|
||||
) {
|
||||
Surface(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(getAppBarTokens().backgroundColor(getAppBarInfo()))
|
||||
) {
|
||||
Row(
|
||||
Modifier
|
||||
.requiredHeight(56.dp * appTitleDelta)
|
||||
.animateContentSize()
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp)
|
||||
.scale(scaleX = 1.0F, scaleY = appTitleDelta)
|
||||
.alpha(if (appTitleDelta != 1.0F) appTitleDelta / 3 else 1.0F),
|
||||
horizontalArrangement = Arrangement.Start,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
if (appBarSize != AppBarSize.Large && navigationIcon.isIconAvailable()) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.then(
|
||||
if (navigationIcon.onClick != null) {
|
||||
Modifier.clickable(
|
||||
role = Role.Button,
|
||||
onClick = navigationIcon.onClick!!
|
||||
)
|
||||
} else
|
||||
Modifier
|
||||
), contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
navigationIcon.value(),
|
||||
navigationIcon.contentDescription,
|
||||
modifier = Modifier
|
||||
.padding(getAppBarTokens().navigationIconPadding(getAppBarInfo()))
|
||||
.size(getAppBarTokens().leftIconSize(getAppBarInfo())),
|
||||
tint = getAppBarTokens().navigationIconColor(getAppBarInfo())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (appBarSize != AppBarSize.Medium)
|
||||
logo?.invoke()
|
||||
|
||||
val titleFontInfo = getAppBarTokens().titleTypography(getAppBarInfo())
|
||||
val subtitleFontInfo =
|
||||
getAppBarTokens().subtitleTypography(getAppBarInfo())
|
||||
|
||||
if (appBarSize != AppBarSize.Large && !subTitle.isNullOrBlank()) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1F)
|
||||
.padding(getAppBarTokens().textPadding(getAppBarInfo()))
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.then(
|
||||
if (postTitleIcon.onClick != null && appBarSize == AppBarSize.Small)
|
||||
Modifier.clickable(onClick = postTitleIcon.onClick!!)
|
||||
else
|
||||
Modifier
|
||||
), verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
style = TextStyle(
|
||||
color = getAppBarTokens().titleTextColor(getAppBarInfo()),
|
||||
fontSize = titleFontInfo.fontSize.size,
|
||||
lineHeight = titleFontInfo.fontSize.lineHeight,
|
||||
fontWeight = titleFontInfo.weight,
|
||||
platformStyle = PlatformTextStyle(
|
||||
includeFontPadding = false
|
||||
)
|
||||
),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
if (postTitleIcon.isIconAvailable() && appBarSize == AppBarSize.Small)
|
||||
Icon(
|
||||
postTitleIcon.value(themeMode),
|
||||
postTitleIcon.contentDescription,
|
||||
modifier = Modifier
|
||||
.size(getAppBarTokens().titleIconSize(getAppBarInfo())),
|
||||
tint = getAppBarTokens().titleIconColor(getAppBarInfo())
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.then(
|
||||
if (postSubtitleIcon.onClick != null)
|
||||
Modifier.clickable(onClick = postSubtitleIcon.onClick!!)
|
||||
else
|
||||
Modifier
|
||||
), verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
if (preSubtitleIcon.isIconAvailable())
|
||||
Icon(
|
||||
preSubtitleIcon.value(themeMode),
|
||||
preSubtitleIcon.contentDescription,
|
||||
modifier = Modifier
|
||||
.size(
|
||||
getAppBarTokens().subtitleIconSize(
|
||||
getAppBarInfo()
|
||||
)
|
||||
),
|
||||
tint = getAppBarTokens().subtitleIconColor(getAppBarInfo())
|
||||
)
|
||||
Text(
|
||||
subTitle,
|
||||
style = TextStyle(
|
||||
color = getAppBarTokens().subtitleTextColor(
|
||||
getAppBarInfo()
|
||||
),
|
||||
fontSize = subtitleFontInfo.fontSize.size,
|
||||
lineHeight = subtitleFontInfo.fontSize.lineHeight,
|
||||
fontWeight = subtitleFontInfo.weight
|
||||
),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
if (postSubtitleIcon.isIconAvailable())
|
||||
Icon(
|
||||
postSubtitleIcon.value(themeMode),
|
||||
postSubtitleIcon.contentDescription,
|
||||
modifier = Modifier
|
||||
.size(
|
||||
getAppBarTokens().subtitleIconSize(
|
||||
getAppBarInfo()
|
||||
)
|
||||
),
|
||||
tint = getAppBarTokens().subtitleIconColor(getAppBarInfo())
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text(
|
||||
text = title,
|
||||
modifier = Modifier
|
||||
.padding(getAppBarTokens().textPadding(getAppBarInfo()))
|
||||
.weight(1F),
|
||||
style = TextStyle(
|
||||
color = getAppBarTokens().titleTextColor(getAppBarInfo()),
|
||||
fontSize = titleFontInfo.fontSize.size,
|
||||
lineHeight = titleFontInfo.fontSize.lineHeight,
|
||||
fontWeight = titleFontInfo.weight,
|
||||
platformStyle = PlatformTextStyle(
|
||||
includeFontPadding = false
|
||||
)
|
||||
),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
|
||||
if (rightAccessoryView != null) {
|
||||
rightAccessoryView()
|
||||
}
|
||||
}
|
||||
|
||||
if (searchBar != null) {
|
||||
Row(
|
||||
modifier
|
||||
.animateContentSize()
|
||||
.fillMaxWidth()
|
||||
.then(if (!searchMode) Modifier.height(56.dp * accessoryDelta) else Modifier)
|
||||
.padding(vertical = 8.dp),
|
||||
horizontalArrangement = Arrangement.Center
|
||||
) {
|
||||
searchBar()
|
||||
}
|
||||
}
|
||||
if (bottomBar != null && (searchMode || searchBar == null)) {
|
||||
Row(
|
||||
Modifier
|
||||
.animateContentSize()
|
||||
.fillMaxWidth()
|
||||
.then(if (!searchMode) Modifier.height(48.dp * accessoryDelta) else Modifier)
|
||||
.padding(vertical = 8.dp)
|
||||
) {
|
||||
bottomBar()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getAppBarTokens(): AppBarTokens {
|
||||
return LocalAppBarTokens.current
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getAppBarInfo(): AppBarInfo {
|
||||
return LocalAppBarInfo.current
|
||||
}
|
|
@ -64,9 +64,11 @@ fun SearchBar(
|
|||
keyboardOptions: KeyboardOptions = KeyboardOptions(),
|
||||
keyboardActions: KeyboardActions = KeyboardActions(),
|
||||
searchHint: String = LocalContext.current.resources.getString(R.string.fluentui_search),
|
||||
focusByDefault: Boolean = false,
|
||||
selectedPerson: Person? = null,
|
||||
personaChipOnClick: (() -> Unit)? = null,
|
||||
microphoneCallback: (() -> Unit)? = null,
|
||||
navigationIconCallback: (() -> Unit)? = null,
|
||||
rightAccessoryIcon: ImageVector? = null,
|
||||
rightAccessoryIconDescription: String = "",
|
||||
rightAccessoryViewOnClick: (() -> Unit)? = null,
|
||||
|
@ -93,279 +95,296 @@ fun SearchBar(
|
|||
val scope = rememberCoroutineScope()
|
||||
|
||||
Row(
|
||||
modifier
|
||||
.requiredHeight(getSearchBarTokens().height(getSearchBarInfo()))
|
||||
.fillMaxWidth()
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.background(
|
||||
getSearchBarTokens().inputBackgroundColor(getSearchBarInfo()),
|
||||
RoundedCornerShape(8.dp)
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
modifier = modifier
|
||||
.background(getSearchBarTokens().backgroundColor(getSearchBarInfo()))
|
||||
.padding(getSearchBarTokens().searchBarPadding(getSearchBarInfo()))
|
||||
) {
|
||||
//Left Section
|
||||
AnimatedContent(searchHasFocus) {
|
||||
var onClick: (() -> Unit)? = null
|
||||
var icon: ImageVector? = null
|
||||
var contentDescription: String? = null
|
||||
Row(
|
||||
Modifier
|
||||
.requiredHeight(getSearchBarTokens().height(getSearchBarInfo()))
|
||||
.fillMaxWidth()
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.background(
|
||||
getSearchBarTokens().inputBackgroundColor(getSearchBarInfo()),
|
||||
RoundedCornerShape(8.dp)
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
//Left Section
|
||||
AnimatedContent(searchHasFocus) {
|
||||
var onClick: (() -> Unit)? = null
|
||||
var icon: ImageVector? = null
|
||||
var contentDescription: String? = null
|
||||
|
||||
when (it) {
|
||||
true -> {
|
||||
onClick = {
|
||||
scope.launch {
|
||||
queryText = ""
|
||||
when (it) {
|
||||
true -> {
|
||||
onClick = {
|
||||
scope.launch {
|
||||
queryText = ""
|
||||
selectedPerson = null
|
||||
|
||||
searching = true
|
||||
onValueChange(queryText, selectedPerson)
|
||||
searching = false
|
||||
|
||||
focusManager.clearFocus()
|
||||
searchHasFocus = false
|
||||
}
|
||||
navigationIconCallback?.invoke()
|
||||
}
|
||||
icon = SearchBarIcons.Arrowback
|
||||
contentDescription =
|
||||
LocalContext.current.resources.getString(R.string.fluentui_back)
|
||||
}
|
||||
false -> {
|
||||
onClick = {
|
||||
scope.launch {
|
||||
focusRequester.requestFocus()
|
||||
}
|
||||
}
|
||||
icon = SearchBarIcons.Search
|
||||
contentDescription =
|
||||
LocalContext.current.resources.getString(R.string.fluentui_search)
|
||||
}
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(44.dp, 40.dp)
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(),
|
||||
enabled = enabled,
|
||||
onClick = onClick,
|
||||
role = Role.Button
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
icon,
|
||||
contentDescription,
|
||||
modifier = Modifier
|
||||
.size(getSearchBarTokens().leftIconSize(getSearchBarInfo())),
|
||||
tint = getSearchBarTokens().leftIconColor(getSearchBarInfo())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//Center Section
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.height(24.dp)
|
||||
.weight(1F)
|
||||
.onKeyEvent {
|
||||
if (it.key == Key.Backspace) {
|
||||
scope.launch {
|
||||
if (personaChipSelected) {
|
||||
selectedPerson = null
|
||||
personaChipSelected = false
|
||||
|
||||
searching = true
|
||||
onValueChange(queryText, selectedPerson)
|
||||
searching = false
|
||||
} else {
|
||||
personaChipSelected = true
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
},
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
LaunchedEffect(selectedPerson) {
|
||||
queryText = ""
|
||||
if (personaChipSelected)
|
||||
personaChipSelected = false
|
||||
|
||||
searching = true
|
||||
onValueChange(queryText, selectedPerson)
|
||||
searching = false
|
||||
}
|
||||
|
||||
if (selectedPerson != null) {
|
||||
SearchBarPersonaChip(
|
||||
person = selectedPerson!!,
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
style = style,
|
||||
enabled = enabled,
|
||||
selected = personaChipSelected,
|
||||
onClick = {
|
||||
personaChipSelected = !personaChipSelected
|
||||
personaChipOnClick?.invoke()
|
||||
},
|
||||
onCloseClick = {
|
||||
selectedPerson = null
|
||||
|
||||
searching = true
|
||||
onValueChange(queryText, selectedPerson)
|
||||
searching = false
|
||||
|
||||
focusManager.clearFocus()
|
||||
searchHasFocus = false
|
||||
}
|
||||
}
|
||||
icon = SearchBarIcons.Arrowback
|
||||
contentDescription =
|
||||
LocalContext.current.resources.getString(R.string.fluentui_back)
|
||||
)
|
||||
}
|
||||
false -> {
|
||||
onClick = {
|
||||
|
||||
BasicTextField(
|
||||
value = queryText,
|
||||
onValueChange = {
|
||||
scope.launch {
|
||||
focusRequester.requestFocus()
|
||||
queryText = it
|
||||
personaChipSelected = false
|
||||
|
||||
searching = true
|
||||
onValueChange(queryText, selectedPerson)
|
||||
searching = false
|
||||
}
|
||||
},
|
||||
singleLine = true,
|
||||
keyboardOptions = keyboardOptions,
|
||||
keyboardActions = keyboardActions,
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.weight(1F)
|
||||
.focusRequester(focusRequester)
|
||||
.onFocusChanged { focusState ->
|
||||
when {
|
||||
focusState.isFocused ->
|
||||
searchHasFocus = true
|
||||
}
|
||||
},
|
||||
textStyle = TextStyle(
|
||||
fontSize = getSearchBarTokens().typography(getSearchBarInfo()).fontSize.size,
|
||||
lineHeight = getSearchBarTokens().typography(getSearchBarInfo()).fontSize.size,
|
||||
color = getSearchBarTokens().textColor(getSearchBarInfo())
|
||||
),
|
||||
decorationBox = @Composable { innerTextField ->
|
||||
Box(
|
||||
Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.CenterStart
|
||||
) {
|
||||
if (queryText.isEmpty()) {
|
||||
Text(
|
||||
searchHint,
|
||||
style = TextStyle(
|
||||
fontSize = getSearchBarTokens().typography(
|
||||
getSearchBarInfo()
|
||||
).fontSize.size,
|
||||
lineHeight = getSearchBarTokens().typography(
|
||||
getSearchBarInfo()
|
||||
).fontSize.size,
|
||||
color = getSearchBarTokens().textColor(getSearchBarInfo()),
|
||||
)
|
||||
)
|
||||
}
|
||||
innerTextField()
|
||||
}
|
||||
}
|
||||
icon = SearchBarIcons.Search
|
||||
contentDescription =
|
||||
LocalContext.current.resources.getString(R.string.fluentui_search)
|
||||
}
|
||||
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(44.dp, 40.dp)
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(),
|
||||
enabled = enabled,
|
||||
onClick = onClick,
|
||||
role = Role.Button
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
icon,
|
||||
contentDescription,
|
||||
modifier = Modifier
|
||||
.size(getSearchBarTokens().leftIconSize(getSearchBarInfo())),
|
||||
tint = getSearchBarTokens().leftIconColor(getSearchBarInfo())
|
||||
)
|
||||
}
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
if (focusByDefault)
|
||||
focusRequester.requestFocus()
|
||||
}
|
||||
|
||||
//Center Section
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.height(24.dp)
|
||||
.weight(1F)
|
||||
.onKeyEvent {
|
||||
if (it.key == Key.Backspace) {
|
||||
scope.launch {
|
||||
if (personaChipSelected) {
|
||||
selectedPerson = null
|
||||
personaChipSelected = false
|
||||
|
||||
searching = true
|
||||
onValueChange(queryText, selectedPerson)
|
||||
searching = false
|
||||
} else {
|
||||
personaChipSelected = true
|
||||
//Right Section
|
||||
AnimatedContent((queryText.isBlank() && selectedPerson == null)) {
|
||||
when (it) {
|
||||
true ->
|
||||
if (microphoneCallback != null) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(44.dp, 40.dp)
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(),
|
||||
enabled = enabled,
|
||||
onClick = microphoneCallback,
|
||||
role = Role.Button
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
SearchBarIcons.Microphone,
|
||||
LocalContext.current.resources.getString(R.string.fluentui_microphone),
|
||||
modifier = Modifier
|
||||
.size(
|
||||
getSearchBarTokens().rightIconSize(
|
||||
getSearchBarInfo()
|
||||
)
|
||||
),
|
||||
tint = getSearchBarTokens().rightIconColor(getSearchBarInfo())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
},
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
LaunchedEffect(selectedPerson) {
|
||||
queryText = ""
|
||||
if (personaChipSelected)
|
||||
personaChipSelected = false
|
||||
|
||||
searching = true
|
||||
onValueChange(queryText, selectedPerson)
|
||||
searching = false
|
||||
}
|
||||
|
||||
if (selectedPerson != null) {
|
||||
SearchBarPersonaChip(
|
||||
person = selectedPerson!!,
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
style = style,
|
||||
enabled = enabled,
|
||||
selected = personaChipSelected,
|
||||
onClick = {
|
||||
personaChipSelected = !personaChipSelected
|
||||
personaChipOnClick?.invoke()
|
||||
},
|
||||
onCloseClick = {
|
||||
selectedPerson = null
|
||||
|
||||
searching = true
|
||||
onValueChange(queryText, selectedPerson)
|
||||
searching = false
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
BasicTextField(
|
||||
value = queryText,
|
||||
onValueChange = {
|
||||
scope.launch {
|
||||
queryText = it
|
||||
personaChipSelected = false
|
||||
|
||||
searching = true
|
||||
onValueChange(queryText, selectedPerson)
|
||||
searching = false
|
||||
}
|
||||
},
|
||||
singleLine = true,
|
||||
keyboardOptions = keyboardOptions,
|
||||
keyboardActions = keyboardActions,
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.weight(1F)
|
||||
.focusRequester(focusRequester)
|
||||
.onFocusChanged { focusState ->
|
||||
when {
|
||||
focusState.isFocused ->
|
||||
searchHasFocus = true
|
||||
}
|
||||
},
|
||||
textStyle = TextStyle(
|
||||
fontSize = getSearchBarTokens().typography(getSearchBarInfo()).fontSize.size,
|
||||
lineHeight = getSearchBarTokens().typography(getSearchBarInfo()).fontSize.size,
|
||||
color = getSearchBarTokens().textColor(getSearchBarInfo())
|
||||
),
|
||||
decorationBox = @Composable { innerTextField ->
|
||||
Box(
|
||||
Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.CenterStart
|
||||
) {
|
||||
if (queryText.isEmpty()) {
|
||||
Text(
|
||||
searchHint,
|
||||
style = TextStyle(
|
||||
fontSize = getSearchBarTokens().typography(getSearchBarInfo()).fontSize.size,
|
||||
lineHeight = getSearchBarTokens().typography(
|
||||
getSearchBarInfo()
|
||||
).fontSize.size,
|
||||
color = getSearchBarTokens().textColor(getSearchBarInfo()),
|
||||
)
|
||||
)
|
||||
}
|
||||
innerTextField()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
//Right Section
|
||||
AnimatedContent((queryText.isBlank() && selectedPerson == null)) {
|
||||
when (it) {
|
||||
true ->
|
||||
if (microphoneCallback != null) {
|
||||
false ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(44.dp, 40.dp)
|
||||
.padding(
|
||||
getSearchBarTokens().progressIndicatorRightPadding(
|
||||
getSearchBarInfo()
|
||||
)
|
||||
)
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(),
|
||||
enabled = enabled,
|
||||
onClick = microphoneCallback,
|
||||
onClick = {
|
||||
scope.launch {
|
||||
queryText = ""
|
||||
selectedPerson = null
|
||||
|
||||
searching = true
|
||||
onValueChange(queryText, selectedPerson)
|
||||
searching = false
|
||||
}
|
||||
},
|
||||
role = Role.Button
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (searching)
|
||||
CircularProgressIndicator(
|
||||
size = getSearchBarTokens().circularProgressIndicatorSize(
|
||||
getSearchBarInfo()
|
||||
)
|
||||
)
|
||||
Icon(
|
||||
SearchBarIcons.Microphone,
|
||||
LocalContext.current.resources.getString(R.string.fluentui_microphone),
|
||||
SearchBarIcons.Dismisscircle,
|
||||
LocalContext.current.resources.getString(R.string.fluentui_clear_text),
|
||||
modifier = Modifier
|
||||
.size(getSearchBarTokens().rightIconSize(getSearchBarInfo())),
|
||||
tint = getSearchBarTokens().rightIconColor(getSearchBarInfo())
|
||||
)
|
||||
}
|
||||
}
|
||||
false ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(44.dp, 40.dp)
|
||||
.padding(
|
||||
getSearchBarTokens().progressIndicatorRightPadding(
|
||||
getSearchBarInfo()
|
||||
)
|
||||
)
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(),
|
||||
enabled = enabled,
|
||||
onClick = {
|
||||
scope.launch {
|
||||
queryText = ""
|
||||
selectedPerson = null
|
||||
|
||||
searching = true
|
||||
onValueChange(queryText, selectedPerson)
|
||||
searching = false
|
||||
}
|
||||
},
|
||||
role = Role.Button
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (searching)
|
||||
CircularProgressIndicator(
|
||||
size = getSearchBarTokens().circularProgressIndicatorSize(
|
||||
getSearchBarInfo()
|
||||
)
|
||||
)
|
||||
Icon(
|
||||
SearchBarIcons.Dismisscircle,
|
||||
LocalContext.current.resources.getString(R.string.fluentui_clear_text),
|
||||
modifier = Modifier
|
||||
.size(getSearchBarTokens().rightIconSize(getSearchBarInfo())),
|
||||
tint = getSearchBarTokens().rightIconColor(getSearchBarInfo())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rightAccessoryIcon != null && rightAccessoryViewOnClick != null) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.size(44.dp, 40.dp)
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(),
|
||||
enabled = enabled,
|
||||
onClick = rightAccessoryViewOnClick,
|
||||
role = Role.Button
|
||||
),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
rightAccessoryIcon,
|
||||
rightAccessoryIconDescription,
|
||||
if (rightAccessoryIcon != null && rightAccessoryViewOnClick != null) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.size(getSearchBarTokens().rightIconSize(getSearchBarInfo())),
|
||||
tint = getSearchBarTokens().rightIconColor(getSearchBarInfo())
|
||||
)
|
||||
Icon(
|
||||
ListItemIcons.Chevron,
|
||||
LocalContext.current.resources.getString(R.string.fluentui_chevron),
|
||||
Modifier.rotate(90F)
|
||||
)
|
||||
.size(44.dp, 40.dp)
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(),
|
||||
enabled = enabled,
|
||||
onClick = rightAccessoryViewOnClick,
|
||||
role = Role.Button
|
||||
),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
rightAccessoryIcon,
|
||||
rightAccessoryIconDescription,
|
||||
modifier = Modifier
|
||||
.size(getSearchBarTokens().rightIconSize(getSearchBarInfo())),
|
||||
tint = getSearchBarTokens().rightIconColor(getSearchBarInfo())
|
||||
)
|
||||
Icon(
|
||||
ListItemIcons.Chevron,
|
||||
LocalContext.current.resources.getString(R.string.fluentui_chevron),
|
||||
Modifier.rotate(90F)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче