Skip to content

Commit

Permalink
Advanced options (#234)
Browse files Browse the repository at this point in the history
* fix:add typescript config object to storybook config. causing issues with compilation over swicth component.

* fix: remove dupe i created of component. move to folder with story

* refactor: forwardRef for number input and create controlled number input to work with react-hook-form controller

* update: have option to present without divider.

* chore: advanced options for new cluster creation

* update: add advanced options to cluster creation.

* miscellaneous things. mvp request for cluster creation.

* fix: review changes
  • Loading branch information
D-B-Hawk authored Aug 16, 2023
1 parent ee51b58 commit fc4d8f4
Show file tree
Hide file tree
Showing 25 changed files with 568 additions and 365 deletions.
3 changes: 3 additions & 0 deletions .storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ module.exports = {
features: {
previewMdx2: true,
},
typescript: {
reactDocgen: 'react-docgen',
},
};
1 change: 1 addition & 0 deletions components/clusterTable/clusterTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export type ClusterInfo = Pick<
> & {
nodes?: number;
instanceSize?: string;
workerNodes?: ClusterInfo[];
};

type ClusterRowProps = ClusterInfo & {
Expand Down
62 changes: 0 additions & 62 deletions components/controlledFields/Radio.tsx

This file was deleted.

61 changes: 0 additions & 61 deletions components/controlledFields/RadioGroup/index.tsx

This file was deleted.

27 changes: 27 additions & 0 deletions components/controlledFields/numberInput/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import { Control, Controller, FieldValues, UseControllerProps } from 'react-hook-form';

import NumberInput, { NumberInputProps } from '../../numberInput';

export interface ControlledTextFieldProps<T extends FieldValues> extends UseControllerProps<T> {
disabled?: boolean;
label: string;
required?: boolean;
control: Control<T>;
numberInputProps?: NumberInputProps['inputProps'];
}

function ControlledNumberInput<T extends FieldValues>({
label,
numberInputProps,
...props
}: ControlledTextFieldProps<T>) {
return (
<Controller
{...props}
render={({ field }) => <NumberInput label={label} inputProps={numberInputProps} {...field} />}
/>
);
}

export default ControlledNumberInput;
27 changes: 27 additions & 0 deletions components/controlledFields/numberInput/numberInput.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import { Story } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { useForm } from 'react-hook-form';

import ControlledNumberInput from '.';

export default {
title: 'Components/ControlledNumberInput',
component: ControlledNumberInput,
};

const DefaultTemplate: Story = () => {
const { control } = useForm({
defaultValues: {
numberOfNodes: 3,
},
});
return (
<form onSubmit={() => action('onSubmit')}>
<ControlledNumberInput label="Number of nodes" name="numberOfNodes" control={control} />
<button type="submit">Submit</button>
</form>
);
};

export const Default = DefaultTemplate.bind({});
60 changes: 60 additions & 0 deletions components/controlledFields/radio/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';
import { FormControlLabel, Radio, RadioGroup } from '@mui/material';
import { Control, Controller, UseControllerProps, FieldValues } from 'react-hook-form';

import Typography from '../../typography';
import { VOLCANIC_SAND } from '../../../constants/colors';

export interface ControlledTextFieldProps<T extends FieldValues> extends UseControllerProps<T> {
control: Control<T>;
required?: boolean;
rules: {
required: boolean;
pattern?: RegExp;
};
options: Array<{ label: string; value: string }>;
}

function ControlledRadio<T extends FieldValues>({
defaultValue,
name,
options,
required,
...props
}: ControlledTextFieldProps<T>) {
return (
<Controller
{...props}
name={name}
render={({ field }) => (
<RadioGroup defaultValue={defaultValue} name={name}>
{options.map(({ label, value }) => (
<FormControlLabel
key={label}
value={value}
control={
<Radio
{...field}
name={name}
required={required}
inputRef={field.ref}
value={value}
onChange={(e) => {
field.onChange(e);
}}
/>
}
label={
<Typography variant="body2" color={VOLCANIC_SAND}>
{label}
</Typography>
}
/>
))}
</RadioGroup>
)}
/>
);
}

export default ControlledRadio;
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import React from 'react';
import { Story } from '@storybook/react';
import { useForm } from 'react-hook-form';

import RadioGroup from '.';
import Radio from './';

export default {
title: 'Components/RadioGroup',
component: RadioGroup,
title: 'Components/Radio',
component: Radio,
};

const DefaultTemplate: Story = () => {
Expand All @@ -17,7 +17,7 @@ const DefaultTemplate: Story = () => {
});

return (
<RadioGroup
<Radio
control={control}
label="Gender"
rules={{ required: false }}
Expand Down
4 changes: 3 additions & 1 deletion components/learnMore/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ export interface LearnMoreProps {
href: string;
linkTitle: string;
installType?: InstallationType;
withoutDivider?: boolean;
}

const LearnMore: FunctionComponent<LearnMoreProps> = ({
description,
href,
installType,
linkTitle,
withoutDivider,
}) => {
const docsDomainLink = `https://docs.kubefirst.io/${
installType && [InstallationType.DIGITAL_OCEAN, InstallationType.VULTR].includes(installType)
Expand All @@ -27,7 +29,7 @@ const LearnMore: FunctionComponent<LearnMoreProps> = ({

return (
<>
<Divider sx={{ m: '-20px', p: '8px 0' }} />
{!withoutDivider && <Divider sx={{ m: '-20px', p: '8px 0' }} />}
<Text variant="labelLarge">
{description}{' '}
<NextLink
Expand Down
64 changes: 42 additions & 22 deletions components/numberInput/index.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,63 @@
import React, { FunctionComponent, ComponentPropsWithoutRef, InputHTMLAttributes } from 'react';
import React, { ComponentPropsWithoutRef, InputHTMLAttributes, useState, forwardRef } from 'react';
import Image from 'next/image';
import styled from 'styled-components';

import removeIconSrc from '../../assets/remove.svg';
import addIconSrc from '../../assets/add.svg';
import { noop } from '../../utils/noop';
import Typography from '../../components/typography';
import { EXCLUSIVE_PLUM } from '../../constants/colors';

import { Root, NumInput, InputContainer, LabelContainer } from './numberInput.styled';
import { Root, NumInput, InputContainer, LabelContainer, Asterisk } from './numberInput.styled';

interface NumberInputProps extends ComponentPropsWithoutRef<'label'> {
export interface NumberInputProps extends Omit<ComponentPropsWithoutRef<'label'>, 'onChange'> {
label?: string;
onIncrease: () => void;
onDecrease: () => void;
inputProps: InputHTMLAttributes<HTMLInputElement>;
inputProps?: InputHTMLAttributes<HTMLInputElement>;
onChange?: (value: number) => void;
}

const NumberInput: FunctionComponent<NumberInputProps> = ({
onIncrease,
onDecrease,
label,
inputProps,
...rest
}) => {
const NumberInput = forwardRef<HTMLLabelElement | null, NumberInputProps>(function NumberInput(
{ label, onChange = noop, inputProps = {}, ...rest },
ref,
) {
const [value, setValue] = useState(Number(inputProps.min ?? 0));
return (
<Root {...rest}>
<LabelContainer>
{label}
{inputProps.required && <span>*</span>}
</LabelContainer>
<Root {...rest} ref={ref}>
{label && (
<LabelContainer>
<Typography variant="labelLarge" color={EXCLUSIVE_PLUM}>
{label}
</Typography>
{inputProps.required && <Asterisk>*</Asterisk>}
</LabelContainer>
)}
<InputContainer>
<button type="button" onClick={onDecrease}>
<button
type="button"
onClick={() => {
const curValue = value - 1;
setValue(curValue);
onChange(curValue);
}}
disabled={value === inputProps.min || inputProps.disabled}
>
<Image src={removeIconSrc} alt="remove" width={20} height={20} />
</button>
<NumInput {...inputProps} />
<button type="button" onClick={onIncrease}>
<NumInput {...inputProps} value={value} readOnly />
<button
type="button"
onClick={() => {
const curValue = value + 1;
setValue(curValue);
onChange(curValue);
}}
disabled={inputProps.disabled}
>
<Image src={addIconSrc} alt="add" width={20} height={20} />
</button>
</InputContainer>
</Root>
);
};
});

export default styled(NumberInput)``;
Loading

0 comments on commit fc4d8f4

Please sign in to comment.