ionic-framework
ionic-framework copied to clipboard
feat: allow custom spinners for `ion-spinner`/`ion-loading`
Prequisites
- [X] I have read the Contributing Guidelines.
- [X] I agree to follow the Code of Conduct.
- [X] I have searched for existing issues that already include this feature request, without success.
Describe the Feature Request
Allow an HTML element (such as one created with createElement()
) to be given to the ion-spinner
. This functionality should be able to come through to ion-loading
, as it uses an ion-spinner
under the hood.
Describe the Use Case
Sometimes I want a spinner that "just works", but want it to be slightly more "on brand" than a stock style.
I created a Vue component that holds an animated SVG (for easy reuse), but have no way to use it with Ionic.
Note: a Vue component gets compiled to standard HTML elements, so the root element of the Vue component can be passed to the ion-spinner
.
Maybe using a custom spinner design violates someone's interface design guidelines/rules? (looking at you Apple)
Describe Preferred Solution
Allow an element to be given when creating a spinner using the spinner controller.
Not sure which way would be best.
Maybe change the spinner
property/param to allow HTMLElement
as well or something?
For the element version of ion-spinner
, it could use a named slot: slot="spinner"
?
Describe Alternatives
- Use a custom spinner instead of
ion-spinner
. This can actually work in many cases, but not when I want to useion-loading
. - Set the spinner style to
none
and target the background of the spinner with CSS. e.g.background: url(#my-spinner-svg)
Someone on the Ionic forum mentioned doing this as a workaround. I can find it again if needed. This unfortunately is more complex and only allows for a single SVG to be set.
Related Code
No response
Additional Information
As to implementing, I looked at Ionic's source, and I think this could get hairy. If it would be too complex, please say so and feel free to drop the request :).
I'll discuss this with the team; thanks for the issue!
@darrylnoakes You can use a custom spinner with ion-loading through clever use of css. I don't have time to document it now, but it is possible.
I'd also love to have this possibility, without a hacky CSS workaround.
I'm using tailwindcss with this css. Note that there are default values for each aspect of the spinner, but they can be overridden by the --loading-overlay-*
variables:
@keyframes loading-spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.loading-overlay {
--backdrop-opacity: var(--loading-overlay-backdrop-opacity, 60%) !important;
& .loading-wrapper {
--background: var(
--loading-overlay-background,
theme('colors.neutral.900')
);
@apply rounded-xl py-5 pr-5 !important;
}
/* Customize the text of the loading message */
& .loading-content {
padding-left: var(--loading-overlay-size, 16px) !important;
font-size: var(
--loading-overlay-font-size,
theme('fontSize.lg')
) !important;
font-weight: var(
--loading-overlay-font-weight,
theme('fontWeight.normal')
) !important;
line-height: var(--loading-overlay-size, 20px);
color: var(--loading-overlay-text-color, white) !important;
@apply ml-0 !important;
/* Insert our custom spinner */
&::before {
content: '';
position: absolute;
left: var(--loading-overlay-left-margin, 18px);
width: var(--loading-overlay-size, 22px);
height: var(--loading-overlay-size, 22px);
border: 3px solid rgb(255 255 255 / 15%);
border-top: 3px solid rgb(255 255 255 / 80%);
border-radius: 50%;
animation: var(
--loading-overlay-animation,
loading-spin 1.5s linear infinite
);
}
}
}
.md .loading-overlay .loading-content {
/* On Android, move the spinner closer to the text */
@apply ml-2 !important;
&::before {
left: var(--loading-overlay-left-margin, 16px);
}
}
Then create a spinner like this:
const controller = await loadingController.create({
message: toValue(message),
spinner: null,
cssClass: 'loading-overlay',
})
Please add this option as soon as possible!