diff --git a/src/features/online-board/components/BoardDetailsHeader/FlightStatusButton.test.tsx b/src/features/online-board/components/BoardDetailsHeader/FlightStatusButton.test.tsx
new file mode 100644
index 00000000..36966463
--- /dev/null
+++ b/src/features/online-board/components/BoardDetailsHeader/FlightStatusButton.test.tsx
@@ -0,0 +1,65 @@
+// @vitest-environment jsdom
+import { describe, it, expect, vi, beforeEach } from "vitest";
+import { render, screen, fireEvent } from "@testing-library/react";
+import { FlightStatusButton } from "./FlightStatusButton.js";
+import type { ISimpleFlight } from "../../types.js";
+
+vi.mock("@/i18n/provider.js", () => ({
+ useTranslation: () => ({ t: (k: string) => k }),
+}));
+
+function makeFlight(carrier = "SU"): ISimpleFlight {
+ return {
+ id: "X",
+ routeType: "Direct",
+ flyingTime: "1h",
+ status: "Scheduled",
+ flightId: { carrier, flightNumber: "0022", suffix: "", date: "20260417" },
+ operatingBy: { carrier, flightNumber: "0022" },
+ leg: {} as never,
+ } as ISimpleFlight;
+}
+
+describe("FlightStatusButton", () => {
+ beforeEach(() => {
+ Object.defineProperty(window, "open", { value: vi.fn(), writable: true });
+ });
+
+ it("renders label SHARED.DETAILS", () => {
+ render();
+ expect(screen.getByText("SHARED.DETAILS")).toBeTruthy();
+ });
+
+ it("has data-testid flight-status-button", () => {
+ render();
+ expect(screen.getByTestId("flight-status-button")).toBeTruthy();
+ });
+
+ it("SU click opens native onlineboard details URL", () => {
+ render();
+ fireEvent.click(screen.getByTestId("flight-status-button"));
+ const openMock = window.open as ReturnType;
+ expect(openMock).toHaveBeenCalledTimes(1);
+ expect(openMock.mock.calls[0]![0]).toBe("/ru/onlineboard/SU0022-20260417");
+ });
+
+ it("HZ click opens flyaurora URL", () => {
+ render();
+ fireEvent.click(screen.getByTestId("flight-status-button"));
+ const openMock = window.open as ReturnType;
+ expect(openMock).toHaveBeenCalledTimes(1);
+ expect(openMock.mock.calls[0]![0]).toContain("flyaurora.ru");
+ });
+
+ it("small prop adds --small modifier class", () => {
+ render();
+ const btn = screen.getByTestId("flight-status-button");
+ expect(btn.className).toContain("flight-action-btn--small");
+ });
+
+ it("default (small=false) does not add --small class", () => {
+ render();
+ const btn = screen.getByTestId("flight-status-button");
+ expect(btn.className).not.toContain("flight-action-btn--small");
+ });
+});
diff --git a/src/features/online-board/components/BoardDetailsHeader/FlightStatusButton.tsx b/src/features/online-board/components/BoardDetailsHeader/FlightStatusButton.tsx
new file mode 100644
index 00000000..52e78c30
--- /dev/null
+++ b/src/features/online-board/components/BoardDetailsHeader/FlightStatusButton.tsx
@@ -0,0 +1,56 @@
+import type { FC } from "react";
+import { useTranslation } from "@/i18n/provider.js";
+import type { ISimpleFlight } from "../../types.js";
+import { AIRLINES } from "./airlines.js";
+import { buildOnlineBoardUrl } from "../../url.js";
+import "./actions.scss";
+
+export interface FlightStatusButtonProps {
+ flight: ISimpleFlight;
+ locale: string;
+ small?: boolean;
+}
+
+export const FlightStatusButton: FC = ({ flight, locale, small }) => {
+ const { t } = useTranslation();
+
+ const handleClick = () => {
+ const carrier = flight.operatingBy.carrier;
+ if (!carrier) return;
+ const config = AIRLINES[carrier];
+ if (!config) return;
+
+ if (config.hasNativeStatus) {
+ const path = buildOnlineBoardUrl({
+ type: "details",
+ carrier: flight.flightId.carrier,
+ flightNumber: flight.flightId.flightNumber,
+ ...(flight.flightId.suffix ? { suffix: flight.flightId.suffix } : {}),
+ date: flight.flightId.date,
+ });
+ window.open(`/${locale}/${path}`, "_blank", "noopener,noreferrer");
+ } else if (config.statusUrl) {
+ window.open(config.statusUrl, "_blank", "noopener,noreferrer");
+ }
+ };
+
+ const classes = [
+ "flight-action-btn",
+ "flight-action-btn--blue-light",
+ small ? "flight-action-btn--small" : "",
+ ]
+ .filter(Boolean)
+ .join(" ");
+
+ return (
+
+ );
+};