feat(chip): add small size (#29514)
Co-authored-by: Brandy Carney <brandyscarney@users.noreply.github.com>
@ -578,6 +578,7 @@ ion-chip,prop,disabled,boolean,false,false,false
|
||||
ion-chip,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-chip,prop,outline,boolean,false,false,false
|
||||
ion-chip,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false
|
||||
ion-chip,prop,size,"large" | "small" | undefined,undefined,false,false
|
||||
ion-chip,prop,theme,"ios" | "md" | "ionic",undefined,false,false
|
||||
ion-chip,css-prop,--background,ios
|
||||
ion-chip,css-prop,--background,md
|
||||
|
8
core/src/components.d.ts
vendored
@ -766,6 +766,10 @@ export namespace Components {
|
||||
* Set to `"soft"` for a chip with slightly rounded corners, `"round"` for a chip with fully rounded corners, or `"rectangular"` for a chip without rounded corners. Defaults to `"round"` for the `"ionic"` theme and `"soft"` for all other themes.
|
||||
*/
|
||||
"shape"?: 'soft' | 'round' | 'rectangular';
|
||||
/**
|
||||
* Set to `"small"` for a chip with less height and padding. Defaults to `"large"` for the ionic theme, and undefined for all other themes.
|
||||
*/
|
||||
"size"?: 'small' | 'large';
|
||||
/**
|
||||
* The theme determines the visual appearance of the component.
|
||||
*/
|
||||
@ -6026,6 +6030,10 @@ declare namespace LocalJSX {
|
||||
* Set to `"soft"` for a chip with slightly rounded corners, `"round"` for a chip with fully rounded corners, or `"rectangular"` for a chip without rounded corners. Defaults to `"round"` for the `"ionic"` theme and `"soft"` for all other themes.
|
||||
*/
|
||||
"shape"?: 'soft' | 'round' | 'rectangular';
|
||||
/**
|
||||
* Set to `"small"` for a chip with less height and padding. Defaults to `"large"` for the ionic theme, and undefined for all other themes.
|
||||
*/
|
||||
"size"?: 'small' | 'large';
|
||||
/**
|
||||
* The theme determines the visual appearance of the component.
|
||||
*/
|
||||
|
@ -1,4 +1,5 @@
|
||||
@use "../../themes/ionic/ionic.globals.scss" as globals;
|
||||
@use "../../foundations/ionic.vars.scss" as tokens;
|
||||
|
||||
// Ionic Chip
|
||||
// --------------------------------------------------
|
||||
@ -9,13 +10,12 @@ $ionic-states-hover: #{rgba(#05080f, 0.16)}; // We should review how to make thi
|
||||
|
||||
:host {
|
||||
--background: #{globals.$ionic-color-neutral-10};
|
||||
--border-color: transparent;
|
||||
--color: #{globals.$ionic-color-neutral-900};
|
||||
--focus-ring-color: #{$ionic-states-focus-primary};
|
||||
--focus-ring-width: #{globals.$ionic-border-size-medium};
|
||||
|
||||
@include globals.font-smoothing;
|
||||
@include globals.padding(globals.$ionic-space-xs, globals.$ionic-space-xxs);
|
||||
@include globals.padding(globals.$ionic-space-xxs, globals.$ionic-space-xs);
|
||||
@include globals.border-radius(var(--border-radius));
|
||||
|
||||
display: inline-flex;
|
||||
@ -27,18 +27,10 @@ $ionic-states-hover: #{rgba(#05080f, 0.16)}; // We should review how to make thi
|
||||
|
||||
gap: globals.$ionic-space-xxxs;
|
||||
|
||||
min-height: 32px;
|
||||
|
||||
border-width: globals.$ionic-border-size-small;
|
||||
border-style: solid;
|
||||
|
||||
border-color: var(--border-color);
|
||||
|
||||
background: var(--background);
|
||||
color: var(--color);
|
||||
|
||||
font-family: globals.$ionic-font-family;
|
||||
font-size: globals.$ionic-font-size-m;
|
||||
font-weight: globals.$ionic-font-weight-medium;
|
||||
|
||||
line-height: globals.$ionic-font-line-height-full;
|
||||
@ -57,6 +49,8 @@ $ionic-states-hover: #{rgba(#05080f, 0.16)}; // We should review how to make thi
|
||||
|
||||
:host(.chip-outline) {
|
||||
--background: transparent;
|
||||
border-width: globals.$ionic-border-size-small;
|
||||
|
||||
border-color: globals.$ionic-color-neutral-100;
|
||||
}
|
||||
|
||||
@ -105,3 +99,18 @@ $ionic-states-hover: #{rgba(#05080f, 0.16)}; // We should review how to make thi
|
||||
::slotted(ion-icon) {
|
||||
font-size: globals.$ionic-font-size-l;
|
||||
}
|
||||
|
||||
// Size
|
||||
// ---------------------------------------------
|
||||
|
||||
:host(.chip-small) {
|
||||
min-height: 24px;
|
||||
|
||||
font-size: #{tokens.$ionic-font-size-s};
|
||||
}
|
||||
|
||||
:host(.chip-large) {
|
||||
min-height: 32px;
|
||||
|
||||
font-size: globals.$ionic-font-size-m;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import type { ComponentInterface } from '@stencil/core';
|
||||
import { Component, Host, Prop, h } from '@stencil/core';
|
||||
import { printIonWarning } from '@utils/logging';
|
||||
import { createColorClasses } from '@utils/theme';
|
||||
|
||||
import { getIonTheme } from '../../global/ionic-global';
|
||||
@ -57,8 +58,31 @@ export class Chip implements ComponentInterface {
|
||||
return shape;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to `"small"` for a chip with less height and padding.
|
||||
*
|
||||
* Defaults to `"large"` for the ionic theme, and undefined for all other themes.
|
||||
*/
|
||||
@Prop() size?: 'small' | 'large';
|
||||
|
||||
private getSize() {
|
||||
const theme = getIonTheme(this);
|
||||
const { size } = this;
|
||||
|
||||
if (theme === 'ionic') {
|
||||
return size !== undefined ? size : 'large';
|
||||
// TODO(ROU-10695): remove the size !== undefined when we add support for
|
||||
// the `ios` and `md` themes.
|
||||
} else if (size !== undefined) {
|
||||
printIonWarning(`The "${size}" size is not supported in the ${theme} theme.`);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
render() {
|
||||
const theme = getIonTheme(this);
|
||||
const size = this.getSize();
|
||||
|
||||
const shape = this.getShape();
|
||||
|
||||
@ -72,6 +96,7 @@ export class Chip implements ComponentInterface {
|
||||
'chip-disabled': this.disabled,
|
||||
'ion-activatable': true,
|
||||
'ion-focusable': !this.disabled,
|
||||
[`chip-${size}`]: size !== undefined,
|
||||
})}
|
||||
>
|
||||
<slot></slot>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1023 B After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1010 B After Width: | Height: | Size: 1010 B |
Before Width: | Height: | Size: 889 B After Width: | Height: | Size: 888 B |
35
core/src/components/chip/test/size/chip.e2e.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
/**
|
||||
* This behavior does not vary across modes/directions.
|
||||
*/
|
||||
configs({ modes: ['ionic-md'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
test.describe(title('chip: size'), () => {
|
||||
test('should render small chip', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`<ion-chip size="small">
|
||||
<ion-label>Small</ion-label>
|
||||
</ion-chip>`,
|
||||
config
|
||||
);
|
||||
|
||||
const chip = page.locator('ion-chip');
|
||||
|
||||
await expect(chip).toHaveScreenshot(screenshot(`chip-size-small`));
|
||||
});
|
||||
|
||||
test('should render large chip', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`<ion-chip size="large">
|
||||
<ion-label>Large</ion-label>
|
||||
</ion-chip>`,
|
||||
config
|
||||
);
|
||||
|
||||
const chip = page.locator('ion-chip');
|
||||
|
||||
await expect(chip).toHaveScreenshot(screenshot(`chip-size-large`));
|
||||
});
|
||||
});
|
||||
});
|
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1020 B |
After Width: | Height: | Size: 871 B |
After Width: | Height: | Size: 852 B |
After Width: | Height: | Size: 784 B |
162
core/src/components/chip/test/size/index.html
Normal file
@ -0,0 +1,162 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Chip - Size</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>
|
||||
<style>
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(250px, 1fr));
|
||||
grid-row-gap: 20px;
|
||||
grid-column-gap: 20px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
.grid {
|
||||
grid-template-columns: 1fr;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<ion-app>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Chip - Size</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding" id="content" style="text-align: center">
|
||||
<h2>Default Size</h2>
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
<ion-chip>
|
||||
<ion-label>Default</ion-label>
|
||||
</ion-chip>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<ion-chip>
|
||||
<ion-icon name="checkmark-circle"></ion-icon>
|
||||
<ion-label>With Icon</ion-label>
|
||||
</ion-chip>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<ion-chip>
|
||||
<ion-avatar>
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48cGF0aCBmaWxsPSIjYzVkYmZmIiBkPSJNMCAwaDUxMnY1MTJIMHoiLz48cGF0aCBkPSJNMjU2IDMwNGM2MS42IDAgMTEyLTUwLjQgMTEyLTExMlMzMTcuNiA4MCAyNTYgODBzLTExMiA1MC40LTExMiAxMTIgNTAuNCAxMTIgMTEyIDExMnptMCA0MGMtNzQuMiAwLTIyNCAzNy44LTIyNCAxMTJ2NTZoNDQ4di01NmMwLTc0LjItMTQ5LjgtMTEyLTIyNC0xMTJ6IiBmaWxsPSIjODJhZWZmIi8+PC9zdmc+"
|
||||
/>
|
||||
</ion-avatar>
|
||||
<ion-label>With Avatar</ion-label>
|
||||
</ion-chip>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<ion-chip>
|
||||
<ion-avatar>
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48cGF0aCBmaWxsPSIjYzVkYmZmIiBkPSJNMCAwaDUxMnY1MTJIMHoiLz48cGF0aCBkPSJNMjU2IDMwNGM2MS42IDAgMTEyLTUwLjQgMTEyLTExMlMzMTcuNiA4MCAyNTYgODBzLTExMiA1MC40LTExMiAxMTIgNTAuNCAxMTIgMTEyIDExMnptMCA0MGMtNzQuMiAwLTIyNCAzNy44LTIyNCAxMTJ2NTZoNDQ4di01NmMwLTc0LjItMTQ5LjgtMTEyLTIyNC0xMTJ6IiBmaWxsPSIjODJhZWZmIi8+PC9zdmc+"
|
||||
/>
|
||||
</ion-avatar>
|
||||
<ion-label>With Icon and Avatar</ion-label>
|
||||
<ion-icon name="close-circle"></ion-icon>
|
||||
</ion-chip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Small</h2>
|
||||
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
<ion-chip size="small">
|
||||
<ion-label>Default</ion-label>
|
||||
</ion-chip>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<ion-chip size="small">
|
||||
<ion-icon name="checkmark-circle"></ion-icon>
|
||||
<ion-label>With Icon</ion-label>
|
||||
</ion-chip>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<ion-chip size="small">
|
||||
<ion-avatar>
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48cGF0aCBmaWxsPSIjYzVkYmZmIiBkPSJNMCAwaDUxMnY1MTJIMHoiLz48cGF0aCBkPSJNMjU2IDMwNGM2MS42IDAgMTEyLTUwLjQgMTEyLTExMlMzMTcuNiA4MCAyNTYgODBzLTExMiA1MC40LTExMiAxMTIgNTAuNCAxMTIgMTEyIDExMnptMCA0MGMtNzQuMiAwLTIyNCAzNy44LTIyNCAxMTJ2NTZoNDQ4di01NmMwLTc0LjItMTQ5LjgtMTEyLTIyNC0xMTJ6IiBmaWxsPSIjODJhZWZmIi8+PC9zdmc+"
|
||||
/>
|
||||
</ion-avatar>
|
||||
<ion-label>With Avatar</ion-label>
|
||||
</ion-chip>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<ion-chip size="small">
|
||||
<ion-avatar>
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48cGF0aCBmaWxsPSIjYzVkYmZmIiBkPSJNMCAwaDUxMnY1MTJIMHoiLz48cGF0aCBkPSJNMjU2IDMwNGM2MS42IDAgMTEyLTUwLjQgMTEyLTExMlMzMTcuNiA4MCAyNTYgODBzLTExMiA1MC40LTExMiAxMTIgNTAuNCAxMTIgMTEyIDExMnptMCA0MGMtNzQuMiAwLTIyNCAzNy44LTIyNCAxMTJ2NTZoNDQ4di01NmMwLTc0LjItMTQ5LjgtMTEyLTIyNC0xMTJ6IiBmaWxsPSIjODJhZWZmIi8+PC9zdmc+"
|
||||
/>
|
||||
</ion-avatar>
|
||||
<ion-label>With Icon and Avatar</ion-label>
|
||||
<ion-icon name="close-circle"></ion-icon>
|
||||
</ion-chip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Large</h2>
|
||||
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
<ion-chip size="large">
|
||||
<ion-label>Default</ion-label>
|
||||
</ion-chip>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<ion-chip size="large">
|
||||
<ion-icon name="checkmark-circle"></ion-icon>
|
||||
<ion-label>With Icon</ion-label>
|
||||
</ion-chip>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<ion-chip size="large">
|
||||
<ion-avatar>
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48cGF0aCBmaWxsPSIjYzVkYmZmIiBkPSJNMCAwaDUxMnY1MTJIMHoiLz48cGF0aCBkPSJNMjU2IDMwNGM2MS42IDAgMTEyLTUwLjQgMTEyLTExMlMzMTcuNiA4MCAyNTYgODBzLTExMiA1MC40LTExMiAxMTIgNTAuNCAxMTIgMTEyIDExMnptMCA0MGMtNzQuMiAwLTIyNCAzNy44LTIyNCAxMTJ2NTZoNDQ4di01NmMwLTc0LjItMTQ5LjgtMTEyLTIyNC0xMTJ6IiBmaWxsPSIjODJhZWZmIi8+PC9zdmc+"
|
||||
/>
|
||||
</ion-avatar>
|
||||
<ion-label>With Avatar</ion-label>
|
||||
</ion-chip>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<ion-chip size="large">
|
||||
<ion-avatar>
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48cGF0aCBmaWxsPSIjYzVkYmZmIiBkPSJNMCAwaDUxMnY1MTJIMHoiLz48cGF0aCBkPSJNMjU2IDMwNGM2MS42IDAgMTEyLTUwLjQgMTEyLTExMlMzMTcuNiA4MCAyNTYgODBzLTExMiA1MC40LTExMiAxMTIgNTAuNCAxMTIgMTEyIDExMnptMCA0MGMtNzQuMiAwLTIyNCAzNy44LTIyNCAxMTJ2NTZoNDQ4di01NmMwLTc0LjItMTQ5LjgtMTEyLTIyNC0xMTJ6IiBmaWxsPSIjODJhZWZmIi8+PC9zdmc+"
|
||||
/>
|
||||
</ion-avatar>
|
||||
<ion-label>With Icon and Avatar</ion-label>
|
||||
<ion-icon name="close-circle"></ion-icon>
|
||||
</ion-chip>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
</body>
|
||||
</html>
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
@ -549,14 +549,14 @@ setting the `checked` property.
|
||||
|
||||
|
||||
@ProxyCmp({
|
||||
inputs: ['color', 'disabled', 'mode', 'outline', 'shape', 'theme']
|
||||
inputs: ['color', 'disabled', 'mode', 'outline', 'shape', 'size', 'theme']
|
||||
})
|
||||
@Component({
|
||||
selector: 'ion-chip',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: '<ng-content></ng-content>',
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||
inputs: ['color', 'disabled', 'mode', 'outline', 'shape', 'theme'],
|
||||
inputs: ['color', 'disabled', 'mode', 'outline', 'shape', 'size', 'theme'],
|
||||
})
|
||||
export class IonChip {
|
||||
protected el: HTMLElement;
|
||||
|
@ -612,14 +612,14 @@ export declare interface IonCardTitle extends Components.IonCardTitle {}
|
||||
|
||||
@ProxyCmp({
|
||||
defineCustomElementFn: defineIonChip,
|
||||
inputs: ['color', 'disabled', 'mode', 'outline', 'shape', 'theme']
|
||||
inputs: ['color', 'disabled', 'mode', 'outline', 'shape', 'size', 'theme']
|
||||
})
|
||||
@Component({
|
||||
selector: 'ion-chip',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: '<ng-content></ng-content>',
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||
inputs: ['color', 'disabled', 'mode', 'outline', 'shape', 'theme'],
|
||||
inputs: ['color', 'disabled', 'mode', 'outline', 'shape', 'size', 'theme'],
|
||||
standalone: true
|
||||
})
|
||||
export class IonChip {
|
||||
|
@ -231,7 +231,8 @@ export const IonChip = /*@__PURE__*/ defineContainer<JSX.IonChip>('ion-chip', de
|
||||
'color',
|
||||
'outline',
|
||||
'disabled',
|
||||
'shape'
|
||||
'shape',
|
||||
'size'
|
||||
]);
|
||||
|
||||
|
||||
|