Skip to content

Commit

Permalink
Merge pull request #929 from buildo/no-absolute-positioning
Browse files Browse the repository at this point in the history
Use flex positioning for all input accessories
  • Loading branch information
gabro authored Oct 23, 2024
2 parents f10975b + b6ee04e commit 1b09154
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 224 deletions.
1 change: 0 additions & 1 deletion packages/bento-design-system/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@
"clsx": "1.2.1",
"deepmerge-ts": "4.3.0",
"lodash.pick": "4.4.0",
"react-cool-dimensions": "2.0.7",
"react-dropzone": "14.2.9",
"react-input-mask": "2.0.4",
"react-is": "18.3.1",
Expand Down
51 changes: 19 additions & 32 deletions packages/bento-design-system/src/DateField/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { useBentoConfig } from "../BentoConfigContext";
import { getRadiusPropsFromConfig } from "../util/BorderRadiusConfig";
import { Body } from "../Typography/Body/Body";
import { Inline } from "../Layout/Inline";
import useDimensions from "react-cool-dimensions";
import { IconCalendar, IconMinus } from "../Icons";
import { AriaButtonProps } from "@react-types/button";
import { IconButton } from "../IconButton/IconButton";
Expand Down Expand Up @@ -89,11 +88,6 @@ export function Input(props: Props) {
const config = useBentoConfig().input;
const dateFieldConfig = useBentoConfig().dateField;

const { observe: rightAccessoryRef, width: rightAccessoryWidth } = useDimensions({
// This is needed to include the padding in the width
useBorderBoxSize: true,
});

const { validationState, isDisabled, isReadOnly } = match(props)
.with({ type: "single" }, (props) => {
return {
Expand Down Expand Up @@ -128,6 +122,8 @@ export function Input(props: Props) {
return (
<Box
{...getRadiusPropsFromConfig(config.radius)}
display="flex"
gap={config.internalSpacing}
paddingX={config.paddingX}
paddingY={config.paddingY}
background={config.background.default}
Expand All @@ -144,36 +140,27 @@ export function Input(props: Props) {
readOnly: isReadOnly,
},
]}
style={{ paddingRight: rightAccessoryWidth, ...getReadOnlyBackgroundStyle(config) }}
position="relative"
style={{ ...getReadOnlyBackgroundStyle(config), justifyContent: "space-between" }}
disabled={isDisabled}
readOnly={isReadOnly}
>
{props.type === "single" ? (
<DateField fieldProps={props.fieldProps} />
) : (
<Columns space={dateFieldConfig.internalPadding} alignY="stretch">
<DateField fieldProps={props.fieldProps.start} />
<Column width="content">
<Box display="flex" height="full" alignItems="center">
<IconMinus size={dateFieldConfig.rangeSeparatorSize} />
</Box>
</Column>
<DateField fieldProps={props.fieldProps.end} />
</Columns>
)}
<Box flexGrow={1}>
{props.type === "single" ? (
<DateField fieldProps={props.fieldProps} />
) : (
<Columns space={dateFieldConfig.internalPadding} alignY="stretch">
<DateField fieldProps={props.fieldProps.start} />
<Column width="content">
<Box display="flex" height="full" alignItems="center">
<IconMinus size={dateFieldConfig.rangeSeparatorSize} />
</Box>
</Column>
<DateField fieldProps={props.fieldProps.end} />
</Columns>
)}
</Box>
{!isReadOnly && (
<Box
ref={rightAccessoryRef}
position="absolute"
display="flex"
justifyContent="center"
alignItems="center"
paddingX={config.paddingX}
top={0}
bottom={0}
right={0}
>
<Box display="flex" justifyContent="center" alignItems="center">
<IconButton
kind="transparent"
hierarchy="secondary"
Expand Down
120 changes: 71 additions & 49 deletions packages/bento-design-system/src/Field/Field.css.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createVar } from "@vanilla-extract/css";
import { createVar, style } from "@vanilla-extract/css";
import { bentoSprinkles } from "../internal/sprinkles.css";
import { strictRecipe } from "../util/strictRecipe";
import { vars } from "../vars.css";
Expand All @@ -7,66 +7,88 @@ export const readOnlyBackground = createVar();

const notDisabled = ":not(:disabled):not([disabled])";

export const inputRecipe = strictRecipe({
base: [
{
"::placeholder": {
color: vars.textColor.textSecondary,
},
selectors: {
"&:disabled, &[disabled]": {
background: vars.backgroundColor.backgroundPrimary,
export const input = style({
background: "transparent",
"::placeholder": {
color: vars.textColor.textSecondary,
},
selectors: {
[`&:disabled::placeholder`]: {
color: vars.textColor.textDisabled,
},
},
});

const inputContainerRecipeVariants = {
validation: {
valid: [
bentoSprinkles({
boxShadow: {
default: "outlineInputEnabled",
hover: "outlineInputHover",
focus: "outlineInputFocus",
},
"&:disabled::placeholder": {
color: vars.textColor.textDisabled,
}),
{
selectors: {
[`&:focus-within${notDisabled}`]: {
boxShadow: vars.boxShadow.outlineInputFocus,
},
},
[`input&:read-only${notDisabled}, textarea&:read-only${notDisabled}, &.readOnly${notDisabled}, &[readonly]${notDisabled}`]:
{
background: readOnlyBackground,
},
],
invalid: [
bentoSprinkles({
boxShadow: {
default: "outlineNegative",
focus: "outlineNegativeStrong",
},
}),
{
selectors: {
[`&:focus-within${notDisabled}`]: {
boxShadow: vars.boxShadow.outlineNegativeStrong,
},
},
},
},
],
notSet: {},
},
};

export const inputContainerRecipe = strictRecipe({
base: [
bentoSprinkles({
boxShadow: {
disabled: "outlineInputDisabled",
},
outline: "none",
}),
],
variants: {
validation: {
valid: [
bentoSprinkles({
boxShadow: {
default: "outlineInputEnabled",
hover: "outlineInputHover",
focus: "outlineInputFocus",
},
}),
{
selectors: {
[`&:focus-within${notDisabled}`]: {
boxShadow: vars.boxShadow.outlineInputFocus,
},
},
{
selectors: {
[`&:disabled, &[disabled]`]: {
background: vars.backgroundColor.backgroundPrimary,
},
],
invalid: [
bentoSprinkles({
boxShadow: {
default: "outlineNegative",
focus: "outlineNegativeStrong",
},
}),
{
selectors: {
[`&:focus-within${notDisabled}`]: {
boxShadow: vars.boxShadow.outlineNegativeStrong,
},
[`input&:read-only${notDisabled}, textarea&:read-only${notDisabled}, &.readOnly${notDisabled}, &[readonly]${notDisabled}`]:
{
background: readOnlyBackground,
},
},
},
],
variants: inputContainerRecipeVariants,
});

export const inputRecipe = strictRecipe({
base: [
input,
{
selectors: {
"&[disabled], &:disabled": {
boxShadow: vars.boxShadow.outlineInputDisabled,
},
],
notSet: {},
},
},
},
],
variants: inputContainerRecipeVariants,
});
48 changes: 18 additions & 30 deletions packages/bento-design-system/src/NumberField/BaseNumberInput.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { useLocale } from "@react-aria/i18n";
import { useMemo } from "react";
import useDimensions from "react-cool-dimensions";
import { Label, LocalizedString, Box, Children, Columns } from "..";
import { inputRecipe } from "../Field/Field.css";
import { inputContainerRecipe, input } from "../Field/Field.css";
import { bodyRecipe } from "../Typography/Body/Body.css";
import { BaseNumberProps, FormatProps } from "./types";
import { useBentoConfig } from "../BentoConfigContext";
Expand All @@ -21,11 +20,6 @@ export function BaseNumberInput(props: Props) {
const config = useBentoConfig().input;
const { locale } = useLocale();

const { observe: rightAccessoryRef, width: rightAccessoryWidth } = useDimensions({
// This is needed to include the padding in the width
useBorderBoxSize: true,
});

// Memoizing the currency code calculation to avoid repeating it at every render
const currencyCode = useMemo((): LocalizedString | undefined => {
if (props.kind === "currency") {
Expand Down Expand Up @@ -73,15 +67,25 @@ export function BaseNumberInput(props: Props) {
.with([__.nullish, not(__.nullish)], () => rightAccessoryContent)
.with([not(__.nullish), __.nullish], () => props.rightAccessory)
.with([not(__.nullish), not(__.nullish)], () => (
<Columns space={config.paddingX} alignY="center">
<Columns space={config.internalSpacing} alignY="center">
{props.rightAccessory}
{rightAccessoryContent}
</Columns>
))
.exhaustive();

return (
<Box position="relative" display="flex">
<Box
className={inputContainerRecipe({
validation: props.isReadOnly ? "notSet" : props.validationState,
})}
display="flex"
paddingX={config.paddingX}
paddingY={config.paddingY}
gap={config.internalSpacing}
disabled={props.disabled}
{...getRadiusPropsFromConfig(config.radius)}
>
<Box
as="input"
{...props.inputProps}
Expand All @@ -92,37 +96,21 @@ export function BaseNumberInput(props: Props) {
width="full"
height={undefined}
className={[
inputRecipe({ validation: props.isReadOnly ? "notSet" : props.validationState }),
input,
bodyRecipe({
color: props.disabled ? "disabled" : "primary",
weight: "default",
size: config.fontSize,
ellipsis: false,
}),
]}
{...getRadiusPropsFromConfig(config.radius)}
paddingX={config.paddingX}
paddingY={config.paddingY}
background={config.background.default}
display="flex"
style={{
paddingRight: rightAccessoryWidth,
flexGrow: 1,
...getReadOnlyBackgroundStyle(config),
}}
outline="none"
flexGrow={1}
style={getReadOnlyBackgroundStyle(config)}
/>
{rightAccessory && (
<Box
ref={rightAccessoryRef}
position="absolute"
display="flex"
justifyContent="center"
alignItems="center"
paddingX={16}
top={0}
bottom={0}
right={0}
>
<Box display="flex" justifyContent="center" alignItems="center">
{rightAccessory}
</Box>
)}
Expand Down
20 changes: 0 additions & 20 deletions packages/bento-design-system/src/SearchBar/SearchBar.css.ts

This file was deleted.

Loading

0 comments on commit 1b09154

Please sign in to comment.