@bytebrand/fe-ui-core-autobahn 1.0.4 → 1.0.6

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.
package/cards/CarRow.tsx CHANGED
@@ -102,8 +102,8 @@ const CarRow: React.FunctionComponent<CarRowProps> = ({ car, isFavorite, onToggl
102
102
  <IconButton name="heart" filled active={isFavorite} onClick={onToggleFavorite} label={t('autobahn:card.action.save')} />
103
103
  </div>
104
104
  {/* activity/trust badges — overlaid on the studio-white floor at the bottom of the photo
105
- itself (PM ref), not a separate divided strip below it. Opposite corner from the photo
106
- count so the two never collide. */}
105
+ itself (PM ref), not a separate divided strip below it. Bottom-right, raised above the
106
+ carousel dots and the photo-count badge (positioning lives in .gallery-badges, md3.css). */}
107
107
  <GalleryBadges car={car} t={t} />
108
108
  </div>
109
109
 
@@ -494,38 +494,38 @@ export interface GalleryBadgesProps {
494
494
  }
495
495
 
496
496
  /**
497
- * Trust/activity badges overlaid on the photo itself, bottom-left (PM reference, 2026-07-10) —
498
- * flat icon+text, no pill border/background/divider, sitting on the studio-white floor every
499
- * inventory photo already has (see .cc-media/.listcard-media background in md3.css). Mirrors the
500
- * mobile VDP gallery header (availability · views · favorites · Geprüft).
497
+ * Trust/activity badges overlaid on the photo itself, bottom-right (PM reference, 2026-07-10),
498
+ * Figma pill styling (border/radius/height — see .gallery-pill in md3.css). Mirrors the mobile
499
+ * VDP gallery header (availability · views · favorites · Geprüft).
501
500
  *
502
- * PM decision (Viktoriia — "this logic already exists on prod"): the row is all-or-nothing. A
503
- * missing or zero view/favorite count is NOT shown as "0×" — the whole row (including the
504
- * always-on availability/Geprüft items) is hidden rather than reading as an empty/broken card. It
505
- * only appears once BOTH counts are real and positive.
501
+ * Each pill is independent, not all-or-nothing: a missing or zero view/favorite count just omits
502
+ * THAT pill (never shown as "0×") — availability and Geprüft still render on their own terms.
503
+ * .gallery-badges is anchored via `right`, not `left` (md3.css), so however many pills survive
504
+ * they stay stuck to the right edge instead of drifting to wherever the row happens to start.
506
505
  */
507
- export const GalleryBadges: React.FunctionComponent<GalleryBadgesProps> = ({ car, t }) => {
508
- if (!car.viewsCount || !car.favoritesCount) return null;
509
- return (
510
- <div className="gallery-badges" style={{ position: 'absolute', left: 10, bottom: 10, zIndex: 3 }}>
511
- {car.availability && (
512
- <span className="gallery-pill">
513
- <Icon name="circle-check" size={15} stroke={2} color="var(--md-good)" />
514
- {car.availability}
515
- </span>
516
- )}
506
+ export const GalleryBadges: React.FunctionComponent<GalleryBadgesProps> = ({ car, t }) => (
507
+ <div className="gallery-badges">
508
+ {car.availability && (
509
+ <span className="gallery-pill">
510
+ <Icon name="circle-check" size={15} stroke={2} color="var(--md-good)" />
511
+ {car.availability}
512
+ </span>
513
+ )}
514
+ {!!car.viewsCount && (
517
515
  <span className="gallery-pill">
518
516
  <Icon name="eye" size={15} stroke={1.9} />
519
517
  {t('autobahn:card.activity.viewsCount', { count: car.viewsCount })}
520
518
  </span>
519
+ )}
520
+ {!!car.favoritesCount && (
521
521
  <span className="gallery-pill">
522
522
  <Icon name="heart" size={15} stroke={1.9} />
523
523
  {t('autobahn:card.activity.favoritesCount', { count: car.favoritesCount })}
524
524
  </span>
525
- <span className="gallery-pill">
526
- <Icon name="shield-check" size={15} stroke={1.9} />
527
- {t('autobahn:card.trust.checked')}
528
- </span>
529
- </div>
530
- );
531
- };
525
+ )}
526
+ <span className="gallery-pill">
527
+ <Icon name="shield-check" size={15} stroke={1.9} />
528
+ {t('autobahn:card.trust.checked')}
529
+ </span>
530
+ </div>
531
+ );
package/cards/types.ts CHANGED
@@ -114,9 +114,9 @@ export interface AutobahnCar {
114
114
 
115
115
  // --- gallery activity strip (real data: UserActionsAPI 'stats/viewers', loaded async and
116
116
  // keyed by carId in SearchResultsStore.statsData — see fieldMapping.ts). Absent until that
117
- // fetch resolves. PM decision: the WHOLE badge row (availability/views/favorites/Geprüft)
118
- // is all-or-nothing — it renders only when BOTH counts are present and > 0; a missing or
119
- // zero count hides the entire row rather than showing a "0×" pill (GalleryBadges). ---
117
+ // fetch resolves. Each pill in the badge row is independent (GalleryBadges): a missing or
118
+ // zero count omits just that pill (never a "0×"), availability/Geprüft still show on their
119
+ // own terms — the row is anchored to the right edge so it never looks lopsided. ---
120
120
  /** total detail-page views (stats totalCarImpCount) — shown as the eye pill under the image. */
121
121
  viewsCount?: number;
122
122
  /** total users who favorited this car (stats totalFavCount) — shown as the heart pill under the image. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytebrand/fe-ui-core-autobahn",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "auto.de md3 (Autobahn) design system — UI primitives, cards, chrome, VDP modules, theme CSS and locales. Ships raw TypeScript source (like fe-ui-core before it); each consumer's bundler compiles it.",
5
5
  "main": "index.ts",
6
6
  "license": "UNLICENSED",
package/theme/md3.css CHANGED
@@ -1003,12 +1003,15 @@
1003
1003
  /* horizontal listing card (SRP): image | info | price */
1004
1004
  .md3 .listcard { display: grid; grid-template-columns: 300px 1fr 240px; align-items: stretch; }
1005
1005
  .md3 .listcard-media { position: relative; min-height: 100%; }
1006
- /* activity/trust badges overlaid on the photo's studio-white floor, bottom-left (opposite corner
1007
- from the bottom-right photo-count .imglabel so they never collide) — PM ref, no divider/box,
1008
- flat icon+text pairs. */
1009
- .md3 .gallery-badges { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
1010
- .md3 .gallery-pill { display: inline-flex; align-items: center; gap: 5px; color: var(--md-on-surface-variant);
1011
- font-size: 13px; font-weight: 600; white-space: nowrap; }
1006
+ /* activity/trust badges overlaid on the photo's studio-white floor, bottom-right, RAISED above
1007
+ the carousel's pagination dots (CardCarousel: bottom:9, ~6px tall) and the bottom-right
1008
+ photo-count .imglabel (bottom:10, 26px tall) so nothing collides. Figma pill styling: 30px
1009
+ tall, 11px corner radius, 1px border (not a full pill, not divider/box-less flat text). */
1010
+ .md3 .gallery-badges { position: absolute; right: 10px; bottom: 44px; z-index: 3;
1011
+ display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; max-width: calc(100% - 20px); }
1012
+ .md3 .gallery-pill { display: inline-flex; align-items: center; gap: 5px; height: 30px; padding: 0 10px;
1013
+ border-radius: 11px; border: 1px solid var(--md-outline-variant); background: var(--md-sc-lowest);
1014
+ color: var(--md-on-surface); font-size: 12.5px; font-weight: 600; white-space: nowrap; }
1012
1015
  .md3 .listcard-info { padding: 16px 18px; display: flex; flex-direction: column; gap: 11px; min-width: 0; }
1013
1016
  .md3 .listcard-price { position: relative; padding: 16px 18px; border-left: 1px solid var(--md-outline-variant);
1014
1017
  display: flex; flex-direction: column; justify-content: flex-start; gap: 16px; background: var(--md-sc-low); }