Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cb 3773 form controls #2023

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
aaba27d
feat: migrate InputFiles to css modules
teunlao Sep 25, 2023
654e1bf
feat: migrate InputFiles to css modules
teunlao Sep 25, 2023
ffb40be
feat: migrate Radio to css modules
teunlao Sep 25, 2023
3eee099
feat: migrate Textarea to css modules
teunlao Sep 25, 2023
68941e6
feat: migrate Filter to css modules
teunlao Sep 25, 2023
fffff59
feat: migrate InputFileTextContent to css modules
teunlao Sep 25, 2023
9c63c5c
feat: migrate FormBox and FormBoxElement to css modules
teunlao Sep 25, 2023
47770a4
feat: migrate FormGroup to css modules
teunlao Sep 25, 2023
13e38b1
fix: fixes after review
teunlao Sep 27, 2023
9170a7b
fix: remove old styles from Filter
teunlao Sep 27, 2023
37ed2ee
fix: remove old styles from InputField
teunlao Sep 27, 2023
69f6359
fix: remove old styles from Textarea
teunlao Sep 27, 2023
5826b82
Merge remote-tracking branch 'origin/devel' into CB-3773-form-controls
teunlao Sep 27, 2023
4582f7c
fix: refactor with field components
teunlao Sep 27, 2023
c5b13da
fix: fixes after review
teunlao Sep 28, 2023
46ca56b
Merge branch 'devel' into CB-3773-form-controls
Wroud Sep 28, 2023
77359aa
Merge branch 'devel' into CB-3773-form-controls
mr-anton-t Sep 28, 2023
6be7ffc
Merge remote-tracking branch 'origin/devel' into CB-3773-form-controls
teunlao Sep 28, 2023
c93909e
fix: remove mod prop from UseFormInfoCredentials
teunlao Sep 28, 2023
910376d
fix: users table filter styles
teunlao Oct 2, 2023
7b4236a
Merge remote-tracking branch 'origin/devel' into CB-3773-form-controls
teunlao Oct 2, 2023
123b785
fix: users table filter styles
teunlao Oct 2, 2023
75a6462
Merge branch 'devel' into CB-3773-form-controls
mr-anton-t Oct 3, 2023
943b9d5
Merge branch 'devel' into CB-3773-form-controls
mr-anton-t Oct 3, 2023
d04c829
Merge branch 'devel' into CB-3773-form-controls
mr-anton-t Oct 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
* you may not use this file except in compliance with the License.
*/
import { filterLayoutFakeProps, getLayoutProps } from '../../Containers/filterLayoutFakeProps';
import elementsSizeStyles from '../../Containers/shared/ElementsSize.m.css';
import { s } from '../../s';
import { useS } from '../../useS';
import formControlStyles from '../FormControl.m.css';
import { Field } from '../Field';
import { FieldLabel } from '../FieldLabel';
import { isControlPresented } from '../isControlPresented';
import { Checkbox, CheckboxBaseProps, CheckboxType, ICheckboxControlledProps, ICheckboxObjectProps } from './Checkbox';
import fieldCheckboxStyles from './FieldCheckbox.m.css';
Expand All @@ -21,20 +21,20 @@ export const FieldCheckbox: CheckboxType = function FieldCheckbox({
}: CheckboxBaseProps & (ICheckboxControlledProps | ICheckboxObjectProps<any>)) {
const layoutProps = getLayoutProps(rest);
const checkboxProps = filterLayoutFakeProps(rest);
const styles = useS(elementsSizeStyles, formControlStyles, fieldCheckboxStyles);
const styles = useS(fieldCheckboxStyles);

if (checkboxProps.autoHide && !isControlPresented(checkboxProps.name, checkboxProps.state)) {
return null;
}

return (
<div data-testid="field" className={s(styles, { field: true, ...layoutProps }, className)}>
<Field {...layoutProps} className={s(styles, { field: true }, className)}>
<Checkbox {...(checkboxProps as CheckboxBaseProps & ICheckboxControlledProps)} className={styles.checkbox} />
{children && (
<label data-testid="field-label" htmlFor={checkboxProps.id || checkboxProps.name} title={checkboxProps.title} className={styles.fieldLabel}>
<FieldLabel htmlFor={checkboxProps.id || checkboxProps.name} title={checkboxProps.title} className={styles.fieldLabel}>
{children}
</label>
</FieldLabel>
)}
</div>
</Field>
);
};
31 changes: 14 additions & 17 deletions webapp/packages/core-blocks/src/FormControls/Checkboxes/Switch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
import { observer } from 'mobx-react-lite';

import { filterLayoutFakeProps } from '../../Containers/filterLayoutFakeProps';
import elementsSizeStyles from '../../Containers/shared/ElementsSize.m.css';
import { s } from '../../s';
import { useS } from '../../useS';
import formControlStyles from '../FormControl.m.css';
import { Field } from '../Field';
import { FieldDescription } from '../FieldDescription';
import { FieldLabel } from '../FieldLabel';
import { isControlPresented } from '../isControlPresented';
import type { ICheckboxControlledProps, ICheckboxObjectProps } from './Checkbox';
import switchStyles from './Switch.m.css';
Expand Down Expand Up @@ -64,19 +65,19 @@ export const Switch: SwitchType = observer(function Switch({
onChange,
});
rest = filterLayoutFakeProps(rest);
const styles = useS(elementsSizeStyles, formControlStyles, switchStyles, ...mod.map(mod => switchMod[mod]));
const styles = useS(switchStyles, ...mod.map(mod => switchMod[mod]));

if (autoHide && !isControlPresented(name, state)) {
return null;
}

return (
<div data-testid="field" className={s(styles, { field: true }, className)} title={rest.title}>
<div data-testid="switch-body" className={styles.switchBody}>
<div data-testid="switch-control" className={s(styles, { switchControl: true, disabled: disabled, checked: checkboxState.checked })}>
<div data-testid="switch-control-track" className={styles.switchControlTrack} />
<div data-testid="switch-control-underlay" className={styles.switchControlUnderlay}>
<div data-testid="switch-control-thumb" className={styles.switchControlThumb} />
<Field className={className} title={rest.title}>
<div className={styles.switchBody}>
<div className={s(styles, { switchControl: true, disabled: disabled, checked: checkboxState.checked })}>
<div className={styles.switchControlTrack} />
<div className={styles.switchControlUnderlay}>
<div className={styles.switchControlThumb} />
<input
{...rest}
type="checkbox"
Expand All @@ -91,15 +92,11 @@ export const Switch: SwitchType = observer(function Switch({
/>
</div>
</div>
<label htmlFor={id || value || name} data-testid="field-label" className={styles.fieldLabel}>
<FieldLabel htmlFor={id || value || name} className={styles.fieldLabel}>
{children}
</label>
</FieldLabel>
</div>
{description && (
<div data-testid="field-description" className={styles.fieldDescription}>
{description}
</div>
)}
</div>
{description && <FieldDescription>{description}</FieldDescription>}
</Field>
);
});
14 changes: 8 additions & 6 deletions webapp/packages/core-blocks/src/FormControls/Combobox.m.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@
margin: 0;
}

.fieldLabel {
display: block;
padding-bottom: 10px;
composes: theme-typography--body1 from global;
font-weight: 500;
.input {
padding-right: 24px !important;
}

.input {
padding-right: 24px !important;
font-size: 12px;

&.select {
cursor: pointer;
user-select: none;
}
}

.menuButton {
Expand Down
25 changes: 10 additions & 15 deletions webapp/packages/core-blocks/src/FormControls/Combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { Menu, MenuButton, MenuItem, useMenuState } from 'reakit/Menu';

import { filterLayoutFakeProps, getLayoutProps } from '../Containers/filterLayoutFakeProps';
import type { ILayoutSizeProps } from '../Containers/ILayoutSizeProps';
import elementsSizeStyles from '../Containers/shared/ElementsSize.m.css';
import { getComputed } from '../getComputed';
import { Icon } from '../Icon';
import { IconOrImage } from '../IconOrImage';
Expand All @@ -20,8 +19,10 @@ import { useTranslate } from '../localization/useTranslate';
import { s } from '../s';
import { useS } from '../useS';
import comboboxStyles from './Combobox.m.css';
import { Field } from './Field';
import { FieldDescription } from './FieldDescription';
import { FieldLabel } from './FieldLabel';
import { FormContext } from './FormContext';
import formControlStyles from './FormControl.m.css';

type BaseProps<TKey, TValue> = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'onSelect' | 'name' | 'value' | 'defaultValue'> &
ILayoutSizeProps & {
Expand Down Expand Up @@ -93,7 +94,7 @@ export const Combobox: ComboboxType = observer(function Combobox({
const context = useContext(FormContext);
const menuRef = useRef<HTMLDivElement>(null);
const [inputRef, setInputRef] = useState<HTMLInputElement | null>(null);
const styles = useS(elementsSizeStyles, formControlStyles, comboboxStyles);
const styles = useS(comboboxStyles);

const menu = useMenuState({
placement: 'bottom-end',
Expand Down Expand Up @@ -255,12 +256,12 @@ export const Combobox: ComboboxType = observer(function Combobox({
}

return (
<div data-testid="field" className={s(styles, { field: true, inline, ...layoutProps }, className)}>
<Field {...layoutProps} className={s(styles, { field: true, inline }, className)}>
{children && (
<div title={title} data-testid="field-label" className={styles.fieldLabel}>
<FieldLabel title={title} className={styles.fieldLabel}>
{children}
{rest.required && ' *'}
</div>
</FieldLabel>
)}
<div data-testid="input-box" className={styles.inputBox}>
{(icon || loading) && (
Expand Down Expand Up @@ -322,20 +323,14 @@ export const Combobox: ComboboxType = observer(function Combobox({
{icon && typeof icon === 'string' ? <IconOrImage icon={icon} className={styles.iconOrImage} /> : icon}
</div>
)}
<div data-testid="item-value" className={styles.itemValue}>
{valueSelector(item)}
</div>
<div>{valueSelector(item)}</div>
</MenuItem>
);
})
)}
</Menu>
</div>
{description && (
<div data-testid="field-description" className={styles.fieldDescription}>
{description}
</div>
)}
</div>
{description && <FieldDescription>{description}</FieldDescription>}
</Field>
);
});
3 changes: 3 additions & 0 deletions webapp/packages/core-blocks/src/FormControls/Field.m.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.field {
box-sizing: border-box;
}
25 changes: 25 additions & 0 deletions webapp/packages/core-blocks/src/FormControls/Field.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { observer } from 'mobx-react-lite';
import type { HTMLAttributes, PropsWithChildren } from 'react';

import { getLayoutProps } from '../Containers/filterLayoutFakeProps';
import type { ILayoutSizeProps } from '../Containers/ILayoutSizeProps';
import elementsSizeStyles from '../Containers/shared/ElementsSize.m.css';
import { s } from '../s';
import { useS } from '../useS';
import fieldStyles from './Field.m.css';

type Props = ILayoutSizeProps &
HTMLAttributes<HTMLDivElement> & {
className?: string;
};
export const Field: React.FC<PropsWithChildren<Props>> = observer(function Field({ children, className, ...rest }) {
const styles = useS(fieldStyles, elementsSizeStyles);

const layoutProps = getLayoutProps(rest);

return (
<div {...rest} className={s(styles, { ...layoutProps, field: true }, className)}>
{children}
</div>
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.fieldDescription {
composes: theme-typography--caption from global;
color: var(--theme-text-hint-on-background);
box-sizing: border-box;
padding-top: 4px;
min-height: 24px;

&.invalid {
color: var(--theme-negative);
}
}
16 changes: 16 additions & 0 deletions webapp/packages/core-blocks/src/FormControls/FieldDescription.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { observer } from 'mobx-react-lite';
import type { PropsWithChildren } from 'react';

import { s } from '../s';
import { useS } from '../useS';
import fieldDescriptionStyles from './FieldDescription.m.css';

interface Props {
className?: string;
invalid?: boolean;
}
export const FieldDescription: React.FC<PropsWithChildren<Props>> = observer(function FieldDescription({ children, className, invalid }) {
const styles = useS(fieldDescriptionStyles);

return <div className={s(styles, { fieldDescription: true, invalid }, className)}>{children}</div>;
});
16 changes: 16 additions & 0 deletions webapp/packages/core-blocks/src/FormControls/FieldLabel.m.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.fieldLabel {
composes: theme-typography--body1 from global;
display: block;
box-sizing: border-box;
overflow: hidden;
white-space: initial;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
font-weight: 500;
}

.fieldLabel:not(:empty) {
padding-bottom: 10px;
}
27 changes: 27 additions & 0 deletions webapp/packages/core-blocks/src/FormControls/FieldLabel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { observer } from 'mobx-react-lite';
import type { LabelHTMLAttributes, PropsWithChildren } from 'react';

import { s } from '../s';
import { useS } from '../useS';
import fieldLabelStyles from './FieldLabel.m.css';

type Props = LabelHTMLAttributes<HTMLLabelElement> & {
className?: string;
title?: string;
required?: boolean;
};
export const FieldLabel: React.FC<PropsWithChildren<Props>> = observer(function FieldLabel({
children,
className,
required,
...rest
}) {
const styles = useS(fieldLabelStyles);

return (
<label {...rest} className={s(styles, { fieldLabel: true }, className)}>
{children}
{required && ' *'}
</label>
);
});
46 changes: 46 additions & 0 deletions webapp/packages/core-blocks/src/FormControls/Filter.m.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.filterContainer {
position: relative;
min-width: 24px;
min-height: 24px;
}
.inputField {
display: none;
width: 300px;
&.max {
width: 100%;
}
&.toggled {
display: block;
}

& input {
padding-right: 40px !important;
}

}
.iconButton {
position: absolute;
right: 0;
top: 0;
margin: 0;
width: 24px;
height: 24px;
border-radius: 2px;
cursor: auto;

&.toggled {
right: 4px;
top: 4px;
}
&.cross {
width: 16px;
height: 16px;
top: 8px;
right: 8px;
}
}

.toggleMode {
composes: theme-background-primary theme-text-on-primary from global;
cursor: pointer;
}
Loading
Loading