UX audit found that Graph’s “Add Source” button used a filled Button with primaryContainer colors, inconsistent with the InputNodeSelectorSection outlined-pill pattern used by every other “add a related node” action in the catalog. A previous fix attempt swapped it to OutlinedButton but was reverted: colorScheme.outline (#2C2D2D in ChirpyDark) is the same value as GraphMenuBar’s Card surface container color, so the button rendered with an invisible border — a real loss of affordance.
OutlinedButton’s default border resolves to colorScheme.outline, and Material3’s surfaceContainerHigh (the Card default) happens to match that value in the project’s dark theme. No explicit override was set, so the border vanished against the Card background.
GraphScreen.kt GraphMenuBar(): replaced Button(colors = ButtonDefaults.buttonColors(containerColor = primaryContainer)) with OutlinedButton(border = BorderStroke(1.dp, colorScheme.primary), modifier = Modifier.fillMaxWidth()). Using primary rather than outline for the border guarantees contrast against any surface container in both dark and light themes, since primary is explicitly designed to be high-contrast against surfaces.
When placing an OutlinedButton inside a Card, verify that colorScheme.outline contrasts against that Card’s actual background before relying on the default border. If the Card uses the M3 default (surfaceContainerHigh) in a dark theme, the outline may be invisible — pass an explicit border = BorderStroke(…, colorScheme.primary) to guarantee affordance. As a rule: colorScheme.primary is always safe for a visible action border on any surface; colorScheme.outline is only safe when the surrounding container’s color is confirmed to differ.