Skip to content

Commit

Permalink
fix: Misaligned 'Remove' button when no label is present in the attri…
Browse files Browse the repository at this point in the history
…bute editor (#528)
  • Loading branch information
connorlanigan authored and Katie George committed Nov 30, 2022
1 parent 47cc637 commit 78dda28
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 4 deletions.
82 changes: 82 additions & 0 deletions pages/attribute-editor/form-field-label.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useState, useCallback, useMemo } from 'react';
import AttributeEditor, { AttributeEditorProps } from '~components/attribute-editor';
import { Box, FormField, Input, InputProps, NonCancelableCustomEvent } from '~components';

interface Tag {
key?: string;
value?: string;
}

interface ControlProps extends InputProps {
index: number;
setItems?: any;
prop: keyof Tag;
}

const i18nStrings = {
addButtonText: 'Add new user',
removeButtonText: 'Remove',
empty: 'No secondary owners assigned to this resource.',
};

const Control = React.memo(({ value, index, setItems, prop }: ControlProps) => {
return (
<Input
value={value}
ariaLabel="Secondary owner username"
ariaLabelledby=""
onChange={({ detail }) => {
setItems((items: any) => {
const updatedItems = [...items];
updatedItems[index] = { ...updatedItems[index], [prop]: detail.value };
return updatedItems;
});
}}
/>
);
});

export default function AttributeEditorPage() {
const [items, setItems] = useState<Tag[]>([{ key: '' }]);

const definition: AttributeEditorProps.FieldDefinition<Tag>[] = useMemo(
() => [
{
control: ({ key = '' }, itemIndex) => <Control prop="key" value={key} index={itemIndex} setItems={setItems} />,
},
],
[]
);

const onAddButtonClick = useCallback(() => {
setItems(items => [...items, {}]);
}, []);

const onRemoveButtonClick = useCallback(
({ detail: { itemIndex } }: NonCancelableCustomEvent<AttributeEditorProps.RemoveButtonClickDetail>) => {
setItems(items => {
const newItems = items.slice();
newItems.splice(itemIndex, 1);
return newItems;
});
},
[]
);

return (
<Box margin="xl">
<h1>Attribute Editor - Using a form field label</h1>
<FormField label="Secondary owners" description="Secondary owners can edit this profile.">
<AttributeEditor
{...i18nStrings}
items={items}
definition={definition}
onAddButtonClick={onAddButtonClick}
onRemoveButtonClick={onRemoveButtonClick}
/>
</FormField>
</Box>
);
}
12 changes: 9 additions & 3 deletions src/attribute-editor/row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@ export const Row = React.memo(
))}
</InternalColumnLayout>
{removable && (
<ButtonContainer index={index} isNarrowViewport={isNarrowViewport}>
<ButtonContainer
index={index}
isNarrowViewport={isNarrowViewport}
hasLabel={definition.some(row => row.label)}
>
<InternalButton
className={styles['remove-button']}
formAction="none"
Expand All @@ -113,12 +117,14 @@ interface ButtonContainer {
index: number;
children: React.ReactNode;
isNarrowViewport: boolean;
hasLabel: boolean;
}

const ButtonContainer = ({ index, children, isNarrowViewport }: ButtonContainer) => (
const ButtonContainer = ({ index, children, isNarrowViewport, hasLabel }: ButtonContainer) => (
<div
className={clsx({
[styles['button-container']]: !isNarrowViewport && index === 0,
[styles['button-container-haslabel']]: !isNarrowViewport && index === 0 && hasLabel,
[styles['button-container-nolabel']]: !isNarrowViewport && index === 0 && !hasLabel,
[styles['right-align']]: isNarrowViewport,
})}
>
Expand Down
6 changes: 5 additions & 1 deletion src/attribute-editor/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,18 @@
/* used in test-utils */
}

.button-container {
.button-container-haslabel {
// We only support vertical alignment of the remove button for labels with exactly one line.
// The value is calculated as follows:
// padding-top = awsui-form-field-controls: 4px +
// line height (also applies to icon size) awsui-form-field-label: 22px
padding-top: calc(#{awsui.$space-xxs} + #{awsui.$font-body-m-line-height});
}

.button-container-nolabel {
padding-top: #{awsui.$space-xxs};
}

.divider {
border-bottom: awsui.$border-divider-section-width solid awsui.$color-border-divider-default;
}
Expand Down

0 comments on commit 78dda28

Please sign in to comment.