feat: custom 1.0px icons for highest-visibility touchpoints

Hand-drawn Menu, Plus, Mic, AudioLines, Brain, SlidersHorizontal,
Globe, Image with 1.0px stroke (vs Lucide's 1.5px) to match the
lighter W300 typography. Registered in KaizenIcons — all usages
update automatically, no call-site changes.
This commit is contained in:
Bruno Deanoz 2026-06-23 13:05:50 +02:00
parent 0f6e55d77a
commit 3c6a8911c4
2 changed files with 255 additions and 8 deletions

View file

@ -0,0 +1,247 @@
package dev.kaizen.app.ui.icon
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.StrokeJoin
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.path
import androidx.compose.ui.unit.dp
object KaizenCustomIcons {
val Menu: ImageVector by lazy {
ImageVector.Builder("Menu", 24.dp, 24.dp, 24f, 24f).apply {
path(
stroke = SolidColor(Color.Black),
strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Round,
) {
moveTo(4f, 7f)
horizontalLineTo(20f)
moveTo(4f, 12f)
horizontalLineTo(20f)
moveTo(4f, 17f)
horizontalLineTo(20f)
}
}.build()
}
val Plus: ImageVector by lazy {
ImageVector.Builder("Plus", 24.dp, 24.dp, 24f, 24f).apply {
path(
stroke = SolidColor(Color.Black),
strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Round,
) {
moveTo(12f, 5f)
verticalLineTo(19f)
moveTo(5f, 12f)
horizontalLineTo(19f)
}
}.build()
}
val Mic: ImageVector by lazy {
ImageVector.Builder("Mic", 24.dp, 24.dp, 24f, 24f).apply {
path(
stroke = SolidColor(Color.Black),
strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Round,
strokeLineJoin = StrokeJoin.Round,
) {
// Mic body
moveTo(12f, 2f)
curveTo(10.34f, 2f, 9f, 3.34f, 9f, 5f)
verticalLineTo(12f)
curveTo(9f, 13.66f, 10.34f, 15f, 12f, 15f)
curveTo(13.66f, 15f, 15f, 13.66f, 15f, 12f)
verticalLineTo(5f)
curveTo(15f, 3.34f, 13.66f, 2f, 12f, 2f)
close()
}
path(
stroke = SolidColor(Color.Black),
strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Round,
strokeLineJoin = StrokeJoin.Round,
) {
// Outer arc
moveTo(19f, 10f)
curveTo(19f, 14.42f, 15.87f, 18f, 12f, 18f)
curveTo(8.13f, 18f, 5f, 14.42f, 5f, 10f)
// Stem
moveTo(12f, 18f)
verticalLineTo(22f)
// Base
moveTo(8f, 22f)
horizontalLineTo(16f)
}
}.build()
}
val AudioLines: ImageVector by lazy {
ImageVector.Builder("AudioLines", 24.dp, 24.dp, 24f, 24f).apply {
path(
stroke = SolidColor(Color.Black),
strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Round,
) {
moveTo(2f, 10f)
verticalLineTo(14f)
moveTo(6f, 6f)
verticalLineTo(18f)
moveTo(10f, 3f)
verticalLineTo(21f)
moveTo(14f, 6f)
verticalLineTo(18f)
moveTo(18f, 8f)
verticalLineTo(16f)
moveTo(22f, 10f)
verticalLineTo(14f)
}
}.build()
}
val Brain: ImageVector by lazy {
ImageVector.Builder("Brain", 24.dp, 24.dp, 24f, 24f).apply {
path(
stroke = SolidColor(Color.Black),
strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Round,
strokeLineJoin = StrokeJoin.Round,
) {
// Left hemisphere
moveTo(12f, 5f)
curveTo(12f, 5f, 10f, 2f, 7.5f, 2f)
curveTo(5f, 2f, 3f, 4f, 3f, 6.5f)
curveTo(3f, 8f, 3.5f, 9f, 3f, 10f)
curveTo(2f, 11.5f, 2f, 13.5f, 3.5f, 15f)
curveTo(3f, 16f, 3f, 17.5f, 4f, 18.5f)
curveTo(5f, 19.5f, 6.5f, 20f, 8f, 19.5f)
curveTo(9f, 21f, 10.5f, 22f, 12f, 22f)
// Right hemisphere
moveTo(12f, 5f)
curveTo(12f, 5f, 14f, 2f, 16.5f, 2f)
curveTo(19f, 2f, 21f, 4f, 21f, 6.5f)
curveTo(21f, 8f, 20.5f, 9f, 21f, 10f)
curveTo(22f, 11.5f, 22f, 13.5f, 20.5f, 15f)
curveTo(21f, 16f, 21f, 17.5f, 20f, 18.5f)
curveTo(19f, 19.5f, 17.5f, 20f, 16f, 19.5f)
curveTo(15f, 21f, 13.5f, 22f, 12f, 22f)
// Center stem
moveTo(12f, 5f)
verticalLineTo(22f)
}
}.build()
}
val SlidersHorizontal: ImageVector by lazy {
ImageVector.Builder("SlidersHorizontal", 24.dp, 24.dp, 24f, 24f).apply {
path(
stroke = SolidColor(Color.Black),
strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Round,
) {
// Lines
moveTo(21f, 4f)
horizontalLineTo(14f)
moveTo(10f, 4f)
horizontalLineTo(3f)
moveTo(21f, 12f)
horizontalLineTo(12f)
moveTo(8f, 12f)
horizontalLineTo(3f)
moveTo(21f, 20f)
horizontalLineTo(16f)
moveTo(12f, 20f)
horizontalLineTo(3f)
// Knobs as small circles (arc approximation)
// Top knob at x=12, y=4, r=2
moveTo(14f, 4f)
curveTo(14f, 5.1f, 13.1f, 6f, 12f, 6f)
curveTo(10.9f, 6f, 10f, 5.1f, 10f, 4f)
curveTo(10f, 2.9f, 10.9f, 2f, 12f, 2f)
curveTo(13.1f, 2f, 14f, 2.9f, 14f, 4f)
close()
// Middle knob at x=10, y=12, r=2
moveTo(12f, 12f)
curveTo(12f, 13.1f, 11.1f, 14f, 10f, 14f)
curveTo(8.9f, 14f, 8f, 13.1f, 8f, 12f)
curveTo(8f, 10.9f, 8.9f, 10f, 10f, 10f)
curveTo(11.1f, 10f, 12f, 10.9f, 12f, 12f)
close()
// Bottom knob at x=14, y=20, r=2
moveTo(16f, 20f)
curveTo(16f, 21.1f, 15.1f, 22f, 14f, 22f)
curveTo(12.9f, 22f, 12f, 21.1f, 12f, 20f)
curveTo(12f, 18.9f, 12.9f, 18f, 14f, 18f)
curveTo(15.1f, 18f, 16f, 18.9f, 16f, 20f)
close()
}
}.build()
}
val Globe: ImageVector by lazy {
ImageVector.Builder("Globe", 24.dp, 24.dp, 24f, 24f).apply {
path(
stroke = SolidColor(Color.Black),
strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Round,
strokeLineJoin = StrokeJoin.Round,
) {
// Outer circle
moveTo(22f, 12f)
curveTo(22f, 17.52f, 17.52f, 22f, 12f, 22f)
curveTo(6.48f, 22f, 2f, 17.52f, 2f, 12f)
curveTo(2f, 6.48f, 6.48f, 2f, 12f, 2f)
curveTo(17.52f, 2f, 22f, 6.48f, 22f, 12f)
close()
// Vertical ellipse
moveTo(12f, 2f)
curveTo(8f, 2f, 6.5f, 7f, 6.5f, 12f)
curveTo(6.5f, 17f, 8f, 22f, 12f, 22f)
moveTo(12f, 2f)
curveTo(16f, 2f, 17.5f, 7f, 17.5f, 12f)
curveTo(17.5f, 17f, 16f, 22f, 12f, 22f)
// Horizontal line
moveTo(2f, 12f)
horizontalLineTo(22f)
}
}.build()
}
val ImageIcon: ImageVector by lazy {
ImageVector.Builder("ImageIcon", 24.dp, 24.dp, 24f, 24f).apply {
path(
stroke = SolidColor(Color.Black),
strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Round,
strokeLineJoin = StrokeJoin.Round,
) {
// Frame (rounded rect)
moveTo(19f, 3f)
horizontalLineTo(5f)
curveTo(3.9f, 3f, 3f, 3.9f, 3f, 5f)
verticalLineTo(19f)
curveTo(3f, 20.1f, 3.9f, 21f, 5f, 21f)
horizontalLineTo(19f)
curveTo(20.1f, 21f, 21f, 20.1f, 21f, 19f)
verticalLineTo(5f)
curveTo(21f, 3.9f, 20.1f, 3f, 19f, 3f)
close()
// Sun dot
moveTo(10.5f, 8f)
curveTo(10.5f, 8.83f, 9.83f, 9.5f, 9f, 9.5f)
curveTo(8.17f, 9.5f, 7.5f, 8.83f, 7.5f, 8f)
curveTo(7.5f, 7.17f, 8.17f, 6.5f, 9f, 6.5f)
curveTo(9.83f, 6.5f, 10.5f, 7.17f, 10.5f, 8f)
close()
// Mountain
moveTo(21f, 15f)
lineTo(16f, 10f)
lineTo(5f, 21f)
}
}.build()
}
}

View file

@ -23,28 +23,28 @@ object KaizenIcons {
val ArrowLeft: ImageVector get() = Lucide.ArrowLeft
val ChevronDown: ImageVector get() = Lucide.ChevronDown
val ChevronUp: ImageVector get() = Lucide.ChevronUp
val Menu: ImageVector get() = Lucide.Menu
val Menu: ImageVector get() = KaizenCustomIcons.Menu
val MoreVertical: ImageVector get() = Lucide.EllipsisVertical
val Settings: ImageVector get() = Lucide.Settings
val X: ImageVector get() = Lucide.X
// ── Chat ────────────────────────────────────────────────────────────────
val Mic: ImageVector get() = Lucide.Mic
val Mic: ImageVector get() = KaizenCustomIcons.Mic
val Paperclip: ImageVector get() = Lucide.Paperclip
val AudioLines: ImageVector get() = Lucide.AudioLines
val Plus: ImageVector get() = Lucide.Plus
val AudioLines: ImageVector get() = KaizenCustomIcons.AudioLines
val Plus: ImageVector get() = KaizenCustomIcons.Plus
val Send: ImageVector get() = Lucide.SendHorizontal
val Sparkles: ImageVector get() = Lucide.Sparkles
val Square: ImageVector get() = Lucide.Square
val Zap: ImageVector get() = Lucide.Zap
// ── Modes ───────────────────────────────────────────────────────────────
val Brain: ImageVector get() = Lucide.Brain
val Brain: ImageVector get() = KaizenCustomIcons.Brain
val CircleDot: ImageVector get() = Lucide.CircleDot
val Globe: ImageVector get() = Lucide.Globe
val Image: ImageVector get() = Lucide.Image
val Globe: ImageVector get() = KaizenCustomIcons.Globe
val Image: ImageVector get() = KaizenCustomIcons.ImageIcon
val Music: ImageVector get() = Lucide.Music
val SlidersHorizontal: ImageVector get() = Lucide.SlidersHorizontal
val SlidersHorizontal: ImageVector get() = KaizenCustomIcons.SlidersHorizontal
val Video: ImageVector get() = Lucide.Video
// ── Conversation management ─────────────────────────────────────────────