diff --git a/core/src/components.d.ts b/core/src/components.d.ts
index 5d1eff6638c..34135a5a2d1 100644
--- a/core/src/components.d.ts
+++ b/core/src/components.d.ts
@@ -469,7 +469,7 @@ export namespace Components {
*/
"color"?: Color;
/**
- * Set to `"bold"` for a badge with vibrant, bold colors or to `"subtle"` for a badge with muted, subtle colors. Only applies to the `ionic` theme.
+ * Set to `"bold"` for a badge with vibrant, bold colors or to `"subtle"` for a badge with muted, subtle colors. Defaults to `"bold"` if both the hue property and theme config are unset.
*/
"hue"?: 'bold' | 'subtle';
/**
@@ -477,11 +477,11 @@ export namespace Components {
*/
"mode"?: "ios" | "md";
/**
- * Set to `"rectangular"` for non-rounded corners. Set to `"soft"` for slightly rounded corners. Set to `"round"` for fully rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
+ * Set to `"crisp"` for a badge with even slightly rounded corners, `"soft"` for a badge with slightly rounded corners, `"round"` for a badge with fully rounded corners, or `"rectangular"` for a badge without rounded corners. Defaults to `"soft"` if both the shape property and theme config are unset.
*/
- "shape"?: 'soft' | 'round | rectangular';
+ "shape"?: 'crisp' | 'soft' | 'round' | 'rectangular';
/**
- * Set to `"small"` for a small badge. Set to `"medium"` for a medium badge. Set to `"large"` for a large badge, when it is empty (no text or icon). Defaults to `"small"` for the `ionic` theme, undefined for all other themes.
+ * Set to `"small"` for a smaller size. Set to `"medium"` for a medium size. Set to `"large"` for a larger size. Defaults to `"small"` if both the size property and theme config are unset.
*/
"size"?: 'small' | 'medium' | 'large';
/**
@@ -898,7 +898,7 @@ export namespace Components {
*/
"shape"?: IonChipShape;
/**
- * Set to `"small"` for a chip with less height and padding. Defaults to `"large"` if both the size property and theme config are unset.
+ * Set to `"small"` for a chip with less height and padding, or `"large"` for a chip with more height and padding. Defaults to `"large"` if both the size property and theme config are unset.
*/
"size"?: IonChipSize;
}
@@ -6400,7 +6400,7 @@ declare namespace LocalJSX {
*/
"color"?: Color;
/**
- * Set to `"bold"` for a badge with vibrant, bold colors or to `"subtle"` for a badge with muted, subtle colors. Only applies to the `ionic` theme.
+ * Set to `"bold"` for a badge with vibrant, bold colors or to `"subtle"` for a badge with muted, subtle colors. Defaults to `"bold"` if both the hue property and theme config are unset.
*/
"hue"?: 'bold' | 'subtle';
/**
@@ -6408,11 +6408,11 @@ declare namespace LocalJSX {
*/
"mode"?: "ios" | "md";
/**
- * Set to `"rectangular"` for non-rounded corners. Set to `"soft"` for slightly rounded corners. Set to `"round"` for fully rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
+ * Set to `"crisp"` for a badge with even slightly rounded corners, `"soft"` for a badge with slightly rounded corners, `"round"` for a badge with fully rounded corners, or `"rectangular"` for a badge without rounded corners. Defaults to `"soft"` if both the shape property and theme config are unset.
*/
- "shape"?: 'soft' | 'round | rectangular';
+ "shape"?: 'crisp' | 'soft' | 'round' | 'rectangular';
/**
- * Set to `"small"` for a small badge. Set to `"medium"` for a medium badge. Set to `"large"` for a large badge, when it is empty (no text or icon). Defaults to `"small"` for the `ionic` theme, undefined for all other themes.
+ * Set to `"small"` for a smaller size. Set to `"medium"` for a medium size. Set to `"large"` for a larger size. Defaults to `"small"` if both the size property and theme config are unset.
*/
"size"?: 'small' | 'medium' | 'large';
/**
@@ -6864,7 +6864,7 @@ declare namespace LocalJSX {
*/
"shape"?: IonChipShape;
/**
- * Set to `"small"` for a chip with less height and padding. Defaults to `"large"` if both the size property and theme config are unset.
+ * Set to `"small"` for a chip with less height and padding, or `"large"` for a chip with more height and padding. Defaults to `"large"` if both the size property and theme config are unset.
*/
"size"?: IonChipSize;
}
diff --git a/core/src/components/avatar/avatar.common.scss b/core/src/components/avatar/avatar.common.scss
index e24c047ad72..ef4cb3b221a 100644
--- a/core/src/components/avatar/avatar.common.scss
+++ b/core/src/components/avatar/avatar.common.scss
@@ -1,4 +1,4 @@
-@import "../../themes/mixins.scss";
+@use "../../themes/mixins" as mixins;
// Avatar
// --------------------------------------------------
@@ -7,7 +7,7 @@
/**
* @prop --border-radius: Border radius of the avatar and inner image
*/
- @include border-radius(var(--border-radius));
+ @include mixins.border-radius(var(--border-radius));
display: block;
@@ -16,7 +16,7 @@
::slotted(ion-img),
::slotted(img) {
- @include border-radius(var(--border-radius));
+ @include mixins.border-radius(var(--border-radius));
width: 100%;
height: 100%;
diff --git a/core/src/components/avatar/avatar.ionic.scss b/core/src/components/avatar/avatar.ionic.scss
index 11ffcdc881a..d31e6c9c5cb 100644
--- a/core/src/components/avatar/avatar.ionic.scss
+++ b/core/src/components/avatar/avatar.ionic.scss
@@ -169,79 +169,6 @@
height: globals.$ion-scale-800;
}
-// Avatar Badge Empty (hint)
-// --------------------------------------------------
-
-:host ::slotted(ion-badge.badge-vertical-top:empty) {
- @include globals.transform(translate(globals.$ion-scale-050, calc(globals.$ion-scale-050 * -1)));
-}
-
-:host(.avatar-xxsmall) ::slotted(ion-badge.badge-vertical-top:empty) {
- @include globals.transform(translate(globals.$ion-scale-100, calc(globals.$ion-scale-100 * -1)));
-}
-
-:host ::slotted(ion-badge.badge-vertical-bottom:empty) {
- @include globals.transform(translate(0, globals.$ion-scale-100));
-}
-
-:host(.avatar-xxsmall) ::slotted(ion-badge.badge-vertical-bottom:empty) {
- @include globals.transform(translate(globals.$ion-scale-100, globals.$ion-scale-100));
-}
-
-// Avatar Badge Bottom (hint)
-// --------------------------------------------------
-
-:host ::slotted(ion-badge.badge-vertical-bottom:not(:empty)) {
- @include globals.transform(translate(50%, 50%));
-}
-
-:host(.avatar-xxsmall) ::slotted(ion-badge.badge-vertical-bottom:not(:empty)) {
- @include globals.position(null, globals.$ion-scale-100, globals.$ion-scale-100, null);
- @include globals.transform(translate(100%, 100%));
-}
-
-:host(.avatar-xsmall) ::slotted(ion-badge.badge-vertical-bottom:not(:empty)) {
- @include globals.position(null, calc(globals.$ion-scale-050 * -1), calc(globals.$ion-scale-050 * -1), null);
-}
-
-:host(.avatar-small) ::slotted(ion-badge.badge-vertical-bottom:not(:empty)),
-:host(.avatar-medium) ::slotted(ion-badge.badge-vertical-bottom:not(:empty)),
-:host(.avatar-large) ::slotted(ion-badge.badge-vertical-bottom:not(:empty)) {
- @include globals.position(null, globals.$ion-scale-050, globals.$ion-scale-050, null);
-}
-
-:host(.avatar-xlarge) ::slotted(ion-badge.badge-vertical-bottom:not(:empty)) {
- @include globals.position(null, globals.$ion-scale-150, globals.$ion-scale-150, null);
-}
-
-// Avatar Badge Top (hint)
-// --------------------------------------------------
-
-:host ::slotted(ion-badge.badge-vertical-top:not(:empty)) {
- @include globals.transform(translate(50%, -50%));
-}
-
-:host(.avatar-xxsmall) ::slotted(ion-badge.badge-vertical-top:not(:empty)) {
- @include globals.position(globals.$ion-scale-050, 0, null, null);
-}
-
-:host(.avatar-xsmall) ::slotted(ion-badge.badge-vertical-top:not(:empty)) {
- @include globals.position(globals.$ion-scale-100, calc(globals.$ion-scale-050 * -1), null, null);
-}
-
-:host(.avatar-small) ::slotted(ion-badge.badge-vertical-top:not(:empty)),
-:host(.avatar-medium) ::slotted(ion-badge.badge-vertical-top:not(:empty)) {
- @include globals.position(globals.$ion-scale-150, 0, null, null);
-}
-
-:host(.avatar-large) ::slotted(ion-badge.badge-vertical-top:not(:empty)) {
- @include globals.position(globals.$ion-scale-150, globals.$ion-scale-050, null, null);
-}
-
-:host(.avatar-xlarge) ::slotted(ion-badge.badge-vertical-top:not(:empty)) {
- @include globals.position(globals.$ion-scale-150, globals.$ion-scale-150, null, null);
-}
-
// Avatar Disabled
// --------------------------------------------------
:host(.avatar-disabled)::after {
diff --git a/core/src/components/avatar/avatar.md.scss b/core/src/components/avatar/avatar.md.scss
index cfcd2520280..b7679654770 100644
--- a/core/src/components/avatar/avatar.md.scss
+++ b/core/src/components/avatar/avatar.md.scss
@@ -11,22 +11,3 @@
width: $avatar-md-width;
height: $avatar-md-height;
}
-
-// Avatar Empty Badge (hint)
-// --------------------------------------------------
-
-::slotted(ion-badge.badge-vertical-top:empty) {
- @include globals.transform(translate(-50%, 50%));
-}
-
-::slotted(ion-badge.badge-vertical-bottom:empty) {
- @include globals.transform(translateX(-100%));
-}
-
-:host ::slotted(ion-badge.badge-vertical-top:not(:empty)) {
- @include globals.transform(translate(0, 100%));
-}
-
-:host ::slotted(ion-badge.badge-vertical-bottom:not(:empty)) {
- @include globals.transform(translate(0, -100%));
-}
diff --git a/core/src/components/avatar/avatar.tsx b/core/src/components/avatar/avatar.tsx
index da5ccb81707..cdd7b2239ac 100644
--- a/core/src/components/avatar/avatar.tsx
+++ b/core/src/components/avatar/avatar.tsx
@@ -1,5 +1,7 @@
import type { ComponentInterface } from '@stencil/core';
import { Component, Element, Host, Prop, h } from '@stencil/core';
+import type { BadgeObserver } from '@utils/helpers';
+import { createBadgeObserver } from '@utils/helpers';
import { getIonTheme } from '../../global/ionic-global';
@@ -18,6 +20,7 @@ import { getIonTheme } from '../../global/ionic-global';
})
export class Avatar implements ComponentInterface {
@Element() el!: HTMLElement;
+ private badgeObserver?: BadgeObserver;
/**
* Set to `"xxsmall"` for the smallest size.
@@ -45,6 +48,14 @@ export class Avatar implements ComponentInterface {
*/
@Prop() disabled = false;
+ componentDidLoad(): void {
+ this.setupBadgeObserver();
+ }
+
+ disconnectedCallback() {
+ this.destroyBadgeObserver();
+ }
+
get hasImage() {
return !!this.el.querySelector('ion-img') || !!this.el.querySelector('img');
}
@@ -53,14 +64,51 @@ export class Avatar implements ComponentInterface {
return !!this.el.querySelector('ion-icon');
}
- private getSize(): string | undefined {
- const theme = getIonTheme(this);
- const { size } = this;
+ private get hasBadge() {
+ return !!this.el.querySelector('ion-badge');
+ }
- // TODO(ROU-10752): Remove theme check when sizes are defined for all themes.
- if (theme !== 'ionic') {
- return undefined;
+ private onSlotChanged = () => {
+ /**
+ * Badges can be added or removed dynamically to mimic use
+ * cases like notifications. Based on the presence of a
+ * badge, we need to set up or destroy the badge observer.
+ *
+ * If the badge observer is already set up and there is a badge, then we don't need to do anything.
+ */
+ if (this.hasBadge && this.badgeObserver) {
+ return;
+ }
+
+ if (this.hasBadge) {
+ this.setupBadgeObserver();
+ } else {
+ this.destroyBadgeObserver();
}
+ };
+
+ private setupBadgeObserver() {
+ this.destroyBadgeObserver();
+
+ // Only set up the badge observer if there is a badge and it's anchored
+ const badge = this.el.querySelector('ion-badge[vertical]') as HTMLElement | null;
+
+ if (!badge) {
+ return;
+ }
+
+ this.badgeObserver = createBadgeObserver({
+ host: this.el,
+ badge,
+ });
+ }
+
+ private destroyBadgeObserver() {
+ this.badgeObserver?.disconnect();
+ }
+
+ private getSize(): string | undefined {
+ const { size } = this;
if (size === undefined) {
return 'medium';
@@ -102,7 +150,7 @@ export class Avatar implements ComponentInterface {
[`avatar-disabled`]: disabled,
}}
>
-
+
);
}
diff --git a/core/src/components/avatar/test/hint/index.html b/core/src/components/avatar/test/hint/index.html
new file mode 100644
index 00000000000..0c5e1b5c5d8
--- /dev/null
+++ b/core/src/components/avatar/test/hint/index.html
@@ -0,0 +1,97 @@
+
+
+
+
+ Avatar - Hint
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avatar - Hint
+
+
+
+
+
+
+
+
+
diff --git a/core/src/components/badge/badge.common.scss b/core/src/components/badge/badge.common.scss
deleted file mode 100644
index 1523886ea5e..00000000000
--- a/core/src/components/badge/badge.common.scss
+++ /dev/null
@@ -1,47 +0,0 @@
-@use "../../themes/functions.color" as color;
-@import "../../themes/mixins";
-
-// Badge
-// --------------------------------------------------
-
-:host {
- /**
- * @prop --background: Background of the badge
- * @prop --color: Text color of the badge
- *
- * @prop --padding-top: Top padding of the badge
- * @prop --padding-end: Right padding if direction is left-to-right, and left padding if direction is right-to-left of the badge
- * @prop --padding-bottom: Bottom padding of the badge
- * @prop --padding-start: Left padding if direction is left-to-right, and right padding if direction is right-to-left of the badge
- */
- @include font-smoothing();
- @include padding(var(--padding-top), var(--padding-end), var(--padding-bottom), var(--padding-start));
-
- display: inline-block;
-
- background: var(--background);
- color: var(--color);
-
- text-align: center;
-
- white-space: nowrap;
-
- contain: content;
- vertical-align: baseline;
-}
-
-// Badge (hint)
-// --------------------------------------------------
-
-:host([vertical]:not(.in-tab-button)) {
- @include position(null, 0, null, null);
- position: absolute;
-}
-
-:host(:not(.in-tab-button)[vertical].badge-vertical-top) {
- top: 0;
-}
-
-:host(:not(.in-tab-button)[vertical].badge-vertical-bottom) {
- bottom: 0;
-}
diff --git a/core/src/components/badge/badge.ionic.scss b/core/src/components/badge/badge.ionic.scss
index 4342c2b51d3..8df5f000de2 100644
--- a/core/src/components/badge/badge.ionic.scss
+++ b/core/src/components/badge/badge.ionic.scss
@@ -1,5 +1,5 @@
@use "../../themes/ionic/ionic.globals.scss" as globals;
-@use "./badge.common";
+@use "./badge";
// Ionic Badge
// --------------------------------------------------
@@ -10,7 +10,7 @@
--padding-top: #{globals.$ion-space-0};
--padding-bottom: #{globals.$ion-space-0};
- @include globals.typography(globals.$ion-body-sm-medium);
+ @include globals.typography(globals.$ion-body-sm-medium); // TODO: Add this
display: inline-flex;
@@ -51,21 +51,22 @@
/* Soft Badge */
:host(.badge-soft) {
- @include globals.border-radius(globals.$ion-soft-xs);
+ @include globals.border-radius(globals.$ion-soft-xs); // 8px
}
+// TODO: add example that this needs to be done by passing props of small size ane crisp shape
:host(.badge-small.badge-soft) {
- @include globals.border-radius(globals.$ion-soft-2xs);
+ @include globals.border-radius(globals.$ion-soft-2xs); // 4px
}
/* Round Badge */
:host(.badge-round) {
- @include globals.border-radius(globals.$ion-round-sm);
+ @include globals.border-radius(globals.$ion-round-sm); // 999px
}
/* Rectangular Badge */
:host(.badge-rectangular) {
- @include globals.border-radius(globals.$ion-rectangular-sm);
+ @include globals.border-radius(globals.$ion-rectangular-sm); // 0
}
// Badge Sizes
@@ -77,11 +78,12 @@
--padding-end: #{globals.$ion-space-050};
min-width: globals.$ion-scale-400;
- height: globals.$ion-scale-400;
+ height: globals.$ion-scale-400; // 16px
}
:host(.badge-small) ::slotted(ion-icon) {
- width: globals.$ion-scale-300;
+ @include globals.typography(globals.$ion-body-sm-medium); // TODO: Add this
+ width: globals.$ion-scale-300; // 12px
height: globals.$ion-scale-300;
}
@@ -92,10 +94,10 @@
--padding-start: #{globals.$ion-space-100};
--padding-end: #{globals.$ion-space-100};
- @include globals.typography(globals.$ion-body-md-medium);
+ @include globals.typography(globals.$ion-body-md-medium); // TODO: Add this
min-width: globals.$ion-scale-600;
- height: globals.$ion-scale-600;
+ height: globals.$ion-scale-600; // 24px
}
:host(.badge-medium) ::slotted(ion-icon),
@@ -112,6 +114,7 @@
--padding-end: 0;
}
+// TODO: don't add since this is an equivalent of size medium so give example
:host([vertical]:not(:empty)) {
--padding-start: #{globals.$ion-scale-100};
--padding-end: #{globals.$ion-scale-100};
@@ -160,17 +163,18 @@
// Badge in Button
// --------------------------------------------------
+// TODO: add example that this should be using the small size within the ion-button
:host(:not(:empty).in-button) {
- --padding-start: #{globals.$ion-scale-050};
+ --padding-start: #{globals.$ion-scale-050}; // not needed since it is the same as small, give example that it should be using small size
--padding-end: #{globals.$ion-scale-050};
- @include globals.typography(globals.$ion-body-action-xs);
+ @include globals.typography(globals.$ion-body-action-xs); // this is wrong when compared to designs
- min-width: globals.$ion-scale-400;
+ min-width: globals.$ion-scale-400; // not needed since it is the same as small, give example that it should be using small size
height: globals.$ion-scale-400;
::slotted(ion-icon) {
- width: globals.$ion-scale-300;
+ width: globals.$ion-scale-300; // not needed since it is the same as small, give example that it should be using small size
height: globals.$ion-scale-300;
}
}
diff --git a/core/src/components/badge/badge.native.scss b/core/src/components/badge/badge.native.scss
index 0afa59779d6..6bb0eebf0c9 100644
--- a/core/src/components/badge/badge.native.scss
+++ b/core/src/components/badge/badge.native.scss
@@ -1,5 +1,5 @@
@import "../../themes/native/native.globals.md";
-@import "./badge.common";
+@import "./badge";
@import "./badge.native.vars";
// Badge
@@ -15,7 +15,7 @@
min-width: $badge-min-width;
- font-family: $font-family-base;
+ font-family: $font-family-base; // TODO: Add this
font-size: $badge-font-size;
font-weight: $badge-font-weight;
diff --git a/core/src/components/badge/badge.scss b/core/src/components/badge/badge.scss
new file mode 100644
index 00000000000..72b6a55430b
--- /dev/null
+++ b/core/src/components/badge/badge.scss
@@ -0,0 +1,179 @@
+@use "../../themes/mixins" as mixins;
+@use "../../themes/functions.color" as colors;
+
+// Badge: Common Styles
+// --------------------------------------------------
+
+:host {
+ /**
+ * @prop --background: Background of the badge
+ * @prop --color: Text color of the badge
+ *
+ * @prop --padding-top: Top padding of the badge
+ * @prop --padding-end: Right padding if direction is left-to-right, and left padding if direction is right-to-left of the badge
+ * @prop --padding-bottom: Bottom padding of the badge
+ * @prop --padding-start: Left padding if direction is left-to-right, and right padding if direction is right-to-left of the badge
+ */
+ @include mixins.font-smoothing();
+
+ display: inline-flex;
+
+ align-items: center;
+ justify-content: center;
+
+ white-space: nowrap;
+
+ contain: content;
+ vertical-align: baseline;
+}
+
+// Badge: Bold
+// ---------------------------------------------
+
+// Default
+:host(.badge-bold) {
+ background: var(--ion-badge-hue-bold-default-background);
+ color: var(--ion-badge-hue-bold-default-color);
+}
+
+// Colors
+:host(.badge-bold.ion-color) {
+ background: var(--ion-badge-hue-bold-semantic-default-background);
+ color: var(--ion-badge-hue-bold-semantic-default-color);
+}
+
+// Badge: Subtle
+// ---------------------------------------------
+
+// Default
+:host(.badge-subtle) {
+ background: var(--ion-badge-hue-subtle-default-background);
+ color: var(--ion-badge-hue-subtle-default-color);
+}
+
+// Colors
+:host(.badge-subtle.ion-color) {
+ background: var(--ion-badge-hue-subtle-semantic-default-background);
+ color: var(--ion-badge-hue-subtle-semantic-default-color);
+}
+
+// Badge Shapes
+// ---------------------------------------------
+
+:host(.badge-soft) {
+ @include mixins.border-radius(var(--ion-badge-shape-soft-border-radius));
+}
+
+:host(.badge-round) {
+ @include mixins.border-radius(var(--ion-badge-shape-round-border-radius));
+}
+
+:host(.badge-rectangular) {
+ @include mixins.border-radius(var(--ion-badge-shape-rectangular-border-radius));
+}
+
+// Badge Sizes: Standalone
+// ---------------------------------------------
+
+// Small
+:host(.badge-small) {
+ @include mixins.padding(
+ var(--ion-badge-size-small-default-padding-top),
+ var(--ion-badge-size-small-default-padding-end),
+ var(--ion-badge-size-small-default-padding-bottom),
+ var(--ion-badge-size-small-default-padding-start)
+ );
+
+ min-width: var(--ion-badge-size-small-default-min-width);
+ height: var(--ion-badge-size-small-default-height);
+
+ font-size: var(--ion-badge-size-small-default-font-size);
+ font-weight: var(--ion-badge-size-small-default-font-weight);
+
+ line-height: var(--ion-badge-size-small-default-line-height);
+}
+
+:host(.badge-small) ::slotted(ion-icon) {
+ width: var(--ion-badge-size-small-default-icon-width, revert-layer);
+ height: var(--ion-badge-size-small-default-icon-height, revert-layer);
+}
+
+// Medium
+:host(.badge-medium) {
+ @include mixins.padding(
+ var(--ion-badge-size-medium-default-padding-top),
+ var(--ion-badge-size-medium-default-padding-end),
+ var(--ion-badge-size-medium-default-padding-bottom),
+ var(--ion-badge-size-medium-default-padding-start)
+ );
+
+ min-width: var(--ion-badge-size-medium-default-min-width);
+ height: var(--ion-badge-size-medium-default-height);
+
+ font-size: var(--ion-badge-size-medium-default-font-size);
+ font-weight: var(--ion-badge-size-medium-default-font-weight);
+
+ line-height: var(--ion-badge-size-medium-default-line-height);
+}
+
+:host(.badge-medium) ::slotted(ion-icon) {
+ width: var(--ion-badge-size-medium-default-icon-width, revert-layer);
+ height: var(--ion-badge-size-medium-default-icon-height, revert-layer);
+}
+
+// Large
+:host(.badge-large) {
+ @include mixins.padding(
+ var(--ion-badge-size-large-default-padding-top),
+ var(--ion-badge-size-large-default-padding-end),
+ var(--ion-badge-size-large-default-padding-bottom),
+ var(--ion-badge-size-large-default-padding-start)
+ );
+
+ min-width: var(--ion-badge-size-large-default-min-width);
+ height: var(--ion-badge-size-large-default-height);
+
+ font-size: var(--ion-badge-size-large-default-font-size);
+ font-weight: var(--ion-badge-size-large-default-font-weight);
+
+ line-height: var(--ion-badge-size-large-default-line-height);
+}
+
+:host(.badge-large) ::slotted(ion-icon) {
+ width: var(--ion-badge-size-large-default-icon-width, revert-layer);
+ height: var(--ion-badge-size-large-default-icon-height, revert-layer);
+}
+
+// Badge Sizes: Indicator
+// ---------------------------------------------
+
+:host(.badge-small:empty) {
+ min-width: var(--ion-badge-size-small-empty-min-width);
+ height: var(--ion-badge-size-small-empty-height);
+}
+
+/* md */
+:host(.badge-medium:empty) {
+ min-width: var(--ion-badge-size-medium-empty-min-width);
+ height: var(--ion-badge-size-medium-empty-height);
+}
+
+/* lg */
+:host(.badge-large:empty) {
+ min-width: var(--ion-badge-size-large-empty-min-width);
+ height: var(--ion-badge-size-large-empty-height);
+}
+
+// Empty Badge
+// ---------------------------------------------
+
+:host(:empty) {
+ @include mixins.padding(0);
+}
+
+// Badge Indicator (within a component)
+// ---------------------------------------------
+
+:host([vertical]:not(.in-tab-button)) {
+ position: absolute;
+}
diff --git a/core/src/components/badge/badge.tsx b/core/src/components/badge/badge.tsx
index 369c2ad199b..627954c2294 100644
--- a/core/src/components/badge/badge.tsx
+++ b/core/src/components/badge/badge.tsx
@@ -2,6 +2,7 @@ import type { ComponentInterface } from '@stencil/core';
import { Component, Element, Host, Prop, h } from '@stencil/core';
import { createColorClasses, hostContext } from '@utils/theme';
+import { config } from '../../global/config';
import { getIonTheme } from '../../global/ionic-global';
import type { Color } from '../../interface';
@@ -11,15 +12,12 @@ import type { Color } from '../../interface';
*/
@Component({
tag: 'ion-badge',
- styleUrls: {
- ios: 'badge.ios.scss',
- md: 'badge.md.scss',
- ionic: 'badge.ionic.scss',
- },
+ styleUrl: 'badge.scss',
shadow: true,
})
export class Badge implements ComponentInterface {
@Element() el!: HTMLElement;
+ private resizeObserver?: ResizeObserver;
/**
* The color to use from your application's color palette.
@@ -32,25 +30,26 @@ export class Badge implements ComponentInterface {
* Set to `"bold"` for a badge with vibrant, bold colors or to `"subtle"` for
* a badge with muted, subtle colors.
*
- * Only applies to the `ionic` theme.
+ * Defaults to `"bold"` if both the hue property and theme config are unset.
*/
@Prop() hue?: 'bold' | 'subtle';
/**
- * Set to `"rectangular"` for non-rounded corners.
- * Set to `"soft"` for slightly rounded corners.
- * Set to `"round"` for fully rounded corners.
+ * Set to `"crisp"` for a badge with even slightly rounded corners,
+ * `"soft"` for a badge with slightly rounded corners,
+ * `"round"` for a badge with fully rounded corners,
+ * or `"rectangular"` for a badge without rounded corners.
*
- * Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
+ * Defaults to `"soft"` if both the shape property and theme config are unset.
*/
- @Prop() shape?: 'soft' | 'round | rectangular';
+ @Prop() shape?: 'crisp' | 'soft' | 'round' | 'rectangular';
/**
- * Set to `"small"` for a small badge.
- * Set to `"medium"` for a medium badge.
- * Set to `"large"` for a large badge, when it is empty (no text or icon).
+ * Set to `"small"` for a smaller size.
+ * Set to `"medium"` for a medium size.
+ * Set to `"large"` for a larger size.
*
- * Defaults to `"small"` for the `ionic` theme, undefined for all other themes.
+ * Defaults to `"small"` if both the size property and theme config are unset.
*/
@Prop() size?: 'small' | 'medium' | 'large';
@@ -60,34 +59,24 @@ export class Badge implements ComponentInterface {
*/
@Prop() vertical?: 'top' | 'bottom';
- private getShape(): string | undefined {
- const theme = getIonTheme(this);
- const { shape } = this;
-
- // TODO(ROU-10777): Remove theme check when shapes are defined for all themes.
- if (theme !== 'ionic') {
- return undefined;
- }
-
- if (shape === undefined) {
- return 'round';
- }
+ /**
+ * Gets the badge shape. Uses the `shape` property if set, otherwise
+ * checks the theme config and falls back to 'soft' if neither is provided.
+ */
+ get shapeValue(): string {
+ const shapeConfig = config.getObjectValue('IonBadge.shape', 'soft') as string;
+ const shape = this.shape || shapeConfig;
return shape;
}
- private getSize(): string | undefined {
- const theme = getIonTheme(this);
- const { size } = this;
-
- // TODO(FW-6355): Remove theme check when sizes are defined for all themes.
- if (theme !== 'ionic') {
- return undefined;
- }
-
- if (size === undefined) {
- return 'small';
- }
+ /**
+ * Gets the badge size. Uses the `size` property if set, otherwise
+ * checks the theme config and falls back to 'small' if neither is provided.
+ */
+ get sizeValue(): string {
+ const sizeConfig = config.getObjectValue('IonBadge.size', 'small') as string;
+ const size = this.size || sizeConfig;
return size;
}
@@ -117,23 +106,31 @@ export class Badge implements ComponentInterface {
return 'subtle';
}
+ /**
+ * Gets the badge hue. Uses the `hue` property if set, otherwise
+ * checks the theme config and falls back to 'subtle' if neither is provided.
+ */
+ get hueValue(): string {
+ const hueConfig = config.getObjectValue('IonBadge.hue', 'bold') as string;
+ const hue = this.hue || hueConfig;
+
+ return hue;
+ }
+
render() {
- const hue = this.getHue();
- const shape = this.getShape();
- const size = this.getSize();
const theme = getIonTheme(this);
+ const { hueValue, shapeValue, sizeValue, color, vertical, el } = this;
return (
2,
+ [`badge-${hueValue}`]: true,
+ [`badge-${shapeValue}`]: true,
+ [`badge-${sizeValue}`]: true,
+ [`badge-vertical-${vertical}`]: vertical !== undefined,
+ 'in-button': hostContext('ion-button', el),
+ 'in-tab-button': hostContext('ion-tab-button', el),
})}
>
diff --git a/core/src/components/badge/test/hint/index.html b/core/src/components/badge/test/hint/index.html
index fba0d6e73ff..0c1f1fab827 100644
--- a/core/src/components/badge/test/hint/index.html
+++ b/core/src/components/badge/test/hint/index.html
@@ -17,6 +17,14 @@
ion-tab-bar {
width: 100%;
}
+
+ .row {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-around;
+ align-items: center;
+ margin: 16px;
+ }
@@ -35,15 +43,15 @@
Badge small
-
+ Badge Medium
-
+ Badge Large
-
+
@@ -52,184 +60,184 @@
Inside Avatar
-