Migrate the footer component.
parent
794b3bcbdd
commit
57eeeafb7a
|
@ -3,3 +3,48 @@
|
|||
@import "tailwindcss/utilities";
|
||||
|
||||
/* This file is for your main application CSS */
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
touch-action: manipulation;
|
||||
font-feature-settings: 'case' 1, 'rlig' 1, 'calt' 0;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Helvetica Neue',
|
||||
'Helvetica', sans-serif;
|
||||
text-rendering: optimizeLegibility;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
@apply text-white bg-white antialiased;
|
||||
}
|
||||
|
||||
body {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.animated {
|
||||
-webkit-animation-duration: 1s;
|
||||
animation-duration: 1s;
|
||||
-webkit-animation-duration: 1s;
|
||||
animation-duration: 1s;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.height-screen-helper {
|
||||
height: calc(100vh - 80px);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import * as React from 'react'
|
||||
import * as React from "react";
|
||||
import { Footer } from "./components/Footer";
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<div>
|
||||
Hello React!
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import * as React from "react";
|
||||
import clsx from "clsx";
|
||||
|
||||
type ContainerProps<T extends React.ElementType> = {
|
||||
as?: T;
|
||||
className?: string;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
export function Container<T extends React.ElementType = "div">({
|
||||
as,
|
||||
className,
|
||||
children,
|
||||
}: Omit<React.ComponentPropsWithoutRef<T>, keyof ContainerProps<T>> &
|
||||
ContainerProps<T>) {
|
||||
let Component = as ?? "div";
|
||||
|
||||
return (
|
||||
<Component className={clsx("mx-auto max-w-7xl px-6 lg:px-8", className)}>
|
||||
<div className="mx-auto max-w-2xl lg:max-w-none">{children}</div>
|
||||
</Component>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { Container } from "./Container";
|
||||
import { Logo } from "./Logo";
|
||||
|
||||
const navigation = [
|
||||
{
|
||||
title: "Students",
|
||||
links: [{ title: "Find a Coach", href: "/c/" }],
|
||||
},
|
||||
{
|
||||
title: "Company",
|
||||
links: [
|
||||
{ title: "About Us", href: "/about/" },
|
||||
{ title: "Contact Us", href: "/contact/" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
function Navigation() {
|
||||
return (
|
||||
<nav>
|
||||
<ul role="list" className="grid grid-cols-2 gap-8 sm:grid-cols-3">
|
||||
{navigation.map((section, sectionIndex) => (
|
||||
<li key={sectionIndex}>
|
||||
<div className="font-display text-sm font-semibold tracking-wider text-neutral-950">
|
||||
{section.title}
|
||||
</div>
|
||||
<ul role="list" className="mt-4 text-sm text-neutral-700">
|
||||
{section.links.map((link, linkIndex) => (
|
||||
<li key={linkIndex} className="mt-4">
|
||||
<a
|
||||
href={link.href}
|
||||
className="transition hover:text-neutral-950"
|
||||
>
|
||||
{link.title}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
export function Footer() {
|
||||
return (
|
||||
<Container as="footer" className="mt-16 w-full sm:mt-24 lg:mt-28">
|
||||
<div className="grid grid-cols-1 gap-x-8 gap-y-16 lg:grid-cols-2">
|
||||
<Navigation />
|
||||
</div>
|
||||
<div className="mb-12 mt-16 flex flex-wrap items-end justify-between gap-x-6 gap-y-4 border-t border-neutral-950/10 pt-12">
|
||||
<a href="/" aria-label="Home">
|
||||
<Logo className="h-8" />
|
||||
</a>
|
||||
<p className="text-sm text-neutral-700">
|
||||
© BoardWise LLC {new Date().getFullYear()}
|
||||
</p>
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import * as React from "react";
|
||||
import clsx from "clsx";
|
||||
|
||||
import LogoMark from "../icons/Logomark";
|
||||
|
||||
export function Logo({
|
||||
invert = false,
|
||||
}: React.ComponentPropsWithoutRef<"svg"> & { invert?: boolean }) {
|
||||
return (
|
||||
<div className="mr-4 flex flex-nowrap items-center justify-start">
|
||||
<LogoMark
|
||||
className="mr-4 duration-500 ease-in-out hover:rotate-180"
|
||||
invert={invert}
|
||||
/>
|
||||
<p
|
||||
className={clsx(
|
||||
"font-display text-xl font-bold tracking-tight",
|
||||
invert ? "text-white" : "text-neutral-950",
|
||||
)}
|
||||
>
|
||||
BoardWise
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
import * as React from "react";
|
||||
|
||||
const SvgComponent = ({ invert = false, size = 25, ...props }) => {
|
||||
const color = invert ? "rgb(255, 255, 255)" : "rgb(10 10 10)";
|
||||
const radius = 5;
|
||||
const roundedTopRightPath = `
|
||||
M ${size / 2} 0
|
||||
H ${size - radius}
|
||||
Q ${size} 0, ${size} ${radius}
|
||||
V ${size / 2}
|
||||
H ${size / 2}
|
||||
Z`;
|
||||
const roundedBottomLeftPath = `
|
||||
M 0 ${size - radius}
|
||||
Q 0 ${size}, ${radius} ${size}
|
||||
H ${size / 2}
|
||||
V ${size / 2}
|
||||
H 0
|
||||
Z`;
|
||||
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={size}
|
||||
height={size}
|
||||
{...props}
|
||||
>
|
||||
<path d={roundedTopRightPath} fill={color} />
|
||||
<path d={roundedBottomLeftPath} fill={color} />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
export default SvgComponent;
|
|
@ -4,6 +4,15 @@
|
|||
|
||||
let
|
||||
sources = {
|
||||
"clsx-2.0.0" = {
|
||||
name = "clsx";
|
||||
packageName = "clsx";
|
||||
version = "2.0.0";
|
||||
src = fetchurl {
|
||||
url = "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz";
|
||||
sha512 = "rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==";
|
||||
};
|
||||
};
|
||||
"js-tokens-4.0.0" = {
|
||||
name = "js-tokens";
|
||||
packageName = "js-tokens";
|
||||
|
@ -56,6 +65,7 @@ let
|
|||
version = "0.1.0";
|
||||
src = ./.;
|
||||
dependencies = [
|
||||
sources."clsx-2.0.0"
|
||||
sources."js-tokens-4.0.0"
|
||||
sources."loose-envify-1.4.0"
|
||||
sources."react-18.2.0"
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"name": "boardwise",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"clsx": "^2.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
|
@ -72,6 +73,14 @@
|
|||
"integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/clsx": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
|
||||
"integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
|
||||
|
@ -172,6 +181,11 @@
|
|||
"integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
|
||||
"dev": true
|
||||
},
|
||||
"clsx": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
|
||||
"integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q=="
|
||||
},
|
||||
"csstype": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
"name": "boardwise",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"clsx": "^2.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
"compilerOptions": {
|
||||
// Keep in mind that ES6+ syntax to ES5 is not supported in esbuild yet.
|
||||
"target": "es2016",
|
||||
// https://www.typescriptlang.org/docs/handbook/modules/theory.html
|
||||
"module": "nodenext",
|
||||
// Even when transpiling a single module, the TypeScript compiler actually
|
||||
// parses imported files so it can tell whether an imported name is a type
|
||||
// or a value. However, tools like esbuild compile each file in isolation so
|
||||
|
@ -25,6 +27,6 @@
|
|||
// calls. It seems like the "react" value mirrors esbuild's native
|
||||
// "transform" option, but it isn't obvious how these two relate from the
|
||||
// documentation: https://esbuild.github.io/api/#jsx.
|
||||
"jsx": "react"
|
||||
"jsx": "react",
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ config :boardwise, BoardWise.Mailer, adapter: Swoosh.Adapters.Local
|
|||
# specified in this command (e.g. `useDefineForClassFields` as explained in
|
||||
# https://esbuild.github.io/content-types/#tsconfig-json).
|
||||
config :esbuild,
|
||||
version: "0.17.11",
|
||||
version: "0.19.7",
|
||||
default: [
|
||||
args: ~w(
|
||||
./js/app.js
|
||||
|
@ -65,7 +65,7 @@ config :esbuild,
|
|||
|
||||
# Configure tailwind (the version is required)
|
||||
config :tailwind,
|
||||
version: "3.3.2",
|
||||
version: "3.3.5",
|
||||
default: [
|
||||
args: ~w(
|
||||
--config=tailwind.config.js
|
||||
|
|
Loading…
Reference in New Issue