Skip to content

Commit

Permalink
🪟 🎨 Connector Field UX Improvements (#16152)
Browse files Browse the repository at this point in the history
* use Source name and Destination name

* move label messages into info tooltips

* pass tooltip props through IntoTooltip and set placement

* add error message to ControlLabels

* refactor to reduce duplication and add optional indicator

* add label as header in info tooltip and fix tooltip word wrapping

* remove placeholders and style tooltip a bit better

* make example background darker

* remove unnecessary style

* put examples in flex box

* use property label in labeled switch

* use info tool tip for condition section

* remove unused class name

* remove colon

* add styling to lists inside of tooltip

* move errors below inputs and add error flag to control input

* remove label css

* use new property label for array section as well

* fix css

* make examples a bit more circular

* put optional text into translatable string

* fix TextWithHTML props and export

* simplify CSS selector

* rename IProps to Props

* fix export

* move examples into its own component

* remove unnecessary var

* conditionSection feedback

* update design of group sections

* fix empty group control styling

* add comment

* fix position and sizing of group control sections

* adjust margin

* add main changed components to storybook

* linting fixes

* fix group section styling and clean up storybook

* fix stylelint errors

* wrap storybook components in cards

* use card prop to fix build error

* fix info tooltip positioning and prevent wrapping on group label

* adjust infotooltip styling again

* fix info tooltip position on safari as well

* fix styling of condition section dropdown

* small spacing adjustment

* another small padding adjustment

* switch display to block

* simplify scss classes

* rename props class

* fix casing of scss variables

* use scss variables in some places

* move PropertyError to Property folder

* replace displayError with hasError

* rename infoMessage to infoTooltipContent

* move stories to other folders

* fix display and local var

* update snapshots

* properly set htmlFor on group control label and fix nest group control styling

* fix tooltip border radius

* fix group controls border radius

* fix spacing of field forms

* fix input border and background colors

* fix display types in property section

* update snapshot classes
  • Loading branch information
lmossman authored Sep 26, 2022
1 parent 7ce39ed commit c4fb6b7
Show file tree
Hide file tree
Showing 42 changed files with 556 additions and 329 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
@use "../../scss/colors";
@use "../../scss/variables";

$title-height: 34px;
$group-spacing: variables.$spacing-xl;
$border-width: variables.$border-thick;

.container {
margin-bottom: 27px;
min-height: $title-height;
position: relative;
padding-top: calc($title-height / 2);
}

.title {
padding-right: $group-spacing;
display: flex;
align-items: center;
height: $title-height;
position: absolute;
left: 0;
right: 0;
top: 0;

label {
padding-bottom: 0;
}
}

.content {
border-color: colors.$grey-100;
border-style: solid;
border-width: 0 $border-width $border-width;
border-radius: variables.$border-radius-md;

// box-shadow is used for the top border, so that it overlaps with bottom border when height is 0
box-shadow: 0 $border-width colors.$grey-100 inset;
padding: 0 $group-spacing;

// only apply padding when there are children, so that empty group sections border is just a single line
> :first-child {
padding-top: calc($group-spacing + $title-height/2);
}

> div {
margin-bottom: $group-spacing;
}
}
45 changes: 11 additions & 34 deletions airbyte-webapp/src/components/GroupControls/GroupControls.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,23 @@
import React from "react";
import styled from "styled-components";

import { Label } from "components";
import { TextWithHTML } from "components/ui/TextWithHTML";

const GroupTitle = styled.div<{ $fullWidthTitle: boolean }>`
margin-top: -23px;
background: ${({ theme }) => theme.whiteColor};
padding: 0 5px;
display: inline-block;
vertical-align: middle;
width: ${({ $fullWidthTitle }) => ($fullWidthTitle ? "100%" : "auto")};
`;

const FormGroup = styled.div`
margin: 41px 0 27px;
border: 2px solid ${({ theme }) => theme.greyColor20};
box-sizing: border-box;
border-radius: 8px;
padding: 0 20px;
`;
import styles from "./GroupControls.module.scss";

interface GroupControlsProps {
title: React.ReactNode;
description?: string;
name?: string;
fullWidthTitle?: boolean;
}

const GroupControls: React.FC<React.PropsWithChildren<GroupControlsProps>> = ({
title,
description,
children,
name,
fullWidthTitle = false,
}) => {
const GroupControls: React.FC<React.PropsWithChildren<GroupControlsProps>> = ({ title, children, name }) => {
return (
<FormGroup data-testid={name}>
<GroupTitle $fullWidthTitle={fullWidthTitle}>{title}</GroupTitle>
{description && <Label message={<TextWithHTML text={description} />} />}
{children}
</FormGroup>
// This outer div is necessary for .content > :first-child padding to be properly applied in the case of nested GroupControls
<div>
<div className={styles.container}>
<div className={styles.title}>{title}</div>
<div className={styles.content} data-testid={name}>
{children}
</div>
</div>
</div>
);
};

Expand Down
73 changes: 73 additions & 0 deletions airbyte-webapp/src/components/GroupControls/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { ComponentStory, ComponentMeta } from "@storybook/react";

import { Card } from "components/base";

import { FormBlock, FormConditionItem } from "core/form/types";
import { GroupLabel } from "views/Connector/ServiceForm/components/Sections/GroupLabel";
import { SectionContainer } from "views/Connector/ServiceForm/components/Sections/SectionContainer";

import GroupControls from "./GroupControls";

export default {
title: "UI/GroupControls",
component: GroupControls,
} as ComponentMeta<typeof GroupControls>;

const Template: ComponentStory<typeof GroupControls> = (args) => (
<Card withPadding>
<GroupControls {...args} />
</Card>
);

const propOneFormBlock: FormBlock = {
title: "propOne",
type: "string",
isRequired: true,
_type: "formItem",
fieldKey: "propOneKey",
path: "section.conditional.choice_one.prop_one",
};

const propTwoFormBlock: FormBlock = {
title: "propTwo",
type: "string",
isRequired: false,
_type: "formItem",
fieldKey: "propTwoKey",
path: "section.conditional.choice_one.prop_two",
};

const conditionFormField: FormConditionItem = {
conditions: {
ChoiceOne: {
isRequired: true,
_type: "formGroup",
fieldKey: "choice_one_key",
path: "section.conditional.choice_one",
jsonSchema: {},
properties: [propOneFormBlock, propTwoFormBlock],
},
},
isRequired: true,
_type: "formCondition",
fieldKey: "field_key",
path: "section.conditional",
};

const title = <GroupLabel formField={conditionFormField} />;

export const Empty = Template.bind({});
Empty.args = {
title,
};

export const WithContent = Template.bind({});
WithContent.args = {
title,
children: (
<>
<SectionContainer>Content part 1</SectionContainer>
<SectionContainer>Content part 2</SectionContainer>
</>
),
};
8 changes: 7 additions & 1 deletion airbyte-webapp/src/components/Label/Label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ interface IProps {
additionLength?: number;
className?: string;
onClick?: (data: unknown) => void;
htmlFor?: string;
}

const Content = styled.label<{ additionLength?: number | string }>`
Expand All @@ -34,7 +35,12 @@ const MessageText = styled.span<Pick<IProps, "error" | "success">>`
`;

const Label: React.FC<React.PropsWithChildren<IProps>> = (props) => (
<Content additionLength={props.additionLength} className={props.className} onClick={props.onClick}>
<Content
additionLength={props.additionLength}
className={props.className}
onClick={props.onClick}
htmlFor={props.htmlFor}
>
{props.children}
{props.message && (
<span>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@use "../../scss/colors";
@use "../../scss/variables";

.controlContainer {
width: 100%;
}

.optionalText {
display: inline;
color: colors.$grey-300;
font-style: oblique;
padding-left: variables.$spacing-sm;
}

.tooltip {
word-wrap: break-word;
}
31 changes: 22 additions & 9 deletions airbyte-webapp/src/components/LabeledControl/ControlLabels.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,50 @@
import className from "classnames";
import React from "react";
import styled from "styled-components";
import { FormattedMessage } from "react-intl";

import { Text } from "components/base/Text";
import { InfoTooltip } from "components/base/Tooltip";
import Label from "components/Label";

import styles from "./ControlLabels.module.scss";

export interface ControlLabelsProps {
className?: string;
error?: boolean;
success?: boolean;
nextLine?: boolean;
message?: React.ReactNode;
errorMessage?: React.ReactNode;
labelAdditionLength?: number;
label?: React.ReactNode;
infoTooltipContent?: React.ReactNode;
optional?: boolean;
htmlFor?: string;
}

const ControlContainer = styled.div`
width: 100%;
display: inline-block;
`;

const ControlLabels: React.FC<React.PropsWithChildren<ControlLabelsProps>> = (props) => (
<ControlContainer className={props.className}>
<div className={className(styles.controlContainer, props.className)}>
<Label
error={props.error}
success={props.success}
message={props.message}
additionLength={props.labelAdditionLength}
nextLine={props.nextLine}
htmlFor={props.htmlFor}
>
{props.label}
{props.infoTooltipContent && (
<InfoTooltip className={styles.tooltip} placement="top-start">
{props.infoTooltipContent}
</InfoTooltip>
)}
{props.optional && (
<Text size="sm" className={styles.optionalText}>
<FormattedMessage id="form.optional" />
</Text>
)}
</Label>
{props.children}
</ControlContainer>
</div>
);

export { ControlLabels };
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
line-height: 16px;
cursor: pointer;
color: colors.$dark-blue;
display: flex;
flex-direction: row;
align-items: center;

&.disabled {
cursor: auto;
Expand Down
39 changes: 19 additions & 20 deletions airbyte-webapp/src/components/LabeledSwitch/LabeledSwitch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,25 @@ interface LabeledSwitchProps extends React.InputHTMLAttributes<HTMLInputElement>
label?: React.ReactNode;
checkbox?: boolean;
loading?: boolean;
id?: string;
}

export const LabeledSwitch: React.FC<LabeledSwitchProps> = (props) => (
<div className={classNames(styles.labeledSwitch, props.className)}>
<span>
{props.checkbox ? (
<CheckBox {...props} id={`toggle-${props.name}`} />
) : (
<Switch {...props} id={`toggle-${props.name}`} />
)}
</span>
export const LabeledSwitch: React.FC<LabeledSwitchProps> = (props) => {
const switchId = props.id ?? `toggle-${props.name}`;

<label
className={classNames(styles.label, {
[styles.disabled]: props.disabled,
})}
htmlFor={`toggle-${props.name}`}
>
{props.label}
<span className={styles.additionalMessage}>{props.message}</span>
</label>
</div>
);
return (
<div className={classNames(styles.labeledSwitch, props.className)}>
<span>{props.checkbox ? <CheckBox {...props} id={switchId} /> : <Switch {...props} id={switchId} />}</span>

<label
className={classNames(styles.label, {
[styles.disabled]: props.disabled,
})}
htmlFor={switchId}
>
{props.label}
<span className={styles.additionalMessage}>{props.message}</span>
</label>
</div>
);
};
8 changes: 4 additions & 4 deletions airbyte-webapp/src/components/base/DropDown/CustomSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,25 @@ export const CustomSelect = styled(Select)<
font-size: 14px;
line-height: 20px;
min-height: 36px;
flex-wrap: nowrap;
&:hover {
border-color: ${({ theme, $error }) => ($error ? theme.dangerColor : theme.greyColor20)};
background: ${({ theme }) => theme.greyColor20};
border-color: ${({ theme, $error }) => ($error ? theme.dangerColor : theme.greyColor10)};
}
&.react-select__control--menu-is-open {
border: 1px solid ${({ theme }) => theme.primaryColor};
box-shadow: none;
background: ${({ theme }) => theme.primaryColor12};
}
& .react-select__multi-value {
background: rgba(255, 255, 255, 0);
}
& .react-select__value-container {
overflow: visible;
overflow: hidden;
display: flex;
flex-wrap: nowrap;
}
}
`;
5 changes: 1 addition & 4 deletions airbyte-webapp/src/components/base/Input/Input.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@
}

&.error {
background-color: colors.$grey-100;
border-color: colors.$red;
border-color: colors.$red-100;
}

&:not(.disabled, .focused):hover {
background-color: colors.$grey-100;
border-color: colors.$grey-100;

&.light {
Expand All @@ -30,7 +28,6 @@
}

&.focused {
background-color: colors.$primaryColor12;
border-color: colors.$blue;

&.light {
Expand Down
Loading

0 comments on commit c4fb6b7

Please sign in to comment.