Skip to content

Comments

Add unified components for Material 3 from https://github.com/huanshankeji/compose-html-material/pull/21#72

Open
ShreckYe wants to merge 1 commit intodevfrom
add-unified-components-for-compose-html-material-#21
Open

Add unified components for Material 3 from https://github.com/huanshankeji/compose-html-material/pull/21#72
ShreckYe wants to merge 1 commit intodevfrom
add-unified-components-for-compose-html-material-#21

Conversation

@ShreckYe
Copy link
Member

No description provided.

…ial PR #20 with architectural improvements, documentation, and stability fixes (#70)

* Initial plan

* Add simple unified wrapper components: RadioButton, Divider, Slider, Badge

Co-authored-by: ShreckYe <27768951+ShreckYe@users.noreply.github.com>

* Add Chips, Dialog, and Tabs unified wrapper components

Co-authored-by: ShreckYe <27768951+ShreckYe@users.noreply.github.com>

* Add SegmentedButton labs components

Co-authored-by: ShreckYe <27768951+ShreckYe@users.noreply.github.com>

* Add remaining unified wrapper components: Select, ListItem, NavigationDrawer

Co-authored-by: ShreckYe <27768951+ShreckYe@users.noreply.github.com>

* Add new components to Material3 demo

Co-authored-by: ShreckYe <27768951+ShreckYe@users.noreply.github.com>

* Fix compilation errors

* Fix demo: RadioButton with Selection enum, Badge with TaglessText, Chips with separate states, improved Slider

Co-authored-by: ShreckYe <27768951+ShreckYe@users.noreply.github.com>

* Remove ListItem component, use existing ListScope.ListItem implementation

Co-authored-by: ShreckYe <27768951+ShreckYe@users.noreply.github.com>

* Fix SegmentedButton: use Selection enum, add multi-select demo, improve label rendering

Co-authored-by: ShreckYe <27768951+ShreckYe@users.noreply.github.com>

* Refactor to Compose UI naming: Single/MultiChoiceSegmentedButtonRow, move components out of labs, add Select to ext package

Co-authored-by: ShreckYe <27768951+ShreckYe@users.noreply.github.com>

* Update copilot-instructions.md with Material 3 component list and architectural patterns

Co-authored-by: ShreckYe <27768951+ShreckYe@users.noreply.github.com>

* Fix segmented row scope API, composeUi segmented rendering, and ext select behavior; resolve JS webpack segmented import issue

Co-authored-by: ShreckYe <27768951+ShreckYe@users.noreply.github.com>

* Remove the second `List` component added by Copilot

* Review and incompletely fix changes in commit 9ec4b94

* Update README Material 3 API catalog to match implemented components

Co-authored-by: ShreckYe <27768951+ShreckYe@users.noreply.github.com>

* Add m3.material.io component lookup note to copilot instructions

Co-authored-by: ShreckYe <27768951+ShreckYe@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ShreckYe <27768951+ShreckYe@users.noreply.github.com>
Co-authored-by: Yongshun Ye <ShreckYe@gmail.com>
@ShreckYe ShreckYe self-assigned this Feb 21, 2026
@ShreckYe ShreckYe changed the base branch from main to dev February 21, 2026 04:07
@sonarqubecloud
Copy link

@gemini-code-assist
Copy link

Summary of Changes

Hello @ShreckYe, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly expands the library's Material 3 component offerings, providing a wider range of unified UI elements for multiplatform applications. Concurrently, it updates core build dependencies and configurations to ensure compatibility and improve development experience, while formally deprecating and removing Material 2 components to align with modern design standards. These changes aim to enhance the library's feature set and maintain its technical foundation.

Highlights

  • Material 3 Component Expansion: Introduced a comprehensive set of new Material 3 components, including Badge, various Chips (Assist, Filter, Input, Suggestion), AlertDialog, HorizontalDivider, NavigationDrawer (and ModalNavigationDrawer), RadioButton, Segmented Buttons (Single and Multi-choice), Slider, Tabs (TabRow, Tab), and Select components (FilledSelect, OutlinedSelect, SelectOption). These components are implemented with unified APIs across Compose UI and JS DOM platforms.
  • Build System and Dependency Updates: Upgraded various build dependencies and tools, including Kotlin (to 2.3.10), Compose Gradle Plugin (to 1.10.1), Android Gradle Plugin (to 8.12.3), Kobweb (to 0.23.3), and the binary compatibility validator plugin (to 0.18.1). The Gradle wrapper was updated to 9.3.1, and the Android SDK version was bumped to 36.
  • Material 2 Deprecation and Removal: Material 2 components have been officially deprecated and are no longer maintained or published for release since v0.6.0. The demo application has been updated to reflect this by commenting out Material 2 related screens and dependencies, and the material2 module is now commented out in settings.gradle.kts.
  • Project Configuration Enhancements: Added a detailed copilot-instructions.md file to the .github directory, providing a comprehensive overview of the repository, build instructions, architecture, and validation steps. The Gradle JVM memory allocation was increased to 4GB to support Wasm compilation, and org.gradle.configuration-cache=true was added to gradle.properties.
  • Platform Target Adjustments: The iosX64 target was removed from several modules (common, lifecycle-viewmodel, material-icons-core, material2, material3, navigation, demo), streamlining the build process for iOS targets to focus on iosArm64 and iosSimulatorArm64.
  • Dependency Management Refinements: Modified dependency declarations for kobweb-compose and compose-html-common to exclude org.jetbrains.kotlin to prevent potential conflicts. The Kobweb Maven repository was removed from common-conventions.gradle.kts as Kobweb is now available on Maven Central.
Changelog
  • .github/copilot-instructions.md
    • Added a new file providing detailed instructions for Copilot on repository overview, build setup, architecture, and validation.
  • README.md
    • Added a deprecation notice for Material 2 components.
    • Updated the list of supported Material 3 components.
    • Removed the instruction to add the Kobweb Maven repository, as it is now on Maven Central.
  • build.gradle.kts
    • Updated the binary-compatibility-validator plugin version from 0.16.3 to 0.18.1.
    • Removed compose-multiplatform-html-unified-common-legacy from the list of ignored projects for API validation.
  • buildSrc/build.gradle.kts
    • Updated Kotlin version from 2.2.0-RC2 to 2.3.10.
    • Updated Compose Gradle Plugin version from 1.8.1 to 1.10.1.
    • Updated com.huanshankeji.team:gradle-plugins version from 0.9.0 to 0.11.0.
    • Updated Android Gradle Plugin version from 8.10.1 to 8.12.3.
    • Updated com.huanshankeji:common-gradle-dependencies version from 0.9.0-20241203 to 0.10.0-20251024.
    • Added mavenLocal() repository with a TODO comment.
  • buildSrc/src/main/kotlin/Android.kt
    • Updated androidSdkVersion from 35 to 36.
  • buildSrc/src/main/kotlin/VersionsAndDependencies.kt
    • Updated kobweb version from 0.19.2 to 0.23.3.
    • Updated huanshankejiComposeHtml version from 0.4.0 to 0.5.0-SNAPSHOT.
    • Updated materialSymbols version from 0.25.1 to 0.40.2.
    • Added comments with links to releases for kobweb, kmdc, and material-symbols.
  • buildSrc/src/main/kotlin/common-conventions.gradle.kts
    • Removed iosX64() from the list of iOS targets.
    • Removed the Kobweb Maven repository (https://us-central1-maven.pkg.dev/varabyte-repos/public).
    • Moved mavenLocal() to be consistently present.
  • common/api/compose-multiplatform-html-unified-common.klib.api
    • Removed iosX64 from the Klib ABI dump targets and alias.
    • Removed PaddingValuesImpl$stableprop from the ABI dump.
  • common/build.gradle.kts
    • Updated the import for ShreckYe.
    • Reordered the withAndroidTarget() call within the Kotlin targets configuration.
    • Added exclude("org.jetbrains.kotlin") to kobweb-compose and compose-html-common dependencies.
    • Added a 2023 copyright year to the POM for open source publication.
  • common/legacy/build.gradle.kts
    • Updated the import for ShreckYe.
  • demo/build.gradle.kts
    • Removed iosX64() from the list of iOS targets for the demo.
    • Added compilerOptions { target.set("es2015") } for the JS target.
    • Commented out the material2 project dependency.
  • demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/App.kt
    • Commented out the Material2 entry in the Screen enum.
    • Commented out the Material2 composable route in the NavHost.
    • Commented out the 'Material 2' button in the Home screen.
  • demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Material3.kt
    • Added demo implementations for RadioButton, HorizontalDivider, Slider, Badge, AssistChip, FilterChip, InputChip, SuggestionChip, AlertDialog, TabRow, Tab, FilledSelect, OutlinedSelect, SelectOption, SingleChoiceSegmentedButtonRow, MultiChoiceSegmentedButtonRow, SegmentedButton, and NavigationDrawer.
  • demo/src/commonMain/kotlinArchived/com/huanshankeji/compose/material/demo/Material2.kt
    • Renamed the file, effectively archiving the Material 2 demo.
  • demo/src/jsMain/kotlin/com/huanshankeji/compose/material/demo/Main.kt
    • Changed the Material Symbols CSS import mechanism from require("material-symbols/outlined.css") to an @JsModule external object import.
  • gradle.properties
    • Added org.gradle.configuration-cache=true.
    • Increased org.gradle.jvmargs from -Xmx2G to -Xmx4G.
    • Standardized the kotlin.native.enableKlibsCrossCompilation property format.
  • gradle/wrapper/gradle-wrapper.properties
    • Updated the Gradle distribution URL to https://services.gradle.org/distributions/gradle-9.3.1-all.zip.
  • gradlew
    • Removed the CLASSPATH variable and its usage from the gradlew script.
  • gradlew.bat
    • Removed the CLASSPATH variable and its usage from the gradlew.bat script.
  • lifecycle-viewmodel/api/compose-multiplatform-html-unified-lifecycle-viewmodel.klib.api
    • Removed iosX64 from the Klib ABI dump targets.
  • lifecycle-viewmodel/build.gradle.kts
    • Updated the import for ShreckYe.
    • Added a 2024 copyright year to the POM for open source publication.
  • material-icons-core/api/compose-multiplatform-html-unified-material-icons-core.klib.api
    • Removed iosX64 from the Klib ABI dump targets and alias.
  • material-icons-core/build.gradle.kts
    • Updated the import for ShreckYe.
    • Added a 2024 copyright year to the POM for open source publication.
  • material2/api/compose-multiplatform-html-unified-material2.klib.api
    • Removed iosX64 from the Klib ABI dump targets and alias.
  • material2/build.gradle.kts
    • Updated the import for ShreckYe.
    • Added a 2023 copyright year to the POM for open source publication.
  • material2/src/composeUiMain/kotlin/com/huanshankeji/compose/material2/ext/Radio.composeUi.kt
    • Updated the selectable modifier call to include a null interaction source parameter.
  • material3/api/compose-multiplatform-html-unified-material3.klib.api
    • Removed iosX64 from the Klib ABI dump targets and alias.
  • material3/build.gradle.kts
    • Updated the import for ShreckYe.
    • Added exclude("org.jetbrains.kotlin") to compose-html-material3 and compose-html-common dependencies.
    • Added a 2024 copyright year to the POM for open source publication.
  • material3/src/commonMain/kotlin/com/huanshankeji/compose/material3/Badge.kt
    • Added the expect declaration for the Badge composable.
  • material3/src/commonMain/kotlin/com/huanshankeji/compose/material3/Chips.kt
    • Added expect declarations for AssistChip, FilterChip, InputChip, and SuggestionChip composables.
  • material3/src/commonMain/kotlin/com/huanshankeji/compose/material3/Dialog.kt
    • Added the expect declaration for the AlertDialog composable.
  • material3/src/commonMain/kotlin/com/huanshankeji/compose/material3/Divider.kt
    • Added the expect declaration for the HorizontalDivider composable.
  • material3/src/commonMain/kotlin/com/huanshankeji/compose/material3/NavigationDrawer.kt
    • Added expect declarations for NavigationDrawer and ModalNavigationDrawer composables.
  • material3/src/commonMain/kotlin/com/huanshankeji/compose/material3/RadioButton.kt
    • Added the expect declaration for the RadioButton composable.
  • material3/src/commonMain/kotlin/com/huanshankeji/compose/material3/SegmentedButton.kt
    • Added expect declarations for SingleChoiceSegmentedButtonRow, MultiChoiceSegmentedButtonRow, and SegmentedButton composables within their respective scopes.
  • material3/src/commonMain/kotlin/com/huanshankeji/compose/material3/Slider.kt
    • Added the expect declaration for the Slider composable.
  • material3/src/commonMain/kotlin/com/huanshankeji/compose/material3/Tabs.kt
    • Added expect declarations for TabRow and Tab composables.
  • material3/src/commonMain/kotlin/com/huanshankeji/compose/material3/ext/ExposedDropdownMenu.kt
    • Added a TODO comment to rename ExposedDropdownMenuBoxWithTextField to ExposedDropdownMenuBoxWithFilledTextField.
  • material3/src/commonMain/kotlin/com/huanshankeji/compose/material3/ext/Select.kt
    • Added expect declarations for FilledSelect, OutlinedSelect, and SelectOption composables.
  • material3/src/composeUiMain/kotlin/com/huanshankeji/compose/material3/Badge.composeUi.kt
    • Added the actual Compose UI implementation for the Badge composable.
  • material3/src/composeUiMain/kotlin/com/huanshankeji/compose/material3/Chips.composeUi.kt
    • Added actual Compose UI implementations for AssistChip, FilterChip, InputChip, and SuggestionChip composables.
  • material3/src/composeUiMain/kotlin/com/huanshankeji/compose/material3/Dialog.composeUi.kt
    • Added the actual Compose UI implementation for the AlertDialog composable.
  • material3/src/composeUiMain/kotlin/com/huanshankeji/compose/material3/Divider.composeUi.kt
    • Added the actual Compose UI implementation for the HorizontalDivider composable.
  • material3/src/composeUiMain/kotlin/com/huanshankeji/compose/material3/NavigationDrawer.composeUi.kt
    • Added actual Compose UI implementations for NavigationDrawer and ModalNavigationDrawer composables.
  • material3/src/composeUiMain/kotlin/com/huanshankeji/compose/material3/RadioButton.composeUi.kt
    • Added the actual Compose UI implementation for the RadioButton composable.
  • material3/src/composeUiMain/kotlin/com/huanshankeji/compose/material3/SegmentedButton.composeUi.kt
    • Added actual Compose UI implementations for SingleChoiceSegmentedButtonRow, MultiChoiceSegmentedButtonRow, and SegmentedButton composables within their respective scopes.
  • material3/src/composeUiMain/kotlin/com/huanshankeji/compose/material3/Slider.composeUi.kt
    • Added the actual Compose UI implementation for the Slider composable.
  • material3/src/composeUiMain/kotlin/com/huanshankeji/compose/material3/Tabs.composeUi.kt
    • Added actual Compose UI implementations for TabRow and Tab composables.
  • material3/src/composeUiMain/kotlin/com/huanshankeji/compose/material3/ext/Select.composeUi.kt
    • Added actual Compose UI implementations for FilledSelect, OutlinedSelect, and SelectOption composables.
  • material3/src/jsMain/kotlin/com/huanshankeji/compose/material3/Badge.js.kt
    • Added the actual JS DOM implementation for the Badge composable using MdBadge.
  • material3/src/jsMain/kotlin/com/huanshankeji/compose/material3/Chips.js.kt
    • Added actual JS DOM implementations for AssistChip, FilterChip, InputChip, and SuggestionChip composables using their respective Material Web Components.
  • material3/src/jsMain/kotlin/com/huanshankeji/compose/material3/Dialog.js.kt
    • Added the actual JS DOM implementation for the AlertDialog composable using MdDialog.
  • material3/src/jsMain/kotlin/com/huanshankeji/compose/material3/Divider.js.kt
    • Added the actual JS DOM implementation for the HorizontalDivider composable using MdDivider.
  • material3/src/jsMain/kotlin/com/huanshankeji/compose/material3/NavigationDrawer.js.kt
    • Added actual JS DOM implementations for NavigationDrawer and ModalNavigationDrawer composables using MdNavigationDrawer and MdNavigationDrawerModal.
  • material3/src/jsMain/kotlin/com/huanshankeji/compose/material3/RadioButton.js.kt
    • Added the actual JS DOM implementation for the RadioButton composable using MdRadio.
  • material3/src/jsMain/kotlin/com/huanshankeji/compose/material3/SegmentedButton.js.kt
    • Added actual JS DOM implementations for SingleChoiceSegmentedButtonRow, MultiChoiceSegmentedButtonRow, and SegmentedButton composables using MdSegmentedButtonSet and MdOutlinedSegmentedButton.
  • material3/src/jsMain/kotlin/com/huanshankeji/compose/material3/Slider.js.kt
    • Added the actual JS DOM implementation for the Slider composable using MdSlider.
  • material3/src/jsMain/kotlin/com/huanshankeji/compose/material3/Tabs.js.kt
    • Added actual JS DOM implementations for TabRow and Tab composables using MdTabs and MdPrimaryTab.
  • material3/src/jsMain/kotlin/com/huanshankeji/compose/material3/ext/Select.js.kt
    • Added actual JS DOM implementations for FilledSelect, OutlinedSelect, and SelectOption composables using their respective Material Web Components.
  • navigation/api/compose-multiplatform-html-unified-navigation.klib.api
    • Removed iosX64 from the Klib ABI dump targets.
  • navigation/build.gradle.kts
    • Updated the import for ShreckYe.
    • Added a 2024 copyright year to the POM for open source publication.
  • settings.gradle.kts
    • Removed common:legacy from included projects.
    • Commented out material2 from included projects.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/copilot-setup-steps.yml
Activity
  • The pull request introduces a significant number of new Material 3 components with unified APIs for Compose UI and JS DOM.
  • Build system dependencies and configurations have been updated to newer versions, including Kotlin, Gradle, and Android SDK.
  • Material 2 components have been formally deprecated and removed from the demo, indicating a shift towards Material 3.
  • A new copilot-instructions.md file was added to provide comprehensive project documentation.
  • The iosX64 target was removed from several modules, streamlining iOS target configurations.
  • Dependency management was refined by excluding Kotlin from certain transitive dependencies and removing an outdated Maven repository.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request adds a significant number of new unified Material 3 components, along with their expect/actual implementations for Compose UI and JS platforms, and updates the demo application and documentation to reflect these changes. While this is a great step forward, several of the new component implementations are incomplete or have critical bugs, especially on the Compose UI side. There are multiple TODOs left in the code that render components unusable, incorrect implementations that don't match the component's purpose, and missing functionality. I've left specific comments on these issues.

Comment on lines +20 to +36
actual fun ModalNavigationDrawer(
opened: Boolean,
onDismissRequest: () -> Unit,
modifier: Modifier,
content: @Composable () -> Unit
) =
androidx.compose.material3.ModalNavigationDrawer(
drawerContent = { content() },
modifier = modifier.platformModifier,
drawerState = androidx.compose.material3.rememberDrawerState(
if (opened) androidx.compose.material3.DrawerValue.Open
else androidx.compose.material3.DrawerValue.Closed
),
gesturesEnabled = true
) {
// Empty content for the drawer
}

Choose a reason for hiding this comment

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

critical

The composeUi implementation of ModalNavigationDrawer is critically flawed. It uses the content parameter for the drawerContent, but leaves the main content block of the underlying androidx.compose.material3.ModalNavigationDrawer empty. This will result in the drawer appearing over a blank screen. To fix this, the expect declaration for ModalNavigationDrawer should be updated to accept both drawerContent and a main content lambda, and both should be passed to the actual implementation.

Comment on lines +32 to +52
@Composable
actual fun SegmentedButton(
selected: Boolean,
onClick: () -> Unit,
modifier: Modifier,
enabled: Boolean,
icon: @Composable (() -> Unit)?,
label: @Composable () -> Unit
) =
platformScope.SegmentedButton(
selected,
onClick,
SegmentedButtonDefaults.itemShape(
index = TODO(),
count = TODO()
),
modifier.platformModifier,
enabled,
icon = TODO(),
label = label
)

Choose a reason for hiding this comment

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

critical

The composeUi implementation of SegmentedButton within SingleChoiceSegmentedButtonRowScope is incomplete and incorrect. It has TODO() placeholders for index, count, and icon, which are essential for the component to function and render correctly. The call to platformScope.SegmentedButton is also incorrect as platformScope is a RowScope. This makes the SingleChoiceSegmentedButtonRow component unusable on Compose UI platforms.

Comment on lines +56 to +66
@Composable
actual fun SegmentedButton(
selected: Boolean,
onClick: () -> Unit,
modifier: Modifier,
enabled: Boolean,
icon: @Composable (() -> Unit)?,
label: @Composable () -> Unit
) =
TODO() as Unit
}

Choose a reason for hiding this comment

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

critical

The SegmentedButton implementation within MultiChoiceSegmentedButtonRowScope is completely missing and is just a TODO(). This renders the MultiChoiceSegmentedButtonRow component non-functional on Compose UI platforms.

Comment on lines +7 to +17
actual fun NavigationDrawer(
opened: Boolean,
modifier: Modifier,
content: @Composable () -> Unit
) {
// TODO: Implement using Material 3 PermanentNavigationDrawer or similar
// For now, just render content if opened
if (opened) {
content()
}
}

Choose a reason for hiding this comment

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

high

The composeUi implementation of NavigationDrawer is incomplete. It currently only conditionally renders its content based on the opened flag, which doesn't match the behavior of a standard navigation drawer. The TODO comment acknowledges that it should be implemented using PermanentNavigationDrawer or a similar component. As it stands, this implementation is misleading and doesn't provide the expected UI pattern.

Comment on lines +47 to +56
actual fun OutlinedSelect(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier,
enabled: Boolean,
label: String?,
options: @Composable () -> Unit
) =
// TODO use `ExposedDropdownMenuBoxWithOutlinedTextField`
FilledSelect(value, onValueChange, modifier, enabled, label, options)

Choose a reason for hiding this comment

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

high

The OutlinedSelect component is incorrectly implemented as it just delegates to FilledSelect. This means it will render as a filled select instead of an outlined one, which is misleading. The TODO comment indicates this is known, but it's a significant issue that should be addressed.

    // TODO use `ExposedDropdownMenuBoxWithOutlinedTextField`
    // For now, this is a placeholder. It should be implemented with an OutlinedTextField.
    // Example:
    /*
    var expanded by remember { mutableStateOf(false) }
    ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = !expanded }) {
        OutlinedTextField(
            value = value,
            onValueChange = {},
            readOnly = true,
            label = { Text(label ?: "") },
            trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
            modifier = Modifier.menuAnchor()
        )
        ExposedDropdownMenu(
            expanded = expanded,
            onDismissRequest = { expanded = false }
        ) {
            options()
        }
    }
    */
    FilledSelect(value, onValueChange, modifier, enabled, label, options)

Comment on lines +14 to +55
actual fun AlertDialog(
onDismissRequest: () -> Unit,
confirmButton: @Composable () -> Unit,
modifier: Modifier,
dismissButton: @Composable (() -> Unit)?,
icon: @Composable (() -> Unit)?,
title: @Composable (() -> Unit)?,
text: @Composable (() -> Unit)?
) {
var isOpen by remember { mutableStateOf(true) }

if (isOpen) {
MdDialog(
open = true,
attrs = modifier.toAttrs()
) {
title?.let { titleContent ->
Div({
slotEqHeadline()
}) {
icon?.let { iconContent -> iconContent() }
titleContent()
}
}

text?.let { textContent ->
Div({
slotEqContent()
}) {
textContent()
}
}

Div({
slotEqActions()
}) {
dismissButton?.let { dismissBtn -> dismissBtn() }
confirmButton()
}
}
}
}

Choose a reason for hiding this comment

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

high

The JS implementation of AlertDialog has a few issues:

  1. The onDismissRequest lambda is ignored. This means the dialog cannot be dismissed by clicking the background scrim or pressing the Escape key, which is standard behavior.
  2. It uses an internal isOpen state, which is unnecessary as the component's presence in the composition is already controlled externally (as seen in the demo).

To fix this, you should remove the internal state and use an event listener for the closed event on MdDialog to trigger onDismissRequest.

actual fun AlertDialog(
    onDismissRequest: () -> Unit,
    confirmButton: @Composable () -> Unit,
    modifier: Modifier,
    dismissButton: @Composable (() -> Unit)?,
    icon: @Composable (() -> Unit)?,
    title: @Composable (() -> Unit)?,
    text: @Composable (() -> Unit)?
) {
    MdDialog(
        open = true,
        attrs = modifier.toAttrs {
            addEventListener("closed") { onDismissRequest() }
        }
    ) {
        title?.let { titleContent ->
            Div({
                slotEqHeadline()
            }) {
                icon?.let { iconContent -> iconContent() }
                titleContent()
            }
        }

        text?.let { textContent ->
            Div({
                slotEqContent()
            }) {
                textContent()
            }
        }

        Div({
            slotEqActions()
        }) {
            dismissButton?.let { dismissBtn -> dismissBtn() }
            confirmButton()
        }
    }
}

Comment on lines +351 to +374
var selectedValue by remember { mutableStateOf("Option 1") }
Column {
Text("Selected: $selectedValue")
FilledSelect(
value = selectedValue,
onValueChange = { selectedValue = it },
label = "Choose option"
) {
SelectOption("Option 1", "Option 1")
SelectOption("Option 2", "Option 2")
SelectOption("Option 3", "Option 3")
}
}
Column {
OutlinedSelect(
value = selectedValue,
onValueChange = { selectedValue = it },
label = "Choose option"
) {
SelectOption("Option 1", "Option 1")
SelectOption("Option 2", "Option 2")
SelectOption("Option 3", "Option 3")
}
}

Choose a reason for hiding this comment

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

medium

In the demo for Select components, you have a FilledSelect and an OutlinedSelect one after another, both bound to the same selectedValue state. While this works, for better demonstration purposes, consider placing them side-by-side in a Row and adding Text labels to clarify which is which. This would make the demo clearer and easier to understand visually.

Comment on lines +38 to +101
// TODO check their implementations and consider unifying their duplicate implementations

actual class SingleChoiceSegmentedButtonRowScope(val elementScope: ElementScope<HTMLElement>) {
@MaterialWebLabsApi
@Composable
actual fun SegmentedButton(
selected: Boolean,
onClick: () -> Unit,
modifier: Modifier,
enabled: Boolean,
icon: @Composable (() -> Unit)?,
label: @Composable () -> Unit
) {
MdOutlinedSegmentedButton(
disabled = enabled.isFalseOrNull(),
selected = selected.isTrueOrNull(),
hasIcon = (icon != null).isTrueOrNull(),
attrs = modifier.toAttrs {
this.onClick { onClick() }
}
) {
icon?.let { iconContent ->
Div({
slotEqIcon()
}) {
iconContent()
}
}
// Render label in the default slot
label()
}
}
}

actual class MultiChoiceSegmentedButtonRowScope(val elementScope: ElementScope<HTMLElement>) {
@MaterialWebLabsApi
@Composable
actual fun SegmentedButton(
selected: Boolean,
onClick: () -> Unit,
modifier: Modifier,
enabled: Boolean,
icon: @Composable (() -> Unit)?,
label: @Composable () -> Unit
) {
MdOutlinedSegmentedButton(
disabled = enabled.isFalseOrNull(),
selected = selected.isTrueOrNull(),
hasIcon = (icon != null).isTrueOrNull(),
attrs = modifier.toAttrs {
this.onClick { onClick() }
}
) {
icon?.let { iconContent ->
Div({
slotEqIcon()
}) {
iconContent()
}
}
label()
}
}
}

Choose a reason for hiding this comment

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

medium

The TODO comment on line 38 correctly points out that the implementations of SegmentedButton inside SingleChoiceSegmentedButtonRowScope and MultiChoiceSegmentedButtonRowScope are identical. This code duplication should be refactored into a single private function that both scopes can call. This will improve maintainability and reduce the chance of inconsistencies in the future.

Comment on lines +35 to +36
// Note: onValueChangeFinished is not currently supported in the JS implementation
// TODO: Add support for onValueChangeFinished using appropriate event listener

Choose a reason for hiding this comment

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

medium

The onValueChangeFinished callback is not supported in the JS implementation of the Slider. This creates a feature disparity between the Compose UI and JS platforms. While noted with a TODO, this is a limitation that developers should be aware of. It would be good to find a way to support this, perhaps by listening to change or pointerup events on the slider element.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants