Skip to content

Commit 196e217

Browse files
committed
fix(SummaryCard): fix button skeleton padding and merge button width docs
## Bug Fixes - Fix button skeleton 2px bottom padding issue (Issue #15) - Changed .buttonSkeletonWrapper from inline-flex to flex - Eliminates baseline spacing that created extra bottom padding - Loading and data states now have identical height ## Documentation - Merge Button Width Behavior section into main SummaryCards story - Consolidates button width documentation for better discoverability - Shows buttonFullWidth prop behavior with live examples - Demonstrates loading state skeleton consistency - Includes implementation details with CSS code snippet ## Code Quality - Fix lint errors in generate-schemas.ts (use unknown instead of any) - Fix lint error in Button.test.tsx (remove unused variable) - Fix lint error in MapContent.tsx (add eslint-disable for necessary any) ## Changes - Simplified button width logic (removed responsive @media query) - Button width is now fixed based on buttonFullWidth prop only - No responsive behavior - more predictable and maintainable
1 parent a950ae7 commit 196e217

File tree

8 files changed

+266
-18
lines changed

8 files changed

+266
-18
lines changed

CHANGELOG.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.8.0] - 2025-11-08
11+
12+
### Fixed
13+
14+
- **SummaryCard**: Button skeleton width now matches button width (Issue #15)
15+
- Skeleton buttons use the same width logic as real buttons
16+
- `buttonFullWidth={false}` → auto-width (min 120px) for both skeleton and button
17+
- `buttonFullWidth={true}` → full-width (100%) for both skeleton and button
18+
- `buttonFullWidth={undefined}` → variant-based (full for default, auto for flat)
19+
20+
### Changed
21+
22+
- **SummaryCard**: Simplified `buttonFullWidth` behavior
23+
- `buttonFullWidth={false}`: Always auto-width (min 120px)
24+
- `buttonFullWidth={true}`: Always full-width (100%)
25+
- `buttonFullWidth={undefined}`: Full-width for default variant, auto-width for flat variant
26+
- Button width is now fixed and predictable - no responsive behavior
27+
- Simpler implementation using standard CSS
28+
29+
### Technical Details
30+
31+
All components use simple, predictable viewport-based media queries for responsive behavior:
32+
33+
```css
34+
/* SummaryCard: Fixed button widths based on prop */
35+
.buttonSection[data-full-width='false'] .button {
36+
width: auto;
37+
min-width: 120px;
38+
}
39+
40+
/* List & AlbumViewer: Viewport-based responsive behavior */
41+
@media (min-width: 640px) {
42+
/* Tablet/desktop styles */
43+
}
44+
```
45+
1046
## [0.7.0] - 2025-11-08
1147

1248
### Added

packages/ui/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ainativekit/ui",
3-
"version": "0.7.0",
3+
"version": "0.8.0",
44
"description": "AI Native Kit - Component library for AI-powered applications",
55
"type": "module",
66
"main": "./dist/index.cjs",

packages/ui/scripts/generate-schemas.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,8 @@ const indexContent = {
154154
import: '@ainativekit/ui',
155155
};
156156
return acc;
157-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
158157
},
159-
{} as Record<string, any>
158+
{} as Record<string, unknown>
160159
),
161160
};
162161

packages/ui/src/components/Button/__tests__/Button.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ describe('Button', () => {
185185
});
186186

187187
it('should update when brand colors change', () => {
188-
const { container, rerender } = render(
188+
const { rerender } = render(
189189
<ThemeProvider brandColors={{ primary: '#6B46C1' }}>
190190
<Button variant="primary" color="primary">
191191
Button

packages/ui/src/components/Card/SummaryCard.module.css

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -303,22 +303,20 @@
303303
width: 100%;
304304
}
305305

306-
/* Button skeleton wrapper - matches Button component's inline-flex behavior */
306+
/* Button skeleton wrapper */
307307
.buttonSkeletonWrapper {
308-
display: inline-flex;
308+
display: flex;
309309
width: 100%;
310310
}
311311

312-
/* Desktop: Button auto-width when not full-width */
313-
@media (min-width: 768px) /* desktop */ {
314-
.buttonSection[data-full-width='false'] .button {
315-
width: auto;
316-
min-width: 120px;
317-
}
312+
/* Button auto-width when buttonFullWidth={false} */
313+
.buttonSection[data-full-width='false'] .button {
314+
width: auto;
315+
min-width: 120px;
316+
}
318317

319-
.buttonSection[data-full-width='false'] .buttonSkeletonWrapper {
320-
width: var(--button-skeleton-width, 140px);
321-
}
318+
.buttonSection[data-full-width='false'] .buttonSkeletonWrapper {
319+
width: var(--button-skeleton-width, 140px);
322320
}
323321

324322
/* Error State */

packages/ui/src/components/Card/SummaryCard.stories.tsx

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,220 @@ const SummaryCardsComponent: React.FC = () => {
828828
</div>
829829
</section>
830830

831+
{/* Button Width Behavior */}
832+
<section style={{ marginBottom: '64px' }}>
833+
<header style={{ marginBottom: '24px' }}>
834+
<h2 style={{ marginBottom: '8px' }}>Button Width Behavior</h2>
835+
<p style={{ color: 'var(--ai-color-text-secondary)', margin: 0, fontSize: '14px' }}>
836+
SummaryCard buttons have fixed, predictable widths based on the buttonFullWidth prop.
837+
Button width does NOT change based on container or viewport size.
838+
</p>
839+
</header>
840+
841+
{/* buttonFullWidth prop examples */}
842+
<div style={{ marginBottom: '48px' }}>
843+
<h3 style={{ marginBottom: '12px', fontSize: '16px', fontWeight: 600 }}>
844+
buttonFullWidth Prop Behavior
845+
</h3>
846+
<p
847+
style={{
848+
color: 'var(--ai-color-text-secondary)',
849+
fontSize: '14px',
850+
marginBottom: '16px',
851+
}}
852+
>
853+
The button width is determined by the buttonFullWidth prop and never changes based on
854+
container or viewport size.
855+
</p>
856+
<div
857+
style={{
858+
display: 'grid',
859+
gridTemplateColumns: 'repeat(auto-fill, minmax(320px, 1fr))',
860+
gap: '24px',
861+
marginBottom: '16px',
862+
}}
863+
>
864+
<div>
865+
<p style={{ fontSize: '12px', marginBottom: '8px', fontWeight: 600 }}>
866+
buttonFullWidth={'{true}'}
867+
</p>
868+
<SummaryCard
869+
images={SAMPLE_IMAGES.restaurant}
870+
title="Full Width Button"
871+
subtitle="Always 100% width"
872+
badge="9.2"
873+
description="Button spans the full width of the card"
874+
buttonText="Reserve Table"
875+
buttonFullWidth={true}
876+
style={{ maxWidth: `${CARD_WIDTH}px` }}
877+
/>
878+
</div>
879+
880+
<div>
881+
<p style={{ fontSize: '12px', marginBottom: '8px', fontWeight: 600 }}>
882+
buttonFullWidth={'{false}'}
883+
</p>
884+
<SummaryCard
885+
images={SAMPLE_IMAGES.pizza}
886+
title="Auto Width Button"
887+
subtitle="Always auto (min 120px)"
888+
badge="8.5"
889+
description="Button is auto-width with minimum 120px"
890+
buttonText="Order Now"
891+
buttonFullWidth={false}
892+
style={{ maxWidth: `${CARD_WIDTH}px` }}
893+
/>
894+
</div>
895+
896+
<div>
897+
<p style={{ fontSize: '12px', marginBottom: '8px', fontWeight: 600 }}>
898+
buttonFullWidth={'{undefined}'} (flat variant)
899+
</p>
900+
<SummaryCard
901+
variant="flat"
902+
images={SAMPLE_IMAGES.pasta}
903+
title="Default Behavior"
904+
subtitle="Auto for flat variant"
905+
badge="9.0"
906+
description="Flat variant defaults to auto-width button"
907+
buttonText="View Menu"
908+
style={{ maxWidth: `${CARD_WIDTH}px` }}
909+
/>
910+
</div>
911+
</div>
912+
<p
913+
style={{
914+
color: 'var(--ai-color-text-secondary)',
915+
fontSize: '12px',
916+
fontStyle: 'italic',
917+
}}
918+
>
919+
✅ Button widths remain consistent regardless of card container size
920+
</p>
921+
</div>
922+
923+
{/* Loading State Example */}
924+
<div style={{ marginBottom: '48px' }}>
925+
<h3 style={{ marginBottom: '12px', fontSize: '16px', fontWeight: 600 }}>
926+
Loading State - Skeleton Consistency
927+
</h3>
928+
<p
929+
style={{
930+
color: 'var(--ai-color-text-secondary)',
931+
fontSize: '14px',
932+
marginBottom: '16px',
933+
}}
934+
>
935+
Skeleton buttons now match real button widths (fixes Issue #15).
936+
</p>
937+
<div
938+
style={{
939+
display: 'grid',
940+
gridTemplateColumns: 'repeat(auto-fill, minmax(320px, 1fr))',
941+
gap: '24px',
942+
marginBottom: '16px',
943+
}}
944+
>
945+
<div>
946+
<p style={{ fontSize: '12px', marginBottom: '8px', fontWeight: 600 }}>
947+
buttonFullWidth={'{false}'} - Loading
948+
</p>
949+
<SummaryCard
950+
title="Loading State"
951+
subtitle="Auto Width Button"
952+
description="Skeleton button is auto-width (min 120px)"
953+
buttonText="View Details"
954+
buttonFullWidth={false}
955+
loading={true}
956+
style={{ maxWidth: `${CARD_WIDTH}px` }}
957+
/>
958+
</div>
959+
960+
<div>
961+
<p style={{ fontSize: '12px', marginBottom: '8px', fontWeight: 600 }}>
962+
buttonFullWidth={'{false}'} - Loaded
963+
</p>
964+
<SummaryCard
965+
images={SAMPLE_IMAGES.pizza}
966+
title="Loaded State"
967+
subtitle="Auto Width Button"
968+
description="Real button is auto-width (min 120px)"
969+
buttonText="View Details"
970+
buttonFullWidth={false}
971+
style={{ maxWidth: `${CARD_WIDTH}px` }}
972+
/>
973+
</div>
974+
</div>
975+
<p
976+
style={{
977+
color: 'var(--ai-color-text-secondary)',
978+
fontSize: '12px',
979+
fontStyle: 'italic',
980+
}}
981+
>
982+
✅ Skeleton and real buttons have identical widths
983+
</p>
984+
</div>
985+
986+
{/* Technical Details */}
987+
<div
988+
style={{
989+
padding: '24px',
990+
background: 'var(--ai-color-bg-secondary)',
991+
borderRadius: '8px',
992+
}}
993+
>
994+
<h3 style={{ marginBottom: '12px', fontSize: '16px', fontWeight: 600 }}>
995+
Implementation
996+
</h3>
997+
<div style={{ fontSize: '14px', lineHeight: '1.6' }}>
998+
<p style={{ marginBottom: '12px' }}>
999+
SummaryCard uses <strong>simple CSS</strong> for predictable button widths:
1000+
</p>
1001+
<pre
1002+
style={{
1003+
background: 'var(--ai-color-bg-primary)',
1004+
padding: '12px',
1005+
borderRadius: '4px',
1006+
overflow: 'auto',
1007+
fontSize: '12px',
1008+
marginBottom: '12px',
1009+
}}
1010+
>
1011+
{`/* Default: Full width */
1012+
.button {
1013+
width: 100%;
1014+
}
1015+
1016+
/* When buttonFullWidth={false}: Auto width */
1017+
.buttonSection[data-full-width='false'] .button {
1018+
width: auto;
1019+
min-width: 120px;
1020+
}
1021+
1022+
/* Skeleton matches button */
1023+
.buttonSection[data-full-width='false'] .buttonSkeletonWrapper {
1024+
width: var(--button-skeleton-width, 140px);
1025+
}`}
1026+
</pre>
1027+
<ul style={{ margin: 0, paddingLeft: '20px' }}>
1028+
<li>
1029+
<strong>No responsive behavior</strong> - Button width is fixed based on prop
1030+
</li>
1031+
<li>
1032+
<strong>Predictable</strong> - Same width regardless of container or viewport size
1033+
</li>
1034+
<li>
1035+
<strong>Simple</strong> - No container queries needed for SummaryCard buttons
1036+
</li>
1037+
<li>
1038+
<strong>Consistent</strong> - Skeleton and real buttons always match
1039+
</li>
1040+
</ul>
1041+
</div>
1042+
</div>
1043+
</section>
1044+
8311045
{/* Discovery/Browse Mode - Compact Size (NEW - replaces DiscoveryCard) */}
8321046
<section style={{ marginBottom: '64px' }}>
8331047
<header style={{ marginBottom: '24px' }}>

packages/ui/src/components/Card/SummaryCard.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,10 @@ export interface SummaryCardProps extends Omit<CardProps, 'children'> {
166166
buttonDisabled?: boolean;
167167

168168
/**
169-
* Button full width on desktop.
169+
* Button width behavior
170170
* - undefined: Auto (full-width for default variant, auto-width for flat variant)
171-
* - true: Full width on all screen sizes
172-
* - false: Auto width on desktop (min 120px), full width on mobile
171+
* - true: Full width (100%)
172+
* - false: Auto width (min 120px)
173173
* @default undefined (auto based on variant)
174174
*/
175175
buttonFullWidth?: boolean;

packages/ui/src/components/Map/MapContent.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ const PinchZoomHandler: React.FC = () => {
114114
accumulatedDelta.current += e.deltaY;
115115

116116
// Store mouse position for zooming around cursor
117+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
117118
lastMousePos.current = map.mouseEventToContainerPoint(e as any);
118119

119120
// Use shorter debounce (10ms instead of 40ms) for more responsive continuous zooming

0 commit comments

Comments
 (0)