Skip to content

A flexible and hierarchical context menu library for Compose Desktop applications that supports nested submenus, keyboard navigation, and customizable styling.

License

Notifications You must be signed in to change notification settings

thedroiddiv/Corntex

Repository files navigation

Compose Desktop Context Menu

A flexible and hierarchical context menu library for Compose Desktop applications that supports nested submenus, keyboard navigation, and customizable styling.

Demo_Video.mp4

Features

  • Right-click Detection: Automatic context menu triggering on right-click
  • Hierarchical Menus: Support for nested submenus with unlimited depth
  • Customizable Styling: Theme-aware design with customizable colors and dimensions
  • Flexible Items: Support for clickable items, submenus, and visual dividers
  • Keyboard Navigation Supports fully functional keyboard navigation in menus using Arrow keys and Enter.

Quick Start

📦 Installation

dependencies {
    implementation("io.github.thedroiddiv:corntex:<latest-version>")
}

Basic Usage

@Composable  
fun MyComponent() {  
    ContextMenuArea(  
        items = {  
			      listOf(  
                ContextMenuEntry.Single(label = "Cut", onClick = { /* Handle cut */ }),  
                ContextMenuEntry.Single(label = "Copy", onClick = { /* Handle copy */ }),  
                ContextMenuEntry.Single(label = "Paste", onClick = { /* Handle paste */ })  
            )  
        }  
  ) {  
		  Text("Right-click me for context menu!")  
    }  
}

Advanced Usage with Submenus

@Composable  
@Composable  
fun AdvancedContextMenu() {
    ContextMenuArea(items = {
        listOf(
            ContextMenuEntry.Single(
                label = "New File",
                icon = painterResource("icons/file.png"),
                onClick = { /* Create new file */ }
            ),
            ContextMenuEntry.Submenu(
                label = "Export As",
                icon = painterResource("icons/export.png"),
                submenuItems = listOf(
                    ContextMenuEntry.Single("PDF", onClick = { /* Export as PDF */ }),
                    ContextMenuEntry.Single("PNG", onClick = { /* Export as PNG */ }),
                    ContextMenuEntry.Divider,
                    ContextMenuEntry.Single("Other...", onClick = { /* Show export dialog */ })
                )
            ),
            ContextMenuEntry.Divider, ContextMenuEntry.Single(
                label = "Delete",
                enabled = false, // Disabled item  
                onClick = { /* Handle delete */ }
            )
        )
    }
    ) {
        // Your content here
        Card(modifier = Modifier.size(200.dp)) {
            Text("Right-click for advanced menu")
        }
    }
}

Manual State Management

For more control over menu behavior, you can manage the state manually:

@Composable
fun ManualStateExample() {
    val contextMenuState = rememberContextMenuState()
    var selectedItem by remember { mutableStateOf<String?>(null) }
    ContextMenuArea(state = contextMenuState) {
        ListItem(
            modifier = Modifier.onClick(
                enabled = true,
                interactionSource = MutableInteractionSource()
            ) {
                selectedItem = "Hello World"
                contextMenuState.show(
                    position = IntOffset(0, 0),
                    items = listOf(
                        ContextMenuEntry.Single(
                            "Option 1",
                            onClick = { /* Handle option 1 click for item */ }),
                        ContextMenuEntry.Single(
                            "Option 2",
                            onClick = { /* Handle option 2 click for item. */ })
                    )
                )
            }
        ) {
            Text("Hello World")
        }
    }
}

API Reference

ContextMenuArea

The main composable for creating context menu areas.

@Composable  
fun ContextMenuArea(  
 items: () -> List<ContextMenuEntry>,
 modifier: Modifier = Modifier,
 content: @Composable () -> Unit
)  
  
@Composable
fun ContextMenuArea(
    modifier: Modifier = Modifier,
    state: HierarchicalContextMenuState,
    content: @Composable () -> Unit
)

HierarchicalContextMenuState

State holder for managing context menu visibility and hierarchy.

class HierarchicalContextMenuState {  
	val openMenus: List<MenuLevel>
 	fun show(position: IntOffset, items: List<ContextMenuEntry>)  
 	fun hide()
 	fun onItemHover(item: ContextMenuEntry, bottomRight: IntOffset)
}  

Utility Functions

rememberContextMenuState

@Composable  
fun rememberContextMenuState(): HierarchicalContextMenuState  

Creates and remembers a context menu state for the current composition.

contextMenuOpenDetector

fun Modifier.contextMenuOpenDetector(  
	state: HierarchicalContextMenuState,
	items: () -> List<ContextMenuEntry>
): Modifier  

Modifier that detects right-click events and shows the context menu.

Customization

Theme Customization

The library uses a theme system for consistent styling. You can customize colors, dimensions and typography through the ContextMenuTheme:

ContextMenuTheme(
    colors = darkContextMenuColor // or provide a .copy/custom instance,
    tokens = defaultContextMenuTokens // or provide a .copy/ustom instance,
    typography = defaultContextMenuTypography // or provide a .copy/custom instance
) {
    DesktopApp()
}

Custom Representation

For complete customization, implement your own ContextMenuRepresentation:

class CustomContextMenuRepresentation : ContextMenuRepresentation {  
   @Composable override fun Representation(state: HierarchicalContextMenuState) {
    // Your custom menu implementation
   }
}  

About

A flexible and hierarchical context menu library for Compose Desktop applications that supports nested submenus, keyboard navigation, and customizable styling.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published