@porsche-design-system/components-react 4.4.0 → 4.5.0-rc.1

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/CHANGELOG.md CHANGED
@@ -14,6 +14,30 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0),
14
14
 
15
15
  ## [Unreleased]
16
16
 
17
+ ## [4.5.0-rc.1] - 2026-07-20
18
+
19
+ ### Fixed
20
+
21
+ - `Flyout`, `Modal`, `Sheet` ([#4602](https://github.com/porsche-design-system/porsche-design-system/pull/4602)):
22
+ - focus ring color of dismiss button
23
+ - hover color visibility of dismiss button
24
+ - `Popover`: Trigger icon no longer gets squished when placed inside a constrained flex/grid parent
25
+ ([#4602](https://github.com/porsche-design-system/porsche-design-system/pull/4602))
26
+
27
+ ## [4.5.0-rc.0] - 2026-07-17
28
+
29
+ ### Changed
30
+
31
+ - `AG Grid`: Bumped peer dependency to support AG Grid new major version 36
32
+ ([#4553](https://github.com/porsche-design-system/porsche-design-system/pull/4553))
33
+ - `Popover`: Aligned shadowed popover trigger button style with button-pure
34
+ ([#4596](https://github.com/porsche-design-system/porsche-design-system/pull/4596))
35
+
36
+ ### Fixed
37
+
38
+ - `Popover`: A `margin` set on the host is now applied to the shadowed trigger button
39
+ ([#4596](https://github.com/porsche-design-system/porsche-design-system/pull/4596))
40
+
17
41
  ## [4.4.0] - 2026-07-15
18
42
 
19
43
  ## [4.4.0-rc.1] - 2026-07-10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@porsche-design-system/components-react",
3
- "version": "4.4.0",
3
+ "version": "4.5.0-rc.1",
4
4
  "description": "Porsche Design System is a component library designed to help developers create the best experience for software or services distributed by Dr. Ing. h.c. F. Porsche AG.",
5
5
  "keywords": [
6
6
  "porsche",
@@ -21,12 +21,12 @@
21
21
  "url": "https://github.com/porsche-design-system/porsche-design-system"
22
22
  },
23
23
  "dependencies": {
24
- "@porsche-design-system/components-js": "4.4.0"
24
+ "@porsche-design-system/components-js": "4.5.0-rc.1"
25
25
  },
26
26
  "peerDependencies": {
27
- "ag-grid-community": ">= 35.0.0 <36.0.0",
28
- "ag-grid-enterprise": ">= 35.0.0 <36.0.0",
29
- "ag-grid-react": ">= 35.0.0 <36.0.0",
27
+ "ag-grid-community": ">= 36.0.0 <37.0.0",
28
+ "ag-grid-enterprise": ">= 36.0.0 <37.0.0",
29
+ "ag-grid-react": ">= 36.0.0 <37.0.0",
30
30
  "react": ">=19.0.0 <20.0.0",
31
31
  "react-dom": ">=19.0.0 <20.0.0",
32
32
  "tailwindcss": ">= 4.0.0 <5.0.0"
@@ -3849,7 +3849,7 @@ const OPTION_LIST_SAFE_ZONE = 6;
3849
3849
 
3850
3850
  const getCDNBaseURL = () => global.PORSCHE_DESIGN_SYSTEM_CDN_URL + "/porsche-design-system";
3851
3851
 
3852
- const prefix = `[Porsche Design System v${"4.4.0"}]` // this part isn't covered by unit tests
3852
+ const prefix = `[Porsche Design System v${"4.5.0-rc.1"}]` // this part isn't covered by unit tests
3853
3853
  ;
3854
3854
  const consoleError = (...messages) => {
3855
3855
  console.error(prefix, ...messages);
@@ -4289,17 +4289,19 @@ const weightMap = {
4289
4289
  // Inlined `close` icon (mirrors packages/assets/projects/icons/src/close.svg) rendered as a CSS mask, so the dismiss
4290
4290
  // button needs neither a nested `p-button` nor a `p-icon` (which would fetch the SVG from the CDN asynchronously).
4291
4291
  const iconClose = getInlineSVGBackgroundImage('<path d="m18 6.706-5.294 5.294 5.294 5.294-.706.706-5.294-5.294-5.294 5.294-.706-.706 5.294-5.294-5.294-5.294.706-.706 5.294 5.294 5.294-5.294z"/>');
4292
- // NOTE: Values copied (and reduced to the fixed `compact` + `hideLabel` case the dismiss button always uses) from
4293
- // `getVariantColors` in `packages/components/src/styles/link-button-styles.ts` to keep the visual identical to the
4294
- // previously nested `p-button`. If the shared button styling changes, mirror it here (or extract a shared helper).
4295
4292
  const getVariantColors$1 = (variant) => {
4296
4293
  const colors = {
4297
- primary: {
4298
- textColor: ref(colorCanvas),
4299
- backgroundColor: ref(colorPrimary),
4300
- backgroundColorHover: ref(colorContrastHigh),
4294
+ canvas: {
4295
+ textColor: ref(colorPrimary),
4296
+ backgroundColor: ref(colorCanvas),
4297
+ backgroundColorHover: ref(colorSurface),
4301
4298
  },
4302
- secondary: {
4299
+ surface: {
4300
+ textColor: ref(colorPrimary),
4301
+ backgroundColor: ref(colorSurface),
4302
+ backgroundColorHover: ref(colorCanvas),
4303
+ },
4304
+ frosted: {
4303
4305
  textColor: ref(colorPrimary),
4304
4306
  backgroundColor: ref(colorFrostedStrong),
4305
4307
  backgroundColorHover: ref(colorFrosted),
@@ -4333,7 +4335,7 @@ const getFCDismissButtonStyles = (variant) => {
4333
4335
  // opaque `primary` background it is invisible AND — because the dialog consumer additionally applies
4334
4336
  // `filter: invert(1)` on the same element (see `getDialogDismissButtonJssStyle`) — the blurred backdrop bleeds past
4335
4337
  // the circular edge and the invert amplifies it into a visible glow/halo. So it is applied for `secondary` only.
4336
- ...(variant === 'secondary' && {
4338
+ ...(variant === 'frosted' && {
4337
4339
  WebkitBackdropFilter: ref(blurFrosted),
4338
4340
  backdropFilter: ref(blurFrosted),
4339
4341
  }),
@@ -4417,7 +4419,7 @@ const getFunctionalComponentNotificationBaseStyles = (state, hasAction, hasDismi
4417
4419
  ...(hasDismissButton && {
4418
4420
  dismiss: {
4419
4421
  // native dismiss button visual (secondary variant); grid positioning is applied on top
4420
- ...getFCDismissButtonStyles('secondary'),
4422
+ ...getFCDismissButtonStyles('frosted'),
4421
4423
  gridArea: `1/4/-1`,
4422
4424
  alignSelf: 'flex-start',
4423
4425
  marginBlock: `calc(-6 * ${ref(spacingStatic2Xs)})`,
@@ -5751,8 +5753,6 @@ const getFunctionalComponentLabelAfterStyles = () => {
5751
5753
  // last line. `:host(:has([slot="label-after"]))` would be an alternative but lacks reliable Chrome support for now.
5752
5754
  '&::slotted(*)': {
5753
5755
  ...addImportantToEachRule({
5754
- display: 'inline-block',
5755
- verticalAlign: 'top',
5756
5756
  marginInlineStart: ref(spacingStaticXs$1),
5757
5757
  }),
5758
5758
  },
@@ -6042,11 +6042,11 @@ const getDialogTransitionJssStyle = (isVisible, slideIn) => {
6042
6042
  transition: `${getTransition('opacity', duration, easing)}, ${getTransition('transform', duration, easing)}`,
6043
6043
  };
6044
6044
  };
6045
- const getDialogDismissButtonJssStyle = () => {
6045
+ const getDialogDismissButtonJssStyle = (variant) => {
6046
6046
  return {
6047
6047
  // native dismiss button visual (primary variant); positioning + the `invert` filter (renders it light on the
6048
6048
  // dialog) are applied on top below
6049
- ...getFCDismissButtonStyles('primary'),
6049
+ ...getFCDismissButtonStyles(variant),
6050
6050
  gridArea: '1/3',
6051
6051
  zIndex: 5, // controls layering + creates new stacking context (prevents content within to be above other dialog areas)
6052
6052
  position: 'sticky',
@@ -6054,7 +6054,6 @@ const getDialogDismissButtonJssStyle = () => {
6054
6054
  marginTop: `calc(-1 * ${dialogPaddingTop} + ${ref(spacingFluidSm)})`,
6055
6055
  marginInlineEnd: ref(spacingFluidSm),
6056
6056
  placeSelf: 'flex-start flex-end',
6057
- filter: 'invert(1) brightness(1.02)',
6058
6057
  };
6059
6058
  };
6060
6059
  const getSlotJssStyle = () => {
@@ -7254,7 +7253,7 @@ const getComponentCss$V = (isOpen, background, backdrop, position, hasHeader, ha
7254
7253
  gridTemplateRows: hasHeader ? 'auto 1fr auto' : '1fr',
7255
7254
  }),
7256
7255
  },
7257
- dismiss: getDialogDismissButtonJssStyle(),
7256
+ dismiss: getDialogDismissButtonJssStyle(background),
7258
7257
  });
7259
7258
  };
7260
7259
 
@@ -8068,7 +8067,7 @@ const getComponentCss$C = (isOpen, background, backdrop, fullscreen, hasDismissB
8068
8067
  }),
8069
8068
  },
8070
8069
  ...(hasDismissButton && {
8071
- dismiss: getDialogDismissButtonJssStyle(),
8070
+ dismiss: getDialogDismissButtonJssStyle(background),
8072
8071
  }),
8073
8072
  });
8074
8073
  };
@@ -8442,6 +8441,13 @@ const getComponentCss$w = (hideLabel, state, isDisabled, isLoading, length, isCo
8442
8441
  // Minimum gap (in px) kept between the panel and the viewport edges. Used both as Floating UI `shift`/`flip` padding
8443
8442
  // and to inset the panel's default max-width/height (`100dvw/dvh - 2 * POPOVER_SAFE_ZONE`) so it never touches the edge.
8444
8443
  const POPOVER_SAFE_ZONE = 8;
8444
+ // Arrow geometry (in px), single source of truth shared by the JSS `.arrow` rule (`popover-styles.ts`) and the
8445
+ // runtime positioning/orientation logic (`popover.tsx`). Named by geometry rather than `width`/`height` because the
8446
+ // arrow is rotated per placement, so its rendered CSS `width`/`height` swap depending on the panel edge it attaches to.
8447
+ // - `POPOVER_ARROW_BASE`: length of the triangle's base along the panel edge.
8448
+ // - `POPOVER_ARROW_THICKNESS`: depth of the triangle perpendicular to the panel edge (how far it protrudes).
8449
+ const POPOVER_ARROW_BASE = 24;
8450
+ const POPOVER_ARROW_THICKNESS = 12;
8445
8451
 
8446
8452
  /**
8447
8453
  * @css-variable {"name": "--p-popover-w", "description": "Width of the popover.", "defaultValue": "max-content"}
@@ -8505,6 +8511,9 @@ const getComponentCss$v = (isOpen, isCompact, skipEntryTransition) => {
8505
8511
  // flow. Enabled by anchoring Floating UI to the assigned trigger element (see `triggerElement` in popover.tsx)
8506
8512
  // instead of the `<slot>` box, so the slot no longer needs a layout box of its own.
8507
8513
  display: 'contents',
8514
+ // Explicit baseline (matches the `margin` initial value) that the trigger button inherits via `margin: inherit`.
8515
+ // A consumer margin on the host (`p-popover { margin: … }`) overrides this and thus flows through to the button.
8516
+ margin: '0',
8508
8517
  ...addImportantToEachRule(hostHiddenStyles),
8509
8518
  },
8510
8519
  'slot:not([name]), p': {
@@ -8522,30 +8531,49 @@ const getComponentCss$v = (isOpen, isCompact, skipEntryTransition) => {
8522
8531
  },
8523
8532
  button: {
8524
8533
  all: 'unset',
8534
+ // The :host uses `display: contents` and thus has no box of its own, so a consumer-defined margin on the host
8535
+ // (e.g. `p-popover { margin: … }`) would be dropped. `inherit` forwards that margin onto the actual trigger button.
8536
+ margin: 'inherit',
8525
8537
  display: 'inline-grid',
8526
8538
  verticalAlign: 'top',
8527
8539
  font: `${ref(typescaleSm$1)} ${ref(fontPorscheNext$1)}`, // needed for correct width/height definition based on ex-unit
8528
8540
  width: ref(leadingNormal$1),
8529
8541
  height: ref(leadingNormal$1),
8530
- borderRadius: ref(radiusFull),
8542
+ // The :host uses `display: contents`, so this fixed-size trigger button becomes the flex/grid item in the
8543
+ // consumer's layout (e.g. p-accordion's `summary-after` slot, which is `display: flex`). Its visible box is drawn
8544
+ // purely by the `::before`/`::after` pseudo-elements (icon `mask`), so it has no intrinsic content width and its
8545
+ // automatic minimum size collapses towards 0 — a competing sibling (e.g. long summary text) would otherwise
8546
+ // squeeze the info icon flat. `flex: none` keeps the icon at its intended size instead of shrinking.
8547
+ flex: 'none',
8531
8548
  cursor: 'pointer',
8532
- background: ref(colorFrosted),
8533
- transition: getTransition('background-color'),
8534
- WebkitBackdropFilter: ref(blurFrosted),
8535
- backdropFilter: ref(blurFrosted),
8536
8549
  ...hoverMediaQuery({
8537
- '&:hover': {
8538
- background: ref(colorFrostedSoft),
8550
+ '&:hover::before': {
8551
+ background: ref(colorFrostedStrong),
8552
+ WebkitBackdropFilter: ref(blurFrosted),
8553
+ backdropFilter: ref(blurFrosted),
8539
8554
  },
8540
8555
  }),
8541
- '&:focus-visible': getFocusBaseStyles(),
8556
+ '&:focus-visible::before': getFocusBaseStyles(),
8557
+ '&::before': {
8558
+ gridArea: '1/1',
8559
+ content: '""',
8560
+ margin: '-2px',
8561
+ transition: getTransition('background-color'),
8562
+ borderRadius: ref(radiusFull),
8563
+ ...(isOpen && {
8564
+ background: ref(colorFrosted),
8565
+ WebkitBackdropFilter: ref(blurFrosted),
8566
+ backdropFilter: ref(blurFrosted),
8567
+ }),
8568
+ },
8542
8569
  '&::after': {
8570
+ gridArea: '1/1',
8543
8571
  content: '""',
8544
8572
  WebkitMask: `${iconInfo} center/contain no-repeat`, // necessary for Sogou browser support :-)
8545
8573
  mask: `${iconInfo} center/contain no-repeat`,
8546
8574
  background: ref(colorPrimary),
8547
8575
  ...forcedColorsMediaQuery({
8548
- background: 'CanvasText',
8576
+ background: 'ButtonText',
8549
8577
  }),
8550
8578
  },
8551
8579
  },
@@ -8606,8 +8634,9 @@ const getComponentCss$v = (isOpen, isCompact, skipEntryTransition) => {
8606
8634
  },
8607
8635
  arrow: {
8608
8636
  position: 'absolute',
8609
- width: '24px',
8610
- height: '12px',
8637
+ // Resting orientation (bottom placement): base spans the panel edge, thickness protrudes towards the trigger.
8638
+ width: `${POPOVER_ARROW_BASE}px`,
8639
+ height: `${POPOVER_ARROW_THICKNESS}px`,
8611
8640
  clipPath: 'polygon(50% 0, 100% 110%, 0 110%)',
8612
8641
  background: 'inherit',
8613
8642
  ...forcedColorsMediaQuery({
@@ -9255,7 +9284,7 @@ const getComponentCss$n = (isOpen, background, hasDismissButton) => {
9255
9284
  }),
9256
9285
  },
9257
9286
  ...(hasDismissButton && {
9258
- dismiss: getDialogDismissButtonJssStyle(),
9287
+ dismiss: getDialogDismissButtonJssStyle(background),
9259
9288
  }),
9260
9289
  });
9261
9290
  };
@@ -3482,7 +3482,7 @@ const hasShowPickerSupport = () => (hasDocument &&
3482
3482
  'showPicker' in HTMLInputElement.prototype &&
3483
3483
  CSS.supports('selector(::-webkit-calendar-picker-indicator)'));
3484
3484
 
3485
- const prefix = `[Porsche Design System v${"4.4.0"}]` // this part isn't covered by unit tests
3485
+ const prefix = `[Porsche Design System v${"4.5.0-rc.1"}]` // this part isn't covered by unit tests
3486
3486
  ;
3487
3487
  const consoleError$1 = (...messages) => {
3488
3488
  console.error(prefix, ...messages);
@@ -3847,7 +3847,7 @@ const OPTION_LIST_SAFE_ZONE = 6;
3847
3847
 
3848
3848
  const getCDNBaseURL = () => global.PORSCHE_DESIGN_SYSTEM_CDN_URL + "/porsche-design-system";
3849
3849
 
3850
- const prefix = `[Porsche Design System v${"4.4.0"}]` // this part isn't covered by unit tests
3850
+ const prefix = `[Porsche Design System v${"4.5.0-rc.1"}]` // this part isn't covered by unit tests
3851
3851
  ;
3852
3852
  const consoleError = (...messages) => {
3853
3853
  console.error(prefix, ...messages);
@@ -4287,17 +4287,19 @@ const weightMap = {
4287
4287
  // Inlined `close` icon (mirrors packages/assets/projects/icons/src/close.svg) rendered as a CSS mask, so the dismiss
4288
4288
  // button needs neither a nested `p-button` nor a `p-icon` (which would fetch the SVG from the CDN asynchronously).
4289
4289
  const iconClose = getInlineSVGBackgroundImage('<path d="m18 6.706-5.294 5.294 5.294 5.294-.706.706-5.294-5.294-5.294 5.294-.706-.706 5.294-5.294-5.294-5.294.706-.706 5.294 5.294 5.294-5.294z"/>');
4290
- // NOTE: Values copied (and reduced to the fixed `compact` + `hideLabel` case the dismiss button always uses) from
4291
- // `getVariantColors` in `packages/components/src/styles/link-button-styles.ts` to keep the visual identical to the
4292
- // previously nested `p-button`. If the shared button styling changes, mirror it here (or extract a shared helper).
4293
4290
  const getVariantColors$1 = (variant) => {
4294
4291
  const colors = {
4295
- primary: {
4296
- textColor: ref(colorCanvas),
4297
- backgroundColor: ref(colorPrimary),
4298
- backgroundColorHover: ref(colorContrastHigh),
4292
+ canvas: {
4293
+ textColor: ref(colorPrimary),
4294
+ backgroundColor: ref(colorCanvas),
4295
+ backgroundColorHover: ref(colorSurface),
4299
4296
  },
4300
- secondary: {
4297
+ surface: {
4298
+ textColor: ref(colorPrimary),
4299
+ backgroundColor: ref(colorSurface),
4300
+ backgroundColorHover: ref(colorCanvas),
4301
+ },
4302
+ frosted: {
4301
4303
  textColor: ref(colorPrimary),
4302
4304
  backgroundColor: ref(colorFrostedStrong),
4303
4305
  backgroundColorHover: ref(colorFrosted),
@@ -4331,7 +4333,7 @@ const getFCDismissButtonStyles = (variant) => {
4331
4333
  // opaque `primary` background it is invisible AND — because the dialog consumer additionally applies
4332
4334
  // `filter: invert(1)` on the same element (see `getDialogDismissButtonJssStyle`) — the blurred backdrop bleeds past
4333
4335
  // the circular edge and the invert amplifies it into a visible glow/halo. So it is applied for `secondary` only.
4334
- ...(variant === 'secondary' && {
4336
+ ...(variant === 'frosted' && {
4335
4337
  WebkitBackdropFilter: ref(blurFrosted),
4336
4338
  backdropFilter: ref(blurFrosted),
4337
4339
  }),
@@ -4415,7 +4417,7 @@ const getFunctionalComponentNotificationBaseStyles = (state, hasAction, hasDismi
4415
4417
  ...(hasDismissButton && {
4416
4418
  dismiss: {
4417
4419
  // native dismiss button visual (secondary variant); grid positioning is applied on top
4418
- ...getFCDismissButtonStyles('secondary'),
4420
+ ...getFCDismissButtonStyles('frosted'),
4419
4421
  gridArea: `1/4/-1`,
4420
4422
  alignSelf: 'flex-start',
4421
4423
  marginBlock: `calc(-6 * ${ref(spacingStatic2Xs)})`,
@@ -5749,8 +5751,6 @@ const getFunctionalComponentLabelAfterStyles = () => {
5749
5751
  // last line. `:host(:has([slot="label-after"]))` would be an alternative but lacks reliable Chrome support for now.
5750
5752
  '&::slotted(*)': {
5751
5753
  ...addImportantToEachRule({
5752
- display: 'inline-block',
5753
- verticalAlign: 'top',
5754
5754
  marginInlineStart: ref(spacingStaticXs$1),
5755
5755
  }),
5756
5756
  },
@@ -6040,11 +6040,11 @@ const getDialogTransitionJssStyle = (isVisible, slideIn) => {
6040
6040
  transition: `${getTransition('opacity', duration, easing)}, ${getTransition('transform', duration, easing)}`,
6041
6041
  };
6042
6042
  };
6043
- const getDialogDismissButtonJssStyle = () => {
6043
+ const getDialogDismissButtonJssStyle = (variant) => {
6044
6044
  return {
6045
6045
  // native dismiss button visual (primary variant); positioning + the `invert` filter (renders it light on the
6046
6046
  // dialog) are applied on top below
6047
- ...getFCDismissButtonStyles('primary'),
6047
+ ...getFCDismissButtonStyles(variant),
6048
6048
  gridArea: '1/3',
6049
6049
  zIndex: 5, // controls layering + creates new stacking context (prevents content within to be above other dialog areas)
6050
6050
  position: 'sticky',
@@ -6052,7 +6052,6 @@ const getDialogDismissButtonJssStyle = () => {
6052
6052
  marginTop: `calc(-1 * ${dialogPaddingTop} + ${ref(spacingFluidSm)})`,
6053
6053
  marginInlineEnd: ref(spacingFluidSm),
6054
6054
  placeSelf: 'flex-start flex-end',
6055
- filter: 'invert(1) brightness(1.02)',
6056
6055
  };
6057
6056
  };
6058
6057
  const getSlotJssStyle = () => {
@@ -7252,7 +7251,7 @@ const getComponentCss$V = (isOpen, background, backdrop, position, hasHeader, ha
7252
7251
  gridTemplateRows: hasHeader ? 'auto 1fr auto' : '1fr',
7253
7252
  }),
7254
7253
  },
7255
- dismiss: getDialogDismissButtonJssStyle(),
7254
+ dismiss: getDialogDismissButtonJssStyle(background),
7256
7255
  });
7257
7256
  };
7258
7257
 
@@ -8066,7 +8065,7 @@ const getComponentCss$C = (isOpen, background, backdrop, fullscreen, hasDismissB
8066
8065
  }),
8067
8066
  },
8068
8067
  ...(hasDismissButton && {
8069
- dismiss: getDialogDismissButtonJssStyle(),
8068
+ dismiss: getDialogDismissButtonJssStyle(background),
8070
8069
  }),
8071
8070
  });
8072
8071
  };
@@ -8440,6 +8439,13 @@ const getComponentCss$w = (hideLabel, state, isDisabled, isLoading, length, isCo
8440
8439
  // Minimum gap (in px) kept between the panel and the viewport edges. Used both as Floating UI `shift`/`flip` padding
8441
8440
  // and to inset the panel's default max-width/height (`100dvw/dvh - 2 * POPOVER_SAFE_ZONE`) so it never touches the edge.
8442
8441
  const POPOVER_SAFE_ZONE = 8;
8442
+ // Arrow geometry (in px), single source of truth shared by the JSS `.arrow` rule (`popover-styles.ts`) and the
8443
+ // runtime positioning/orientation logic (`popover.tsx`). Named by geometry rather than `width`/`height` because the
8444
+ // arrow is rotated per placement, so its rendered CSS `width`/`height` swap depending on the panel edge it attaches to.
8445
+ // - `POPOVER_ARROW_BASE`: length of the triangle's base along the panel edge.
8446
+ // - `POPOVER_ARROW_THICKNESS`: depth of the triangle perpendicular to the panel edge (how far it protrudes).
8447
+ const POPOVER_ARROW_BASE = 24;
8448
+ const POPOVER_ARROW_THICKNESS = 12;
8443
8449
 
8444
8450
  /**
8445
8451
  * @css-variable {"name": "--p-popover-w", "description": "Width of the popover.", "defaultValue": "max-content"}
@@ -8503,6 +8509,9 @@ const getComponentCss$v = (isOpen, isCompact, skipEntryTransition) => {
8503
8509
  // flow. Enabled by anchoring Floating UI to the assigned trigger element (see `triggerElement` in popover.tsx)
8504
8510
  // instead of the `<slot>` box, so the slot no longer needs a layout box of its own.
8505
8511
  display: 'contents',
8512
+ // Explicit baseline (matches the `margin` initial value) that the trigger button inherits via `margin: inherit`.
8513
+ // A consumer margin on the host (`p-popover { margin: … }`) overrides this and thus flows through to the button.
8514
+ margin: '0',
8506
8515
  ...addImportantToEachRule(hostHiddenStyles),
8507
8516
  },
8508
8517
  'slot:not([name]), p': {
@@ -8520,30 +8529,49 @@ const getComponentCss$v = (isOpen, isCompact, skipEntryTransition) => {
8520
8529
  },
8521
8530
  button: {
8522
8531
  all: 'unset',
8532
+ // The :host uses `display: contents` and thus has no box of its own, so a consumer-defined margin on the host
8533
+ // (e.g. `p-popover { margin: … }`) would be dropped. `inherit` forwards that margin onto the actual trigger button.
8534
+ margin: 'inherit',
8523
8535
  display: 'inline-grid',
8524
8536
  verticalAlign: 'top',
8525
8537
  font: `${ref(typescaleSm$1)} ${ref(fontPorscheNext$1)}`, // needed for correct width/height definition based on ex-unit
8526
8538
  width: ref(leadingNormal$1),
8527
8539
  height: ref(leadingNormal$1),
8528
- borderRadius: ref(radiusFull),
8540
+ // The :host uses `display: contents`, so this fixed-size trigger button becomes the flex/grid item in the
8541
+ // consumer's layout (e.g. p-accordion's `summary-after` slot, which is `display: flex`). Its visible box is drawn
8542
+ // purely by the `::before`/`::after` pseudo-elements (icon `mask`), so it has no intrinsic content width and its
8543
+ // automatic minimum size collapses towards 0 — a competing sibling (e.g. long summary text) would otherwise
8544
+ // squeeze the info icon flat. `flex: none` keeps the icon at its intended size instead of shrinking.
8545
+ flex: 'none',
8529
8546
  cursor: 'pointer',
8530
- background: ref(colorFrosted),
8531
- transition: getTransition('background-color'),
8532
- WebkitBackdropFilter: ref(blurFrosted),
8533
- backdropFilter: ref(blurFrosted),
8534
8547
  ...hoverMediaQuery({
8535
- '&:hover': {
8536
- background: ref(colorFrostedSoft),
8548
+ '&:hover::before': {
8549
+ background: ref(colorFrostedStrong),
8550
+ WebkitBackdropFilter: ref(blurFrosted),
8551
+ backdropFilter: ref(blurFrosted),
8537
8552
  },
8538
8553
  }),
8539
- '&:focus-visible': getFocusBaseStyles(),
8554
+ '&:focus-visible::before': getFocusBaseStyles(),
8555
+ '&::before': {
8556
+ gridArea: '1/1',
8557
+ content: '""',
8558
+ margin: '-2px',
8559
+ transition: getTransition('background-color'),
8560
+ borderRadius: ref(radiusFull),
8561
+ ...(isOpen && {
8562
+ background: ref(colorFrosted),
8563
+ WebkitBackdropFilter: ref(blurFrosted),
8564
+ backdropFilter: ref(blurFrosted),
8565
+ }),
8566
+ },
8540
8567
  '&::after': {
8568
+ gridArea: '1/1',
8541
8569
  content: '""',
8542
8570
  WebkitMask: `${iconInfo} center/contain no-repeat`, // necessary for Sogou browser support :-)
8543
8571
  mask: `${iconInfo} center/contain no-repeat`,
8544
8572
  background: ref(colorPrimary),
8545
8573
  ...forcedColorsMediaQuery({
8546
- background: 'CanvasText',
8574
+ background: 'ButtonText',
8547
8575
  }),
8548
8576
  },
8549
8577
  },
@@ -8604,8 +8632,9 @@ const getComponentCss$v = (isOpen, isCompact, skipEntryTransition) => {
8604
8632
  },
8605
8633
  arrow: {
8606
8634
  position: 'absolute',
8607
- width: '24px',
8608
- height: '12px',
8635
+ // Resting orientation (bottom placement): base spans the panel edge, thickness protrudes towards the trigger.
8636
+ width: `${POPOVER_ARROW_BASE}px`,
8637
+ height: `${POPOVER_ARROW_THICKNESS}px`,
8609
8638
  clipPath: 'polygon(50% 0, 100% 110%, 0 110%)',
8610
8639
  background: 'inherit',
8611
8640
  ...forcedColorsMediaQuery({
@@ -9253,7 +9282,7 @@ const getComponentCss$n = (isOpen, background, hasDismissButton) => {
9253
9282
  }),
9254
9283
  },
9255
9284
  ...(hasDismissButton && {
9256
- dismiss: getDialogDismissButtonJssStyle(),
9285
+ dismiss: getDialogDismissButtonJssStyle(background),
9257
9286
  }),
9258
9287
  });
9259
9288
  };
@@ -3480,7 +3480,7 @@ const hasShowPickerSupport = () => (hasDocument &&
3480
3480
  'showPicker' in HTMLInputElement.prototype &&
3481
3481
  CSS.supports('selector(::-webkit-calendar-picker-indicator)'));
3482
3482
 
3483
- const prefix = `[Porsche Design System v${"4.4.0"}]` // this part isn't covered by unit tests
3483
+ const prefix = `[Porsche Design System v${"4.5.0-rc.1"}]` // this part isn't covered by unit tests
3484
3484
  ;
3485
3485
  const consoleError$1 = (...messages) => {
3486
3486
  console.error(prefix, ...messages);