Basic navbar, tailwindcss setup, and other stuff
This commit is contained in:
8
web/config/postcss.config.js
Normal file
8
web/config/postcss.config.js
Normal file
@ -0,0 +1,8 @@
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('tailwindcss')(path.resolve(__dirname, 'tailwind.config.js')),
|
||||
require('autoprefixer'),
|
||||
],
|
||||
}
|
19
web/config/tailwind.config.js
Normal file
19
web/config/tailwind.config.js
Normal file
@ -0,0 +1,19 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export const content = ['src/**/*.{js,jsx,ts,tsx}']
|
||||
export const theme = {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
inter: ['Inter', 'sans-serif'],
|
||||
},
|
||||
colors: {
|
||||
logo: {
|
||||
DEFAULT: '#246EB9',
|
||||
hover: '#1f5d9d',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
export const plugins = [require('daisyui')]
|
||||
export const daisyui = {
|
||||
themes: ['light', 'dark'],
|
||||
}
|
@ -11,16 +11,24 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@mdi/js": "^7.3.67",
|
||||
"@mdi/react": "^1.6.1",
|
||||
"@redwoodjs/forms": "6.3.2",
|
||||
"@redwoodjs/router": "6.3.2",
|
||||
"@redwoodjs/web": "6.3.2",
|
||||
"prop-types": "15.8.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"react-dom": "18.2.0",
|
||||
"theme-change": "^2.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@redwoodjs/vite": "6.3.2",
|
||||
"@types/react": "18.2.14",
|
||||
"@types/react-dom": "18.2.6"
|
||||
"@types/react-dom": "18.2.6",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"daisyui": "^3.9.3",
|
||||
"postcss": "^8.4.31",
|
||||
"postcss-loader": "^7.3.3",
|
||||
"tailwindcss": "^3.3.3"
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,16 @@
|
||||
// 'src/pages/HomePage/HomePage.js' -> HomePage
|
||||
// 'src/pages/Admin/BooksPage/BooksPage.js' -> AdminBooksPage
|
||||
|
||||
import { Router, Route } from '@redwoodjs/router'
|
||||
import { Router, Route, Set } from '@redwoodjs/router'
|
||||
|
||||
import NavbarLayout from 'src/layouts/NavbarLayout'
|
||||
|
||||
const Routes = () => {
|
||||
return (
|
||||
<Router>
|
||||
<Set wrap={NavbarLayout}>
|
||||
<Route path="/" page={HomePage} name="home" />
|
||||
</Set>
|
||||
<Route notfound page={NotFoundPage} />
|
||||
</Router>
|
||||
)
|
||||
|
25
web/src/components/ThemeToggle/ThemeToggle.stories.tsx
Normal file
25
web/src/components/ThemeToggle/ThemeToggle.stories.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
// Pass props to your component by passing an `args` object to your story
|
||||
//
|
||||
// ```tsx
|
||||
// export const Primary: Story = {
|
||||
// args: {
|
||||
// propName: propValue
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// See https://storybook.js.org/docs/react/writing-stories/args.
|
||||
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
import ThemeToggle from './ThemeToggle'
|
||||
|
||||
const meta: Meta<typeof ThemeToggle> = {
|
||||
component: ThemeToggle,
|
||||
}
|
||||
|
||||
export default meta
|
||||
|
||||
type Story = StoryObj<typeof ThemeToggle>
|
||||
|
||||
export const Primary: Story = {}
|
14
web/src/components/ThemeToggle/ThemeToggle.test.tsx
Normal file
14
web/src/components/ThemeToggle/ThemeToggle.test.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import { render } from '@redwoodjs/testing/web'
|
||||
|
||||
import ThemeToggle from './ThemeToggle'
|
||||
|
||||
// Improve this test with help from the Redwood Testing Doc:
|
||||
// https://redwoodjs.com/docs/testing#testing-components
|
||||
|
||||
describe('ThemeToggle', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<ThemeToggle />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
36
web/src/components/ThemeToggle/ThemeToggle.tsx
Normal file
36
web/src/components/ThemeToggle/ThemeToggle.tsx
Normal file
@ -0,0 +1,36 @@
|
||||
import { useEffect } from 'react'
|
||||
|
||||
import { mdiWeatherSunny, mdiWeatherNight } from '@mdi/js'
|
||||
import Icon from '@mdi/react'
|
||||
import { themeChange } from 'theme-change'
|
||||
|
||||
const ThemeToggle = () => {
|
||||
let isDark = false
|
||||
|
||||
if (typeof window !== 'undefined')
|
||||
isDark = localStorage.getItem('theme') === 'dark'
|
||||
|
||||
useEffect(() => {
|
||||
themeChange(false)
|
||||
return () => {
|
||||
themeChange(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<label className="btn btn-ghost swap swap-rotate w-12 hover:shadow-lg">
|
||||
<input
|
||||
type="checkbox"
|
||||
defaultChecked={isDark}
|
||||
data-toggle-theme="light,dark"
|
||||
/>
|
||||
<Icon
|
||||
path={mdiWeatherSunny}
|
||||
className="swap-off h-8 w-8 text-yellow-500"
|
||||
/>
|
||||
<Icon path={mdiWeatherNight} className="swap-on h-8 w-8 text-blue-500" />
|
||||
</label>
|
||||
)
|
||||
}
|
||||
|
||||
export default ThemeToggle
|
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* START --- SETUP TAILWINDCSS EDIT
|
||||
*
|
||||
* `yarn rw setup ui tailwindcss` placed these directives here
|
||||
* to inject Tailwind's styles into your CSS.
|
||||
* For more information, see: https://tailwindcss.com/docs/installation
|
||||
*/
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
/**
|
||||
* END --- SETUP TAILWINDCSS EDIT
|
||||
*/
|
||||
|
@ -1,10 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html data-theme="light" lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" type="image/png" href="/favicon.png" />
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&family=Open+Sans:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
13
web/src/layouts/NavbarLayout/NavbarLayout.stories.tsx
Normal file
13
web/src/layouts/NavbarLayout/NavbarLayout.stories.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
import NavbarLayout from './NavbarLayout'
|
||||
|
||||
const meta: Meta<typeof NavbarLayout> = {
|
||||
component: NavbarLayout,
|
||||
}
|
||||
|
||||
export default meta
|
||||
|
||||
type Story = StoryObj<typeof NavbarLayout>
|
||||
|
||||
export const Primary: Story = {}
|
14
web/src/layouts/NavbarLayout/NavbarLayout.test.tsx
Normal file
14
web/src/layouts/NavbarLayout/NavbarLayout.test.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import { render } from '@redwoodjs/testing/web'
|
||||
|
||||
import NavbarLayout from './NavbarLayout'
|
||||
|
||||
// Improve this test with help from the Redwood Testing Doc:
|
||||
// https://redwoodjs.com/docs/testing#testing-pages-layouts
|
||||
|
||||
describe('NavbarLayout', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<NavbarLayout />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
90
web/src/layouts/NavbarLayout/NavbarLayout.tsx
Normal file
90
web/src/layouts/NavbarLayout/NavbarLayout.tsx
Normal file
@ -0,0 +1,90 @@
|
||||
import { mdiChip, mdiMenu } from '@mdi/js'
|
||||
import Icon from '@mdi/react'
|
||||
|
||||
import { Link, routes } from '@redwoodjs/router'
|
||||
|
||||
import ThemeToggle from 'src/components/ThemeToggle/ThemeToggle'
|
||||
|
||||
type NavBarLayoutProps = {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
const NavBarLayout = ({ children }: NavBarLayoutProps) => {
|
||||
return (
|
||||
<>
|
||||
<div className="navbar bg-base-100 shadow-lg">
|
||||
<div className="justify-start space-x-3">
|
||||
<Icon path={mdiChip} className="ml-3 h-10 text-logo" />
|
||||
<Link
|
||||
to={routes.home()}
|
||||
className="btn btn-ghost items-center hover:shadow-lg"
|
||||
>
|
||||
<p className="font-inter text-xl normal-case tracking-tight">
|
||||
Parts Inventory
|
||||
</p>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="ml-auto justify-end space-x-3">
|
||||
{/* <ul className="relative hidden items-center space-x-3 lg:flex">
|
||||
<li>
|
||||
<Link
|
||||
to={routes.faq()}
|
||||
className="btn btn-ghost font-inter hover:shadow-lg"
|
||||
>
|
||||
FAQ
|
||||
</Link>
|
||||
</li>
|
||||
</ul> */}
|
||||
<ThemeToggle />
|
||||
<div className="lg:hidden">
|
||||
<input
|
||||
id="mobile-menu-drawer"
|
||||
type="checkbox"
|
||||
className="drawer-toggle"
|
||||
defaultChecked={false}
|
||||
/>
|
||||
<div className="drawer-content">
|
||||
<label
|
||||
htmlFor="mobile-menu-drawer"
|
||||
className="btn btn-ghost drawer-button hover:shadow-lg"
|
||||
>
|
||||
<Icon path={mdiMenu} className="h-8 w-8" />
|
||||
</label>
|
||||
</div>
|
||||
<div className="drawer-side z-50">
|
||||
<label htmlFor="mobile-menu-drawer" className="drawer-overlay">
|
||||
<br />
|
||||
</label>
|
||||
<ul className="min-h-full w-80 space-y-3 bg-base-100 p-3 text-base-content shadow-lg">
|
||||
<li>
|
||||
<div className="flex justify-center space-x-3">
|
||||
<Icon path={mdiChip} className="ml-3 h-10 text-logo" />
|
||||
<Link
|
||||
to={routes.home()}
|
||||
className="btn btn-ghost items-center hover:shadow-lg"
|
||||
>
|
||||
<p className="font-inter text-xl normal-case tracking-tight">
|
||||
Parts Inventory
|
||||
</p>
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
{/* <li>
|
||||
<Link
|
||||
to={routes.faq()}
|
||||
className="btn btn-ghost w-full hover:shadow-lg"
|
||||
>
|
||||
<p className="font-inter text-base">FAQ</p>
|
||||
</Link>
|
||||
</li> */}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<main className="m-3">{children}</main>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default NavBarLayout
|
13
web/src/pages/HomePage/HomePage.stories.tsx
Normal file
13
web/src/pages/HomePage/HomePage.stories.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
import HomePage from './HomePage'
|
||||
|
||||
const meta: Meta<typeof HomePage> = {
|
||||
component: HomePage,
|
||||
}
|
||||
|
||||
export default meta
|
||||
|
||||
type Story = StoryObj<typeof HomePage>
|
||||
|
||||
export const Primary: Story = {}
|
14
web/src/pages/HomePage/HomePage.test.tsx
Normal file
14
web/src/pages/HomePage/HomePage.test.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import { render } from '@redwoodjs/testing/web'
|
||||
|
||||
import HomePage from './HomePage'
|
||||
|
||||
// Improve this test with help from the Redwood Testing Doc:
|
||||
// https://redwoodjs.com/docs/testing#testing-pages-layouts
|
||||
|
||||
describe('HomePage', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<HomePage />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
21
web/src/pages/HomePage/HomePage.tsx
Normal file
21
web/src/pages/HomePage/HomePage.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
import { Link, routes } from '@redwoodjs/router'
|
||||
import { MetaTags } from '@redwoodjs/web'
|
||||
|
||||
const HomePage = () => {
|
||||
return (
|
||||
<>
|
||||
<MetaTags title="Home" description="Home page" />
|
||||
|
||||
<h1>HomePage</h1>
|
||||
<p>
|
||||
Find me in <code>./web/src/pages/HomePage/HomePage.tsx</code>
|
||||
</p>
|
||||
<p>
|
||||
My default route is named <code>home</code>, link to me with `
|
||||
<Link to={routes.home()}>Home</Link>`
|
||||
</p>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default HomePage
|
Reference in New Issue
Block a user