WIP PWA for Grain
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: ensure feed layout is full width to prevent skeleton shift

- Add width: 100% to grain-feed-layout to prevent shrinking to content
- Update skeleton to use display: block matching profile header
- Use percentage-based widths for skeleton placeholders

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

+8 -50
-45
docs/plans/2025-12-29-profile-skeleton-design.md
··· 1 - # Profile Header Skeleton 2 - 3 - ## Problem 4 - 5 - Fresh profile loads cause layout shift. The spinner takes minimal space (~24px), then the full header (~200px) pops in when data arrives. 6 - 7 - ## Solution 8 - 9 - Add a skeleton loader that matches the profile header's exact dimensions. 10 - 11 - ## Component Structure 12 - 13 - ``` 14 - grain-profile-header-skeleton 15 - ├── .top-row (flex) 16 - │ ├── .avatar-placeholder (80px circle) 17 - │ └── .right-column (flex: 1) 18 - │ ├── .handle-placeholder (120px × 20px bar) 19 - │ ├── .name-placeholder (80px × 14px bar) 20 - │ ├── .stats-placeholder (3 small boxes) 21 - │ └── .bio-placeholder (2 lines, varying widths) 22 - └── .button-placeholder (full-width bar for follow button) 23 - ``` 24 - 25 - ## Styling 26 - 27 - - Placeholders: `background: var(--color-bg-elevated)` with pulse animation 28 - - Border radius: 4-8px for text bars, 50% for avatar 29 - - Spacing: Match `grain-profile-header` exactly 30 - - Animation: 1.5s ease-in-out infinite pulse 31 - 32 - ## File Changes 33 - 34 - | File | Change | 35 - |------|--------| 36 - | `src/components/molecules/grain-profile-header-skeleton.js` | New component | 37 - | `src/components/pages/grain-profile.js` | Swap spinner for skeleton | 38 - 39 - ## Integration 40 - 41 - Replace spinner with skeleton in `grain-profile.js`: 42 - 43 - ```javascript 44 - ${this._loading ? html`<grain-profile-header-skeleton></grain-profile-header-skeleton>` : ''} 45 - ```
+7 -5
src/components/molecules/grain-profile-header-skeleton.js
··· 4 4 static styles = css` 5 5 :host { 6 6 display: block; 7 - width: 100%; 8 7 padding: var(--space-md) var(--space-sm); 9 8 } 10 9 @media (min-width: 600px) { ··· 42 41 margin-bottom: var(--space-xs); 43 42 } 44 43 .handle { 45 - width: 140px; 44 + width: 60%; 45 + max-width: 200px; 46 46 height: 22px; 47 47 } 48 48 .menu-icon { ··· 51 51 border-radius: 50%; 52 52 } 53 53 .name { 54 - width: 90px; 54 + width: 40%; 55 + max-width: 120px; 55 56 height: 16px; 56 57 margin-bottom: var(--space-xs); 57 58 } ··· 61 62 margin-bottom: var(--space-xs); 62 63 } 63 64 .stat { 64 - width: 85px; 65 + width: 80px; 65 66 height: 16px; 66 67 } 67 68 .bio { 68 - width: 180px; 69 + width: 70%; 70 + max-width: 250px; 69 71 height: 16px; 70 72 margin-top: var(--space-xs); 71 73 }
+1
src/components/templates/grain-feed-layout.js
··· 6 6 display: flex; 7 7 flex-direction: column; 8 8 flex: 1; 9 + width: 100%; 9 10 max-width: var(--feed-max-width); 10 11 margin: 0 auto; 11 12 min-height: 100%;