Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
0999986
Add navigation bar tokens
paulinea Jul 10, 2025
d4b507d
Add OUDS navigation bar component
paulinea Jul 10, 2025
2ca4df5
Add navigation bar component in demo app
paulinea Jul 10, 2025
267df2d
Add snapshots
paulinea Jul 10, 2025
42d2af8
Replace preview state by preview enum entry
paulinea Jul 10, 2025
6e812bd
Allow badges on navigation bar items
paulinea Jul 11, 2025
f736c32
Fix after rebase
paulinea Oct 13, 2025
c0088f9
Fix after rebase
paulinea Oct 22, 2025
aa6c375
Update navigation bar component to the last version with new tokens
paulinea Oct 24, 2025
21b020b
Implement blurred navigation bar with Haze library
paulinea Nov 3, 2025
6effe2b
Add navigation bar screenshots
paulinea Nov 3, 2025
48d6ffb
Update navigation bar illustration
paulinea Nov 4, 2025
fdb0976
Add badge customization in navigation bar
paulinea Nov 4, 2025
d8ceaf7
Support navigation bar badge accessibility
paulinea Nov 5, 2025
6ea19a7
Add navigation bar tests
paulinea Nov 5, 2025
d901a4e
Document how to implement a translucent blurred navigation bar
paulinea Nov 5, 2025
7529439
Remove useless tokens
paulinea Nov 5, 2025
60c00e9
Add missing tokens
paulinea Nov 5, 2025
4910129
Add translucent parameter to OudsNavigationBar
paulinea Nov 5, 2025
f4bfff3
Add border around navigation bar badge
paulinea Nov 5, 2025
ec63310
Update navigation bar snapshots
paulinea Nov 5, 2025
6cd3a57
Update navigation bar illustration by adding horizontal padding
paulinea Nov 5, 2025
b449f85
Display the opaque version of the bar before Android 13
paulinea Nov 6, 2025
c9385c1
Fix after rebase
paulinea Nov 10, 2025
ee21996
Remove disabled state for OudsNavigationBarItem
paulinea Nov 10, 2025
62e1a0b
Update snapshots
paulinea Nov 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions NOTICE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ app/src/alpha/res/drawable-v24/ic_launcher_background.xml
app/src/alpha/res/drawable/ic_launcher_foreground.xml
app/src/beta/res/drawable-v24/ic_launcher_background.xml
app/src/beta/res/drawable/ic_launcher_foreground.xml
app/src/main/res/drawable/ic_avatar.xml
app/src/main/res/drawable/ic_border.xml
app/src/main/res/drawable/ic_call.xml
app/src/main/res/drawable/ic_chevron_down.xml
Expand All @@ -22,11 +23,15 @@ app/src/main/res/drawable/ic_dimension.xml
app/src/main/res/drawable/ic_filters.xml
app/src/main/res/drawable/ic_filter_effects.xml
app/src/main/res/drawable/ic_heart.xml
app/src/main/res/drawable/ic_home.xml
app/src/main/res/drawable/ic_info.xml
app/src/main/res/drawable/ic_layers.xml
app/src/main/res/drawable/ic_menu_grid.xml
app/src/main/res/drawable/ic_notification_alert.xml
app/src/main/res/drawable/ic_palette.xml
app/src/main/res/drawable/ic_settings.xml
app/src/main/res/drawable/ic_sms_message.xml
app/src/main/res/drawable/ic_shop_store.xml
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A detail, ic_shop_store should be placed before ic_sms_message.

app/src/main/res/drawable/ic_solar_palette.xml
app/src/main/res/drawable/ic_typography.xml
app/src/main/res/drawable/ic_ui_dark_mode.xml
Expand Down
1 change: 1 addition & 0 deletions THIRD_PARTY.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ requirements of the relevant license of the Third Party software they are using.
|-----------------------------------------------------------------------|-----------------------|--------------------|
| [Firebase](https://github.com/firebase/firebase-android-sdk) | © 2019 Google LLC | Apache License 2.0 |
| [Git Changelog Lib](https://github.com/tomasbjerre/git-changelog-lib) | | Apache License 2.0 |
| [Haze](https://github.com/chrisbanes/haze) | © 2024 Chris Banes | Apache License 2.0 |
| [OUDS Android](https://github.com/Orange-OpenSource/ouds-android) | © 2024-2025 Orange SA | MIT License |
| [ZXing](https://github.com/zxing/zxing) | © ZXing authors | Apache License 2.0 |
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ dependencies {
implementation(libs.androidx.navigation.compose)
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.crashlytics)
implementation(libs.haze)
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
implementation(libs.kotlin.reflect)
Expand Down
48 changes: 19 additions & 29 deletions app/src/main/java/com/orange/ouds/app/ui/BottomBar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,56 +31,46 @@ import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.windowInsetsBottomHeight
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.PreviewLightDark
import com.orange.ouds.app.R
import com.orange.ouds.core.component.OudsNavigationBar
import com.orange.ouds.core.component.OudsNavigationBarItem
import com.orange.ouds.core.component.OudsNavigationBarItemIcon
import com.orange.ouds.core.theme.OudsTheme
import com.orange.ouds.core.utilities.OudsPreview

@Composable
fun BottomBar(currentRoute: String, navigateToRoute: (String) -> Unit, visible: Boolean = true) {
fun BottomBar(currentRoute: String, navigateToRoute: (String) -> Unit, modifier: Modifier = Modifier, visible: Boolean = true) {
Column(modifier = Modifier.windowInsetsPadding(WindowInsets.displayCutout.only(WindowInsetsSides.Horizontal))) {
val navigationBarBackgroundColor = OudsTheme.colorScheme.background.secondary //TODO Temporary color. Waiting for Material colors from Maxime.
val systemNavigationBackgroundColor = OudsTheme.colorScheme.background.secondary //TODO Temporary color. Waiting for Material colors from Maxime.
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(100)),
exit = fadeOut(tween(100))
) {
val items = BottomBarItem.entries.toTypedArray()
NavigationBar(
modifier = Modifier.consumeWindowInsets(WindowInsets.navigationBars),
containerColor = navigationBarBackgroundColor,
content = {
items.forEach { item ->
NavigationBarItem(
selected = currentRoute == item.route,
icon = {
Icon(painterResource(item.iconRes), null)
},
label = {
Text(
text = stringResource(item.titleRes),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
},
onClick = { navigateToRoute(item.route) }
)
}
OudsNavigationBar(
modifier = modifier.consumeWindowInsets(WindowInsets.navigationBars),
translucent = true
) {
items.forEach { item ->
OudsNavigationBarItem(
modifier = Modifier.weight(1f),
selected = currentRoute == item.route,
icon = OudsNavigationBarItemIcon(painter = painterResource(item.iconRes), ""),
label = stringResource(item.titleRes),
onClick = { navigateToRoute(item.route) }
)
}
)
}
}
val systemNavigationBarBackgroundColor by animateColorAsState(if (visible) navigationBarBackgroundColor else MaterialTheme.colorScheme.surface)
val systemNavigationBarBackgroundColor by animateColorAsState(if (visible) systemNavigationBackgroundColor else MaterialTheme.colorScheme.surface)
Spacer(
modifier = Modifier
.background(systemNavigationBarBackgroundColor)
Expand Down
16 changes: 15 additions & 1 deletion app/src/main/java/com/orange/ouds/app/ui/MainScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatDelegate
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.displayCutout
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.union
import androidx.compose.material3.Scaffold
Expand All @@ -37,6 +39,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
import androidx.core.content.getSystemService
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.navigation.compose.NavHost
Expand All @@ -46,6 +49,10 @@ import com.orange.ouds.core.utilities.OudsPreview
import com.orange.ouds.foundation.extensions.orElse
import com.orange.ouds.theme.OudsThemeSettings
import com.orange.ouds.theme.orange.ORANGE_THEME_NAME
import dev.chrisbanes.haze.HazeStyle
import dev.chrisbanes.haze.hazeEffect
import dev.chrisbanes.haze.hazeSource
import dev.chrisbanes.haze.rememberHazeState

@Composable
fun MainScreen(mainViewModel: MainViewModel = hiltViewModel()) {
Expand Down Expand Up @@ -85,6 +92,8 @@ fun MainScreen(
var changeThemeDialogVisible by rememberSaveable { mutableStateOf(false) }
var changeThemeSettingsDialogVisible by rememberSaveable { mutableStateOf(false) }

val hazeState = rememberHazeState(blurEnabled = true)

OudsTheme(
theme = mainState.themeState.currentTheme,
darkThemeEnabled = isSystemInDarkTheme,
Expand All @@ -107,6 +116,10 @@ fun MainScreen(
},
bottomBar = {
BottomBar(
modifier = Modifier.hazeEffect(
state = hazeState,
style = HazeStyle(tint = null, blurRadius = OudsTheme.navigationBarBlur.dp)
),
currentRoute = mainState.navigationState.currentRoute.orEmpty(),
navigateToRoute = { route ->
mainState.navigationState.navigateToBottomBarRoute(route)
Expand All @@ -120,7 +133,8 @@ fun MainScreen(
startDestination = BottomBarItem.Tokens.route,
modifier = Modifier
.consumeWindowInsets(innerPadding)
.padding(innerPadding)
.padding(top = innerPadding.calculateTopPadding(), bottom = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding())
.hazeSource(state = hazeState)
) {
appNavGraph(mainState)
}
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/com/orange/ouds/app/ui/about/AboutScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import androidx.annotation.StringRes
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ListItem
Expand All @@ -41,6 +43,7 @@ import com.orange.ouds.app.BuildConfig
import com.orange.ouds.app.R
import com.orange.ouds.app.ui.utilities.composable.Screen
import com.orange.ouds.app.ui.utilities.listItemHorizontalPadding
import com.orange.ouds.core.component.OudsNavigationBarHeight
import com.orange.ouds.core.theme.OudsTheme
import com.orange.ouds.core.utilities.OudsPreview

Expand Down Expand Up @@ -122,6 +125,9 @@ fun AboutScreen(onMenuItemClick: (id: Int) -> Unit) {
headlineContent = { Text(text = stringResource(id = item.labelRes), style = OudsTheme.typography.body.strong.large) }
)
}
item {
Spacer(modifier = Modifier.height(OudsNavigationBarHeight))
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.orange.ouds.app.ui.components.chip.SuggestionChipDemoScreen
import com.orange.ouds.app.ui.components.coloredbackground.ColoredBackgroundDemoScreen
import com.orange.ouds.app.ui.components.divider.DividerDemoScreen
import com.orange.ouds.app.ui.components.link.LinkDemoScreen
import com.orange.ouds.app.ui.components.navigationbar.NavigationBarDemoScreen
import com.orange.ouds.app.ui.components.radiobutton.RadioButtonDemoScreen
import com.orange.ouds.app.ui.components.radiobutton.RadioButtonItemDemoScreen
import com.orange.ouds.app.ui.components.switch.SwitchDemoScreen
Expand Down Expand Up @@ -100,6 +101,13 @@ sealed class Component(
demoScreen = { LinkDemoScreen() }
)

data object NavigationBar : Component(
R.string.app_components_navigationBar_label,
R.string.app_components_navigationBar_description_text,
{ NavigationBarIllustration() },
demoScreen = { NavigationBarDemoScreen() }
)

data object RadioButton : Component(
R.string.app_components_radioButton_label,
R.string.app_components_radioButton_description_text,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.dp
Expand All @@ -40,6 +41,9 @@ import com.orange.ouds.core.component.OudsFilterChip
import com.orange.ouds.core.component.OudsHorizontalDivider
import com.orange.ouds.core.component.OudsLink
import com.orange.ouds.core.component.OudsLinkArrow
import com.orange.ouds.core.component.OudsNavigationBar
import com.orange.ouds.core.component.OudsNavigationBarItem
import com.orange.ouds.core.component.OudsNavigationBarItemIcon
import com.orange.ouds.core.component.OudsRadioButton
import com.orange.ouds.core.component.OudsSwitch
import com.orange.ouds.core.component.OudsTag
Expand Down Expand Up @@ -127,6 +131,24 @@ fun LinkIllustration() = ComponentIllustration {
)
}

@Composable
fun NavigationBarIllustration() = ComponentIllustration {
OudsNavigationBar(modifier = Modifier.padding(horizontal = 12.dp)) {
for (index in 0..2) {
OudsNavigationBarItem(
modifier = Modifier.weight(1f),
selected = index == 0,
onClick = {},
icon = OudsNavigationBarItemIcon(
painter = painterResource(R.drawable.ic_heart),
contentDescription = ""
),
label = stringResource(R.string.app_components_common_label_label)
)
}
}
}

@Composable
fun RadioButtonIllustration() = ComponentIllustration {
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ package com.orange.ouds.app.ui.components

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
Expand All @@ -24,6 +26,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewLightDark
import com.orange.ouds.app.ui.utilities.composable.LargeCard
import com.orange.ouds.app.ui.utilities.composable.Screen
import com.orange.ouds.core.component.OudsNavigationBarHeight
import com.orange.ouds.core.theme.OudsTheme
import com.orange.ouds.core.utilities.OudsPreview

Expand Down Expand Up @@ -52,6 +55,7 @@ private fun ComponentsScreen(components: List<Component>, onComponentClick: (Lon
onClick = { onComponentClick(component.id) }
)
}
Spacer(modifier = Modifier.height(OudsNavigationBarHeight))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if there is a more conventional way of doing this with the window insets. I did not take time to look at this but I can investigate that point (I need to read the documentation again because I forgot everything about window insets 😅).

}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ private fun BadgeDemoContent(state: BadgeDemoState) {
val modifier = Modifier.alpha(alpha)
when (type) {
BadgeDemoState.Type.Standard -> {
val contentDescription = stringResource(id = R.string.app_components_badge_unreadNotifications_a11y)
val contentDescription = stringResource(id = R.string.app_components_common_unreadNotificationsBadge_a11y)
OudsBadge(
modifier = modifier.semantics { this.contentDescription = contentDescription },
status = status,
Expand All @@ -137,7 +137,7 @@ private fun BadgeDemoContent(state: BadgeDemoState) {
)
}
BadgeDemoState.Type.Count -> {
val contentDescription = pluralStringResource(id = R.plurals.app_components_badge_unreadMessageCount_a11y, count = count, count)
val contentDescription = pluralStringResource(id = R.plurals.app_components_common_unreadMessageCountBadge_a11y, count = count, count)
OudsBadge(
modifier = modifier.semantics { this.contentDescription = contentDescription },
count = count,
Expand Down
Loading