Skip to content

Commit

Permalink
fix: Updating handling of ComboboxInput to better handle multiline va…
Browse files Browse the repository at this point in the history
…riants
  • Loading branch information
Brandon Dow committed May 21, 2024
1 parent ad81e36 commit 4aa6153
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 12 deletions.
7 changes: 5 additions & 2 deletions src/Css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3966,12 +3966,15 @@ class CssBuilder<T extends Properties> {
}

// visuallyHidden
/** Sets `position: "absolute"; overflow: "hidden"; clip: "inset(50%)"; clipPath: ""; border: 0; height: "1px"; margin: "-1px"; width: "1px"; padding: 0; whiteSpace: "nowrap"`. */
/** Sets `position: "absolute"; overflow: "hidden"; clip: "inset(50%)"; clipPath: ""; border: 0; height: "1px"; margin: "-1px"; width: "1px"; padding: 0; whiteSpace: "nowrap"; opacity: 0`. */
get visuallyHidden() {
return this.add("position", "absolute").add("overflow", "hidden").add("clip", "inset(50%)").add("clipPath", "").add(
"border",
0,
).add("height", "1px").add("margin", "-1px").add("width", "1px").add("padding", 0).add("whiteSpace", "nowrap");
).add("height", "1px").add("margin", "-1px").add("width", "1px").add("padding", 0).add("whiteSpace", "nowrap").add(
"opacity",
0,
);
}

// contentEmpty
Expand Down
5 changes: 3 additions & 2 deletions src/components/Chips.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ export interface ChipsProps<X> {
values: string[] | ChipValue[];
xss?: X;
compact?: boolean;
wrap?: boolean;
}

/** Renders a list of `Chip`s, with wrapping & appropriate margin between each `Chip`. */
export function Chips<X extends Only<ChipsXss, X>>(props: ChipsProps<X>) {
const { wrap } = usePresentationContext();
const { values, compact, xss = {} } = props;
const { wrap: presentationWrap } = usePresentationContext();
const { values, compact, xss = {}, wrap = presentationWrap } = props;
return (
<div
css={{
Expand Down
22 changes: 17 additions & 5 deletions src/inputs/TextFieldBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,7 @@ export function TextFieldBase<X extends Only<TextFieldXss, X>>(props: TextFieldB
container: Css.df.fdc.w100.maxw(fieldMaxWidth).relative.if(labelStyle === "left").maxw100.fdr.gap2.jcsb.aic.$,
inputWrapper: {
...Css[typeScale].df.aic.br4.px1.w100
.hPx(fieldHeight - maybeSmaller)
.if(compact)
.hPx(compactFieldHeight - maybeSmaller).$,
...Css.bgColor(bgColor)
.bgColor(bgColor)
.gray900.if(contrast)
.white.if(labelStyle === "left").w50.$,
// When borderless then perceived vertical alignments are misaligned. As there is no longer a border, then the field looks oddly indented.
Expand All @@ -141,6 +138,15 @@ export function TextFieldBase<X extends Only<TextFieldXss, X>>(props: TextFieldB
: Css.bGray300.if(contrast).bGray700.$),
// Do not add borders to compound fields. A compound field is responsible for drawing its own borders
...(!compound ? Css.ba.$ : {}),
// When multiline is true, then we want to allow the field to grow to the height of the content, but not shrink below the minHeight
// Otherwise, set fixed heights values accordingly.
...(multiline
? Css.mhPx(fieldHeight - maybeSmaller)
.if(compact)
.mhPx(compactFieldHeight - maybeSmaller).$
: Css.hPx(fieldHeight - maybeSmaller)
.if(compact)
.hPx(compactFieldHeight - maybeSmaller).$),
},
inputWrapperReadOnly: {
...Css[typeScale].df.aic.w100.gray900.if(contrast).white.if(labelStyle === "left").w50.$,
Expand Down Expand Up @@ -255,9 +261,15 @@ export function TextFieldBase<X extends Only<TextFieldXss, X>>(props: TextFieldB
{startAdornment && <span css={Css.df.aic.asc.fs0.br4.pr1.$}>{startAdornment}</span>}
{unfocusedPlaceholder && (
<div
// Setting -1 tabIndex as this is a scrollable container, which is focusable by default.
// However, we want the user's focus to move to the field element, which will hide this container.
tabIndex={-1}
{...tid.unfocusedPlaceholderContainer}
css={{
...Css.df.asc.w100.maxh100.overflowAuto.$,
...Css.df.asc.w100.maxhPx(74).overflowAuto.$,
...fieldStyles.input,
...(showHover ? fieldStyles.hover : {}),
...(inputProps.disabled ? fieldStyles.disabled : {}),
...(isFocused && Css.visuallyHidden.$),
}}
>
Expand Down
10 changes: 8 additions & 2 deletions src/inputs/hooks/useGrowingTextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@ export function useGrowingTextField({ inputRef, inputWrapRef, value, disabled }:
}, [inputRef, disabled, inputWrapRef]);

useLayoutEffect(() => {
if (disabled) return;
if (disabled) {
// reset the height property if it was flipped to disabled
if (inputWrapRef.current) {
inputWrapRef.current.style.removeProperty("height");
}
return;
}

if (inputRef.current) {
// Temp hack until we can figure out a better way to ensure proper measurements when rendered through a portal (i.e. Modals)
Expand All @@ -37,5 +43,5 @@ export function useGrowingTextField({ inputRef, inputWrapRef, value, disabled }:
}
onHeightChange();
}
}, [onHeightChange, value, inputRef, disabled]);
}, [onHeightChange, value, inputRef, disabled, inputWrapRef]);
}
14 changes: 13 additions & 1 deletion src/inputs/internal/ComboBoxInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { useTreeSelectFieldProvider } from "src/inputs/TreeSelectField/TreeSelec
import { isLeveledNode } from "src/inputs/TreeSelectField/utils";
import { Value } from "src/inputs/Value";
import { maybeCall } from "src/utils";
import { useGrowingTextField } from "src/inputs/hooks/useGrowingTextField";

interface ComboBoxInputProps<O, V extends Value> extends PresentationFieldProps {
buttonProps: any;
Expand Down Expand Up @@ -94,11 +95,22 @@ export function ComboBoxInput<O, V extends Value>(props: ComboBoxInputProps<O, V

const chipLabels = isTree ? selectedOptionsLabels || [] : selectedOptions.map((o) => getOptionLabel(o));

useGrowingTextField({
// This says: When using a multiselect, then only enable the growing textfield when we are focused on it.
// Because otherwise, we're not displaying the input element that dictates the height (we're displaying <Chips/>). This would cause incorrect calculations
disabled: (isMultiSelect && (!allowWrap || !isFocused)) || (!isMultiSelect && !allowWrap),
inputRef,
inputWrapRef,
value: inputProps.value,
});

return (
<TextFieldBase
{...otherProps}
{...multilineProps}
unfocusedPlaceholder={showChipSelection && <Chips compact={otherProps.compact} values={chipLabels} />}
unfocusedPlaceholder={
showChipSelection && <Chips compact={otherProps.compact} values={chipLabels} wrap={allowWrap} />
}
inputRef={inputRef}
inputWrapRef={inputWrapRef}
errorMsg={errorMsg}
Expand Down
1 change: 1 addition & 0 deletions truss-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ const sections: Sections = {
width: "1px",
padding: 0,
whiteSpace: "nowrap",
opacity: 0,
}),
],
contentEmpty: () => [newMethod("contentEmpty", { content: "''" })],
Expand Down

0 comments on commit 4aa6153

Please sign in to comment.