diff --git a/cypress/e2e/footer.cy.ts b/cypress/e2e/footer.cy.ts
new file mode 100644
index 0000000..83e9bad
--- /dev/null
+++ b/cypress/e2e/footer.cy.ts
@@ -0,0 +1,13 @@
+describe("Footer", () => {
+ beforeEach(() => {
+ cy.visit("http://localhost:3000/dashboard");
+ });
+
+ it("renders the footer", () => {
+ cy.get("footer").should("be.visible");
+ cy.get("footer").find("a").should("have.length", 4);
+ cy.get("footer")
+ .find("img")
+ .should("have.attr", "src", "/icons/logo-small.svg");
+ });
+});
diff --git a/cypress/e2e/navigation.cy.ts b/cypress/e2e/navigation.cy.ts
index 336ce22..2a9ddee 100644
--- a/cypress/e2e/navigation.cy.ts
+++ b/cypress/e2e/navigation.cy.ts
@@ -47,16 +47,24 @@ describe("Sidebar Navigation", () => {
cy.get("nav").contains("Issues").should("not.exist");
});
- it("shows large logo when switching to landscape mode while navigation is collapsed", () => {
+ it.only("shows large logo when switching to landscape mode while navigation is collapsed", () => {
// collapse navigation
cy.get("nav").contains("Collapse").click();
- cy.get("img[src='/icons/logo-small.svg']").should("be.visible");
- cy.get("img[src='/icons/logo-large.svg']").should("not.be.visible");
+ cy.get("header")
+ .find("img[src='/icons/logo-small.svg']")
+ .should("be.visible");
+ cy.get("header")
+ .find("img[src='/icons/logo-large.svg']")
+ .should("not.be.visible");
//switch to landscape mode that uses the mobile menu
cy.viewport(900, 1025);
- cy.get("img[src='/icons/logo-small.svg']").should("not.be.visible");
- cy.get("img[src='/icons/logo-large.svg']").should("be.visible");
+ cy.get("header")
+ .find("img[src='/icons/logo-large.svg']")
+ .should("be.visible");
+ cy.get("header")
+ .find("img[src='/icons/logo-small.svg']")
+ .should("not.be.visible");
});
it("support link has correct href", () => {
diff --git a/features/layout/footer/footer-link.module.scss b/features/layout/footer/footer-link.module.scss
new file mode 100644
index 0000000..85c7eca
--- /dev/null
+++ b/features/layout/footer/footer-link.module.scss
@@ -0,0 +1,16 @@
+@use "@styles/color";
+@use "@styles/font";
+@use "@styles/space";
+@use "@styles/breakpoint";
+@use "@styles/misc";
+
+.listItem {
+ list-style-type: none;
+ display: inline;
+ margin: 0 space.$s3;
+}
+
+.anchor {
+ text-decoration: none;
+ color: inherit;
+}
diff --git a/features/layout/footer/footer-link.tsx b/features/layout/footer/footer-link.tsx
new file mode 100644
index 0000000..791af01
--- /dev/null
+++ b/features/layout/footer/footer-link.tsx
@@ -0,0 +1,18 @@
+import Link from "next/link";
+import React from "react";
+import styles from "./footer-link.module.scss";
+
+type FooterLinkProps = {
+ text: string;
+ href: string;
+};
+
+export function FooterLink({ text, href }: FooterLinkProps) {
+ return (
+
+
+ {text}
+
+
+ );
+}
diff --git a/features/layout/footer/footer.module.scss b/features/layout/footer/footer.module.scss
new file mode 100644
index 0000000..762101e
--- /dev/null
+++ b/features/layout/footer/footer.module.scss
@@ -0,0 +1,68 @@
+@use "@styles/color";
+@use "@styles/font";
+@use "@styles/space";
+@use "@styles/breakpoint";
+@use "@styles/misc";
+
+.container {
+ display: flex;
+ flex-direction: column;
+ text-align: center;
+ background: color.$gray-50;
+ padding: 0 space.$s6;
+
+ @media (min-width: breakpoint.$desktop) {
+ flex-direction: row;
+ }
+}
+
+.content {
+ align-items: center;
+ display: flex;
+ flex-direction: column;
+
+ @media (min-width: breakpoint.$desktop) {
+ width: 100%;
+ flex-direction: row;
+ justify-content: space-between;
+ }
+}
+
+.linkList {
+ order: 1;
+ margin: space.$s6;
+ padding: 0;
+
+ @media (min-width: breakpoint.$desktop) {
+ order: 2;
+ }
+}
+
+.version {
+ color: color.$gray-400;
+ margin: space.$s6 0;
+ order: 3;
+
+ @media (min-width: breakpoint.$desktop) {
+ order: 1;
+ }
+}
+
+.links {
+ color: color.$gray-500;
+ order: 1;
+
+ @media (min-width: breakpoint.$desktop) {
+ order: 2;
+ }
+}
+
+.logo {
+ padding: 0;
+ margin: 0;
+ order: 2;
+
+ @media (min-width: breakpoint.$desktop) {
+ order: 3;
+ }
+}
diff --git a/features/layout/footer/footer.tsx b/features/layout/footer/footer.tsx
new file mode 100644
index 0000000..46bd367
--- /dev/null
+++ b/features/layout/footer/footer.tsx
@@ -0,0 +1,45 @@
+import { version } from "../../../package.json";
+import { FooterLink } from "./footer-link";
+import styles from "./footer.module.scss";
+
+const footerLinks = [
+ {
+ text: "Docs",
+ href: "#",
+ },
+ {
+ text: "API",
+ href: "#",
+ },
+ {
+ text: "Help",
+ href: "#",
+ },
+ {
+ text: "Community",
+ href: "#",
+ },
+];
+
+export const Footer = () => (
+
+);
diff --git a/features/layout/footer/index.ts b/features/layout/footer/index.ts
new file mode 100644
index 0000000..25eaacd
--- /dev/null
+++ b/features/layout/footer/index.ts
@@ -0,0 +1 @@
+export { Footer } from "./footer";
diff --git a/features/layout/index.ts b/features/layout/index.ts
index 4edac3f..7b38112 100644
--- a/features/layout/index.ts
+++ b/features/layout/index.ts
@@ -1,2 +1,3 @@
export * from "./page-container";
export * from "./sidebar-navigation";
+export * from "./footer";
diff --git a/features/layout/page-container/page-container.tsx b/features/layout/page-container/page-container.tsx
index fd12efc..5f55557 100644
--- a/features/layout/page-container/page-container.tsx
+++ b/features/layout/page-container/page-container.tsx
@@ -1,5 +1,6 @@
import Head from "next/head";
import { SidebarNavigation } from "../sidebar-navigation";
+import { Footer } from "../footer";
import styles from "./page-container.module.scss";
type PageContainerProps = {
@@ -20,13 +21,16 @@ export function PageContainer({ children, title, info }: PageContainerProps) {
-
-
-
{title}
-
{info}
- {children}
-
-
+
+
+
+
{title}
+
{info}
+ {children}
+
+
+
+
);
}