Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(rtl-customisation): changed the header back button orientations o… #5984

Merged
merged 6 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .changeset/neat-lobsters-return.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
"@refinedev/antd": patch
---

fix(antd): use appropriate icons for RTL direction layouts

Previously CRUD components and `<ThemedSiderV2 />` component used hardcoded icons which doesn't fit well for RTL layouts. This PR uses Ant Design's `ConfigProvider` context to use `direction` to determine the appropriate icons for RTL layouts.

**Example**

```tsx
import { ConfigProvider } from 'antd';
import { Refine } from '@refinedev/antd';

const App = () => (
<ConfigProvider direction="rtl">
<Refine
{/* ... */}
/>
</ConfigProvider>
);
```

When any CRUD component or `<ThemedSiderV2 />` component is rendered, the icons will be rendered with respect to the `direction` prop of `ConfigProvider`.
33 changes: 33 additions & 0 deletions packages/antd/src/components/pageHeader/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from "react";
import { render, TestWrapper } from "@test";
import { PageHeader } from "./";
import { ConfigProvider } from "antd";

describe("PageHeader", () => {
it("should render default back button with respect to direction from config", async () => {
const { rerender, queryByLabelText } = render(
<ConfigProvider>
<PageHeader onBack={() => 0} title="title">
content
</PageHeader>
</ConfigProvider>,
{
wrapper: TestWrapper({}),
},
);

expect(queryByLabelText("arrow-left")).toBeTruthy();
expect(queryByLabelText("arrow-right")).toBeFalsy();

rerender(
<ConfigProvider direction="rtl">
<PageHeader onBack={() => 0} title="title">
content
</PageHeader>
</ConfigProvider>,
);

expect(queryByLabelText("arrow-left")).toBeFalsy();
expect(queryByLabelText("arrow-right")).toBeTruthy();
});
});
21 changes: 12 additions & 9 deletions packages/antd/src/components/pageHeader/index.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import React, { type FC } from "react";
import React, { useContext, type FC } from "react";
import {
PageHeader as AntdPageHeader,
type PageHeaderProps as AntdPageHeaderProps,
} from "@ant-design/pro-layout";
import { Button, Typography } from "antd";
import { ArrowLeftOutlined } from "@ant-design/icons";
import { Button, ConfigProvider, Typography } from "antd";
import { ArrowLeftOutlined, ArrowRightOutlined } from "@ant-design/icons";
import { RefinePageHeaderClassNames } from "@refinedev/ui-types";

export type PageHeaderProps = AntdPageHeaderProps;

export const PageHeader: FC<AntdPageHeaderProps> = ({ children, ...props }) => {
const direction = useContext(ConfigProvider.ConfigContext)?.direction;
const renderBackButton = () => {
const BackIcon =
direction === "rtl" ? ArrowRightOutlined : ArrowLeftOutlined;

// @ts-expect-error Ant Design Icon's v5.0.1 has an issue with @types/react@^18.2.66
return <Button type="text" icon={<BackIcon />} />;
};
const backIcon =
typeof props.backIcon === "undefined" ? (
// @ts-expect-error Ant Design Icon's v5.0.1 has an issue with @types/react@^18.2.66
<Button type="text" icon={<ArrowLeftOutlined />} />
) : (
props.backIcon
);
typeof props.backIcon === "undefined" ? renderBackButton() : props.backIcon;

const title =
typeof props.title === "string" ? (
Expand Down
40 changes: 40 additions & 0 deletions packages/antd/src/components/themedLayoutV2/sider/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type * as Grid from "antd/lib/grid";
import { TestWrapper } from "@test/index";
import { ThemedSiderV2 } from "./index";
import { layoutSiderTests } from "@refinedev/ui-tests";
import { ConfigProvider } from "antd";

jest.mock("antd/lib/grid", () => {
// Require the original module to not be mocked...
Expand Down Expand Up @@ -48,4 +49,43 @@ describe("Sider", () => {
height: "100vh",
});
});

it("should render sider trigger with respect to direction from config", async () => {
const { rerender, container } = render(
<ConfigProvider>
<ThemedSiderV2 />
</ConfigProvider>,
{
wrapper: TestWrapper({}),
},
);

expect(
container.querySelector(
".ant-layout-sider-trigger .anticon.anticon-left",
),
).toBeTruthy();
expect(
container.querySelector(
".ant-layout-sider-trigger .anticon.anticon-right",
),
).toBeFalsy();

rerender(
<ConfigProvider direction="rtl">
<ThemedSiderV2 />
</ConfigProvider>,
);

expect(
container.querySelector(
".ant-layout-sider-trigger .anticon.anticon-right",
),
).toBeTruthy();
expect(
container.querySelector(
".ant-layout-sider-trigger .anticon.anticon-left",
),
).toBeFalsy();
});
});
38 changes: 21 additions & 17 deletions packages/antd/src/components/themedLayoutV2/sider/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import React from "react";
import { Layout, Menu, Grid, Drawer, Button, theme } from "antd";
import React, { useContext } from "react";
import {
Layout,
Menu,
Grid,
Drawer,
Button,
theme,
ConfigProvider,
} from "antd";
import {
DashboardOutlined,
LogoutOutlined,
Expand Down Expand Up @@ -46,6 +54,7 @@ export const ThemedSiderV2: React.FC<RefineThemedLayoutV2SiderProps> = ({
} = useThemedLayoutContext();

const isExistAuthentication = useIsExistAuthentication();
const direction = useContext(ConfigProvider.ConfigContext)?.direction;
const routerType = useRouterType();
const NewLink = useLink();
const { warnWhen, setWarnWhen } = useWarnAboutChange();
Expand Down Expand Up @@ -282,6 +291,15 @@ export const ThemedSiderV2: React.FC<RefineThemedLayoutV2SiderProps> = ({
siderStyles.height = "100vh";
siderStyles.zIndex = 999;
}
const renderClosingIcons = () => {
const iconProps = { style: { color: token.colorPrimary } };
const OpenIcon = direction === "rtl" ? RightOutlined : LeftOutlined;
const CollapsedIcon = direction === "rtl" ? LeftOutlined : RightOutlined;
const IconComponent = siderCollapsed ? CollapsedIcon : OpenIcon;

// @ts-expect-error Ant Design Icon's v5.0.1 has an issue with @types/react@^18.2.66
return <IconComponent {...iconProps} />;
};

return (
<>
Expand Down Expand Up @@ -314,21 +332,7 @@ export const ThemedSiderV2: React.FC<RefineThemedLayoutV2SiderProps> = ({
backgroundColor: token.colorBgElevated,
}}
>
{siderCollapsed ? (
// @ts-expect-error Ant Design Icon's v5.0.1 has an issue with @types/react@^18.2.66
<RightOutlined
style={{
color: token.colorPrimary,
}}
/>
) : (
// @ts-expect-error Ant Design Icon's v5.0.1 has an issue with @types/react@^18.2.66
<LeftOutlined
style={{
color: token.colorPrimary,
}}
/>
)}
{renderClosingIcons()}
</Button>
}
>
Expand Down
Loading