Skip to content

Commit

Permalink
feat(versioning): Add V2 UI; make backend more synchronous; add to co…
Browse files Browse the repository at this point in the history
…mponent library (#12542)
  • Loading branch information
asikowitz authored Feb 4, 2025
1 parent e1ce780 commit b51327e
Show file tree
Hide file tree
Showing 90 changed files with 3,899 additions and 725 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,11 @@ export const sizes = () => (
export const colors = () => (
<GridList>
<Badge count={100} />
<Badge count={100} colorScheme="violet" />
<Badge count={100} colorScheme="green" />
<Badge count={100} colorScheme="red" />
<Badge count={100} colorScheme="blue" />
<Badge count={100} colorScheme="gray" />
<Badge count={100} color="violet" />
<Badge count={100} color="green" />
<Badge count={100} color="red" />
<Badge count={100} color="blue" />
<Badge count={100} color="gray" />
</GridList>
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { HTMLAttributes } from 'react';
import { PillProps } from '../Pills/types';

export interface BadgeProps extends HTMLAttributes<HTMLElement>, Omit<PillProps, 'label'> {
export interface BadgeProps extends Omit<PillProps, 'label'>, Omit<HTMLAttributes<HTMLElement>, 'color'> {
count: number;
overflowCount?: number;
showZero?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const formatBadgeValue = (value: number, overflowCount?: number): string
return `${overflowCount}+`;
};

export function omitKeys<T extends object, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {
export function omitKeys<T extends object, K extends keyof T>(obj: T | undefined, keys: K[]): Omit<T, K> {
const { ...rest } = obj;

keys.forEach((key) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { LoadingOutlined } from '@ant-design/icons';
import { Icon } from '@components';

import { ButtonBase } from './components';
import { ButtonProps } from './types';
import { ButtonProps, ButtonPropsDefaults } from './types';

export const buttonDefaults: ButtonProps = {
export const buttonDefaults: ButtonPropsDefaults = {
variant: 'filled',
color: 'violet',
size: 'md',
Expand All @@ -32,27 +32,26 @@ export const Button = ({
children,
...props
}: ButtonProps) => {
const sharedProps = {
const styleProps = {
variant,
color,
size,
isCircle,
isLoading,
isActive,
isDisabled,
disabled: isDisabled,
};

if (isLoading) {
return (
<ButtonBase {...sharedProps} {...props}>
<ButtonBase {...styleProps} {...props}>
<LoadingOutlined rotate={10} /> {!isCircle && children}
</ButtonBase>
);
}

return (
<ButtonBase {...sharedProps} {...props}>
<ButtonBase {...styleProps} {...props}>
{icon && iconPosition === 'left' && <Icon icon={icon} size={iconSize || size} />}
{!isCircle && children}
{icon && iconPosition === 'right' && <Icon icon={icon} size={iconSize || size} />}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import styled from 'styled-components';

import { spacing } from '@components/theme';
import { ButtonProps } from './types';
import { ButtonStyleProps } from './types';
import { getButtonStyle } from './utils';

export const ButtonBase = styled.button(
// Dynamic styles
(props: ButtonProps) => ({ ...getButtonStyle(props as ButtonProps) }),
(props: ButtonStyleProps) => ({ ...getButtonStyle(props) }),
{
// Base root styles
display: 'flex',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,24 @@ import { ButtonHTMLAttributes } from 'react';
import type { IconNames } from '@components';
import type { SizeOptions, ColorOptions, FontSizeOptions } from '@components/theme/config';

export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'filled' | 'outline' | 'text';
color?: ColorOptions;
size?: SizeOptions;
export type ButtonVariant = 'filled' | 'outline' | 'text';

export interface ButtonPropsDefaults {
variant: ButtonVariant;
color: ColorOptions;
size: SizeOptions;
iconPosition: 'left' | 'right';
isCircle: boolean;
isLoading: boolean;
isDisabled: boolean;
isActive: boolean;
}

export interface ButtonProps
extends Partial<ButtonPropsDefaults>,
Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'color'> {
icon?: IconNames;
iconPosition?: 'left' | 'right';
iconSize?: FontSizeOptions;
isCircle?: boolean;
isLoading?: boolean;
isDisabled?: boolean;
isActive?: boolean;
}

export type ButtonStyleProps = Omit<ButtonPropsDefaults, 'iconPosition'>;
101 changes: 62 additions & 39 deletions datahub-web-react/src/alchemy-components/components/Button/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,25 @@
*/

import { typography, colors, shadows, radius, spacing } from '@components/theme';
import { ColorOptions, SizeOptions } from '@components/theme/config';
import { getColor, getFontSize } from '@components/theme/utils';
import { ButtonProps } from './types';
import { CSSObject } from 'styled-components';
import { ButtonStyleProps, ButtonVariant } from './types';

interface ColorStyles {
bgColor: string;
hoverBgColor: string;
activeBgColor: string;
disabledBgColor: string;
borderColor: string;
activeBorderColor: string;
disabledBorderColor: string;
textColor: string;
disabledTextColor: string;
}

// Utility function to get color styles for button - does not generate CSS
const getButtonColorStyles = (variant, color) => {
const getButtonColorStyles = (variant: ButtonVariant, color: ColorOptions): ColorStyles => {
const color500 = getColor(color, 500); // value of 500 shade
const isViolet = color === 'violet';

Expand Down Expand Up @@ -79,49 +93,49 @@ const getButtonColorStyles = (variant, color) => {
};

// Generate color styles for button
const getButtonVariantStyles = (variant, color) => {
const getButtonVariantStyles = (variant: ButtonVariant, colorStyles: ColorStyles): CSSObject => {
const variantStyles = {
filled: {
backgroundColor: color.bgColor,
border: `1px solid ${color.borderColor}`,
color: color.textColor,
backgroundColor: colorStyles.bgColor,
border: `1px solid ${colorStyles.borderColor}`,
color: colorStyles.textColor,
'&:hover': {
backgroundColor: color.hoverBgColor,
border: `1px solid ${color.hoverBgColor}`,
backgroundColor: colorStyles.hoverBgColor,
border: `1px solid ${colorStyles.hoverBgColor}`,
boxShadow: shadows.sm,
},
'&:disabled': {
backgroundColor: color.disabledBgColor,
border: `1px solid ${color.disabledBorderColor}`,
color: color.disabledTextColor,
backgroundColor: colorStyles.disabledBgColor,
border: `1px solid ${colorStyles.disabledBorderColor}`,
color: colorStyles.disabledTextColor,
boxShadow: shadows.xs,
},
},
outline: {
backgroundColor: 'transparent',
border: `1px solid ${color.borderColor}`,
color: color.textColor,
border: `1px solid ${colorStyles.borderColor}`,
color: colorStyles.textColor,
'&:hover': {
backgroundColor: color.hoverBgColor,
backgroundColor: colorStyles.hoverBgColor,
boxShadow: 'none',
},
'&:disabled': {
backgroundColor: color.disabledBgColor,
border: `1px solid ${color.disabledBorderColor}`,
color: color.disabledTextColor,
backgroundColor: colorStyles.disabledBgColor,
border: `1px solid ${colorStyles.disabledBorderColor}`,
color: colorStyles.disabledTextColor,
boxShadow: shadows.xs,
},
},
text: {
backgroundColor: 'transparent',
border: 'none',
color: color.textColor,
color: colorStyles.textColor,
'&:hover': {
backgroundColor: color.hoverBgColor,
backgroundColor: colorStyles.hoverBgColor,
},
'&:disabled': {
backgroundColor: color.disabledBgColor,
color: color.disabledTextColor,
backgroundColor: colorStyles.disabledBgColor,
color: colorStyles.disabledTextColor,
},
},
};
Expand All @@ -130,7 +144,7 @@ const getButtonVariantStyles = (variant, color) => {
};

// Generate font styles for button
const getButtonFontStyles = (size) => {
const getButtonFontStyles = (size: SizeOptions) => {
const baseFontStyles = {
fontFamily: typography.fonts.body,
fontWeight: typography.fontWeights.normal,
Expand Down Expand Up @@ -160,39 +174,46 @@ const getButtonFontStyles = (size) => {
};

// Generate radii styles for button
const getButtonRadiiStyles = (isCircle) => {
const getButtonRadiiStyles = (isCircle: boolean) => {
if (isCircle) return { borderRadius: radius.full };
return { borderRadius: radius.sm }; // radius is the same for all button sizes
};

// Generate padding styles for button
const getButtonPadding = (size, isCircle) => {
const getButtonPadding = (size: SizeOptions, variant: ButtonVariant, isCircle: boolean) => {
if (isCircle) return { padding: spacing.xsm };

const paddingStyles = {
sm: {
padding: '8px 12px',
vertical: 8,
horizontal: 12,
},
md: {
padding: '10px 12px',
vertical: 10,
horizontal: 12,
},
lg: {
padding: '10px 16px',
vertical: 10,
horizontal: 16,
},
xl: {
padding: '12px 20px',
vertical: 12,
horizontal: 20,
},
};

return paddingStyles[size];
const selectedStyle = paddingStyles[size];
const verticalPadding = selectedStyle.vertical;
const horizontalPadding = variant === 'text' ? 0 : selectedStyle.horizontal;
return { padding: `${verticalPadding}px ${horizontalPadding}px` };
};

// Generate active styles for button
const getButtonActiveStyles = (styleColors) => ({
const getButtonActiveStyles = (colorStyles: ColorStyles) => ({
borderColor: 'transparent',
backgroundColor: styleColors.activeBgColor,
backgroundColor: colorStyles.activeBgColor,
// TODO: Figure out how to make the #fff interior border transparent
boxShadow: `0 0 0 2px #fff, 0 0 0 4px ${styleColors.activeBgColor}`,
boxShadow: `0 0 0 2px #fff, 0 0 0 4px ${colorStyles.activeBgColor}`,
});

// Generate loading styles for button
Expand All @@ -204,17 +225,17 @@ const getButtonLoadingStyles = () => ({
/*
* Main function to generate styles for button
*/
export const getButtonStyle = (props: ButtonProps) => {
const { variant, color, size, isCircle, isActive, isLoading } = props;
export const getButtonStyle = (props: ButtonStyleProps) => {
const { variant, color, size, isCircle, isActive, isLoading, isDisabled } = props;

// Get map of colors
const colorStyles = getButtonColorStyles(variant, color) || ({} as any);
const colorStyles = getButtonColorStyles(variant, color);

// Define styles for button
const variantStyles = getButtonVariantStyles(variant, colorStyles);
const fontStyles = getButtonFontStyles(size);
const radiiStyles = getButtonRadiiStyles(isCircle);
const paddingStyles = getButtonPadding(size, isCircle);
const paddingStyles = getButtonPadding(size, variant, isCircle);

// Base of all generated styles
let styles = {
Expand All @@ -226,9 +247,11 @@ export const getButtonStyle = (props: ButtonProps) => {

// Focus & Active styles are the same, but active styles are applied conditionally & override prevs styles
const activeStyles = { ...getButtonActiveStyles(colorStyles) };
styles['&:focus'] = activeStyles;
styles['&:active'] = activeStyles;
if (isActive) styles = { ...styles, ...activeStyles };
if (!isDisabled && isActive) {
styles['&:focus'] = activeStyles;
styles['&:active'] = activeStyles;
styles = { ...styles, ...activeStyles };
}

// Loading styles
if (isLoading) styles = { ...styles, ...getButtonLoadingStyles() };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const Card = ({
<Pill
label={`${Math.abs(percent)}%`}
size="sm"
colorScheme={percent < 0 ? 'red' : 'green'}
color={percent < 0 ? 'red' : 'green'}
leftIcon={percent < 0 ? 'TrendingDown' : 'TrendingUp'}
clickable={false}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react';

import { HeadingProps } from './types';
import { HeadingProps, HeadingPropsDefaults } from './types';
import { H1, H2, H3, H4, H5, H6 } from './components';

export const headingDefaults: HeadingProps = {
export const headingDefaults: HeadingPropsDefaults = {
type: 'h1',
color: 'inherit',
size: '2xl',
Expand All @@ -15,9 +15,10 @@ export const Heading = ({
size = headingDefaults.size,
color = headingDefaults.color,
weight = headingDefaults.weight,
colorLevel,
children,
}: HeadingProps) => {
const sharedProps = { size, color, weight };
const sharedProps = { size, color, colorLevel, weight };

switch (type) {
case 'h1':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import styled from 'styled-components';

import { typography, colors } from '@components/theme';
import { getColor, getFontSize } from '@components/theme/utils';
import { HeadingProps } from './types';
import { HeadingStyleProps } from './types';

const headingStyles = {
H1: {
Expand Down Expand Up @@ -48,10 +48,10 @@ const baseStyles = {
};

// Prop Driven Styles
const propStyles = (props, isText = false) => {
const propStyles = (props: HeadingStyleProps, isText = false) => {
const styles = {} as any;
if (props.size) styles.fontSize = getFontSize(props.size);
if (props.color) styles.color = getColor(props.color);
if (props.color) styles.color = getColor(props.color, props.colorLevel);
if (props.weight) styles.fontWeight = typography.fontWeights[props.weight];
if (isText) styles.lineHeight = typography.lineHeights[props.size];
return styles;
Expand All @@ -62,8 +62,8 @@ const headings = {} as any;

['H1', 'H2', 'H3', 'H4', 'H5', 'H6'].forEach((heading) => {
const component = styled[heading.toLowerCase()];
headings[heading] = component({ ...baseStyles, ...headingStyles[heading] }, (props: HeadingProps) => ({
...propStyles(props as HeadingProps),
headings[heading] = component({ ...baseStyles, ...headingStyles[heading] }, (props: HeadingStyleProps) => ({
...propStyles(props),
}));
});

Expand Down
Loading

0 comments on commit b51327e

Please sign in to comment.