;
+
+CircularProgress.propTypes /* remove-proptypes */ = {
+ // ----------------------------- Warning --------------------------------
+ // | These PropTypes are generated from the TypeScript type definitions |
+ // | To update them edit TypeScript types and run "yarn proptypes" |
+ // ----------------------------------------------------------------------
+ /**
+ * @ignore
+ */
+ children: PropTypes.node,
+ /**
+ * @ignore
+ */
+ className: PropTypes.string,
+ /**
+ * The color of the component. It supports those theme colors that make sense for this component.
+ * @default 'primary'
+ */
+ color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
+ PropTypes.oneOf(['danger', 'info', 'neutral', 'primary', 'success', 'warning']),
+ PropTypes.string,
+ ]),
+ /**
+ * The component used for the root node.
+ * Either a string to use a HTML element or a component.
+ */
+ component: PropTypes.elementType,
+ /**
+ * The props used for each slot inside the CircularProgress.
+ * @default {}
+ */
+ componentsProps: PropTypes.shape({
+ progress: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
+ root: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
+ svg: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
+ track: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
+ }),
+ /**
+ * The boolean to select a variant.
+ * Use indeterminate when there is no progress value.
+ * @default false
+ */
+ determinate: PropTypes.bool,
+ /**
+ * The size of the component.
+ * It accepts theme values between 'sm' and 'lg'.
+ * @default 'md'
+ */
+ size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
+ PropTypes.oneOf(['sm', 'md', 'lg']),
+ PropTypes.string,
+ ]),
+ /**
+ * The system prop that allows defining system overrides as well as additional CSS styles.
+ */
+ sx: PropTypes.oneOfType([
+ PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])),
+ PropTypes.func,
+ PropTypes.object,
+ ]),
+ /**
+ * The thickness of the circle.
+ */
+ thickness: PropTypes.number,
+ /**
+ * The value of the progress indicator for the determinate variant.
+ * Value between 0 and 100.
+ *
+ * For indeterminate, @default 25
+ */
+ value: PropTypes.number,
+ /**
+ * The variant to use.
+ * @default 'soft'
+ */
+ variant: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
+ PropTypes.oneOf(['outlined', 'plain', 'soft', 'solid']),
+ PropTypes.string,
+ ]),
+} as any;
+
+export default CircularProgress;
diff --git a/packages/mui-joy/src/CircularProgress/CircularProgressProps.ts b/packages/mui-joy/src/CircularProgress/CircularProgressProps.ts
new file mode 100644
index 00000000000000..968e87ac2113c5
--- /dev/null
+++ b/packages/mui-joy/src/CircularProgress/CircularProgressProps.ts
@@ -0,0 +1,77 @@
+import { SlotComponentProps } from '@mui/base/utils';
+import { OverridableStringUnion, OverrideProps } from '@mui/types';
+import * as React from 'react';
+import { ColorPaletteProp, SxProps, VariantProp } from '../styles/types';
+
+export type CircularProgressSlot = 'root' | 'svg' | 'track' | 'progress';
+
+export interface CircularProgressPropsColorOverrides {}
+export interface CircularProgressPropsSizeOverrides {}
+export interface CircularProgressPropsVariantOverrides {}
+
+interface ComponentsProps {
+ root?: SlotComponentProps<'span', { sx?: SxProps }, CircularProgressOwnerState>;
+ svg?: SlotComponentProps<'svg', { sx?: SxProps }, CircularProgressOwnerState>;
+ track?: SlotComponentProps<'circle', { sx?: SxProps }, CircularProgressOwnerState>;
+ progress?: SlotComponentProps<'circle', { sx?: SxProps }, CircularProgressOwnerState>;
+}
+
+export interface CircularProgressTypeMap {
+ props: P & {
+ /**
+ * The color of the component. It supports those theme colors that make sense for this component.
+ * @default 'primary'
+ */
+ color?: OverridableStringUnion;
+ /**
+ * The props used for each slot inside the CircularProgress.
+ * @default {}
+ */
+ componentsProps?: ComponentsProps;
+ /**
+ * The boolean to select a variant.
+ * Use indeterminate when there is no progress value.
+ * @default false
+ */
+ determinate?: true | false;
+ /**
+ * The size of the component.
+ * It accepts theme values between 'sm' and 'lg'.
+ * @default 'md'
+ */
+ size?: OverridableStringUnion<'sm' | 'md' | 'lg', CircularProgressPropsSizeOverrides>;
+ /**
+ * The system prop that allows defining system overrides as well as additional CSS styles.
+ */
+ sx?: SxProps;
+ /**
+ * The thickness of the circle.
+ */
+ thickness?: number;
+ /**
+ * The value of the progress indicator for the determinate variant.
+ * Value between 0 and 100.
+ *
+ * For indeterminate, @default 25
+ */
+ value?: number;
+ /**
+ * The variant to use.
+ * @default 'soft'
+ */
+ variant?: OverridableStringUnion;
+ };
+ defaultComponent: D;
+}
+
+export type CircularProgressProps<
+ D extends React.ElementType = CircularProgressTypeMap['defaultComponent'],
+ P = { component?: React.ElementType },
+> = OverrideProps, D>;
+
+export interface CircularProgressOwnerState extends CircularProgressProps {
+ /**
+ * @internal the explicit size on the instance:
+ */
+ instanceSize: CircularProgressProps['size'];
+}
diff --git a/packages/mui-joy/src/CircularProgress/circularProgressClasses.ts b/packages/mui-joy/src/CircularProgress/circularProgressClasses.ts
new file mode 100644
index 00000000000000..fa3065de409a7a
--- /dev/null
+++ b/packages/mui-joy/src/CircularProgress/circularProgressClasses.ts
@@ -0,0 +1,72 @@
+import { generateUtilityClass, generateUtilityClasses } from '../className';
+
+export interface CircularProgressClasses {
+ /** Styles applied to the root element. */
+ root: string;
+ /** Styles applied to the root element if `determinate` is true. */
+ determinate: string;
+ /** Styles applied to the svg element. */
+ svg: string;
+ /** Styles applied to the `track` element. */
+ track: string;
+ /** Styles applied to the `progress` element. */
+ progress: string;
+ /** Styles applied to the root element if `color="primary"`. */
+ colorPrimary: string;
+ /** Styles applied to the root element if `color="neutral"`. */
+ colorNeutral: string;
+ /** Styles applied to the root element if `color="danger"`. */
+ colorDanger: string;
+ /** Styles applied to the root element if `color="info"`. */
+ colorInfo: string;
+ /** Styles applied to the root element if `color="success"`. */
+ colorSuccess: string;
+ /** Styles applied to the root element if `color="warning"`. */
+ colorWarning: string;
+ /** Styles applied to the root element if `size="sm"`. */
+ sizeSm: string;
+ /** Styles applied to the root element if `size="md"`. */
+ sizeMd: string;
+ /** Styles applied to the root element if `size="lg"`. */
+ sizeLg: string;
+ /** Styles applied to the root element if `variant="plain"`. */
+ variantPlain: string;
+ /** Styles applied to the root element if `variant="outlined"`. */
+ variantOutlined: string;
+ /** Styles applied to the root element if `variant="soft"`. */
+ variantSoft: string;
+ /** Styles applied to the root element if `variant="solid"`. */
+ variantSolid: string;
+}
+
+export type CircularProgressClassKey = keyof CircularProgressClasses;
+
+export function getCircularProgressUtilityClass(slot: string): string {
+ return generateUtilityClass('JoyCircularProgress', slot);
+}
+
+const circularProgressClasses: CircularProgressClasses = generateUtilityClasses(
+ 'JoyCircularProgress',
+ [
+ 'root',
+ 'determinate',
+ 'svg',
+ 'track',
+ 'progress',
+ 'colorPrimary',
+ 'colorNeutral',
+ 'colorDanger',
+ 'colorInfo',
+ 'colorSuccess',
+ 'colorWarning',
+ 'sizeSm',
+ 'sizeMd',
+ 'sizeLg',
+ 'variantPlain',
+ 'variantOutlined',
+ 'variantSoft',
+ 'variantSolid',
+ ],
+);
+
+export default circularProgressClasses;
diff --git a/packages/mui-joy/src/CircularProgress/index.ts b/packages/mui-joy/src/CircularProgress/index.ts
new file mode 100644
index 00000000000000..44a57d7f65fa32
--- /dev/null
+++ b/packages/mui-joy/src/CircularProgress/index.ts
@@ -0,0 +1,4 @@
+export { default } from './CircularProgress';
+export * from './circularProgressClasses';
+export { default as circularProgressClasses } from './circularProgressClasses';
+export * from './CircularProgressProps';
diff --git a/packages/mui-joy/src/IconButton/IconButton.tsx b/packages/mui-joy/src/IconButton/IconButton.tsx
index 68ebfbc7b7cd6c..6e809307157859 100644
--- a/packages/mui-joy/src/IconButton/IconButton.tsx
+++ b/packages/mui-joy/src/IconButton/IconButton.tsx
@@ -38,6 +38,7 @@ export const IconButtonRoot = styled('button', {
})<{ ownerState: IconButtonOwnerState }>(({ theme, ownerState }) => [
{
'--Icon-margin': 'initial', // reset the icon's margin.
+ '--CircularProgress-size': 'var(--Icon-fontSize)',
...(ownerState.size === 'sm' && {
'--Icon-fontSize': 'calc(var(--IconButton-size, 2rem) / 1.6)', // 1.25rem by default
minWidth: 'var(--IconButton-size, 2rem)', // use min-width instead of height to make the button resilient to its content
diff --git a/packages/mui-joy/src/Link/Link.tsx b/packages/mui-joy/src/Link/Link.tsx
index 97572853c0f4f7..d497c4320c7d32 100644
--- a/packages/mui-joy/src/Link/Link.tsx
+++ b/packages/mui-joy/src/Link/Link.tsx
@@ -61,6 +61,7 @@ const LinkRoot = styled('a', {
return [
{
'--Icon-fontSize': '1.25em',
+ '--CircularProgress-size': '1em',
...(ownerState.level && ownerState.level !== 'inherit' && theme.typography[ownerState.level]),
...(ownerState.level === 'inherit' && {
fontSize: 'inherit',
diff --git a/packages/mui-joy/src/index.ts b/packages/mui-joy/src/index.ts
index 52f274426d1b2c..d1b615bd72462a 100644
--- a/packages/mui-joy/src/index.ts
+++ b/packages/mui-joy/src/index.ts
@@ -25,6 +25,9 @@ export * from './Breadcrumbs';
export { default as Button } from './Button';
export * from './Button';
+export { default as CircularProgress } from './CircularProgress';
+export * from './CircularProgress';
+
export { default as Card } from './Card';
export * from './Card';
diff --git a/packages/mui-joy/src/styles/components.d.ts b/packages/mui-joy/src/styles/components.d.ts
index 4ecc210e0a1fde..35bdbbdf2edce6 100644
--- a/packages/mui-joy/src/styles/components.d.ts
+++ b/packages/mui-joy/src/styles/components.d.ts
@@ -39,6 +39,11 @@ import {
ChipDeleteOwnerState,
ChipDeleteSlot,
} from '../ChipDelete/ChipDeleteProps';
+import {
+ CircularProgressProps,
+ CircularProgressOwnerState,
+ CircularProgressSlot,
+} from '../CircularProgress/CircularProgressProps';
import { ContainerProps, ContainerSlot } from '../Container/ContainerProps';
import {
FormHelperTextProps,
@@ -172,6 +177,10 @@ export interface Components {
defaultProps?: Partial;
styleOverrides?: OverridesStyleRules;
};
+ JoyCircularProgress?: {
+ defaultProps?: Partial;
+ styleOverrides?: OverridesStyleRules;
+ };
JoyCard?: {
defaultProps?: Partial;
styleOverrides?: OverridesStyleRules;
diff --git a/packages/mui-joy/src/styles/extendTheme.spec.ts b/packages/mui-joy/src/styles/extendTheme.spec.ts
index 5e037e1c204861..e4aa2cf50c5ebc 100644
--- a/packages/mui-joy/src/styles/extendTheme.spec.ts
+++ b/packages/mui-joy/src/styles/extendTheme.spec.ts
@@ -12,6 +12,7 @@ import { CardOverflowOwnerState } from '@mui/joy/CardOverflow';
import { CheckboxOwnerState } from '@mui/joy/Checkbox';
import { ChipOwnerState } from '@mui/joy/Chip';
import { ChipDeleteOwnerState } from '@mui/joy/ChipDelete';
+import { CircularProgressOwnerState } from '@mui/joy/CircularProgress';
import { ContainerProps } from '@mui/joy/Container';
import { FormHelperTextOwnerState } from '@mui/joy/FormHelperText';
import { FormLabelOwnerState } from '@mui/joy/FormLabel';
@@ -299,6 +300,38 @@ extendTheme({
},
},
},
+ JoyCircularProgress: {
+ defaultProps: {
+ variant: 'solid',
+ color: 'primary',
+ },
+ styleOverrides: {
+ root: ({ ownerState }) => {
+ expectType, typeof ownerState>(
+ ownerState,
+ );
+ return {};
+ },
+ svg: ({ ownerState }) => {
+ expectType, typeof ownerState>(
+ ownerState,
+ );
+ return {};
+ },
+ track: ({ ownerState }) => {
+ expectType, typeof ownerState>(
+ ownerState,
+ );
+ return {};
+ },
+ progress: ({ ownerState }) => {
+ expectType, typeof ownerState>(
+ ownerState,
+ );
+ return {};
+ },
+ },
+ },
JoyContainer: {
defaultProps: {
disableGutters: true,