Solution still using Canvas(..)
You will need to extend the Path out with a secondary path.cubicTo(..)
call.
Here's a quick and dirty function I've written to generate these cubic curves based on bottomLeft and TopRight values of the curve in the canvas
@Composable
fun CurveShape() {
Canvas(
modifier = Modifier
.height(80.dp)
.fillMaxWidth()
.background(Color.White)
) {
drawCubicCurve(
bottomLeft = Offset(0f, size.height),
topRight = Offset(size.width, 0f),
color = Color.Black
)
}
}
fun DrawScope.drawCubicCurve(
bottomLeft: Offset,
topRight: Offset,
color: Color = Color.White
) {
val x1Modifier = 0.41f
val x2Modifier = 0.22f
val x3Modifier = 0.5f
val y1Modifier = 0f
val y2Modifier = 1f
val y3Modifier = 1f
val delta = topRight.minus(bottomLeft)
val width = delta.x
val height = delta.y
val path = Path()
path.moveTo(bottomLeft.x, bottomLeft.y)
path.cubicTo(
x1 = bottomLeft.x.plus(width.times(x1Modifier)),
y1 = bottomLeft.y.plus(height.times(y1Modifier)),
x2 = bottomLeft.x.plus(width.times(x2Modifier)),
y2 = topRight.y.times(y2Modifier),
x3 = bottomLeft.x.plus(width.times(x3Modifier)),
y3 = topRight.y.times(y3Modifier),
)
path.cubicTo(
x1 = topRight.x.minus(width.times(x2Modifier)),
y1 = topRight.y.times(y2Modifier),
x2 = topRight.x.minus(width.times(x1Modifier)),
y2 = bottomLeft.y.plus(height.times(y1Modifier)),
x3 = topRight.x,
y3 = bottomLeft.y,
)
drawPath(
path = path,
alpha = 0.5f,
brush = Brush.verticalGradient(
colors = listOf(
color.copy(alpha = 0.0f),
color.copy(alpha = 0.7f),
color
), startY = bottomLeft.y, endY = topRight.y
)
)
drawPath(
color = color,
path = path,
)
}

My code draws the curve the other way around as you want it, so I encourage you to play around with the values here to get the resulting curve you want :)
Additionally calling .reset()
is only required because you have remembered the Path(..). I'd advise you to not remember the Path() as you want to recalculate it whenever a recomposition occurs as the measurements of the Canvas may have changed. Resulting in a different path