Skip to content

Commit

Permalink
fix: remove mandatory prop
Browse files Browse the repository at this point in the history
  • Loading branch information
abelflopes committed Sep 23, 2024
1 parent 61550f5 commit fa39045
Show file tree
Hide file tree
Showing 18 changed files with 378 additions and 32 deletions.
5 changes: 3 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/components/_provisional/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"@react-ck/card": "^1.8.11",
"@react-ck/elevation": "^1.1.16",
"@react-ck/empty-state": "^1.2.7",
"@react-ck/form-field": "^1.3.16",
"@react-ck/icon": "^3.6.0",
"@react-ck/input": "^1.4.16",
"@react-ck/layers": "^1.3.5",
Expand Down
52 changes: 52 additions & 0 deletions packages/components/_provisional/src/boolean-input/BooleaInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import styles from "./styles/index.module.scss";
import React, { useMemo, useState } from "react";
import classNames from "classnames";
import { type FormFieldContextProps, useFormFieldContext } from "@react-ck/form-field";
import { type BooleanInputIconComponent } from "./types";

export interface BooleaInputProps extends React.ComponentProps<"input"> {
Icon: BooleanInputIconComponent;
skin?: FormFieldContextProps["skin"];
}

export const BooleaInput = ({
Icon,
skin,
className,
id,
checked,
value,
name,
onChange,
...otherProps
}: Readonly<BooleaInputProps>): React.ReactElement => {
const formFieldContext = useFormFieldContext();

const computedId = useMemo(() => formFieldContext?.id ?? id, [formFieldContext?.id, id]);

const [localChecked, setLocalChecked] = useState(Boolean(checked));

return (
<span className={classNames(styles.root, className)}>
<input
{...otherProps}
id={computedId}
name={name}
checked={checked}
value={value}
className={styles.input}
onChange={(e) => {
onChange?.(e);
setLocalChecked(e.target.checked);
}}
/>

<Icon
name={name}
checked={localChecked}
value={value}
skin={skin ?? formFieldContext?.skin}
/>
</span>
);
};
3 changes: 3 additions & 0 deletions packages/components/_provisional/src/boolean-input/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./types";

export * from "./BooleaInput";
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@use "@react-ck/theme";

.root {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
}

.input {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
appearance: none;
cursor: pointer;
z-index: 1;
}
12 changes: 12 additions & 0 deletions packages/components/_provisional/src/boolean-input/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { type FormFieldContextProps } from "@react-ck/form-field";
import { type ComponentProps } from "react";

interface BaseProps extends Required<Pick<ComponentProps<"input">, "checked" | "name" | "value">> {
skin: FormFieldContextProps["skin"];
}

export type BooleanInputIconProps = {
[key in keyof BaseProps]: BaseProps[key] | undefined;
};

export type BooleanInputIconComponent = (props: BooleanInputIconProps) => React.ReactNode;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import styles from "./styles/icon.module.scss";
import React from "react";
import { IconCheck } from "@react-ck/icon/icons/IconCheck";
import { Icon } from "@react-ck/icon";
import classNames from "classnames";
import { type BooleanInputIconComponent } from "../boolean-input";

export const CheckboxIconDefault: BooleanInputIconComponent = ({ checked }) => (
<span
className={classNames(styles.root, {
[`${styles.checked}`]: checked,
})}>
<Icon className={styles.icon}>
<IconCheck />
</Icon>
</span>
);
13 changes: 13 additions & 0 deletions packages/components/_provisional/src/checkbox/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";
import { CheckboxIconDefault } from "./CheckboxIconDefault";
import { BooleaInput, type BooleaInputProps } from "../boolean-input";

export type CheckboxProps = Omit<BooleaInputProps, "type" | "Icon"> &
Partial<Pick<BooleaInputProps, "Icon">>;

export const Checkbox = ({
Icon = CheckboxIconDefault,
...otherProps
}: Readonly<CheckboxProps>): React.ReactElement => (
<BooleaInput type="checkbox" Icon={Icon} {...otherProps} />
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@use "@react-ck/theme";
@use "@react-ck/scss-utils";

.root {
display: inline-block;
background-color: theme.get-color(neutral-light-1);
border: theme.get-color(neutral-light-2) solid scss-utils.get-css-var(spacing, border);

padding: theme.get-spacing(0.25);
border-radius: theme.get-spacing(0.5);
line-height: 0;

&.checked .icon {
transform: scale(1);
}
}

.icon {
transition: all 0.15s ease;
will-change: transform;

transform: scale(0);
}
4 changes: 4 additions & 0 deletions packages/components/_provisional/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ export * from "./file-uploader";
export * from "./attachment";

export * from "./snippet";

export * from "./checkbox";

export * from "./radio";
13 changes: 13 additions & 0 deletions packages/components/_provisional/src/radio/RadioIconDefault.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import styles from "./styles/icon.module.scss";
import React from "react";
import classNames from "classnames";
import { type BooleanInputIconComponent } from "../boolean-input";

export const RadioIconDefault: BooleanInputIconComponent = ({ checked }) => (
<span
className={classNames(styles.root, {
[`${styles.checked}`]: checked,
})}>
<span className={styles.icon} />
</span>
);
13 changes: 13 additions & 0 deletions packages/components/_provisional/src/radio/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";
import { RadioIconDefault } from "./RadioIconDefault";
import { BooleaInput, type BooleaInputProps } from "../boolean-input";

export type RadioProps = Omit<BooleaInputProps, "type" | "Icon"> &
Partial<Pick<BooleaInputProps, "Icon">>;

export const Radio = ({
Icon = RadioIconDefault,
...otherProps
}: Readonly<RadioProps>): React.ReactElement => (
<BooleaInput type="radio" Icon={Icon} {...otherProps} />
);
28 changes: 28 additions & 0 deletions packages/components/_provisional/src/radio/styles/icon.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@use "@react-ck/theme";
@use "@react-ck/scss-utils";

.root {
display: inline-flex;
align-items: center;
justify-content: center;
border: theme.get-color(neutral-light-2) solid scss-utils.get-css-var(spacing, border);
padding: theme.get-spacing(0.5);
border-radius: 50%;

&.checked .icon {
transform: scale(1);
}
}

.icon {
display: block;
height: theme.get-spacing(1.4);
width: theme.get-spacing(1.4);
border-radius: 50%;
background-color: theme.get-color(highlight-primary);

transition: all 0.15s ease;
will-change: transform;

transform: scale(0);
}
49 changes: 35 additions & 14 deletions packages/components/form-field/src/FormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export interface FormFieldProps
extends Pick<React.HTMLAttributes<HTMLDivElement>, "children" | "className"> {
/** Specifies the visual style of the form-field */
skin?: Exclude<FormFieldContextProps["skin"], "ghost">;
/** Defines the structure of the form-field */
variation?: "default" | "inline";
/** The main label for the form field */
label?: React.ReactNode;
/** The description text for the form field */
Expand All @@ -26,6 +28,7 @@ export interface FormFieldProps

export const FormField = ({
skin = "default",
variation = "default",
label,
description,
validationMessage,
Expand All @@ -45,23 +48,41 @@ export const FormField = ({

return (
<FormFieldContext.Provider value={context}>
<div {...otherProps} className={classNames(styles.root, styles[skin], className)}>
{label ? (
<Text variation="small" margin="none" as={<label htmlFor={id}>{label}</label>} />
) : null}
<div
{...otherProps}
className={classNames(
styles.root,
styles[`skin_${skin}`],
styles[`variation_${variation}`],
className,
)}>
<div className={styles.main_content}>
{label ? (
<Text
className={styles.label}
variation={variation === "default" ? "small" : "p"}
margin="none"
as={<label htmlFor={id}>{label}</label>}
/>
) : null}

<div className={styles.content}>{children}</div>
<div className={styles.input_wrapper}>{children}</div>
</div>

{description ? (
<Text variation="small" margin="none">
{description}
</Text>
) : null}
{description || validationMessage ? (
<div>
{description ? (
<Text variation="small" margin="none" className={styles.description}>
{description}
</Text>
) : null}

{validationMessage ? (
<Text className={styles.validation_message} variation="small" margin="none">
{validationMessage}
</Text>
{validationMessage ? (
<Text className={styles.validation_message} variation="small" margin="none">
{validationMessage}
</Text>
) : null}
</div>
) : null}
</div>
</FormFieldContext.Provider>
Expand Down
Loading

0 comments on commit fa39045

Please sign in to comment.