Skip to content

Commit

Permalink
feat: progress: add progress component to octuple (#420)
Browse files Browse the repository at this point in the history
* feat: progress: add progress component to octuple

consolidates reset component and clear fix mixins, fixes tree import type

* chore: progress: export progress

* chore: progress: fix import typo

* chore: progress: address pr feedback

* chore: progress: remove redundant uid helper

* chore: progress: add support for custom labels and simplify title value logic
  • Loading branch information
dkilgore-eightfold authored Oct 17, 2022
1 parent aba0df7 commit aa1ad1d
Show file tree
Hide file tree
Showing 33 changed files with 38,952 additions and 12,289 deletions.
13 changes: 0 additions & 13 deletions src/components/DateTimePicker/DatePicker/Styles/mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,6 @@ $picker-input-padding-vertical: max(
padding: $padding-top 0 $padding-bottom $padding-horizontal;
}

// Picker css reset
@mixin reset-component() {
box-sizing: border-box;
margin: 0;
padding: 0;
color: var(--text-primary-color);
font-size: 14px;
font-variant: tabular-nums;
line-height: 1.5715;
list-style: none;
font-feature-settings: 'tnum';
}

// Picker scroll bars
@mixin scroll-bars() {
-ms-overflow-style: none;
Expand Down
12 changes: 0 additions & 12 deletions src/components/Form/Styles/mixins.scss
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
@mixin reset-component() {
box-sizing: border-box;
margin: 0;
padding: 0;
color: var(--text-primary-color);
font-size: $text-font-size-2;
font-variant: tabular-nums;
line-height: 1.5715;
list-style: none;
font-feature-settings: 'tnum';
}

@mixin reset-form() {
legend {
display: block;
Expand Down
94 changes: 94 additions & 0 deletions src/components/Progress/Circle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React, { FC } from 'react';
import OcCircle, { VIEW_BOX_SIZE } from './Internal/OcCircle';
import { CircleProps } from './Progress.types';
import { getSuccessPercent, validProgress } from './Utils';
import { mergeClasses } from '../../shared/utilities';

import styles from './progress.module.scss';

const DEFAULT_CIRCLE_SIZE: number = 120;
const DEFAULT_GAP_DEGREE: number = 75;
const DEFAULT_STROKE_WIDTH_DIVISOR: number = 1.6;
const FAlLBACK_STROKE_WIDTH: number = 4;
const FONT_SIZE_FLOAT: number = 0.15;

function getPercentage({ percent, success }: CircleProps): number[] {
const realSuccessPercent = validProgress(getSuccessPercent({ success }));
return [
realSuccessPercent,
validProgress(validProgress(percent) - realSuccessPercent),
];
}

function getStrokeColor({
success = {},
strokeColor,
}: Partial<CircleProps>): (string | Record<string, string>)[] {
const { strokeColor: successColor } = success;
return [successColor || 'var(--success-color)', strokeColor || null!];
}

const Circle: FC<CircleProps> = (props) => {
const {
children,
gapDegree,
gapPosition,
strokeLinecap = 'butt',
strokeWidth = VIEW_BOX_SIZE / DEFAULT_STROKE_WIDTH_DIVISOR,
success,
trailColor = null,
type,
width,
} = props;

const circleSize: number = width || DEFAULT_CIRCLE_SIZE;
const circleStyle: React.CSSProperties = {
width: circleSize,
height: circleSize,
fontSize: circleSize * FONT_SIZE_FLOAT + FAlLBACK_STROKE_WIDTH,
};
const circleWidth: number = strokeWidth || FAlLBACK_STROKE_WIDTH;
const gapPos: 'top' | 'bottom' | 'left' | 'right' =
gapPosition || (type === 'dashboard' && 'bottom') || undefined;

const getGapDegree = (): number => {
// Support gapDeg = 0 when type = 'dashboard'
if (gapDegree || gapDegree === 0) {
return gapDegree;
}
if (type === 'dashboard') {
return DEFAULT_GAP_DEGREE;
}
return undefined;
};

const isGradient: boolean =
Object.prototype.toString.call(props.strokeColor) === '[object Object]';
const strokeColor: (string | Record<string, string>)[] = getStrokeColor({
success,
strokeColor: props.strokeColor,
});

const wrapperClassNames: string = mergeClasses([
styles.progressInner,
{ [styles.progressCircleGradient]: isGradient },
]);

return (
<div className={wrapperClassNames} style={circleStyle}>
<OcCircle
gapDegree={getGapDegree()}
gapPosition={gapPos}
percent={getPercentage(props)}
strokeColor={strokeColor}
strokeLinecap={strokeLinecap}
strokeWidth={circleWidth}
trailColor={trailColor}
trailWidth={circleWidth}
/>
{children}
</div>
);
};

export default Circle;
38 changes: 38 additions & 0 deletions src/components/Progress/Internal/Common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useRef, useEffect } from 'react';

export const MAX_PERCENT: number = 100;

export const useTransitionDuration = (): SVGPathElement[] => {
const pathsRef: React.MutableRefObject<SVGPathElement[]> = useRef<
SVGPathElement[]
>([]);
const prevTimeStamp: React.MutableRefObject<any> = useRef(null);

useEffect(() => {
const now: number = Date.now();
let updated: boolean = false;

pathsRef.current.forEach((path: SVGPathElement) => {
if (!path) {
return;
}

updated = true;
const pathStyle: CSSStyleDeclaration = path.style;
pathStyle.transitionDuration = '.3s, .3s, .3s, .06s';

if (
prevTimeStamp.current &&
now - prevTimeStamp.current < MAX_PERCENT
) {
pathStyle.transitionDuration = '0s, 0s';
}
});

if (updated) {
prevTimeStamp.current = Date.now();
}
});

return pathsRef.current;
};
Loading

0 comments on commit aa1ad1d

Please sign in to comment.