#[non_exhaustive]pub enum FindingKind {
Show 13 variants
RawColor,
Overflow,
TextOverflow,
DuplicateId,
Alignment,
Spacing,
MissingSurfaceFill,
ReinventedWidget,
FocusRingObscured,
ScrollbarObscuresFocusable,
DeadTooltip,
CornerStackup,
UnpaddedSurfacePanel,
}Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
RawColor
Overflow
TextOverflow
DuplicateId
Alignment
Spacing
MissingSurfaceFill
surface_role(SurfaceRole::Panel) on a node with no fill — the
role only paints stroke + shadow, so the surface reads as a
thin border floating over the parent. Either set a fill
(tokens::CARD is the usual choice) or — more often — swap to a
widget like card() / sidebar() that bundles role + fill +
stroke + radius + shadow correctly. (Raised is also
decorative but this lint stays narrow to Panel since
button(...).ghost() legitimately produces a Raised node with
no fill.)
ReinventedWidget
A column / row / stack whose visual recipe matches a stock
widget (card, sidebar, …). Reach for the named widget instead —
it bundles the right surface role, radius, shadow, and content
padding. The structural smells live in the widget catalog README;
this lint catches the two highest-confidence signatures
(fill=CARD + stroke=BORDER + radius>0 ⇒ card(),
fill=CARD + stroke=BORDER + width=SIDEBAR_WIDTH without a Panel
surface role ⇒ sidebar()).
FocusRingObscured
A focusable node’s paint_overflow band (the focus-ring band)
would render obscured at runtime — either because the nearest
clipping ancestor’s scissor cuts it, or because a later-painted
sibling’s rect overlaps the bleed region and paints on top.
Common fixes:
- Clipped: give the clipping ancestor (or an intermediate
container) padding ≥
tokens::RING_WIDTHon the clipped side so the band lives inside the scissor. - Occluded: add gap between the focusable element and the
neighbor (≥
tokens::RING_WIDTH), or restructure so the neighbor doesn’t sit on the focusable element’s edge.
ScrollbarObscuresFocusable
A focusable node sits inside a scrolling ancestor whose scrollbar thumb is currently rendered (content overflows), and the focusable’s rect overlaps the thumb’s track on the x-axis — so the thumb paints on top of the control whenever the user scrolls to it.
The trap is that giving the scroll itself horizontal padding
(the natural reading of FocusRingObscured’s message) shifts
inner and the thumb together: padding clears the focus-ring
scissor, but the thumb still sits in the rightmost
SCROLLBAR_THUMB_WIDTH + SCROLLBAR_TRACK_INSET pixels of the
children’s visible area.
Fix: move horizontal padding inside the scroll, onto a wrapper that constrains children to a narrower content rect, so the thumb sits in a reserved gutter to the right of content.
DeadTooltip
.tooltip() on a node that has no .key(). Tooltips fire
through the hit-test pipeline, and hit_test only returns
keyed nodes — hover skips past unkeyed leaves to the nearest
keyed ancestor (which has a different computed_id and a
different tooltip lookup), so the tooltip is silently dead.
Fix: add .key("…") to the same node that carries the
tooltip. For info-only chrome inside list rows (sha cells,
timestamps, chips, identicon avatars) the usual key is a
synthetic one like "row:{idx}.<part>" — its only purpose is
to make the tooltip’s hover land. Moving the .tooltip() to
a keyed ancestor instead conflates “I want a hover popover
here” with “I’m declaring a click/focus target,” and is
usually not what you want.
CornerStackup
A filled child paints into a rounded ancestor’s corner-curve area without rounding its own matching corner. The child’s flat-cornered fill obscures the parent’s curve and stroke, producing the “sharp corner superimposed on a radiused container” artifact.
The canonical recipe (card_header([...]).fill(MUTED) inside
card([...])) is auto-fixed by the metrics pass — see
crate::metrics. This lint catches hand-rolled cases:
reinvented cards with reinvented headers, custom inspector
frames, accordion-like containers, etc.
Fix: set the matching corner radii on the child
(.radius(Corners::top(N)) for a header strip,
Corners::bottom(N) for a footer), or add padding to the
parent so the child is inset from the curve.
UnpaddedSurfacePanel
A surface_role=Panel node whose direct children sit flush
against one or more of its outer edges with no padding
(neither on the panel nor on the touching child) to inset the
content. The canonical trip is card([...]) called without
the card_header / card_content / card_footer slot
wrappers and without an explicit .padding(...): card()
itself carries no inner padding, so titles paint on the top
stroke, action buttons paint on the bottom stroke, and chip
rows pin to the left edge.
The check is per-side. A side is treated as “padded” — and so
is not flagged — when either the panel itself pads on that
side, or any child whose rect touches that side carries
inward padding on that side. So the canonical anatomy
(card_header pads top/left/right, card_footer pads
bottom/left/right, both at SPACE_6) stays quiet without
special-casing.
Fixes:
- Wrap content in the slot anatomy:
card([card_header([...]), card_content([...]), card_footer([...])])— each slot bakes the shadcnSPACE_6padding recipe. - For dense list-row cards where the slot padding feels too
generous, pad the panel itself:
card([...]).padding(Sides::all(tokens::SPACE_4)).
Trait Implementations§
Source§impl Clone for FindingKind
impl Clone for FindingKind
Source§fn clone(&self) -> FindingKind
fn clone(&self) -> FindingKind
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for FindingKind
impl Debug for FindingKind
Source§impl PartialEq for FindingKind
impl PartialEq for FindingKind
Source§fn eq(&self, other: &FindingKind) -> bool
fn eq(&self, other: &FindingKind) -> bool
self and other values to be equal, and is used by ==.impl Copy for FindingKind
impl Eq for FindingKind
impl StructuralPartialEq for FindingKind
Auto Trait Implementations§
impl Freeze for FindingKind
impl RefUnwindSafe for FindingKind
impl Send for FindingKind
impl Sync for FindingKind
impl Unpin for FindingKind
impl UnsafeUnpin for FindingKind
impl UnwindSafe for FindingKind
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.