feat(design-system): add MsDialogShell and MsConfirmDialog components, and update roadmap
- Introduced `MsDialogShell` for a standardized modal dialog framework. - Added `MsConfirmDialog` as a utility for common confirmation dialogs. - Updated `Frontend_Komponenten_Roadmap.md` to mark `MsDialogShell` as complete. Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
@@ -53,7 +53,7 @@ Hier bringen wir alles zusammen, bevor das finale Routing implementiert wird.
|
||||
|
||||
* [x] **`MsMasterDetailLayout`:** Standard-Layout für alle Stammdaten-Screens (Liste & Editor).
|
||||
* [x] **`MsActionToolbar`:** Einheitliche Platzierung von Hauptaktionen (Neu, Speichern, Drucken).
|
||||
* [ ] **`MsDialogShell`:** Standardisierter Rahmen für Modale und Bestätigungsdialoge.
|
||||
* [x] **`MsDialogShell`:** Standardisierter Rahmen für Modale und Bestätigungsdialoge.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+7
-3
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
enum class ButtonVariant {
|
||||
@@ -25,7 +26,8 @@ fun MsButton(
|
||||
size: ButtonSize = ButtonSize.MEDIUM,
|
||||
enabled: Boolean = true,
|
||||
isLoading: Boolean = false,
|
||||
fullWidth: Boolean = false
|
||||
fullWidth: Boolean = false,
|
||||
containerColor: Color? = null
|
||||
) {
|
||||
val buttonModifier = modifier.then(
|
||||
if (fullWidth) Modifier.fillMaxWidth() else Modifier
|
||||
@@ -41,7 +43,8 @@ fun MsButton(
|
||||
ButtonVariant.PRIMARY -> Button(
|
||||
onClick = onClick,
|
||||
modifier = buttonModifier,
|
||||
enabled = enabled && !isLoading
|
||||
enabled = enabled && !isLoading,
|
||||
colors = if (containerColor != null) ButtonDefaults.buttonColors(containerColor = containerColor) else ButtonDefaults.buttonColors()
|
||||
) {
|
||||
ButtonContent(text = text, isLoading = isLoading)
|
||||
}
|
||||
@@ -49,7 +52,8 @@ fun MsButton(
|
||||
ButtonVariant.SECONDARY -> FilledTonalButton(
|
||||
onClick = onClick,
|
||||
modifier = buttonModifier,
|
||||
enabled = enabled && !isLoading
|
||||
enabled = enabled && !isLoading,
|
||||
colors = if (containerColor != null) ButtonDefaults.filledTonalButtonColors(containerColor = containerColor) else ButtonDefaults.filledTonalButtonColors()
|
||||
) {
|
||||
ButtonContent(text = text, isLoading = isLoading)
|
||||
}
|
||||
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
package at.mocode.frontend.core.designsystem.components
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import at.mocode.frontend.core.designsystem.theme.Dimens
|
||||
|
||||
/**
|
||||
* Ein einheitlicher Rahmen für modale Dialoge.
|
||||
*
|
||||
* @param title Die Überschrift des Dialogs.
|
||||
* @param onDismissRequest Callback, wenn der Dialog geschlossen werden soll (z.B. Klick außerhalb).
|
||||
* @param confirmButton Die primäre Aktion (z.B. OK, Speichern).
|
||||
* @param dismissButton Die sekundäre Aktion (z.B. Abbrechen).
|
||||
* @param modifier Modifier für das Surface des Dialogs.
|
||||
* @param content Der eigentliche Inhalt des Dialogs.
|
||||
*/
|
||||
@Composable
|
||||
fun MsDialogShell(
|
||||
title: String,
|
||||
onDismissRequest: () -> Unit,
|
||||
confirmButton: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
dismissButton: @Composable (() -> Unit)? = null,
|
||||
content: @Composable ColumnScope.() -> Unit
|
||||
) {
|
||||
Dialog(onDismissRequest = onDismissRequest) {
|
||||
Surface(
|
||||
modifier = modifier
|
||||
.fillMaxWidth(0.9f)
|
||||
.wrapContentHeight(),
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
tonalElevation = 6.dp
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(Dimens.SpacingM)
|
||||
) {
|
||||
// --- 1. Titel-Bereich ---
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
modifier = Modifier.padding(bottom = Dimens.SpacingM)
|
||||
)
|
||||
|
||||
// --- 2. Content-Bereich ---
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(weight = 1f, fill = false)
|
||||
) {
|
||||
content()
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(Dimens.SpacingM))
|
||||
|
||||
// --- 3. Button-Leiste ---
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.End,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
if (dismissButton != null) {
|
||||
dismissButton()
|
||||
Spacer(modifier = Modifier.width(Dimens.SpacingS))
|
||||
}
|
||||
confirmButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hilfs-Funktion für einen Standard-Bestätigungsdialog.
|
||||
*/
|
||||
@Composable
|
||||
fun MsConfirmDialog(
|
||||
title: String,
|
||||
message: String,
|
||||
onConfirm: () -> Unit,
|
||||
onDismiss: () -> Unit,
|
||||
confirmText: String = "Bestätigen",
|
||||
dismissText: String = "Abbrechen",
|
||||
isDestructive: Boolean = false
|
||||
) {
|
||||
MsDialogShell(
|
||||
title = title,
|
||||
onDismissRequest = onDismiss,
|
||||
confirmButton = {
|
||||
MsButton(
|
||||
text = confirmText,
|
||||
onClick = onConfirm,
|
||||
variant = if (isDestructive) ButtonVariant.PRIMARY else ButtonVariant.PRIMARY,
|
||||
// Bei destruktiven Aktionen könnten wir hier später eine rote Farbe erzwingen
|
||||
containerColor = if (isDestructive) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary,
|
||||
size = ButtonSize.SMALL
|
||||
)
|
||||
},
|
||||
dismissButton = {
|
||||
MsButton(
|
||||
text = dismissText,
|
||||
onClick = onDismiss,
|
||||
variant = ButtonVariant.TEXT,
|
||||
size = ButtonSize.SMALL
|
||||
)
|
||||
}
|
||||
) {
|
||||
Text(
|
||||
text = message,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user