diff --git a/BREAKING.md b/BREAKING.md index 4dde0c88e2b..bf30ee6cc18 100644 --- a/BREAKING.md +++ b/BREAKING.md @@ -19,6 +19,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver - [Card](#version-9x-card) - [Chip](#version-9x-chip) - [Grid](#version-9x-grid) + - [Spinner](#version-9x-spinner)

Components

@@ -32,7 +33,14 @@ This is a comprehensive list of the breaking changes introduced in the major ver

Chip

-- The `border-radius` of the `ios` and `md` chip now defaults to `10px` and `8px`, respectively, instead of `16px` in accordance with the iOS and Material Design 3 guidelines. To revert to the previous appearance, set the `shape` to `"round"`, or override the `--border-radius` CSS variable to specify a different value. +- Component CSS variables have been removed. The component now utilizes the centralized Ionic Theming system. Global updates should be managed via the theme tokens file, while component-specific overrides are handled through localized CSS variables. + - `--color` is replaced by `IonChip.hue.bold.solid.default` for global styles and `--ion-chip-hue-bold-solid-default-color` for component-specific styles if the chip has a bold hue and solid fill. + - `--color` is replaced by `IonChip.hue.bold.outline.default` for global styles and `--ion-chip-hue-bold-outline-default-color` for component-specific styles if the chip has a bold hue and outline fill. + - `--color` is replaced by `IonChip.hue.subtle.solid.default` for global styles and `--ion-chip-hue-subtle-solid-default-color` for component-specific styles if the chip has a subtle hue and solid fill. + - `--color` is replaced by `IonChip.hue.subtle.outline.default` for global styles and `--ion-chip-hue-subtle-outline-default-color` for component-specific styles if the chip has a subtle hue and outline fill. +- The `outline` property has been deprecated. To achieve an outlined chip, set the `fill` property to `"outline"`. The class `.chip-outline` has also been updated to `.chip-fill-outline` for clarity. +- Specific theme classes (e.g., `ion-chip.md`) are no longer supported. Style modifications based on the active theme must be implemented using theme tokens rather than direct class targeting. +- The `border-radius` of the `ios` and `md` chip now defaults to `10px` and `8px`, respectively, instead of `16px` in accordance with the iOS and Material Design 3 guidelines. To revert to the previous appearance, set the `shape` to `"round"`, or override the `IonChip.shape.round.border.radius` to specify a different value for global styles and `--ion-chip-shape-round-border-radius` for component-specific styles.

Grid

@@ -140,4 +148,13 @@ To reorder two columns where column 1 has `size="9" push="3"` and column 2 has ` -``` \ No newline at end of file +``` + +

Spinner

+ +- Component CSS variables have been removed. The component now utilizes the centralized Ionic Theming system. Global updates should be managed via the theme tokens file, while component-specific overrides are handled through localized CSS variables. + - `--color` is replaced by `IonSpinner.color` for global styles and +`--ion-spinner-color` for component-specific styles. +- CSS classes now include the property name to improve clarity. + - `.spinner-[spinner-name]` → `.spinner-name-[spinner-name]` +- Specific theme classes (e.g., `ion-spinner.md`) are no longer supported. Style modifications based on the active theme must be implemented using theme tokens rather than direct class targeting. diff --git a/core/api.txt b/core/api.txt index 9551b242b94..a38d887794c 100644 --- a/core/api.txt +++ b/core/api.txt @@ -602,11 +602,101 @@ 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,css-prop,--border-radius -ion-chip,css-prop,--color -ion-chip,css-prop,--focus-ring-color -ion-chip,css-prop,--focus-ring-style -ion-chip,css-prop,--focus-ring-width +ion-chip,css-prop,--ion-chip-avatar-height +ion-chip,css-prop,--ion-chip-avatar-leading-margin-bottom +ion-chip,css-prop,--ion-chip-avatar-leading-margin-end +ion-chip,css-prop,--ion-chip-avatar-leading-margin-start +ion-chip,css-prop,--ion-chip-avatar-leading-margin-top +ion-chip,css-prop,--ion-chip-avatar-trailing-margin-bottom +ion-chip,css-prop,--ion-chip-avatar-trailing-margin-end +ion-chip,css-prop,--ion-chip-avatar-trailing-margin-start +ion-chip,css-prop,--ion-chip-avatar-trailing-margin-top +ion-chip,css-prop,--ion-chip-avatar-width +ion-chip,css-prop,--ion-chip-font-weight +ion-chip,css-prop,--ion-chip-gap +ion-chip,css-prop,--ion-chip-hue-bold-outline-activated-background +ion-chip,css-prop,--ion-chip-hue-bold-outline-default-background +ion-chip,css-prop,--ion-chip-hue-bold-outline-default-border-color +ion-chip,css-prop,--ion-chip-hue-bold-outline-default-border-style +ion-chip,css-prop,--ion-chip-hue-bold-outline-default-border-width +ion-chip,css-prop,--ion-chip-hue-bold-outline-default-color +ion-chip,css-prop,--ion-chip-hue-bold-outline-focus-background +ion-chip,css-prop,--ion-chip-hue-bold-outline-hover-background +ion-chip,css-prop,--ion-chip-hue-bold-outline-semantic-activated-background +ion-chip,css-prop,--ion-chip-hue-bold-outline-semantic-default-background +ion-chip,css-prop,--ion-chip-hue-bold-outline-semantic-default-border-color +ion-chip,css-prop,--ion-chip-hue-bold-outline-semantic-default-border-style +ion-chip,css-prop,--ion-chip-hue-bold-outline-semantic-default-border-width +ion-chip,css-prop,--ion-chip-hue-bold-outline-semantic-default-color +ion-chip,css-prop,--ion-chip-hue-bold-outline-semantic-focus-background +ion-chip,css-prop,--ion-chip-hue-bold-outline-semantic-hover-background +ion-chip,css-prop,--ion-chip-hue-bold-solid-activated-background +ion-chip,css-prop,--ion-chip-hue-bold-solid-default-background +ion-chip,css-prop,--ion-chip-hue-bold-solid-default-color +ion-chip,css-prop,--ion-chip-hue-bold-solid-focus-background +ion-chip,css-prop,--ion-chip-hue-bold-solid-hover-background +ion-chip,css-prop,--ion-chip-hue-bold-solid-semantic-activated-background +ion-chip,css-prop,--ion-chip-hue-bold-solid-semantic-default-background +ion-chip,css-prop,--ion-chip-hue-bold-solid-semantic-default-color +ion-chip,css-prop,--ion-chip-hue-bold-solid-semantic-focus-background +ion-chip,css-prop,--ion-chip-hue-bold-solid-semantic-hover-background +ion-chip,css-prop,--ion-chip-hue-subtle-outline-activated-background +ion-chip,css-prop,--ion-chip-hue-subtle-outline-default-background +ion-chip,css-prop,--ion-chip-hue-subtle-outline-default-border-color +ion-chip,css-prop,--ion-chip-hue-subtle-outline-default-border-style +ion-chip,css-prop,--ion-chip-hue-subtle-outline-default-border-width +ion-chip,css-prop,--ion-chip-hue-subtle-outline-default-color +ion-chip,css-prop,--ion-chip-hue-subtle-outline-focus-background +ion-chip,css-prop,--ion-chip-hue-subtle-outline-hover-background +ion-chip,css-prop,--ion-chip-hue-subtle-outline-semantic-activated-background +ion-chip,css-prop,--ion-chip-hue-subtle-outline-semantic-default-background +ion-chip,css-prop,--ion-chip-hue-subtle-outline-semantic-default-border-color +ion-chip,css-prop,--ion-chip-hue-subtle-outline-semantic-default-border-style +ion-chip,css-prop,--ion-chip-hue-subtle-outline-semantic-default-border-width +ion-chip,css-prop,--ion-chip-hue-subtle-outline-semantic-default-color +ion-chip,css-prop,--ion-chip-hue-subtle-outline-semantic-focus-background +ion-chip,css-prop,--ion-chip-hue-subtle-outline-semantic-hover-background +ion-chip,css-prop,--ion-chip-hue-subtle-solid-activated-background +ion-chip,css-prop,--ion-chip-hue-subtle-solid-default-background +ion-chip,css-prop,--ion-chip-hue-subtle-solid-default-color +ion-chip,css-prop,--ion-chip-hue-subtle-solid-focus-background +ion-chip,css-prop,--ion-chip-hue-subtle-solid-hover-background +ion-chip,css-prop,--ion-chip-hue-subtle-solid-semantic-activated-background +ion-chip,css-prop,--ion-chip-hue-subtle-solid-semantic-default-background +ion-chip,css-prop,--ion-chip-hue-subtle-solid-semantic-default-color +ion-chip,css-prop,--ion-chip-hue-subtle-solid-semantic-focus-background +ion-chip,css-prop,--ion-chip-hue-subtle-solid-semantic-hover-background +ion-chip,css-prop,--ion-chip-icon-color +ion-chip,css-prop,--ion-chip-icon-font-size +ion-chip,css-prop,--ion-chip-icon-leading-margin-bottom +ion-chip,css-prop,--ion-chip-icon-leading-margin-end +ion-chip,css-prop,--ion-chip-icon-leading-margin-start +ion-chip,css-prop,--ion-chip-icon-leading-margin-top +ion-chip,css-prop,--ion-chip-icon-trailing-margin-bottom +ion-chip,css-prop,--ion-chip-icon-trailing-margin-end +ion-chip,css-prop,--ion-chip-icon-trailing-margin-start +ion-chip,css-prop,--ion-chip-icon-trailing-margin-top +ion-chip,css-prop,--ion-chip-letter-spacing +ion-chip,css-prop,--ion-chip-line-height +ion-chip,css-prop,--ion-chip-margin-bottom +ion-chip,css-prop,--ion-chip-margin-end +ion-chip,css-prop,--ion-chip-margin-start +ion-chip,css-prop,--ion-chip-margin-top +ion-chip,css-prop,--ion-chip-padding-bottom +ion-chip,css-prop,--ion-chip-padding-end +ion-chip,css-prop,--ion-chip-padding-start +ion-chip,css-prop,--ion-chip-padding-top +ion-chip,css-prop,--ion-chip-shape-rectangular-border-radius +ion-chip,css-prop,--ion-chip-shape-round-border-radius +ion-chip,css-prop,--ion-chip-shape-soft-border-radius +ion-chip,css-prop,--ion-chip-size-large-font-size +ion-chip,css-prop,--ion-chip-size-large-min-height +ion-chip,css-prop,--ion-chip-size-small-font-size +ion-chip,css-prop,--ion-chip-size-small-min-height +ion-chip,css-prop,--ion-chip-state-disabled-opacity +ion-chip,css-prop,--ion-chip-state-focus-ring-color +ion-chip,css-prop,--ion-chip-state-focus-ring-style +ion-chip,css-prop,--ion-chip-state-focus-ring-width ion-col,shadow ion-col,prop,mode,"ios" | "md",undefined,false,false @@ -2309,10 +2399,24 @@ ion-spinner,prop,mode,"ios" | "md",undefined,false,false ion-spinner,prop,name,"bubbles" | "circles" | "circular" | "crescent" | "dots" | "lines" | "lines-sharp" | "lines-sharp-small" | "lines-small" | undefined,undefined,false,false ion-spinner,prop,paused,boolean,false,false,false ion-spinner,prop,size,"large" | "medium" | "small" | "xlarge" | "xsmall" | undefined,undefined,false,false -ion-spinner,prop,theme,"ios" | "md" | "ionic",undefined,false,false -ion-spinner,css-prop,--color,ionic -ion-spinner,css-prop,--color,ios -ion-spinner,css-prop,--color,md +ion-spinner,css-prop,--ion-spinner-circular-stroke-width +ion-spinner,css-prop,--ion-spinner-color +ion-spinner,css-prop,--ion-spinner-crescent-stroke-width +ion-spinner,css-prop,--ion-spinner-dots-stroke-width +ion-spinner,css-prop,--ion-spinner-lines-sharp-small-stroke-width +ion-spinner,css-prop,--ion-spinner-lines-sharp-stroke-width +ion-spinner,css-prop,--ion-spinner-lines-small-stroke-width +ion-spinner,css-prop,--ion-spinner-lines-stroke-width +ion-spinner,css-prop,--ion-spinner-size-large-height +ion-spinner,css-prop,--ion-spinner-size-large-width +ion-spinner,css-prop,--ion-spinner-size-medium-height +ion-spinner,css-prop,--ion-spinner-size-medium-width +ion-spinner,css-prop,--ion-spinner-size-small-height +ion-spinner,css-prop,--ion-spinner-size-small-width +ion-spinner,css-prop,--ion-spinner-size-xlarge-height +ion-spinner,css-prop,--ion-spinner-size-xlarge-width +ion-spinner,css-prop,--ion-spinner-size-xsmall-height +ion-spinner,css-prop,--ion-spinner-size-xsmall-width ion-split-pane,shadow ion-split-pane,prop,contentId,string | undefined,undefined,false,true diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 5bc8b061e63..7769ddba3af 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -39,6 +39,7 @@ import { SegmentViewScrollEvent } from "./components/segment-view/segment-view-i import { SelectChangeEventDetail, SelectCompareFn, SelectInterface } from "./components/select/select-interface"; import { SelectModalOption } from "./components/select-modal/select-modal-interface"; import { SelectPopoverOption } from "./components/select-popover/select-popover-interface"; +import { SpinnerSize } from "./components/spinner/spinner.interfaces"; import { TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout } from "./components/tab-bar/tab-bar-interface"; import { TextareaChangeEventDetail, TextareaInputEventDetail } from "./components/textarea/textarea-interface"; import { ToastButton, ToastDismissOptions, ToastLayout, ToastPosition, ToastPresentOptions, ToastSwipeGestureDirection } from "./components/toast/toast-interface"; @@ -77,6 +78,7 @@ export { SegmentViewScrollEvent } from "./components/segment-view/segment-view-i export { SelectChangeEventDetail, SelectCompareFn, SelectInterface } from "./components/select/select-interface"; export { SelectModalOption } from "./components/select-modal/select-modal-interface"; export { SelectPopoverOption } from "./components/select-popover/select-popover-interface"; +export { SpinnerSize } from "./components/spinner/spinner.interfaces"; export { TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout } from "./components/tab-bar/tab-bar-interface"; export { TextareaChangeEventDetail, TextareaInputEventDetail } from "./components/textarea/textarea-interface"; export { ToastButton, ToastDismissOptions, ToastLayout, ToastPosition, ToastPresentOptions, ToastSwipeGestureDirection } from "./components/toast/toast-interface"; @@ -872,11 +874,11 @@ export namespace Components { */ "disabled": boolean; /** - * The fill for the chip. Set to `"outline"` for a chip with a border and background. Set to `"solid"` for a chip with a background. Defaults to `"solid"`. + * The fill for the chip. Set to `"outline"` for a chip with a border and background. Set to `"solid"` for a chip with a background. Defaults to `"solid"` if both the fill property and theme config are unset. */ "fill"?: 'outline' | 'solid'; /** - * Set to `"bold"` for a chip with vibrant, bold colors or to `"subtle"` for a chip with muted, subtle colors. Defaults to `"subtle"`. + * Set to `"bold"` for a chip with vibrant, bold colors or to `"subtle"` for a chip with muted, subtle colors. Defaults to `"subtle"` if both the hue property and theme config are unset. */ "hue"?: 'bold' | 'subtle'; /** @@ -890,11 +892,11 @@ export namespace Components { */ "outline": boolean; /** - * 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"`. + * 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"` if both the shape property and theme config are unset. */ "shape"?: 'soft' | 'round' | 'rectangular'; /** - * Set to `"small"` for a chip with less height and padding. Defaults to `"large"`. + * Set to `"small"` for a chip with less height and padding. Defaults to `"large"` if both the size property and theme config are unset. */ "size"?: 'small' | 'large'; } @@ -3881,13 +3883,9 @@ export namespace Components { */ "paused": boolean; /** - * Set to `"xsmall"` for the smallest size. Set to `"small"` for a smaller size. Set to `"medium"` for a medium size. Set to `"large"` for a large size. Set to `"xlarge"` for the largest size. Defaults to `"xsmall"` for the `ionic` theme, undefined for all other themes. + * Set to `"xsmall"` for the smallest size. Set to `"small"` for a smaller size. Set to `"medium"` for a medium size. Set to `"large"` for a large size. Set to `"xlarge"` for the largest size. Defaults to `"medium"` if both the size property and theme config are unset. */ - "size"?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge'; - /** - * The theme determines the visual appearance of the component. - */ - "theme"?: "ios" | "md" | "ionic"; + "size"?: SpinnerSize; } interface IonSplitPane { /** @@ -6846,11 +6844,11 @@ declare namespace LocalJSX { */ "disabled"?: boolean; /** - * The fill for the chip. Set to `"outline"` for a chip with a border and background. Set to `"solid"` for a chip with a background. Defaults to `"solid"`. + * The fill for the chip. Set to `"outline"` for a chip with a border and background. Set to `"solid"` for a chip with a background. Defaults to `"solid"` if both the fill property and theme config are unset. */ "fill"?: 'outline' | 'solid'; /** - * Set to `"bold"` for a chip with vibrant, bold colors or to `"subtle"` for a chip with muted, subtle colors. Defaults to `"subtle"`. + * Set to `"bold"` for a chip with vibrant, bold colors or to `"subtle"` for a chip with muted, subtle colors. Defaults to `"subtle"` if both the hue property and theme config are unset. */ "hue"?: 'bold' | 'subtle'; /** @@ -6864,11 +6862,11 @@ declare namespace LocalJSX { */ "outline"?: boolean; /** - * 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"`. + * 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"` if both the shape property and theme config are unset. */ "shape"?: 'soft' | 'round' | 'rectangular'; /** - * Set to `"small"` for a chip with less height and padding. Defaults to `"large"`. + * Set to `"small"` for a chip with less height and padding. Defaults to `"large"` if both the size property and theme config are unset. */ "size"?: 'small' | 'large'; } @@ -9911,13 +9909,9 @@ declare namespace LocalJSX { */ "paused"?: boolean; /** - * Set to `"xsmall"` for the smallest size. Set to `"small"` for a smaller size. Set to `"medium"` for a medium size. Set to `"large"` for a large size. Set to `"xlarge"` for the largest size. Defaults to `"xsmall"` for the `ionic` theme, undefined for all other themes. + * Set to `"xsmall"` for the smallest size. Set to `"small"` for a smaller size. Set to `"medium"` for a medium size. Set to `"large"` for a large size. Set to `"xlarge"` for the largest size. Defaults to `"medium"` if both the size property and theme config are unset. */ - "size"?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge'; - /** - * The theme determines the visual appearance of the component. - */ - "theme"?: "ios" | "md" | "ionic"; + "size"?: SpinnerSize; } interface IonSplitPane { /** diff --git a/core/src/components/button/button.common.scss b/core/src/components/button/button.common.scss index 8493086766f..b7e43f2e411 100644 --- a/core/src/components/button/button.common.scss +++ b/core/src/components/button/button.common.scss @@ -208,6 +208,10 @@ pointer-events: none; } +::slotted(ion-spinner) { + color: currentColor; +} + // Button Ripple effect // -------------------------------------------------- diff --git a/core/src/components/button/button.ionic.scss b/core/src/components/button/button.ionic.scss index 39503a496fa..21371acf605 100644 --- a/core/src/components/button/button.ionic.scss +++ b/core/src/components/button/button.ionic.scss @@ -166,9 +166,6 @@ // Button with Spinner // ------------------------------------------------------------------------------- -::slotted(ion-spinner) { - --color: currentColor; -} /* Button containing only a spinner */ ::slotted(ion-spinner[slot="start"]), diff --git a/core/src/components/chip/chip.scss b/core/src/components/chip/chip.scss index a3056ea97e2..af1c77c7877 100644 --- a/core/src/components/chip/chip.scss +++ b/core/src/components/chip/chip.scss @@ -6,18 +6,124 @@ :host { /** - * @prop --border-radius: Border radius of the chip - * @prop --color: Color of the chip - * @prop --focus-ring-color: Color of the focus ring - * @prop --focus-ring-style: Style of the focus ring - * @prop --focus-ring-width: Width of the focus ring + * @prop --ion-chip-margin-top: Top margin of the chip + * @prop --ion-chip-margin-end: Right margin if direction is left-to-right, and left margin if direction is right-to-left of the chip + * @prop --ion-chip-margin-bottom: Bottom margin of the chip + * @prop --ion-chip-margin-start: Left margin if direction is left-to-right, and right margin if direction is right-to-left of the chip + * + * @prop --ion-chip-padding-top: Top padding of the chip + * @prop --ion-chip-padding-end: Right padding if direction is left-to-right, and left padding if direction is right-to-left of the chip + * @prop --ion-chip-padding-bottom: Bottom padding of the chip + * @prop --ion-chip-padding-start: Left padding if direction is left-to-right, and right padding if direction is right-to-left of the chip + * + * @prop --ion-chip-font-weight: Font weight of the chip + * @prop --ion-chip-letter-spacing: Letter spacing of the chip + * @prop --ion-chip-line-height: Line height of the chip + * @prop --ion-chip-gap: Gap between slotted elements in the chip + * + * Sizes + * @prop --ion-chip-size-small-min-height: Minimum height of the `small` chip size + * @prop --ion-chip-size-small-font-size: Font size of the `small` chip size + * @prop --ion-chip-size-large-min-height: Minimum height of the `large` chip size + * @prop --ion-chip-size-large-font-size: Font size of the `large` chip size + * + * Shapes + * @prop --ion-chip-shape-soft-border-radius: Border radius of the `soft` chip shape + * @prop --ion-chip-shape-round-border-radius: Border radius of the `round` chip shape + * @prop --ion-chip-shape-rectangular-border-radius: Border radius of the `rectangular` chip shape + * + * Bold Solid + * @prop --ion-chip-hue-bold-solid-default-color: Color of the `bold` hue and `solid` fill combination in the default state + * @prop --ion-chip-hue-bold-solid-default-background: Background color of the `bold` hue and `solid` fill combination in the default state + * @prop --ion-chip-hue-bold-solid-activated-background: Background color of the `bold` hue and `solid` fill combination in the activated state + * @prop --ion-chip-hue-bold-solid-focus-background: Background color of the `bold` hue and `solid` fill combination in the focus state + * @prop --ion-chip-hue-bold-solid-hover-background: Background color of the `bold` hue and `solid` fill combination in the hover state + * @prop --ion-chip-hue-bold-solid-semantic-default-color: Color of the `bold` hue and `solid` fill combination when a semantic color is applied + * @prop --ion-chip-hue-bold-solid-semantic-default-background: Background color of the `bold` hue and `solid` fill combination when a semantic color is applied + * @prop --ion-chip-hue-bold-solid-semantic-activated-background: Background color of the `bold` hue and `solid` fill combination when a semantic color is applied and in the activated state + * @prop --ion-chip-hue-bold-solid-semantic-focus-background: Background color of the `bold` hue and `solid` fill combination when a semantic color is applied and in the focus state + * @prop --ion-chip-hue-bold-solid-semantic-hover-background: Background color of the `bold` hue and `solid` fill combination when a semantic color is applied and in the hover state + * + * Bold Outline + * @prop --ion-chip-hue-bold-outline-default-color: Color of the `bold` hue and `outline` fill combination in the default state + * @prop --ion-chip-hue-bold-outline-default-background: Background color of the `bold` hue and `outline` fill combination in the default state + * @prop --ion-chip-hue-bold-outline-activated-background: Background color of the `bold` hue and `outline` fill combination in the activated state + * @prop --ion-chip-hue-bold-outline-focus-background: Background color of the `bold` hue and `outline` fill combination in the focus state + * @prop --ion-chip-hue-bold-outline-hover-background: Background color of the `bold` hue and `outline` fill combination in the hover state + * @prop --ion-chip-hue-bold-outline-default-border-width: Border width of the `bold` hue and `outline` fill combination in the default state + * @prop --ion-chip-hue-bold-outline-default-border-style: Border style of the `bold` hue and `outline` fill combination in the default state + * @prop --ion-chip-hue-bold-outline-default-border-color: Border color of the `bold` hue and `outline` fill combination in the default state + * @prop --ion-chip-hue-bold-outline-semantic-default-color: Color of the `bold` hue and `outline` fill combination when a semantic color is applied + * @prop --ion-chip-hue-bold-outline-semantic-default-background: Background color of the `bold` hue and `outline` fill combination when a semantic color is applied + * @prop --ion-chip-hue-bold-outline-semantic-activated-background: Background color of the `bold` hue and `outline` fill combination when a semantic color is applied and in the activated state + * @prop --ion-chip-hue-bold-outline-semantic-focus-background: Background color of the `bold` hue and `outline` fill combination when a semantic color is applied and in the focus state + * @prop --ion-chip-hue-bold-outline-semantic-hover-background: Background color of the `bold` hue and `outline` fill combination when a semantic color is applied and in the hover state + * @prop --ion-chip-hue-bold-outline-semantic-default-border-width: Border width of the `bold` hue and `outline` fill combination when a semantic color is applied + * @prop --ion-chip-hue-bold-outline-semantic-default-border-style: Border style of the `bold` hue and `outline` fill combination when a semantic color is applied + * @prop --ion-chip-hue-bold-outline-semantic-default-border-color: Border color of the `bold` hue and `outline` fill combination when a semantic color is applied + * + * Subtle Solid + * @prop --ion-chip-hue-subtle-solid-default-color: Color of the `subtle` hue and `solid` fill combination in the default state + * @prop --ion-chip-hue-subtle-solid-default-background: Background color of the `subtle` hue and `solid` fill combination in the default state + * @prop --ion-chip-hue-subtle-solid-activated-background: Background color of the `subtle` hue and `solid` fill combination in the activated state + * @prop --ion-chip-hue-subtle-solid-focus-background: Background color of the `subtle` hue and `solid` fill combination in the focus state + * @prop --ion-chip-hue-subtle-solid-hover-background: Background color of the `subtle` hue and `solid` fill combination in the hover state + * @prop --ion-chip-hue-subtle-solid-semantic-default-color: Color of the `subtle` hue and `solid` fill combination when a semantic color is applied + * @prop --ion-chip-hue-subtle-solid-semantic-default-background: Background color of the `subtle` hue and `solid` fill combination when a semantic color is applied + * @prop --ion-chip-hue-subtle-solid-semantic-activated-background: Background color of the `subtle` hue and `solid` fill combination when a semantic color is applied and in the activated state + * @prop --ion-chip-hue-subtle-solid-semantic-focus-background: Background color of the `subtle` hue and `solid` fill combination when a semantic color is applied and in the focus state + * @prop --ion-chip-hue-subtle-solid-semantic-hover-background: Background color of the `subtle` hue and `solid` fill combination when a semantic color is applied and in the hover state + * + * Subtle Outline + * @prop --ion-chip-hue-subtle-outline-default-color: Color of the `subtle` hue and `outline` fill combination in the default state + * @prop --ion-chip-hue-subtle-outline-default-background: Background color of the `subtle` hue and `outline` fill combination in the default state + * @prop --ion-chip-hue-subtle-outline-activated-background: Background color of the `subtle` hue and `outline` fill combination in the activated state + * @prop --ion-chip-hue-subtle-outline-focus-background: Background color of the `subtle` hue and `outline` fill combination in the focus state + * @prop --ion-chip-hue-subtle-outline-hover-background: Background color of the `subtle` hue and `outline` fill combination in the hover state + * @prop --ion-chip-hue-subtle-outline-default-border-width: Border width of the `subtle` hue and `outline` fill combination in the default state + * @prop --ion-chip-hue-subtle-outline-default-border-style: Border style of the `subtle` hue and `outline` fill combination in the default state + * @prop --ion-chip-hue-subtle-outline-default-border-color: Border color of the `subtle` hue and `outline` fill combination in the default state + * @prop --ion-chip-hue-subtle-outline-semantic-default-color: Color of the `subtle` hue and `outline` fill combination when a semantic color is applied + * @prop --ion-chip-hue-subtle-outline-semantic-default-background: Background color of the `subtle` hue and `outline` fill combination when a semantic color is applied + * @prop --ion-chip-hue-subtle-outline-semantic-activated-background: Background color of the `subtle` hue and `outline` fill combination when a semantic color is applied and in the activated state + * @prop --ion-chip-hue-subtle-outline-semantic-focus-background: Background color of the `subtle` hue and `outline` fill combination when a semantic color is applied and in the focus state + * @prop --ion-chip-hue-subtle-outline-semantic-hover-background: Background color of the `subtle` hue and `outline` fill combination when a semantic color is applied and in the hover state + * @prop --ion-chip-hue-subtle-outline-semantic-default-border-width: Border width of the `subtle` hue and `outline` fill combination when a semantic color is applied + * @prop --ion-chip-hue-subtle-outline-semantic-default-border-style: Border style of the `subtle` hue and `outline` fill combination when a semantic color is applied + * @prop --ion-chip-hue-subtle-outline-semantic-default-border-color: Border color of the `subtle` hue and `outline` fill combination when a semantic color is applied + * + * States + * @prop --ion-chip-state-focus-ring-color: Color of the focus ring + * @prop --ion-chip-state-focus-ring-style: Style of the focus ring + * @prop --ion-chip-state-focus-ring-width: Width of the focus ring + * @prop --ion-chip-state-disabled-opacity: Opacity of the chip when it is disabled + * + * Slotted Icon + * @prop --ion-chip-icon-color: Color of the slotted `ion-icon` + * @prop --ion-chip-icon-font-size: Font size of the slotted `ion-icon` + * @prop --ion-chip-icon-leading-margin-top: Top margin of the slotted `ion-icon` when it is the first child + * @prop --ion-chip-icon-leading-margin-end: Right margin if direction is left-to-right, and left margin if direction is right-to-left of the slotted `ion-icon` when it is the first child + * @prop --ion-chip-icon-leading-margin-bottom: Bottom margin of the slotted `ion-icon` when it is the first child + * @prop --ion-chip-icon-leading-margin-start: Left margin if direction is left-to-right, and right margin if direction is right-to-left of the slotted `ion-icon` when it is the first child + * @prop --ion-chip-icon-trailing-margin-top: Top margin of the slotted `ion-icon` when it is the last child + * @prop --ion-chip-icon-trailing-margin-end: Right margin if direction is left-to-right, and left margin if direction is right-to-left of the slotted `ion-icon` when it is the last child + * @prop --ion-chip-icon-trailing-margin-bottom: Bottom margin of the slotted `ion-icon` when it is the last child + * @prop --ion-chip-icon-trailing-margin-start: Left margin if direction is left-to-right, and right margin if direction is right-to-left of the slotted `ion-icon` when it is the last child + * + * Slotted Avatar + * @prop --ion-chip-avatar-width: Width of the slotted `ion-avatar` + * @prop --ion-chip-avatar-height: Height of the slotted `ion-avatar` + * @prop --ion-chip-avatar-leading-margin-top: Top margin of the slotted `ion-avatar` when it is the first child + * @prop --ion-chip-avatar-leading-margin-end: Right margin if direction is left-to-right, and left margin if direction is right-to-left of the slotted `ion-avatar` when it is the first child + * @prop --ion-chip-avatar-leading-margin-bottom: Bottom margin of the slotted `ion-avatar` when it is the first child + * @prop --ion-chip-avatar-leading-margin-start: Left margin if direction is left-to-right, and right margin if direction is right-to-left of the slotted `ion-avatar` when it is the first child + * @prop --ion-chip-avatar-trailing-margin-top: Top margin of the slotted `ion-avatar` when it is the last child + * @prop --ion-chip-avatar-trailing-margin-end: Right margin if direction is left-to-right, and left margin if direction is right-to-left of the slotted `ion-avatar` when it is the last child + * @prop --ion-chip-avatar-trailing-margin-bottom: Bottom margin of the slotted `ion-avatar` when it is the last child + * @prop --ion-chip-avatar-trailing-margin-start: Left margin if direction is left-to-right, and right margin if direction is right-to-left of the slotted `ion-avatar` when it is the last child */ - --focus-ring-color: var(--ion-chip-state-focus-ring-color); - --focus-ring-style: var(--ion-chip-state-focus-ring-style); - --focus-ring-width: var(--ion-chip-state-focus-ring-width); @include mixins.font-smoothing(); - @include mixins.border-radius(var(--border-radius)); @include mixins.margin( var(--ion-chip-margin-top), var(--ion-chip-margin-end), @@ -37,8 +143,6 @@ align-items: center; justify-content: center; - color: var(--color); - font-weight: var(--ion-chip-font-weight); letter-spacing: var(--ion-chip-letter-spacing); @@ -72,15 +176,15 @@ // --------------------------------------------- :host(.chip-shape-soft) { - --border-radius: var(--ion-chip-shape-soft-border-radius); + @include mixins.border-radius(var(--ion-chip-shape-soft-border-radius)); } :host(.chip-shape-round) { - --border-radius: var(--ion-chip-shape-round-border-radius); + @include mixins.border-radius(var(--ion-chip-shape-round-border-radius)); } :host(.chip-shape-rectangular) { - --border-radius: var(--ion-chip-shape-rectangular-border-radius); + @include mixins.border-radius(var(--ion-chip-shape-rectangular-border-radius)); } // Chip: Bold Solid @@ -358,7 +462,11 @@ // Focus :host(.ion-focused) { - @include mixins.focused-state(var(--focus-ring-width), var(--focus-ring-style), var(--focus-ring-color)); + @include mixins.focused-state( + var(--ion-chip-state-focus-ring-width), + var(--ion-chip-state-focus-ring-style), + var(--ion-chip-state-focus-ring-color) + ); } // Chip Slotted Elements diff --git a/core/src/components/chip/chip.tsx b/core/src/components/chip/chip.tsx index a4f7c6fbd4d..092ce877ff1 100644 --- a/core/src/components/chip/chip.tsx +++ b/core/src/components/chip/chip.tsx @@ -37,7 +37,7 @@ export class Chip implements ComponentInterface { * Set to `"outline"` for a chip with a border and background. * Set to `"solid"` for a chip with a background. * - * Defaults to `"solid"`. + * Defaults to `"solid"` if both the fill property and theme config are unset. */ @Prop() fill?: 'outline' | 'solid'; @@ -50,7 +50,7 @@ export class Chip implements ComponentInterface { * Set to `"bold"` for a chip with vibrant, bold colors or to `"subtle"` for * a chip with muted, subtle colors. * - * Defaults to `"subtle"`. + * Defaults to `"subtle"` if both the hue property and theme config are unset. */ @Prop() hue?: 'bold' | 'subtle'; @@ -59,7 +59,7 @@ export class Chip implements ComponentInterface { * `"round"` for a chip with fully rounded corners, * or `"rectangular"` for a chip without rounded corners. * - * Defaults to `"round"`. + * Defaults to `"round"` if both the shape property and theme config are unset. */ @Prop() shape?: 'soft' | 'round' | 'rectangular'; @@ -67,7 +67,7 @@ export class Chip implements ComponentInterface { /** * Set to `"small"` for a chip with less height and padding. * - * Defaults to `"large"`. + * Defaults to `"large"` if both the size property and theme config are unset. */ @Prop() size?: 'small' | 'large'; @@ -81,7 +81,8 @@ export class Chip implements ComponentInterface { } /** - * Set the fill based on the custom theme config + * Gets the chip fill. Uses the `fill` property if set, otherwise + * checks the theme config and falls back to 'solid' if neither is provided. */ get fillValue(): string { const fillConfig = config.getObjectValue('IonChip.fill', 'solid') as string; @@ -91,7 +92,8 @@ export class Chip implements ComponentInterface { } /** - * Set the hue based on the custom theme config + * Gets the chip 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('IonChip.hue', 'subtle') as string; @@ -101,7 +103,8 @@ export class Chip implements ComponentInterface { } /** - * Set the shape based on the custom theme config + * Gets the chip shape. Uses the `shape` property if set, otherwise + * checks the theme config and falls back to 'round' if neither is provided. */ get shapeValue(): string { const shapeConfig = config.getObjectValue('IonChip.shape', 'round') as string; @@ -111,7 +114,8 @@ export class Chip implements ComponentInterface { } /** - * Set the size based on the custom theme config + * Gets the chip size. Uses the `size` property if set, otherwise + * checks the theme config and falls back to 'large' if neither is provided. */ get sizeValue(): string { const sizeConfig = config.getObjectValue('IonChip.size', 'large') as string; diff --git a/core/src/components/spinner/spinner-configs.ts b/core/src/components/spinner/spinner-configs.ts index ecc15c14ef6..362503d6275 100644 --- a/core/src/components/spinner/spinner-configs.ts +++ b/core/src/components/spinner/spinner-configs.ts @@ -1,4 +1,4 @@ -import type { SpinnerConfigs } from './spinner-interface'; +import type { SpinnerDefinitions } from './spinner.interfaces'; const spinners = { bubbles: { @@ -150,5 +150,5 @@ const spinners = { }, }; -export const SPINNERS: SpinnerConfigs = spinners; +export const SPINNERS: SpinnerDefinitions = spinners; export type SpinnerTypes = keyof typeof spinners; diff --git a/core/src/components/spinner/spinner-interface.ts b/core/src/components/spinner/spinner-interface.ts deleted file mode 100644 index f2ab24691e2..00000000000 --- a/core/src/components/spinner/spinner-interface.ts +++ /dev/null @@ -1,22 +0,0 @@ -export interface SpinnerConfigs { - [spinnerName: string]: SpinnerConfig; -} - -export interface SpinnerConfig { - dur: number; - circles?: number; - lines?: number; - elmDuration?: boolean; - fn: (dur: number, index: number, total: number) => SpinnerData; -} - -export interface SpinnerData { - r?: number; - y1?: number; - y2?: number; - cx?: number; - cy?: number; - style: { [key: string]: string | undefined }; - viewBox?: string; - transform?: string; -} diff --git a/core/src/components/spinner/spinner.common.scss b/core/src/components/spinner/spinner.common.scss deleted file mode 100644 index 2f1cb572c35..00000000000 --- a/core/src/components/spinner/spinner.common.scss +++ /dev/null @@ -1,206 +0,0 @@ -@import "../../themes/mixins"; -// Required to use the current-color function -@import "../../themes/functions.color"; - -// Spinners -// -------------------------------------------------- - -:host { - /** - * @prop --color: Color of the spinner - */ - - display: inline-block; - position: relative; - - width: 28px; - height: 28px; - - color: var(--color); - - user-select: none; -} - -:host(.ion-color) { - color: current-color(base); -} - -svg { - @include transform-origin(center); - - position: absolute; - - /** - * Do not use @include position - * as the alignment of the elements with - * a spinner should not be RTL aware. - */ - top: 0; - /* stylelint-disable-next-line property-disallowed-list */ - left: 0; - - width: 100%; - height: 100%; - - transform: translateZ(0); -} - -// Spinner: lines / lines-small / lines-sharp / lines-sharp-small -// -------------------------------------------------- - -:host(.spinner-lines) line, -:host(.spinner-lines-small) line, -:host(.spinner-lines-sharp) line, -:host(.spinner-lines-sharp-small) line { - stroke-linecap: round; - stroke: currentColor; -} - -:host(.spinner-lines) svg, -:host(.spinner-lines-small) svg, -:host(.spinner-lines-sharp) svg, -:host(.spinner-lines-sharp-small) svg { - animation: spinner-fade-out 1s linear infinite; -} - -// Spinner: bubbles -// -------------------------------------------------- - -:host(.spinner-bubbles) svg { - animation: spinner-scale-out 1s linear infinite; - fill: currentColor; -} - -// Spinner: circles -// -------------------------------------------------- - -:host(.spinner-circles) svg { - animation: spinner-fade-out 1s linear infinite; - fill: currentColor; -} - -// Spinner: crescent -// -------------------------------------------------- - -:host(.spinner-crescent) circle { - fill: transparent; - stroke-width: 4px; - stroke-dasharray: 128px; - stroke-dashoffset: 82px; - stroke: currentColor; -} - -:host(.spinner-crescent) svg { - animation: spinner-rotate 1s linear infinite; -} - -// Spinner: dots -// -------------------------------------------------- - -:host(.spinner-dots) circle { - stroke-width: 0; - fill: currentColor; -} - -:host(.spinner-dots) svg { - animation: spinner-dots 1s linear infinite; -} - -// Spinner: circular -// -------------------------------------------------- - -:host(.spinner-circular) svg { - animation: spinner-circular linear infinite; -} - -:host(.spinner-circular) circle { - animation: spinner-circular-inner ease-in-out infinite; - stroke: currentColor; - stroke-dasharray: 80px, 200px; - stroke-dashoffset: 0px; - stroke-width: 5.6; - fill: none; -} - -// Spinner: paused -// -------------------------------------------------- - -:host(.spinner-paused), -:host(.spinner-paused) svg, -:host(.spinner-paused) circle { - animation-play-state: paused; -} - -// Animation Keyframes -// -------------------------------------------------- - -@keyframes spinner-fade-out { - 0% { - opacity: 1; - } - - 100% { - opacity: 0; - } -} - -@keyframes spinner-scale-out { - 0% { - transform: scale(1, 1); - } - - 100% { - transform: scale(0, 0); - } -} - -@keyframes spinner-rotate { - 0% { - transform: rotate(0deg); - } - - 100% { - transform: rotate(360deg); - } -} - -@keyframes spinner-dots { - 0% { - transform: scale(1, 1); - - opacity: 0.9; - } - - 50% { - transform: scale(0.4, 0.4); - - opacity: 0.3; - } - - 100% { - transform: scale(1, 1); - - opacity: 0.9; - } -} - -@keyframes spinner-circular { - 100% { - transform: rotate(360deg); - } -} - -@keyframes spinner-circular-inner { - 0% { - stroke-dasharray: 1px, 200px; - stroke-dashoffset: 0px; - } - 50% { - stroke-dasharray: 100px, 200px; - stroke-dashoffset: -15px; - } - 100% { - stroke-dasharray: 100px, 200px; - stroke-dashoffset: -125px; - } -} diff --git a/core/src/components/spinner/spinner.interfaces.ts b/core/src/components/spinner/spinner.interfaces.ts new file mode 100644 index 00000000000..0b45e370de5 --- /dev/null +++ b/core/src/components/spinner/spinner.interfaces.ts @@ -0,0 +1,84 @@ +export interface SpinnerDefinitions { + [spinnerName: string]: SpinnerDefinition; +} + +export interface SpinnerDefinition { + dur: number; + circles?: number; + lines?: number; + elmDuration?: boolean; + fn: (dur: number, index: number, total: number) => SpinnerData; +} + +interface SpinnerData { + r?: number; + y1?: number; + y2?: number; + cx?: number; + cy?: number; + style: { [key: string]: string | undefined }; + viewBox?: string; + transform?: string; +} + +export type IonSpinnerRecipe = { + color?: string; + + lines?: { + stroke?: { + width?: string; + }; + + small?: { + stroke?: { + width?: string; + }; + }; + + sharp?: { + stroke?: { + width?: string; + }; + + small?: { + stroke?: { + width?: string; + }; + }; + }; + }; + + circular?: { + stroke?: { + width?: string; + }; + }; + + crescent?: { + stroke?: { + width?: string; + }; + }; + + dots?: { + stroke?: { + width?: string; + }; + }; + + // Sizes + size?: { + [K in SpinnerSize]?: IonSpinnerSizeDefinition; + }; +}; + +type IonSpinnerSizeDefinition = { + width?: string; + height?: string; +}; + +export type IonSpinnerConfig = { + size?: SpinnerSize; +}; + +export type SpinnerSize = 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge'; diff --git a/core/src/components/spinner/spinner.ionic.scss b/core/src/components/spinner/spinner.ionic.scss deleted file mode 100644 index f8fe09383f6..00000000000 --- a/core/src/components/spinner/spinner.ionic.scss +++ /dev/null @@ -1,62 +0,0 @@ -@use "../../themes/ionic/ionic.globals.scss" as globals; -@use "./spinner.common"; - -// Ionic Spinner -// -------------------------------------------------- - -:host { - --color: #{globals.$ion-primitives-neutral-800}; - - width: globals.$ion-scale-700; - height: globals.$ion-scale-700; -} - -:host(.ion-color-medium) { - color: #{globals.ion-color(medium, contrast, $subtle: true)}; -} - -// Spinner: lines / lines-small / lines-sharp / lines-sharp-small -// -------------------------------------------------- - -:host(.spinner-lines) line, -:host(.spinner-lines-small) line { - stroke-width: globals.$ion-scale-150; -} - -:host(.spinner-lines-sharp) line, -:host(.spinner-lines-sharp-small) line { - stroke-width: globals.$ion-scale-100; -} - -// Sizes -// -------------------------------------------------- - -/* Extra Small */ -:host(.spinner-xsmall) { - width: globals.$ion-scale-600; - height: globals.$ion-scale-600; -} - -/* Small */ -:host(.spinner-small) { - width: globals.$ion-scale-800; - height: globals.$ion-scale-800; -} - -/* Medium */ -:host(.spinner-medium) { - width: globals.$ion-scale-1000; - height: globals.$ion-scale-1000; -} - -/* Large */ -:host(.spinner-large) { - width: globals.$ion-scale-1200; - height: globals.$ion-scale-1200; -} - -/* Extra Large */ -:host(.spinner-xlarge) { - width: globals.$ion-scale-1400; - height: globals.$ion-scale-1400; -} diff --git a/core/src/components/spinner/spinner.native.scss b/core/src/components/spinner/spinner.native.scss deleted file mode 100644 index 03c63c675cf..00000000000 --- a/core/src/components/spinner/spinner.native.scss +++ /dev/null @@ -1,14 +0,0 @@ -@import "./spinner.common.scss"; - -// Spinner: lines / lines-small / lines-sharp / lines-sharp-small -// -------------------------------------------------- - -:host(.spinner-lines) line, -:host(.spinner-lines-small) line { - stroke-width: 7px; -} - -:host(.spinner-lines-sharp) line, -:host(.spinner-lines-sharp-small) line { - stroke-width: 4px; -} diff --git a/core/src/components/spinner/spinner.scss b/core/src/components/spinner/spinner.scss new file mode 100644 index 00000000000..d5236e82225 --- /dev/null +++ b/core/src/components/spinner/spinner.scss @@ -0,0 +1,258 @@ +@use "../../themes/mixins" as mixins; +@use "../../themes/functions.color" as colors; + +// Spinner: Common Styles +// -------------------------------------------------- + +:host { + /** + * @prop --ion-spinner-color: Color of the spinner + * + * @prop --ion-spinner-lines-stroke-width: Stroke width of the `lines` spinner + * @prop --ion-spinner-lines-small-stroke-width: Stroke width of the `lines-small` spinner + * @prop --ion-spinner-lines-sharp-stroke-width: Stroke width of the `lines-sharp` spinner + * @prop --ion-spinner-lines-sharp-small-stroke-width: Stroke width of the `lines-sharp-small` spinner + * @prop --ion-spinner-crescent-stroke-width: Stroke width of the `crescent` spinner + * @prop --ion-spinner-dots-stroke-width: Stroke width of the `dots` spinner + * @prop --ion-spinner-circular-stroke-width: Stroke width of the `circular` spinner + * + * Sizes + * @prop --ion-spinner-size-xsmall-width: Width of the `xsmall` spinner + * @prop --ion-spinner-size-xsmall-height: Height of the `xsmall` spinner + * @prop --ion-spinner-size-small-width: Width of the `small` spinner + * @prop --ion-spinner-size-small-height: Height of the `small` spinner + * @prop --ion-spinner-size-medium-width: Width of the `medium` spinner + * @prop --ion-spinner-size-medium-height: Height of the `medium` spinner + * @prop --ion-spinner-size-large-width: Width of the `large` spinner + * @prop --ion-spinner-size-large-height: Height of the `large` spinner + * @prop --ion-spinner-size-xlarge-width: Width of the `xlarge` spinner + * @prop --ion-spinner-size-xlarge-height: Height of the `xlarge` spinner + */ + + display: inline-block; + position: relative; + + color: var(--ion-spinner-color); + + user-select: none; +} + +:host(.ion-color) { + color: colors.current-color(base); +} + +svg { + @include mixins.transform-origin(center); + + position: absolute; + + /** + * Do not use @include position + * as the alignment of the elements with + * a spinner should not be RTL aware. + */ + top: 0; + /* stylelint-disable-next-line property-disallowed-list */ + left: 0; + + width: 100%; + height: 100%; + + transform: translateZ(0); +} + +// Spinner Names +// -------------------------------------------------- + +// lines / lines-small / lines-sharp / lines-sharp-small +:host(.spinner-name-lines) line, +:host(.spinner-name-lines-small) line, +:host(.spinner-name-lines-sharp) line, +:host(.spinner-name-lines-sharp-small) line { + stroke-linecap: round; + stroke: currentColor; +} + +:host(.spinner-name-lines) svg, +:host(.spinner-name-lines-small) svg, +:host(.spinner-name-lines-sharp) svg, +:host(.spinner-name-lines-sharp-small) svg { + animation: spinner-fade-out 1s linear infinite; +} + +:host(.spinner-name-lines) line { + stroke-width: var(--ion-spinner-lines-stroke-width); +} + +:host(.spinner-name-lines-small) line { + stroke-width: var(--ion-spinner-lines-small-stroke-width); +} + +:host(.spinner-name-lines-sharp) line { + stroke-width: var(--ion-spinner-lines-sharp-stroke-width); +} + +:host(.spinner-name-lines-sharp-small) line { + stroke-width: var(--ion-spinner-lines-sharp-small-stroke-width); +} + +// bubbles +:host(.spinner-name-bubbles) svg { + animation: spinner-scale-out 1s linear infinite; + fill: currentColor; +} + +// circles +:host(.spinner-name-circles) svg { + animation: spinner-fade-out 1s linear infinite; + fill: currentColor; +} + +:host(.spinner-name-crescent) circle { + fill: transparent; + stroke-width: var(--ion-spinner-crescent-stroke-width); + stroke-dasharray: 128px; + stroke-dashoffset: 82px; + stroke: currentColor; +} + +// crescent +:host(.spinner-name-crescent) svg { + animation: spinner-rotate 1s linear infinite; +} + +// dots +:host(.spinner-name-dots) circle { + stroke-width: var(--ion-spinner-dots-stroke-width); + fill: currentColor; +} + +:host(.spinner-name-dots) svg { + animation: spinner-dots 1s linear infinite; +} + +// circular +:host(.spinner-name-circular) svg { + animation: spinner-circular linear infinite; +} + +:host(.spinner-name-circular) circle { + animation: spinner-circular-inner ease-in-out infinite; + stroke: currentColor; + stroke-dasharray: 80px, 200px; + stroke-dashoffset: 0px; + stroke-width: var(--ion-spinner-circular-stroke-width); + fill: none; +} + +// Spinner Sizes +// -------------------------------------------------- + +:host(.spinner-size-xsmall) { + width: var(--ion-spinner-size-xsmall-width); + height: var(--ion-spinner-size-xsmall-height); +} + +:host(.spinner-size-small) { + width: var(--ion-spinner-size-small-width); + height: var(--ion-spinner-size-small-height); +} + +:host(.spinner-size-medium) { + width: var(--ion-spinner-size-medium-width); + height: var(--ion-spinner-size-medium-height); +} + +:host(.spinner-size-large) { + width: var(--ion-spinner-size-large-width); + height: var(--ion-spinner-size-large-height); +} + +:host(.spinner-size-xlarge) { + width: var(--ion-spinner-size-xlarge-width); + height: var(--ion-spinner-size-xlarge-height); +} + +// Spinner States +// -------------------------------------------------- + +// Paused +:host(.spinner-paused), +:host(.spinner-paused) svg, +:host(.spinner-paused) circle { + animation-play-state: paused; +} + +// Animation Keyframes +// -------------------------------------------------- + +@keyframes spinner-fade-out { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +@keyframes spinner-scale-out { + 0% { + transform: scale(1, 1); + } + + 100% { + transform: scale(0, 0); + } +} + +@keyframes spinner-rotate { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + +@keyframes spinner-dots { + 0% { + transform: scale(1, 1); + + opacity: 0.9; + } + + 50% { + transform: scale(0.4, 0.4); + + opacity: 0.3; + } + + 100% { + transform: scale(1, 1); + + opacity: 0.9; + } +} + +@keyframes spinner-circular { + 100% { + transform: rotate(360deg); + } +} + +@keyframes spinner-circular-inner { + 0% { + stroke-dasharray: 1px, 200px; + stroke-dashoffset: 0px; + } + 50% { + stroke-dasharray: 100px, 200px; + stroke-dashoffset: -15px; + } + 100% { + stroke-dasharray: 100px, 200px; + stroke-dashoffset: -125px; + } +} diff --git a/core/src/components/spinner/spinner.tsx b/core/src/components/spinner/spinner.tsx index 0cf6cbd006e..9ba5e8f3a38 100644 --- a/core/src/components/spinner/spinner.tsx +++ b/core/src/components/spinner/spinner.tsx @@ -3,24 +3,19 @@ import { Component, Host, Prop, h } from '@stencil/core'; import { createColorClasses } from '@utils/theme'; import { config } from '../../global/config'; -import { getIonTheme, getIonMode } from '../../global/ionic-global'; +import { getIonMode } from '../../global/ionic-global'; import type { Color } from '../../interface'; import type { SpinnerTypes } from './spinner-configs'; import { SPINNERS } from './spinner-configs'; -import type { SpinnerConfig } from './spinner-interface'; +import type { SpinnerSize, SpinnerDefinition } from './spinner.interfaces'; /** * @virtualProp {"ios" | "md"} mode - The mode determines the platform behaviors of the component. - * @virtualProp {"ios" | "md" | "ionic"} theme - The theme determines the visual appearance of the component. */ @Component({ tag: 'ion-spinner', - styleUrls: { - ios: 'spinner.native.scss', - md: 'spinner.native.scss', - ionic: 'spinner.ionic.scss', - }, + styleUrl: 'spinner.scss', shadow: true, }) export class Spinner implements ComponentInterface { @@ -54,9 +49,9 @@ export class Spinner implements ComponentInterface { * Set to `"large"` for a large size. * Set to `"xlarge"` for the largest size. * - * Defaults to `"xsmall"` for the `ionic` theme, undefined for all other themes. + * Defaults to `"medium"` if both the size property and theme config are unset. */ - @Prop() size?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge'; + @Prop() size?: SpinnerSize; private getName(): SpinnerTypes { const spinnerName = this.name || config.get('spinner'); @@ -67,29 +62,22 @@ export class Spinner implements ComponentInterface { return mode === 'ios' ? 'lines' : 'circular'; } - private getSize(): string | undefined { - const theme = getIonTheme(this); - const { size } = this; - - // TODO(ROU-10912): Remove theme check when sizes are defined for all themes. - if (theme !== 'ionic') { - return undefined; - } - - if (size === undefined) { - return 'xsmall'; - } + /** + * Gets the spinner size. Uses the `size` property if set, otherwise + * checks the theme config and falls back to 'medium' if neither is provided. + */ + get sizeValue(): SpinnerSize { + const sizeConfig = config.getObjectValue('IonSpinner.size', 'medium') as SpinnerSize; + const size = this.size || sizeConfig; return size; } render() { - const self = this; - const theme = getIonTheme(self); - const spinnerName = self.getName(); - const size = this.getSize(); + const { duration: animatedDuration, color, paused, sizeValue } = this; + const spinnerName = this.getName(); const spinner = SPINNERS[spinnerName] ?? SPINNERS['lines']; - const duration = typeof self.duration === 'number' && self.duration > 10 ? self.duration : spinner.dur; + const duration = typeof animatedDuration === 'number' && animatedDuration > 10 ? animatedDuration : spinner.dur; const svgs: SVGElement[] = []; if (spinner.circles !== undefined) { @@ -104,11 +92,10 @@ export class Spinner implements ComponentInterface { return ( { +const buildCircle = (spinner: SpinnerDefinition, duration: number, index: number, total: number) => { const data = spinner.fn(duration, index, total); data.style['animation-duration'] = duration + 'ms'; @@ -136,7 +123,7 @@ const buildCircle = (spinner: SpinnerConfig, duration: number, index: number, to ); }; -const buildLine = (spinner: SpinnerConfig, duration: number, index: number, total: number) => { +const buildLine = (spinner: SpinnerDefinition, duration: number, index: number, total: number) => { const data = spinner.fn(duration, index, total); data.style['animation-duration'] = duration + 'ms'; diff --git a/core/src/components/spinner/test/basic/spinner.e2e.ts b/core/src/components/spinner/test/basic/spinner.e2e.ts index c1e148b28cc..8a4a61c15ac 100644 --- a/core/src/components/spinner/test/basic/spinner.e2e.ts +++ b/core/src/components/spinner/test/basic/spinner.e2e.ts @@ -10,7 +10,7 @@ configs().forEach(({ title, screenshot, config }) => { test('should not have visual regressions', async ({ page }) => { await page.setIonViewport(); - await expect(page).toHaveScreenshot(screenshot(`spinner-basic-diff`)); + await expect(page).toHaveScreenshot(screenshot('spinner-basic')); }); }); }); diff --git a/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-ios-ltr-Mobile-Chrome-linux.png similarity index 100% rename from core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-ios-ltr-Mobile-Chrome-linux.png rename to core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-ios-ltr-Mobile-Chrome-linux.png diff --git a/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-ios-ltr-Mobile-Firefox-linux.png similarity index 100% rename from core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-ios-ltr-Mobile-Firefox-linux.png rename to core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-ios-ltr-Mobile-Firefox-linux.png diff --git a/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-ios-ltr-Mobile-Safari-linux.png similarity index 100% rename from core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-ios-ltr-Mobile-Safari-linux.png rename to core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-ios-ltr-Mobile-Safari-linux.png diff --git a/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-ios-rtl-Mobile-Chrome-linux.png similarity index 100% rename from core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-ios-rtl-Mobile-Chrome-linux.png rename to core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-ios-rtl-Mobile-Chrome-linux.png diff --git a/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-ios-rtl-Mobile-Firefox-linux.png similarity index 100% rename from core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-ios-rtl-Mobile-Firefox-linux.png rename to core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-ios-rtl-Mobile-Firefox-linux.png diff --git a/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-ios-rtl-Mobile-Safari-linux.png similarity index 100% rename from core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-ios-rtl-Mobile-Safari-linux.png rename to core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-ios-rtl-Mobile-Safari-linux.png diff --git a/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-md-ltr-Mobile-Chrome-linux.png similarity index 100% rename from core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-md-ltr-Mobile-Chrome-linux.png rename to core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-md-ltr-Mobile-Chrome-linux.png diff --git a/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-md-ltr-Mobile-Firefox-linux.png similarity index 100% rename from core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-md-ltr-Mobile-Firefox-linux.png rename to core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-md-ltr-Mobile-Firefox-linux.png diff --git a/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-md-ltr-Mobile-Safari-linux.png similarity index 100% rename from core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-md-ltr-Mobile-Safari-linux.png rename to core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-md-ltr-Mobile-Safari-linux.png diff --git a/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-md-rtl-Mobile-Chrome-linux.png similarity index 100% rename from core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-md-rtl-Mobile-Chrome-linux.png rename to core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-md-rtl-Mobile-Chrome-linux.png diff --git a/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-md-rtl-Mobile-Firefox-linux.png similarity index 100% rename from core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-md-rtl-Mobile-Firefox-linux.png rename to core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-md-rtl-Mobile-Firefox-linux.png diff --git a/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-md-rtl-Mobile-Safari-linux.png similarity index 100% rename from core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-diff-md-rtl-Mobile-Safari-linux.png rename to core/src/components/spinner/test/basic/spinner.e2e.ts-snapshots/spinner-basic-md-rtl-Mobile-Safari-linux.png diff --git a/core/src/components/spinner/test/color/index.html b/core/src/components/spinner/test/color/index.html index 4a068f45f20..dc204f811ef 100644 --- a/core/src/components/spinner/test/color/index.html +++ b/core/src/components/spinner/test/color/index.html @@ -12,6 +12,14 @@ + @@ -23,37 +31,52 @@ - - lines (primary) - lines-small (secondary) - circular (tertiary) - dots (success) - bubbles (warning) - circles (danger) - crescent (dark) - lines (paused, - medium) - +
+
+ +

Primary

+
+ +
+ +

Secondary

+
+ +
+ +

Tertiary

+
+ +
+ +

Success

+
+ +
+ +

Warning

+
+ +
+ +

Danger

+
+ +
+ +

Light

+
+ +
+ +

Medium

+
+ +
+ +

Dark

+
+
diff --git a/core/src/components/spinner/test/color/spinner.e2e.ts b/core/src/components/spinner/test/color/spinner.e2e.ts index 89e1ce0e35a..db7d60d7dbf 100644 --- a/core/src/components/spinner/test/color/spinner.e2e.ts +++ b/core/src/components/spinner/test/color/spinner.e2e.ts @@ -6,15 +6,27 @@ import { configs, test } from '@utils/test/playwright'; */ configs({ directions: ['ltr'], modes: ['md'] }).forEach(({ title, screenshot, config }) => { test.describe(title('spinner: color'), () => { - test.beforeEach(async ({ page }) => { - await page.goto('/src/components/spinner/test/color', config); - }); - test.describe('spinner: visual regression tests', () => { - test('should not have visual regressions', async ({ page }) => { - await page.setIonViewport(); + test('should not have visual regressions', async ({ page }) => { + await page.setContent( + ` +
+ + + + + + + + + +
+ `, + config + ); + + const container = page.locator('.container'); - await expect(page).toHaveScreenshot(screenshot(`spinner-color-diff`)); - }); + await expect(container).toHaveScreenshot(screenshot('spinner-color')); }); }); }); diff --git a/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-diff-md-ltr-Mobile-Chrome-linux.png deleted file mode 100644 index f745a35fc42..00000000000 Binary files a/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-diff-md-ltr-Mobile-Chrome-linux.png and /dev/null differ diff --git a/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-diff-md-ltr-Mobile-Firefox-linux.png deleted file mode 100644 index a3d8e1fe23b..00000000000 Binary files a/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-diff-md-ltr-Mobile-Firefox-linux.png and /dev/null differ diff --git a/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-diff-md-ltr-Mobile-Safari-linux.png deleted file mode 100644 index 3185f162f26..00000000000 Binary files a/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-diff-md-ltr-Mobile-Safari-linux.png and /dev/null differ diff --git a/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-md-ltr-Mobile-Chrome-linux.png b/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-md-ltr-Mobile-Chrome-linux.png new file mode 100644 index 00000000000..0648870133e Binary files /dev/null and b/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-md-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-md-ltr-Mobile-Firefox-linux.png b/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-md-ltr-Mobile-Firefox-linux.png new file mode 100644 index 00000000000..c008d7b7d4c Binary files /dev/null and b/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-md-ltr-Mobile-Firefox-linux.png differ diff --git a/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-md-ltr-Mobile-Safari-linux.png b/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-md-ltr-Mobile-Safari-linux.png new file mode 100644 index 00000000000..d4cfa2f02e2 Binary files /dev/null and b/core/src/components/spinner/test/color/spinner.e2e.ts-snapshots/spinner-color-md-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/components/spinner/test/resize/spinner.e2e.ts b/core/src/components/spinner/test/resize/spinner.e2e.ts index 5874f05181c..8f43c22161c 100644 --- a/core/src/components/spinner/test/resize/spinner.e2e.ts +++ b/core/src/components/spinner/test/resize/spinner.e2e.ts @@ -9,29 +9,35 @@ configs({ directions: ['ltr'], modes: ['md'] }).forEach(({ title, screenshot, co test.beforeEach(async ({ page }) => { await page.setViewportSize({ width: 320, height: 340 }); }); - test('should not have visual regressions', async ({ page }) => { + test('should not have visual regressions', async ({ page }, testInfo) => { + testInfo.annotations.push({ + type: 'issue', + description: 'https://github.com/ionic-team/ionic-framework/issues/18115', + }); + await page.setContent( ` - - - - - - - - - - - `, + + + + + + + + + + + + `, config ); - await expect(page).toHaveScreenshot(screenshot(`spinner-resize-diff`)); + await expect(page).toHaveScreenshot(screenshot('spinner-resize')); }); }); }); diff --git a/core/src/components/spinner/test/resize/spinner.e2e.ts-snapshots/spinner-resize-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/spinner/test/resize/spinner.e2e.ts-snapshots/spinner-resize-md-ltr-Mobile-Chrome-linux.png similarity index 100% rename from core/src/components/spinner/test/resize/spinner.e2e.ts-snapshots/spinner-resize-diff-md-ltr-Mobile-Chrome-linux.png rename to core/src/components/spinner/test/resize/spinner.e2e.ts-snapshots/spinner-resize-md-ltr-Mobile-Chrome-linux.png diff --git a/core/src/components/spinner/test/resize/spinner.e2e.ts-snapshots/spinner-resize-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/spinner/test/resize/spinner.e2e.ts-snapshots/spinner-resize-md-ltr-Mobile-Firefox-linux.png similarity index 100% rename from core/src/components/spinner/test/resize/spinner.e2e.ts-snapshots/spinner-resize-diff-md-ltr-Mobile-Firefox-linux.png rename to core/src/components/spinner/test/resize/spinner.e2e.ts-snapshots/spinner-resize-md-ltr-Mobile-Firefox-linux.png diff --git a/core/src/components/spinner/test/resize/spinner.e2e.ts-snapshots/spinner-resize-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/spinner/test/resize/spinner.e2e.ts-snapshots/spinner-resize-md-ltr-Mobile-Safari-linux.png similarity index 100% rename from core/src/components/spinner/test/resize/spinner.e2e.ts-snapshots/spinner-resize-diff-md-ltr-Mobile-Safari-linux.png rename to core/src/components/spinner/test/resize/spinner.e2e.ts-snapshots/spinner-resize-md-ltr-Mobile-Safari-linux.png diff --git a/core/src/components/spinner/test/size/index.html b/core/src/components/spinner/test/size/index.html index f045932d4ca..75e7ec00800 100644 --- a/core/src/components/spinner/test/size/index.html +++ b/core/src/components/spinner/test/size/index.html @@ -12,6 +12,14 @@ + @@ -22,34 +30,79 @@ - - - - -

Default

-
- - -

xsmall

-
- - -

small

-
- - -

medium

-
- - -

large

-
- - -

xlarge

-
-
-
+ + + diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts b/core/src/components/spinner/test/size/spinner.e2e.ts index bb62285cba0..79452e7b885 100644 --- a/core/src/components/spinner/test/size/spinner.e2e.ts +++ b/core/src/components/spinner/test/size/spinner.e2e.ts @@ -3,14 +3,16 @@ import { configs, test } from '@utils/test/playwright'; /** * This behavior does not vary across directions. + * + * `ios` does not differ from `md`. */ -configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screenshot, title }) => { +configs({ directions: ['ltr'], modes: ['md', 'ionic-md'] }).forEach(({ config, screenshot, title }) => { test.describe(title('spinner: size'), () => { test('should render xsmall spinner', async ({ page }) => { await page.setContent( ` - - `, + + `, config ); @@ -22,8 +24,8 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens test('should render small spinner', async ({ page }) => { await page.setContent( ` - - `, + + `, config ); @@ -35,8 +37,8 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens test('should render medium spinner', async ({ page }) => { await page.setContent( ` - - `, + + `, config ); @@ -48,8 +50,8 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens test('should render large spinner', async ({ page }) => { await page.setContent( ` - - `, + + `, config ); @@ -61,8 +63,8 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens test('should render xlarge spinner', async ({ page }) => { await page.setContent( ` - - `, + + `, config ); diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-md-ltr-Mobile-Chrome-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-md-ltr-Mobile-Chrome-linux.png new file mode 100644 index 00000000000..50a012eb4da Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-md-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-md-ltr-Mobile-Firefox-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-md-ltr-Mobile-Firefox-linux.png new file mode 100644 index 00000000000..0d49fa723f2 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-md-ltr-Mobile-Firefox-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-md-ltr-Mobile-Safari-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-md-ltr-Mobile-Safari-linux.png new file mode 100644 index 00000000000..545d00d08d6 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-md-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-md-ltr-Mobile-Chrome-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-md-ltr-Mobile-Chrome-linux.png new file mode 100644 index 00000000000..7f2d0ea6801 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-md-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-md-ltr-Mobile-Firefox-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-md-ltr-Mobile-Firefox-linux.png new file mode 100644 index 00000000000..48a527a9e7b Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-md-ltr-Mobile-Firefox-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-md-ltr-Mobile-Safari-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-md-ltr-Mobile-Safari-linux.png new file mode 100644 index 00000000000..208df033c13 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-md-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-md-ltr-Mobile-Chrome-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-md-ltr-Mobile-Chrome-linux.png new file mode 100644 index 00000000000..2958f7f88a4 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-md-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-md-ltr-Mobile-Firefox-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-md-ltr-Mobile-Firefox-linux.png new file mode 100644 index 00000000000..b844d7104ac Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-md-ltr-Mobile-Firefox-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-md-ltr-Mobile-Safari-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-md-ltr-Mobile-Safari-linux.png new file mode 100644 index 00000000000..adde2f79659 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-md-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-md-ltr-Mobile-Chrome-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-md-ltr-Mobile-Chrome-linux.png new file mode 100644 index 00000000000..1695dbf30cd Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-md-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-md-ltr-Mobile-Firefox-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-md-ltr-Mobile-Firefox-linux.png new file mode 100644 index 00000000000..5f7414866ce Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-md-ltr-Mobile-Firefox-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-md-ltr-Mobile-Safari-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-md-ltr-Mobile-Safari-linux.png new file mode 100644 index 00000000000..570231fd198 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-md-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-md-ltr-Mobile-Chrome-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-md-ltr-Mobile-Chrome-linux.png new file mode 100644 index 00000000000..4e94dd353c3 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-md-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-md-ltr-Mobile-Firefox-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-md-ltr-Mobile-Firefox-linux.png new file mode 100644 index 00000000000..7a457da8bfd Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-md-ltr-Mobile-Firefox-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-md-ltr-Mobile-Safari-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-md-ltr-Mobile-Safari-linux.png new file mode 100644 index 00000000000..8f5903e82c8 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-md-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/themes/ionic/default.tokens.ts b/core/src/themes/ionic/default.tokens.ts index 10687c955ea..9fe7932858a 100644 --- a/core/src/themes/ionic/default.tokens.ts +++ b/core/src/themes/ionic/default.tokens.ts @@ -25,6 +25,10 @@ export const defaultTheme: DefaultTheme = { shape: 'round', size: 'large', }, + + IonSpinner: { + size: 'xsmall', + }, }, }, @@ -261,5 +265,79 @@ export const defaultTheme: DefaultTheme = { }, }, }, + + IonSpinner: { + color: '#626262', + + lines: { + stroke: { + width: 'var(--ion-scaling-150)', + }, + + small: { + stroke: { + width: 'var(--ion-scaling-150)', + }, + }, + + sharp: { + stroke: { + width: 'var(--ion-scaling-100)', + }, + + small: { + stroke: { + width: 'var(--ion-scaling-100)', + }, + }, + }, + }, + + circular: { + stroke: { + width: '5.6', + }, + }, + + crescent: { + stroke: { + width: 'var(--ion-scaling-100)', + }, + }, + + dots: { + stroke: { + width: 'var(--ion-scaling-0)', + }, + }, + + // Sizes + size: { + xsmall: { + width: 'var(--ion-scaling-xs)', + height: 'var(--ion-scaling-xs)', + }, + + small: { + width: 'var(--ion-scaling-md)', + height: 'var(--ion-scaling-md)', + }, + + medium: { + width: 'var(--ion-scaling-lg)', + height: 'var(--ion-scaling-lg)', + }, + + large: { + width: 'var(--ion-scaling-xl)', + height: 'var(--ion-scaling-xl)', + }, + + xlarge: { + width: 'var(--ion-scaling-xxl)', + height: 'var(--ion-scaling-xxl)', + }, + }, + }, }, }; diff --git a/core/src/themes/ios/default.tokens.ts b/core/src/themes/ios/default.tokens.ts index c426ff9ab65..e36d7e3e007 100644 --- a/core/src/themes/ios/default.tokens.ts +++ b/core/src/themes/ios/default.tokens.ts @@ -32,6 +32,10 @@ export const defaultTheme: DefaultTheme = { shape: 'soft', size: 'large', }, + + IonSpinner: { + size: 'medium', + }, }, }, @@ -400,5 +404,79 @@ export const defaultTheme: DefaultTheme = { }, }, }, + + IonSpinner: { + color: 'var(--ion-text-color, #000)', + + lines: { + stroke: { + width: '7px', + }, + + small: { + stroke: { + width: '7px', + }, + }, + + sharp: { + stroke: { + width: 'var(--ion-scaling-100)', + }, + + small: { + stroke: { + width: 'var(--ion-scaling-100)', + }, + }, + }, + }, + + circular: { + stroke: { + width: '5.6', + }, + }, + + crescent: { + stroke: { + width: 'var(--ion-scaling-100)', + }, + }, + + dots: { + stroke: { + width: 'var(--ion-scaling-0)', + }, + }, + + // Sizes + size: { + xsmall: { + width: 'var(--ion-scaling-400)', + height: 'var(--ion-scaling-400)', + }, + + small: { + width: 'var(--ion-scaling-xxs)', + height: 'var(--ion-scaling-xxs)', + }, + + medium: { + width: 'var(--ion-scaling-sm)', + height: 'var(--ion-scaling-sm)', + }, + + large: { + width: 'var(--ion-scaling-lg)', + height: 'var(--ion-scaling-lg)', + }, + + xlarge: { + width: 'var(--ion-scaling-xxxl)', + height: 'var(--ion-scaling-xxxl)', + }, + }, + }, }, }; diff --git a/core/src/themes/md/default.tokens.ts b/core/src/themes/md/default.tokens.ts index 6de8c3c547b..80141bb7f55 100644 --- a/core/src/themes/md/default.tokens.ts +++ b/core/src/themes/md/default.tokens.ts @@ -35,6 +35,10 @@ export const defaultTheme: DefaultTheme = { shape: 'soft', size: 'large', }, + + IonSpinner: { + size: 'medium', + }, }, }, @@ -397,5 +401,79 @@ export const defaultTheme: DefaultTheme = { }, }, }, + + IonSpinner: { + color: 'var(--ion-text-color, #000)', + + lines: { + stroke: { + width: '7px', + }, + + small: { + stroke: { + width: '7px', + }, + }, + + sharp: { + stroke: { + width: 'var(--ion-scaling-100)', + }, + + small: { + stroke: { + width: 'var(--ion-scaling-100)', + }, + }, + }, + }, + + circular: { + stroke: { + width: '5.6', + }, + }, + + crescent: { + stroke: { + width: 'var(--ion-scaling-100)', + }, + }, + + dots: { + stroke: { + width: 'var(--ion-scaling-0)', + }, + }, + + // Sizes + size: { + xsmall: { + width: 'var(--ion-scaling-xxxs)', + height: 'var(--ion-scaling-xxxs)', + }, + + small: { + width: 'var(--ion-scaling-xxs)', + height: 'var(--ion-scaling-xxs)', + }, + + medium: { + width: 'var(--ion-scaling-sm)', + height: 'var(--ion-scaling-sm)', + }, + + large: { + width: 'var(--ion-scaling-lg)', + height: 'var(--ion-scaling-lg)', + }, + + xlarge: { + width: 'var(--ion-scaling-xxxl)', + height: 'var(--ion-scaling-xxxl)', + }, + }, + }, }, }; diff --git a/core/src/themes/themes.interfaces.ts b/core/src/themes/themes.interfaces.ts index dd236fff88b..5cbf366e37b 100644 --- a/core/src/themes/themes.interfaces.ts +++ b/core/src/themes/themes.interfaces.ts @@ -1,4 +1,5 @@ -import type { IonChipRecipe, IonChipConfig } from '../components/chip/chip.interfaces'; +import type { IonChipConfig, IonChipRecipe } from '../components/chip/chip.interfaces'; +import type { IonSpinnerConfig, IonSpinnerRecipe } from '../components/spinner/spinner.interfaces'; import type { IonicConfig as IonicGlobalConfig } from '../utils/config'; // Platform-specific theme @@ -245,6 +246,7 @@ export type BaseTheme = { export type IonicConfig = IonicGlobalConfig & { components?: { IonChip?: IonChipConfig; + IonSpinner?: IonSpinnerConfig; }; }; @@ -282,6 +284,7 @@ export type DefaultTheme = BaseTheme & { type Components = { IonChip?: IonChipRecipe; + IonSpinner?: IonSpinnerRecipe; IonCard?: any; IonItem?: any; diff --git a/packages/angular/src/directives/proxies.ts b/packages/angular/src/directives/proxies.ts index 19731f54a06..b74882e957e 100644 --- a/packages/angular/src/directives/proxies.ts +++ b/packages/angular/src/directives/proxies.ts @@ -2286,14 +2286,14 @@ export declare interface IonSkeletonText extends Components.IonSkeletonText {} @ProxyCmp({ - inputs: ['color', 'duration', 'mode', 'name', 'paused', 'size', 'theme'] + inputs: ['color', 'duration', 'mode', 'name', 'paused', 'size'] }) @Component({ selector: 'ion-spinner', changeDetection: ChangeDetectionStrategy.OnPush, template: '', // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['color', 'duration', 'mode', 'name', 'paused', 'size', 'theme'], + inputs: ['color', 'duration', 'mode', 'name', 'paused', 'size'], }) export class IonSpinner { protected el: HTMLIonSpinnerElement; diff --git a/packages/angular/standalone/src/directives/proxies.ts b/packages/angular/standalone/src/directives/proxies.ts index 15cfacbfdc1..49ce468b73f 100644 --- a/packages/angular/standalone/src/directives/proxies.ts +++ b/packages/angular/standalone/src/directives/proxies.ts @@ -2023,14 +2023,14 @@ export declare interface IonSkeletonText extends Components.IonSkeletonText {} @ProxyCmp({ defineCustomElementFn: defineIonSpinner, - inputs: ['color', 'duration', 'mode', 'name', 'paused', 'size', 'theme'] + inputs: ['color', 'duration', 'mode', 'name', 'paused', 'size'] }) @Component({ selector: 'ion-spinner', changeDetection: ChangeDetectionStrategy.OnPush, template: '', // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['color', 'duration', 'mode', 'name', 'paused', 'size', 'theme'], + inputs: ['color', 'duration', 'mode', 'name', 'paused', 'size'], standalone: true }) export class IonSpinner {