feat(badge): add soft to the ionic theme (#29573)
Co-authored-by: Brandy Carney <brandyscarney@users.noreply.github.com>
@ -312,6 +312,7 @@ ion-backdrop,event,ionBackdropTap,void,true
|
|||||||
ion-badge,shadow
|
ion-badge,shadow
|
||||||
ion-badge,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
|
ion-badge,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
|
||||||
ion-badge,prop,mode,"ios" | "md",undefined,false,false
|
ion-badge,prop,mode,"ios" | "md",undefined,false,false
|
||||||
|
ion-badge,prop,shape,"soft" | undefined,undefined,false,false
|
||||||
ion-badge,prop,size,"large" | "medium" | "small" | "xlarge" | "xsmall" | "xxsmall" | undefined,undefined,false,false
|
ion-badge,prop,size,"large" | "medium" | "small" | "xlarge" | "xsmall" | "xxsmall" | undefined,undefined,false,false
|
||||||
ion-badge,prop,theme,"ios" | "md" | "ionic",undefined,false,false
|
ion-badge,prop,theme,"ios" | "md" | "ionic",undefined,false,false
|
||||||
ion-badge,css-prop,--background,ionic
|
ion-badge,css-prop,--background,ionic
|
||||||
|
8
core/src/components.d.ts
vendored
@ -417,6 +417,10 @@ export namespace Components {
|
|||||||
* The mode determines the platform behaviors of the component.
|
* The mode determines the platform behaviors of the component.
|
||||||
*/
|
*/
|
||||||
"mode"?: "ios" | "md";
|
"mode"?: "ios" | "md";
|
||||||
|
/**
|
||||||
|
* Set to `"soft"` for slightly rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
|
||||||
|
*/
|
||||||
|
"shape"?: 'soft';
|
||||||
/**
|
/**
|
||||||
* Set to `"xxsmall"` for the smallest badge. Set to "xsmall" for a very small badge. Set to `"small"` for a small badge. Set to "medium" for a medium badge. Set to "large" for a large badge. Set to `"xlarge"` for the largest badge. Defaults to `"small"` for the `ionic` theme, undefined for all other themes.
|
* Set to `"xxsmall"` for the smallest badge. Set to "xsmall" for a very small badge. Set to `"small"` for a small badge. Set to "medium" for a medium badge. Set to "large" for a large badge. Set to `"xlarge"` for the largest badge. Defaults to `"small"` for the `ionic` theme, undefined for all other themes.
|
||||||
*/
|
*/
|
||||||
@ -5661,6 +5665,10 @@ declare namespace LocalJSX {
|
|||||||
* The mode determines the platform behaviors of the component.
|
* The mode determines the platform behaviors of the component.
|
||||||
*/
|
*/
|
||||||
"mode"?: "ios" | "md";
|
"mode"?: "ios" | "md";
|
||||||
|
/**
|
||||||
|
* Set to `"soft"` for slightly rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
|
||||||
|
*/
|
||||||
|
"shape"?: 'soft';
|
||||||
/**
|
/**
|
||||||
* Set to `"xxsmall"` for the smallest badge. Set to "xsmall" for a very small badge. Set to `"small"` for a small badge. Set to "medium" for a medium badge. Set to "large" for a large badge. Set to `"xlarge"` for the largest badge. Defaults to `"small"` for the `ionic` theme, undefined for all other themes.
|
* Set to `"xxsmall"` for the smallest badge. Set to "xsmall" for a very small badge. Set to `"small"` for a small badge. Set to "medium" for a medium badge. Set to "large" for a large badge. Set to `"xlarge"` for the largest badge. Defaults to `"small"` for the `ionic` theme, undefined for all other themes.
|
||||||
*/
|
*/
|
||||||
|
@ -18,6 +18,20 @@
|
|||||||
font-weight: globals.$ionic-font-weight-medium;
|
font-weight: globals.$ionic-font-weight-medium;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Badge Shapes
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
/* Soft Badge */
|
||||||
|
:host(.badge-soft) {
|
||||||
|
@include border-radius(globals.$ionic-border-radius-200);
|
||||||
|
}
|
||||||
|
|
||||||
|
:host(.badge-xxsmall.badge-soft),
|
||||||
|
:host(.badge-xsmall.badge-soft),
|
||||||
|
:host(.badge-small.badge-soft) {
|
||||||
|
@include border-radius(globals.$ionic-border-radius-100);
|
||||||
|
}
|
||||||
|
|
||||||
// Badge Sizes
|
// Badge Sizes
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
@ -26,6 +26,13 @@ export class Badge implements ComponentInterface {
|
|||||||
*/
|
*/
|
||||||
@Prop({ reflect: true }) color?: Color;
|
@Prop({ reflect: true }) color?: Color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to `"soft"` for slightly rounded corners.
|
||||||
|
*
|
||||||
|
* Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
|
||||||
|
*/
|
||||||
|
@Prop() shape?: 'soft';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set to `"xxsmall"` for the smallest badge.
|
* Set to `"xxsmall"` for the smallest badge.
|
||||||
* Set to "xsmall" for a very small badge.
|
* Set to "xsmall" for a very small badge.
|
||||||
@ -38,6 +45,22 @@ export class Badge implements ComponentInterface {
|
|||||||
*/
|
*/
|
||||||
@Prop() size?: 'xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
|
@Prop() size?: 'xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
|
||||||
|
|
||||||
|
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';
|
||||||
|
}
|
||||||
|
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
private getSize(): string | undefined {
|
private getSize(): string | undefined {
|
||||||
const theme = getIonTheme(this);
|
const theme = getIonTheme(this);
|
||||||
const { size } = this;
|
const { size } = this;
|
||||||
@ -55,12 +78,14 @@ export class Badge implements ComponentInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const shape = this.getShape();
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
const theme = getIonTheme(this);
|
const theme = getIonTheme(this);
|
||||||
return (
|
return (
|
||||||
<Host
|
<Host
|
||||||
class={createColorClasses(this.color, {
|
class={createColorClasses(this.color, {
|
||||||
[theme]: true,
|
[theme]: true,
|
||||||
|
[`badge-${shape}`]: shape !== undefined,
|
||||||
[`badge-${size}`]: size !== undefined,
|
[`badge-${size}`]: size !== undefined,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
77
core/src/components/badge/test/shape/badge.e2e.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import { expect } from '@playwright/test';
|
||||||
|
import { configs, test } from '@utils/test/playwright';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This behavior does not vary across directions.
|
||||||
|
*/
|
||||||
|
configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screenshot, title }) => {
|
||||||
|
test.describe(title('badge: shape'), () => {
|
||||||
|
test('should render soft badges for smaller sizes', async ({ page }) => {
|
||||||
|
await page.setContent(
|
||||||
|
`
|
||||||
|
<div id="container">
|
||||||
|
<ion-badge shape="soft" size="xxsmall">1</ion-badge>
|
||||||
|
<ion-badge shape="soft" size="xsmall">1</ion-badge>
|
||||||
|
<ion-badge shape="soft" size="small">1</ion-badge>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
config
|
||||||
|
);
|
||||||
|
|
||||||
|
const container = page.locator('#container');
|
||||||
|
|
||||||
|
await expect(container).toHaveScreenshot(screenshot(`badge-shape-soft-smaller-sizes`));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render soft badges with long text for smaller sizes', async ({ page }) => {
|
||||||
|
await page.setContent(
|
||||||
|
`
|
||||||
|
<div id="container">
|
||||||
|
<ion-badge shape="soft" size="xxsmall">99+</ion-badge>
|
||||||
|
<ion-badge shape="soft" size="xsmall">99+</ion-badge>
|
||||||
|
<ion-badge shape="soft" size="small">99+</ion-badge>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
config
|
||||||
|
);
|
||||||
|
|
||||||
|
const container = page.locator('#container');
|
||||||
|
|
||||||
|
await expect(container).toHaveScreenshot(screenshot(`badge-shape-soft-smaller-sizes-long-text`));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render soft badges for larger sizes', async ({ page }) => {
|
||||||
|
await page.setContent(
|
||||||
|
`
|
||||||
|
<div id="container">
|
||||||
|
<ion-badge shape="soft" size="medium">1</ion-badge>
|
||||||
|
<ion-badge shape="soft" size="large">1</ion-badge>
|
||||||
|
<ion-badge shape="soft" size="xlarge">1</ion-badge>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
config
|
||||||
|
);
|
||||||
|
|
||||||
|
const container = page.locator('#container');
|
||||||
|
|
||||||
|
await expect(container).toHaveScreenshot(screenshot(`badge-shape-soft-larger-sizes`));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render soft badges with long text for larger sizes', async ({ page }) => {
|
||||||
|
await page.setContent(
|
||||||
|
`
|
||||||
|
<div id="container">
|
||||||
|
<ion-badge shape="soft" size="medium">99+</ion-badge>
|
||||||
|
<ion-badge shape="soft" size="large">99+</ion-badge>
|
||||||
|
<ion-badge shape="soft" size="xlarge">99+</ion-badge>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
config
|
||||||
|
);
|
||||||
|
|
||||||
|
const container = page.locator('#container');
|
||||||
|
|
||||||
|
await expect(container).toHaveScreenshot(screenshot(`badge-shape-soft-larger-sizes-long-text`));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 809 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 794 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 1.6 KiB |
41
core/src/components/badge/test/shape/index.html
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" dir="ltr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Badge - Shape</title>
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||||
|
/>
|
||||||
|
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
|
||||||
|
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||||
|
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||||
|
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||||
|
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<ion-app>
|
||||||
|
<ion-header>
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-title>Button - Shape</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
|
||||||
|
<ion-content class="ion-padding" id="content" no-bounce>
|
||||||
|
<ion-list>
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>Default</ion-label>
|
||||||
|
<ion-badge slot="end">00</ion-badge>
|
||||||
|
<ion-badge slot="end">99+</ion-badge>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>Soft</ion-label>
|
||||||
|
<ion-badge slot="end" shape="soft">1</ion-badge>
|
||||||
|
<ion-badge slot="end" shape="soft">99+</ion-badge>
|
||||||
|
</ion-item>
|
||||||
|
</ion-list>
|
||||||
|
</ion-content>
|
||||||
|
</ion-app>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -260,14 +260,14 @@ export declare interface IonBackdrop extends Components.IonBackdrop {
|
|||||||
|
|
||||||
|
|
||||||
@ProxyCmp({
|
@ProxyCmp({
|
||||||
inputs: ['color', 'mode', 'size', 'theme']
|
inputs: ['color', 'mode', 'shape', 'size', 'theme']
|
||||||
})
|
})
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ion-badge',
|
selector: 'ion-badge',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
template: '<ng-content></ng-content>',
|
template: '<ng-content></ng-content>',
|
||||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||||
inputs: ['color', 'mode', 'size', 'theme'],
|
inputs: ['color', 'mode', 'shape', 'size', 'theme'],
|
||||||
})
|
})
|
||||||
export class IonBadge {
|
export class IonBadge {
|
||||||
protected el: HTMLElement;
|
protected el: HTMLElement;
|
||||||
|
@ -344,14 +344,14 @@ export declare interface IonBackdrop extends Components.IonBackdrop {
|
|||||||
|
|
||||||
@ProxyCmp({
|
@ProxyCmp({
|
||||||
defineCustomElementFn: defineIonBadge,
|
defineCustomElementFn: defineIonBadge,
|
||||||
inputs: ['color', 'mode', 'size', 'theme']
|
inputs: ['color', 'mode', 'shape', 'size', 'theme']
|
||||||
})
|
})
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ion-badge',
|
selector: 'ion-badge',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
template: '<ng-content></ng-content>',
|
template: '<ng-content></ng-content>',
|
||||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||||
inputs: ['color', 'mode', 'size', 'theme'],
|
inputs: ['color', 'mode', 'shape', 'size', 'theme'],
|
||||||
standalone: true
|
standalone: true
|
||||||
})
|
})
|
||||||
export class IonBadge {
|
export class IonBadge {
|
||||||
|
@ -118,6 +118,7 @@ export const IonBackdrop = /*@__PURE__*/ defineContainer<JSX.IonBackdrop>('ion-b
|
|||||||
|
|
||||||
export const IonBadge = /*@__PURE__*/ defineContainer<JSX.IonBadge>('ion-badge', defineIonBadge, [
|
export const IonBadge = /*@__PURE__*/ defineContainer<JSX.IonBadge>('ion-badge', defineIonBadge, [
|
||||||
'color',
|
'color',
|
||||||
|
'shape',
|
||||||
'size'
|
'size'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|