Barre de menus macOS
Construisez la barre de menus macOS native depuis Compose, avec des items, des raccourcis clavier, des icônes, des badges et des sous-menus pilotés par l'état.
menu-macos vous permet de construire la barre de menus macOS native — la bande en haut
de l'écran, pas dans votre fenêtre — depuis Compose. Vous déclarez les menus et les items sous
forme d'arbre, et le NSMenu natif est reconstruit dès que l'état qu'il lit change.
Ce module n'a d'effet que sur macOS. NativeMenuBar ne fait rien sur les autres
plateformes, vous pouvez donc laisser l'appel dans du code partagé.
Ajouter la dépendance
dependencies {
implementation("dev.nucleusframework:nucleus.menu-macos:2.0.7")
}Cela tire les constantes sf-symbols de
manière transitive, ce qui vous permet de référencer un symbole par son nom sans risque de
faute de frappe.
Construire une barre de menus
Appelez NativeMenuBar depuis un composable proche de la racine de votre application. Le
premier appel à Menu devient le menu de l'application (l'entrée en gras portant le nom
de votre app).
import androidx.compose.runtime.Composable
import dev.nucleusframework.menu.macos.*
import dev.nucleusframework.sfsymbols.SFSymbolObjectsAndTools
import kotlin.system.exitProcess
@Composable
fun App() {
NativeMenuBar {
Menu("MyApp") {
Item("À propos de MyApp") { showAbout() }
Separator()
Item("Quitter", shortcut = NativeKeyShortcut("q")) { exitProcess(0) }
}
Menu("Fichier") {
Item(
"Nouveau",
shortcut = NativeKeyShortcut("n"),
icon = NsMenuItemImage.SystemSymbol(SFSymbolObjectsAndTools.DOCUMENT_BADGE_PLUS),
) { newDocument() }
Item(
"Ouvrir…",
shortcut = NativeKeyShortcut("o"),
icon = NsMenuItemImage.SystemSymbol(SFSymbolObjectsAndTools.FOLDER),
) { open() }
}
MenuHelp("Aide") {
Item("Documentation") { openDocs() }
}
}
// … contenu de la fenêtre
}Fonctionnement
NativeMenuBar sauvegarde la barre de menus courante à la première composition, puis
installe un nouveau NSMenu construit depuis votre DSL. La lambda de construction est un
corps composable ordinaire : elle s'exécute pendant la composition, et le menu natif est
reconstruit dès qu'un état lu à l'intérieur change. Quand le composable quitte la
composition, la barre de menus sauvegardée est restaurée.
Comme le menu est lié à la composition, hébergez NativeMenuBar à la racine de votre
application plutôt que dans le contenu d'une fenêtre. Ainsi le menu survit à l'ouverture
et à la fermeture des fenêtres.
Les menus déclarés avec MenuWindow et MenuHelp sont confiés à AppKit comme les menus
Window et Help bien connus. macOS les remplit alors lui-même : la liste des fenêtres et
« Tout ramener au premier plan » pour Window, et un champ de recherche en haut du menu
Aide.
Référence de l'API
Ajouter des menus et des sous-menus
Menu ajoute un menu de premier niveau au niveau de la barre, ou un sous-menu à
l'intérieur d'un autre menu. Les sous-menus s'imbriquent à n'importe quelle profondeur.
NativeMenuBar {
Menu("Édition") {
Item("Annuler", shortcut = NativeKeyShortcut("z")) { undo() }
Item("Rétablir", shortcut = NativeKeyShortcut("z", shift = true)) { redo() }
Separator()
Menu("Rechercher") {
Item("Rechercher…", shortcut = NativeKeyShortcut("f")) { find() }
Item("Suivant", shortcut = NativeKeyShortcut("g")) { findNext() }
}
}
}Utilisez MenuWindow et MenuHelp pour les menus standard Window et Help. Leur contenu
est optionnel — macOS les complète.
Ajouter des items
Item ajoute un item de menu classique. La lambda finale est le callback de clic,
dispatché sur le thread Swing (EDT). Paramètres courants : enabled, shortcut, icon,
state, badge, subtitle, toolTip et tag.
Item(
"Exporter…",
shortcut = NativeKeyShortcut("e", shift = true),
subtitle = "Enregistrer une copie en PDF",
enabled = document != null,
) { export() }Ajouter des cases à cocher et des boutons radio
CheckboxItem et RadioButtonItem mappent pour vous leur état booléen sur la coche de
l'item. C'est à vous de gérer la sélection.
var darkMode by remember { mutableStateOf(false) }
NativeMenuBar {
Menu("Affichage") {
CheckboxItem(
"Mode sombre",
checked = darkMode,
onCheckedChange = { darkMode = it },
)
Separator()
RadioButtonItem("Clair", selected = !darkMode) { darkMode = false }
RadioButtonItem("Sombre", selected = darkMode) { darkMode = true }
}
}Pour un contrôle plus fin, Item accepte directement un state valant
NsMenuItemState.OFF, NsMenuItemState.ON ou NsMenuItemState.MIXED.
Ajouter des séparateurs, des en-têtes et une recherche
Menu("Historique") {
SearchField(placeholder = "Rechercher dans l'historique")
SectionHeader("Aujourd'hui")
Item("nucleusframework.dev") { open(url) }
Separator()
SectionHeader("Plus tôt")
Item("developer.apple.com") { open(url) }
}SearchField filtre les autres items du menu par titre au fur et à mesure de la saisie.
SectionHeader nécessite macOS 14+ et se replie sur un item désactivé sur les systèmes
plus anciens.
Définir des raccourcis clavier
NativeKeyShortcut utilise par défaut le modificateur Command (⌘). Ajoutez shift,
option, control ou function selon les besoins, et utilisez les constantes
NativeKey pour les touches non imprimables.
Item("Enregistrer", shortcut = NativeKeyShortcut("s")) { save() }
Item("Enregistrer sous…", shortcut = NativeKeyShortcut("s", shift = true)) { saveAs() }
Item("Annuler", shortcut = NativeKeyShortcut(NativeKey.ESCAPE, command = false)) { cancel() }Ajouter des icônes
NsMenuItemImage fournit l'image d'un item depuis un SF Symbol, une image AppKit nommée
ou un chemin de fichier.
Item("Réglages", icon = NsMenuItemImage.SystemSymbol(SFSymbolGeneral.GEAR)) { openSettings() }Le module sf-symbols expose chaque catégorie de symboles — SFSymbolGeneral,
SFSymbolObjectsAndTools, SFSymbolPower, et d'autres — sous forme de constantes typées.
NsMenuItemImage.SystemSymbol accepte aussi un nom de symbole sous forme de chaîne brute.
Ajouter des badges
NsMenuItemBadge affiche un badge stylé par le système à droite d'un item (macOS 14+).
Utilisez Count pour un simple nombre, Text pour une chaîne personnalisée, ou Alerts,
NewItems et Updates pour des libellés localisés par le système.
Item("Boîte de réception", badge = NsMenuItemBadge.Count(unreadCount)) { openInbox() }
Item("Mise à jour logicielle", badge = NsMenuItemBadge.Updates(pendingUpdates)) { openUpdates() }Et ensuite
- Barre d'état système — un item de statut dans la barre de menus et son menu contextuel.
- Mode sombre — détectez l'apparence système pour piloter un item de menu à cocher.
- Icônes Freedesktop — le jeu d'icônes nommées équivalent pour Linux.