feat(design-system): add MsActionToolbar component and update roadmap

- Introduced `MsActionToolbar` for consistent placement of primary actions like Save, Cancel, Add, and Delete.
- Updated `Frontend_Komponenten_Roadmap.md` to mark this component as complete in Phase 4.

Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
2026-03-31 10:52:53 +02:00
parent ad529f7395
commit 96c9abb264
2 changed files with 103 additions and 1 deletions
@@ -0,0 +1,102 @@
package at.mocode.frontend.core.designsystem.components
import androidx.compose.foundation.layout.*
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.VerticalDivider
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import at.mocode.frontend.core.designsystem.theme.Dimens
/**
* Eine einheitliche Aktionsleiste für Editoren und Detail-Ansichten.
*
* @param onSave Callback für "Speichern".
* @param onCancel Callback für "Abbrechen".
* @param onDelete Callback für "Löschen" (Optional).
* @param onAdd Callback für "Neu" (Optional).
* @param extraActions Zusätzliche Aktionen (Optional, z.B. Drucken).
* @param isSaving Zeigt den Ladezustand beim Speichern an.
* @param canSave Steuert die Aktivierung des Speichern-Buttons.
*/
@Composable
fun MsActionToolbar(
onSave: () -> Unit,
onCancel: () -> Unit,
modifier: Modifier = Modifier,
onDelete: (() -> Unit)? = null,
onAdd: (() -> Unit)? = null,
extraActions: @Composable (RowScope.() -> Unit)? = null,
isSaving: Boolean = false,
canSave: Boolean = true,
title: String? = null
) {
Row(
modifier = modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
// --- 1. Titel-Bereich (Optional) ---
if (title != null) {
Text(
text = title,
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface
)
} else {
Spacer(Modifier.width(1.dp))
}
// --- 2. Button-Bereich ---
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(Dimens.SpacingS)
) {
// Extra Aktionen (z.B. Drucken)
extraActions?.invoke(this)
if (extraActions != null && (onAdd != null || onDelete != null)) {
VerticalDivider(modifier = Modifier.height(24.dp).padding(horizontal = 4.dp))
}
// Neu / Löschen
if (onAdd != null) {
MsButton(
text = "Neu",
onClick = onAdd,
variant = ButtonVariant.OUTLINE,
size = ButtonSize.SMALL
)
}
if (onDelete != null) {
MsButton(
text = "Löschen",
onClick = onDelete,
variant = ButtonVariant.TEXT,
size = ButtonSize.SMALL
)
}
VerticalDivider(modifier = Modifier.height(24.dp).padding(horizontal = 4.dp))
// Hauptaktionen: Abbrechen & Speichern
MsButton(
text = "Abbrechen",
onClick = onCancel,
variant = ButtonVariant.TEXT,
size = ButtonSize.SMALL
)
MsButton(
text = "Speichern",
onClick = onSave,
enabled = canSave,
isLoading = isSaving,
size = ButtonSize.SMALL
)
}
}
}