diff --git a/src/blocks/index.ts b/src/blocks/index.ts index e34c56e6ed..2c3677f35f 100644 --- a/src/blocks/index.ts +++ b/src/blocks/index.ts @@ -7,6 +7,7 @@ export { Link, type LinkProps } from './link'; export { Lozenge, type LozengeProps } from './lozenge'; export { Menu, type MenuProps, MenuItem, type MenuItemComponentProps } from './menu'; export { Modal, type ModalProps, modal } from './modal'; +export { ProgressBar, type ProgressBarProps } from './progressBar'; export { Separator, type SeparatorProps } from './separator'; export { Skeleton, type SkeletonProps } from './skeleton'; export { Tabs, type TabsProps, type TabItem } from './tabs'; diff --git a/src/blocks/progressBar/ProgressBar.tsx b/src/blocks/progressBar/ProgressBar.tsx new file mode 100644 index 0000000000..e83c8c9630 --- /dev/null +++ b/src/blocks/progressBar/ProgressBar.tsx @@ -0,0 +1,41 @@ +import type { FC } from 'react'; +import styled, { FlattenSimpleInterpolation } from 'styled-components'; + +import type { ProgressBarProps } from './ProgressBar.types'; +import { getProgressWidthPercentage } from './ProgressBar.utils'; + +const StyledProgressBarContainer = styled.div<{ css?: FlattenSimpleInterpolation }>` + /* Default CSS */ + background-color: var(--components-progress-bar-background-default); + width: 100%; + height: 4px; + border-radius: var(--radius-xxs, 8px); + + /* Extra CSS prop */ + ${({ css }) => css || ''} +`; + +const StyledProgressBar = styled.div<{ width: string }>` + /* Default CSS */ + border-radius: var(--radius-xxs, 8px); + background-color: var(--components-progress-bar-background-progress); + height: 100%; + width: ${({ width }) => width}; + transition: width 0.3s ease; +`; + +const ProgressBar: FC = ({ progress, max = 100, ...rest }) => ( + + + +); + +ProgressBar.displayName = 'ProgressBar'; + +export { ProgressBar }; diff --git a/src/blocks/progressBar/ProgressBar.types.ts b/src/blocks/progressBar/ProgressBar.types.ts new file mode 100644 index 0000000000..5e6a3a805c --- /dev/null +++ b/src/blocks/progressBar/ProgressBar.types.ts @@ -0,0 +1,11 @@ +import { TransformedHTMLAttributes } from 'blocks/Blocks.types'; +import { FlattenSimpleInterpolation } from 'styled-components'; + +export type ProgressBarProps = { + /* Additional prop from styled components to apply custom css to ProgressBar */ + css?: FlattenSimpleInterpolation; + /* Progress value */ + progress: number; + /* Max value */ + max?: number; +} & TransformedHTMLAttributes; diff --git a/src/blocks/progressBar/ProgressBar.utils.ts b/src/blocks/progressBar/ProgressBar.utils.ts new file mode 100644 index 0000000000..cfa68752e3 --- /dev/null +++ b/src/blocks/progressBar/ProgressBar.utils.ts @@ -0,0 +1,4 @@ +export const getProgressWidthPercentage = (progress: number, total = 100) => { + const percentage = (progress / total) * 100; + return Math.min(Math.max(percentage, 0), 100); +}; diff --git a/src/blocks/progressBar/index.ts b/src/blocks/progressBar/index.ts new file mode 100644 index 0000000000..8b5ee6303b --- /dev/null +++ b/src/blocks/progressBar/index.ts @@ -0,0 +1,3 @@ +export * from './ProgressBar'; +export * from './ProgressBar.utils'; +export * from './ProgressBar.types'; diff --git a/src/blocks/theme/colors/colors.semantics.ts b/src/blocks/theme/colors/colors.semantics.ts index a0900a7515..52914b97ec 100644 --- a/src/blocks/theme/colors/colors.semantics.ts +++ b/src/blocks/theme/colors/colors.semantics.ts @@ -12,6 +12,7 @@ import { dropdownSemantics } from '../semantics/semantics.dropdown'; import { iconSemantics } from '../semantics/semantics.icon'; import { inputSemantics } from '../semantics/semantics.input'; import { modalSemantics } from '../semantics/semantics.modal'; +import { progressBarSemantics } from '../semantics/semantics.progress-bar'; import { radioSemantics } from '../semantics/semantics.radio'; import { skeletonSemantics } from '../semantics/semantics.skeleton'; import { strokeSemantics } from '../semantics/semantics.stroke'; @@ -37,6 +38,7 @@ type SemanticKeys = { icon: 'icon'; input: 'components-inputs'; modal: 'components-modal'; + progressBar: 'components-progress-bar'; radio: 'components-radio-button'; surface: 'surface'; stroke: 'stroke'; @@ -62,6 +64,7 @@ export const semanticKeys: SemanticKeys = { icon: 'icon', input: 'components-inputs', modal: 'components-modal', + progressBar: 'components-progress-bar', radio: 'components-radio-button', surface: 'surface', stroke: 'stroke', @@ -87,6 +90,7 @@ export const colorSemantics = { [semanticKeys.icon]: iconSemantics, [semanticKeys.input]: inputSemantics, [semanticKeys.modal]: modalSemantics, + [semanticKeys.progressBar]: progressBarSemantics, [semanticKeys.radio]: radioSemantics, [semanticKeys.surface]: surfaceSemantics, [semanticKeys.stroke]: strokeSemantics, diff --git a/src/blocks/theme/semantics/semantics.progress-bar.ts b/src/blocks/theme/semantics/semantics.progress-bar.ts new file mode 100644 index 0000000000..a8cf42733d --- /dev/null +++ b/src/blocks/theme/semantics/semantics.progress-bar.ts @@ -0,0 +1,6 @@ +import { surfaceSemantics } from './semantics.surface'; + +export const progressBarSemantics = { + 'background-default': { light: surfaceSemantics['secondary'].light, dark: surfaceSemantics['secondary'].dark }, + 'background-progress': { light: surfaceSemantics['brand-medium'].light, dark: surfaceSemantics['brand-medium'].dark }, +};