@commonpub/layer 0.39.0 → 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -124,25 +124,17 @@ const columns = computed(() => props.config.columns ?? 2);
124
124
  .cpub-tab.active { color: var(--accent); border-bottom-color: var(--accent); }
125
125
 
126
126
  /*
127
- * Session 164 polish: cap the grid's max width so cards don't stretch
128
- * into a "giant cards in mobile layout" pattern at desktop widths.
129
- *
130
- * Was: `grid-template-columns: repeat(2, 1fr)` with NO width cap at
131
- * 1440px window, 2 columns of ~700px each. Cards stretched far past
132
- * their natural design width and read as "single column of bigs".
133
- *
134
- * Now: same column behavior but bounded by --content-max-width (default
135
- * 1280px) — matches the tabs-inner cap above (same theme token). At
136
- * 1280px and below, behaves identically to before. Above, the grid
137
- * stays at 1280 centered and cards stay at their design proportions.
138
- *
139
- * `var(--grid-cols)` config still drives column count. Mobile drops to
140
- * 1-column at <=768px (unchanged).
127
+ * Responsive card grid: auto-fill columns at a fixed min-width so cards stay
128
+ * a single, consistent size everywhere (the `--cpub-card-min`/`--cpub-card-gap`
129
+ * tokens — see packages/ui/theme/base.css). The old `repeat(var(--grid-cols),
130
+ * 1fr)` stretched 2 columns to ~470px each ("giant cards"); auto-fill keeps
131
+ * cards at their design width and simply fits as many as the row allows.
132
+ * Bounded by --content-max-width and centered.
141
133
  */
142
134
  .cpub-content-grid {
143
135
  display: grid;
144
- grid-template-columns: repeat(var(--grid-cols, 2), 1fr);
145
- gap: 16px;
136
+ grid-template-columns: repeat(auto-fill, minmax(var(--cpub-card-min, 260px), 1fr));
137
+ gap: var(--cpub-card-gap, 20px);
146
138
  max-width: var(--content-max-width, 1280px);
147
139
  margin-inline: auto;
148
140
  }
@@ -151,5 +143,5 @@ const columns = computed(() => props.config.columns ?? 2);
151
143
  .cpub-btn-load-more { font-family: var(--font-mono); font-size: 11px; padding: 8px 20px; border: var(--border-width-default) solid var(--border); background: var(--surface); color: var(--text-dim); cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }
152
144
  .cpub-btn-load-more:hover { border-color: var(--accent); color: var(--accent); }
153
145
 
154
- @media (max-width: 768px) { .cpub-content-grid { grid-template-columns: 1fr; } }
146
+ @media (max-width: 640px) { .cpub-content-grid { grid-template-columns: 1fr; } }
155
147
  </style>
@@ -26,7 +26,7 @@ const { data: editorialPicks } = await useFetch<PaginatedResponse<Serialized<Con
26
26
  .cpub-editorial-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
27
27
  .cpub-editorial-heading { font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--teal); display: flex; align-items: center; gap: 6px; }
28
28
  .cpub-editorial-heading i { font-size: 10px; }
29
- .cpub-editorial-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
29
+ .cpub-editorial-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--cpub-card-min, 260px), 1fr)); gap: var(--cpub-card-gap, 20px); }
30
30
  .cpub-editorial-single { grid-template-columns: 1fr; max-width: 400px; }
31
31
  @media (max-width: 768px) { .cpub-editorial-grid { grid-template-columns: 1fr; } }
32
32
  </style>
@@ -105,8 +105,8 @@ async function shareProjectToHub(contentId: string): Promise<void> {
105
105
  <style scoped>
106
106
  .cpub-gallery-grid {
107
107
  display: grid;
108
- grid-template-columns: repeat(3, 1fr);
109
- gap: 16px;
108
+ grid-template-columns: repeat(auto-fill, minmax(var(--cpub-card-min, 260px), 1fr));
109
+ gap: var(--cpub-card-gap, 20px);
110
110
  }
111
111
 
112
112
  /* Modal */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commonpub/layer",
3
- "version": "0.39.0",
3
+ "version": "0.41.0",
4
4
  "type": "module",
5
5
  "main": "./nuxt.config.ts",
6
6
  "files": [
@@ -54,15 +54,15 @@
54
54
  "vue-router": "^4.3.0",
55
55
  "zod": "^4.3.6",
56
56
  "@commonpub/auth": "0.7.0",
57
- "@commonpub/docs": "0.6.3",
58
57
  "@commonpub/config": "0.16.0",
58
+ "@commonpub/docs": "0.6.3",
59
+ "@commonpub/explainer": "0.7.15",
59
60
  "@commonpub/editor": "0.7.11",
60
61
  "@commonpub/learning": "0.5.2",
61
- "@commonpub/protocol": "0.12.0",
62
- "@commonpub/explainer": "0.7.15",
63
62
  "@commonpub/schema": "0.24.0",
64
63
  "@commonpub/ui": "0.9.1",
65
- "@commonpub/server": "2.67.0"
64
+ "@commonpub/protocol": "0.12.0",
65
+ "@commonpub/server": "2.69.0"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@testing-library/jest-dom": "^6.9.1",
@@ -111,8 +111,8 @@ const { data, pending } = await useFetch<PaginatedResponse<Serialized<ContentLis
111
111
 
112
112
  .cpub-listing-grid {
113
113
  display: grid;
114
- grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
115
- gap: var(--space-4);
114
+ grid-template-columns: repeat(auto-fill, minmax(var(--cpub-card-min, 260px), 1fr));
115
+ gap: var(--cpub-card-gap, 20px);
116
116
  }
117
117
 
118
118
  .cpub-listing-empty {
package/pages/explore.vue CHANGED
@@ -461,8 +461,8 @@ const sortOptions = [
461
461
  2-col hub/people grid ≈ 470px each) that didn't adapt to the container. */
462
462
  .cpub-explore-grid {
463
463
  display: grid;
464
- grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
465
- gap: 16px;
464
+ grid-template-columns: repeat(auto-fill, minmax(var(--cpub-card-min, 260px), 1fr));
465
+ gap: var(--cpub-card-gap, 20px);
466
466
  }
467
467
 
468
468
  /* Hub cards (horizontal layout — slightly wider min) */
@@ -556,8 +556,8 @@ async function handlePostVote(postId: string): Promise<void> {
556
556
  .cpub-hub-projects-tab { padding: 0; }
557
557
  .cpub-shared-grid {
558
558
  display: grid;
559
- grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
560
- gap: 16px;
559
+ grid-template-columns: repeat(auto-fill, minmax(var(--cpub-card-min, 260px), 1fr));
560
+ gap: var(--cpub-card-gap, 20px);
561
561
  }
562
562
  .cpub-shared-card {
563
563
  background: var(--surface); border: var(--border-width-default) solid var(--border);
package/pages/feed.vue CHANGED
@@ -111,7 +111,7 @@ const filters = computed(() => [
111
111
  .feed-filter.active { border-color: var(--accent); background: var(--accent-bg); color: var(--accent); }
112
112
  .feed-filter i { font-size: 10px; }
113
113
 
114
- .feed-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; }
114
+ .feed-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--cpub-card-min, 260px), 1fr)); gap: var(--cpub-card-gap, 20px); }
115
115
 
116
116
  .feed-loading { text-align: center; padding: 48px 0; color: var(--text-faint); font-size: 13px; }
117
117
 
package/pages/index.vue CHANGED
@@ -720,8 +720,8 @@ async function handleHubJoin(hubSlug: string): Promise<void> {
720
720
 
721
721
  .cpub-editorial-grid {
722
722
  display: grid;
723
- grid-template-columns: repeat(3, 1fr);
724
- gap: 16px;
723
+ grid-template-columns: repeat(auto-fill, minmax(var(--cpub-card-min, 260px), 1fr));
724
+ gap: var(--cpub-card-gap, 20px);
725
725
  }
726
726
 
727
727
  .cpub-editorial-single {
@@ -906,8 +906,8 @@ async function handleHubJoin(hubSlug: string): Promise<void> {
906
906
  /* ─── CONTENT GRID ─── */
907
907
  .cpub-content-grid {
908
908
  display: grid;
909
- grid-template-columns: 1fr 1fr;
910
- gap: 18px;
909
+ grid-template-columns: repeat(auto-fill, minmax(var(--cpub-card-min, 260px), 1fr));
910
+ gap: var(--cpub-card-gap, 20px);
911
911
  margin-bottom: 24px;
912
912
  }
913
913
 
@@ -113,7 +113,7 @@ useSeoMeta({
113
113
  .product-link-btn { display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; border: var(--border-width-default) solid var(--border); background: var(--surface); color: var(--text); text-decoration: none; font-size: 13px; font-weight: 500; box-shadow: var(--shadow-md); }
114
114
  .product-link-btn:hover { box-shadow: var(--shadow-sm); transform: translate(1px, 1px); }
115
115
 
116
- .product-projects-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
116
+ .product-projects-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--cpub-card-min, 260px), 1fr)); gap: var(--cpub-card-gap, 20px); }
117
117
  .product-projects-empty { color: var(--text-faint); font-size: 13px; padding: 24px 0; }
118
118
 
119
119
  .product-sidebar { display: flex; flex-direction: column; gap: 16px; }
package/pages/search.vue CHANGED
@@ -711,8 +711,8 @@ const { data: relatedCommunities } = await useFetch('/api/hubs', {
711
711
  /* ── RESULTS GRID ── */
712
712
  .cpub-results-grid {
713
713
  display: grid;
714
- grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
715
- gap: 20px;
714
+ grid-template-columns: repeat(auto-fill, minmax(var(--cpub-card-min, 260px), 1fr));
715
+ gap: var(--cpub-card-gap, 20px);
716
716
  margin-bottom: 32px;
717
717
  }
718
718
 
@@ -121,8 +121,8 @@ async function loadMore(): Promise<void> {
121
121
 
122
122
  .cpub-tag-grid {
123
123
  display: grid;
124
- grid-template-columns: repeat(3, 1fr);
125
- gap: 16px;
124
+ grid-template-columns: repeat(auto-fill, minmax(var(--cpub-card-min, 260px), 1fr));
125
+ gap: var(--cpub-card-gap, 20px);
126
126
  }
127
127
 
128
128
  .cpub-tag-more {
@@ -295,8 +295,8 @@ onMounted(() => {
295
295
 
296
296
  .cpub-view-related-grid {
297
297
  display: grid;
298
- grid-template-columns: repeat(3, 1fr);
299
- gap: var(--space-4);
298
+ grid-template-columns: repeat(auto-fill, minmax(var(--cpub-card-min, 260px), 1fr));
299
+ gap: var(--cpub-card-gap, 20px);
300
300
  }
301
301
 
302
302
  .cpub-not-found {
@@ -825,8 +825,8 @@ async function handleReport(): Promise<void> {
825
825
  /* Grid */
826
826
  .cpub-grid-3 {
827
827
  display: grid;
828
- grid-template-columns: repeat(3, 1fr);
829
- gap: 16px;
828
+ grid-template-columns: repeat(auto-fill, minmax(var(--cpub-card-min, 260px), 1fr));
829
+ gap: var(--cpub-card-gap, 20px);
830
830
  }
831
831
 
832
832
  .cpub-dropdown {
package/theme/base.css CHANGED
@@ -222,6 +222,15 @@
222
222
  --content-max-width: 60rem; /* 960px */
223
223
  --content-wide-max-width: 75rem;
224
224
 
225
+ /* === CONTENT-CARD GRID ===
226
+ Every grid that lays out <ContentCard> draws its column min-width + gap
227
+ from these tokens so cards are a single, consistent size everywhere they
228
+ appear (home feed, listing pages, search, explore, profiles, hubs…).
229
+ Default values match deveco.io's responsive card grid. Instances retune
230
+ by overriding these tokens in their theme CSS — no per-view edits. */
231
+ --cpub-card-min: 260px; /* min column width before wrapping (auto-fill) */
232
+ --cpub-card-gap: 20px; /* gutter between cards */
233
+
225
234
  /* === FOCUS === */
226
235
  --focus-ring: var(--shadow-accent);
227
236
  }