Skip to content

Commit

Permalink
Merge pull request #4568 from Sage/FE-4440-tab-access-issues
Browse files Browse the repository at this point in the history
docs(tabs): update headerWidth story to use unique id for each tab child  FE-4440
  • Loading branch information
edleeks87 authored Nov 26, 2021
2 parents 74122fb + 42be1eb commit f7c8378
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 215 deletions.
1 change: 0 additions & 1 deletion cypress/support/step-definitions/tabs-steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ Then("Tab {int} content is visible", (id) => {

Then("Second Tab has a link property", () => {
tabById(2)
.find("a")
.should("have.attr", "href", "https://carbon.sage.com/")
.and("have.attr", "target", "_blank");
});
1 change: 1 addition & 0 deletions src/components/tabs/__internal__/tab-title/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./tab-title";
68 changes: 41 additions & 27 deletions src/components/tabs/__internal__/tab-title/tab-title.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const TabTitle = React.forwardRef(
isInSidebar,
href,
onKeyDown,
align,
...tabTitleProps
},
ref
Expand Down Expand Up @@ -73,6 +74,9 @@ const TabTitle = React.forwardRef(
return window.open(href, "_blank");
}

// safari does not focus buttons by default
ref.current?.focus();

return onClick(customEvent);
};

Expand Down Expand Up @@ -121,17 +125,16 @@ const TabTitle = React.forwardRef(
error={error}
warning={warning}
info={info}
size={size}
noRightBorder={noRightBorder}
alternateStyling={alternateStyling || isInSidebar}
borders={borders}
isInSidebar={isInSidebar}
{...tabTitleProps}
{...(isHref && { href, target: "_blank", as: "a" })}
{...tagComponent("tab-header", tabTitleProps)}
onKeyDown={handleKeyDown}
>
<StyledTitleContent
{...(isHref && { href, target: "_blank", as: "a" })}
error={error}
warning={warning}
info={info}
Expand All @@ -145,35 +148,45 @@ const TabTitle = React.forwardRef(
isTabSelected={isTabSelected}
hasCustomLayout={!!customLayout}
alternateStyling={hasAlternateStyling}
align={align}
hasHref={!!href}
>
{renderContent()}
{isHref && <Icon type="link" />}

<StyledLayoutWrapper hasCustomSibling={!!customLayout}>
{error && (
<ValidationIcon
onClick={handleClick}
tooltipPosition="top"
error={errorMessage}
/>
)}

{!error && warning && (
<ValidationIcon
onClick={handleClick}
tooltipPosition="top"
warning={warningMessage}
/>
)}

{!warning && !error && info && (
<ValidationIcon
onClick={handleClick}
tooltipPosition="top"
info={infoMessage}
/>
)}
</StyledLayoutWrapper>
{hasFailedValidation && (
<StyledLayoutWrapper
position={position}
hasCustomSibling={!!customLayout}
>
{error && (
<ValidationIcon
onClick={handleClick}
tooltipPosition="top"
error={errorMessage}
tabIndex={null}
/>
)}

{!error && warning && (
<ValidationIcon
onClick={handleClick}
tooltipPosition="top"
warning={warningMessage}
tabIndex={null}
/>
)}

{!warning && !error && info && (
<ValidationIcon
onClick={handleClick}
tooltipPosition="top"
info={infoMessage}
tabIndex={null}
/>
)}
</StyledLayoutWrapper>
)}
</StyledTitleContent>
{!(hasFailedValidation || hasAlternateStyling) && isTabSelected && (
<StyledSelectedIndicator
Expand Down Expand Up @@ -213,6 +226,7 @@ TabTitle.propTypes = {
customLayout: PropTypes.node,
isInSidebar: PropTypes.bool,
href: PropTypes.string,
align: PropTypes.oneOf(["left", "right"]),
};

export default TabTitle;
39 changes: 39 additions & 0 deletions src/components/tabs/__internal__/tab-title/tab-title.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as React from "react";

export interface TabTitleProps {
title: string;
id?: string;
dataTabId?: string;
className?: string;
children?: React.ReactNode;
isTabSelected?: boolean;
position?: "top" | "left";
errorMessage?: string;
warningMessage?: string;
infoMessage?: string;
errors?: boolean;
warning?: boolean;
info?: boolean;
borders?: boolean;
noLeftBorder?: boolean;
noRightBorder?: boolean;
alternateStyling?: boolean;
isInSidebar?: boolean;
siblings?: React.ReactNode[];
titlePosition?: "before" | "after";
href?: string;
tabIndex?: string;
size?: "default" | "large";
align?: "left" | "right";
customLayout?: React.ReactNode;
onClick?: (
ev: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>
) => void;
onKeyDown?: (
ev: React.KeyboardEvent<HTMLButtonElement | HTMLAnchorElement>
) => void;
}

declare function TabTitle(props: TabTitleProps): JSX.Element;

export default TabTitle;
65 changes: 27 additions & 38 deletions src/components/tabs/__internal__/tab-title/tab-title.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe("TabTitle", () => {
backgroundColor: "transparent",
display: "inline-block",
fontWeight: "bold",
height: "100%",
height: "40px",
},
render({}, mount).find(StyledTabTitle)
);
Expand Down Expand Up @@ -131,7 +131,7 @@ describe("TabTitle", () => {
marginLeft: "-1px",
},
wrapper.find(StyledTabTitle),
{ modifier: ":not(:first-of-type)" }
{ modifier: ":nth-of-type(n + 1)" }
);
});

Expand All @@ -148,7 +148,7 @@ describe("TabTitle", () => {
);

assertStyleMatch(
{ paddingBottom: "6px" },
{ paddingBottom: "9px" },
wrapper.find(StyledTitleContent)
);

Expand Down Expand Up @@ -203,7 +203,7 @@ describe("TabTitle", () => {
backgroundColor: "transparent",
borderBottom: "0px",
borderRight: `2px solid ${baseTheme.tab.background}`,
display: "block",
display: "flex",
height: "auto",
marginLeft: "0px",
},
Expand All @@ -227,6 +227,24 @@ describe("TabTitle", () => {
);
});

it("renders as expected when `align='left'`", () => {
assertStyleMatch(
{ justifyContent: "flex-start", textAlign: "left" },
render({ position: "left", align: "left" }, mount).find(
StyledTitleContent
)
);
});

it("renders as expected when `align='right'`", () => {
assertStyleMatch(
{ justifyContent: "flex-end", textAlign: "right" },
render({ align: "right", position: "left" }, mount).find(
StyledTitleContent
)
);
});

it('applies proper styling when size is "large"', () => {
wrapper = render({ position: "left", size: "large" }, mount);

Expand Down Expand Up @@ -261,7 +279,7 @@ describe("TabTitle", () => {
marginTop: "-1px",
},
wrapper.find(StyledTabTitle),
{ modifier: ":not(:first-of-type)" }
{ modifier: ":nth-of-type(n + 1)" }
);

assertStyleMatch(
Expand Down Expand Up @@ -308,15 +326,6 @@ describe("TabTitle", () => {
);
});

it("applies proper styling when size is large", () => {
wrapper = render({ isTabSelected: true, size: "large" }, mount);

assertStyleMatch(
{ paddingBottom: "6px" },
wrapper.find(StyledTitleContent)
);
});

it("does not apply selected styling", () => {
wrapper = render({ isTabSelected: true, error: true }, mount);

Expand Down Expand Up @@ -424,29 +433,6 @@ describe("TabTitle", () => {
);
});

it('adjusts padding when isTabSelected is true and position is "top"', () => {
wrapper = render(
{
title: "Tab 1",
siblings: [<span>foo</span>, <span>bar</span>],
titlePosition: "before",
isTabSelected: true,
},
mount
);

expect(wrapper.find(StyledTitleContent).props().hasSiblings).toEqual(
true
);
expect(
wrapper.find(StyledTitleContent).props().children[0][0].props.children
).toEqual("Tab 1");
assertStyleMatch(
{ paddingBottom: "8px" },
wrapper.find(StyledTitleContent)
);
});

it('does not adjust padding when isTabSelected is true and position is "left"', () => {
wrapper = render(
{
Expand Down Expand Up @@ -1077,7 +1063,10 @@ describe("TabTitle", () => {
stopPropagation,
target: { dataset: { tabid: "uniqueid1" } },
};
wrapper = render({ onClick }, mount);
wrapper = render(
{ onClick, ref: { current: { focus: jest.fn() } } },
mount
);

wrapper
.find(StyledTitleContent)
Expand Down
Loading

0 comments on commit f7c8378

Please sign in to comment.