diff --git a/examples/blog-preview-card/.gitignore b/examples/blog-preview-card/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/examples/blog-preview-card/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/examples/blog-preview-card/.npmrc b/examples/blog-preview-card/.npmrc new file mode 100644 index 00000000..6b5f38e8 --- /dev/null +++ b/examples/blog-preview-card/.npmrc @@ -0,0 +1,2 @@ +save-exact = true +package-lock = false diff --git a/examples/blog-preview-card/README.md b/examples/blog-preview-card/README.md new file mode 100644 index 00000000..1006b3f1 --- /dev/null +++ b/examples/blog-preview-card/README.md @@ -0,0 +1,23 @@ +# Frontend Mentor Blog Preview Card + +Here is the implementation in [Bau.js](https://github.com/grucloud/bau) of the [Frontend Mentor Blog Preview Card code challenge](https://www.frontendmentor.io/challenges/blog-preview-card-ckPaj01IcS) + +## Workflow + +Install the dependencies: + +```sh +npm install +``` + +Start a development server: + +```sh +npm run dev +``` + +Build a production version: + +```sh +npm run build +``` diff --git a/examples/blog-preview-card/index.html b/examples/blog-preview-card/index.html new file mode 100644 index 00000000..cf6a300f --- /dev/null +++ b/examples/blog-preview-card/index.html @@ -0,0 +1,17 @@ + + + + + + + Blog Preview Card | FrontendMentor + + +
+ + + diff --git a/examples/blog-preview-card/package.json b/examples/blog-preview-card/package.json new file mode 100644 index 00000000..eb1d289d --- /dev/null +++ b/examples/blog-preview-card/package.json @@ -0,0 +1,20 @@ +{ + "name": "frontendmentor-blog-preview-card", + "private": true, + "version": "0.85.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "devDependencies": { + "typescript": "^5.0.2", + "vite": "^5.2.11" + }, + "dependencies": { + "@grucloud/bau": "^0.85.0", + "@grucloud/bau-css": "^0.85.0", + "@grucloud/bau-ui": "^0.85.0" + } +} diff --git a/examples/blog-preview-card/public/assets/images/favicon-32x32.png b/examples/blog-preview-card/public/assets/images/favicon-32x32.png new file mode 100644 index 00000000..1e2df7f0 Binary files /dev/null and b/examples/blog-preview-card/public/assets/images/favicon-32x32.png differ diff --git a/examples/blog-preview-card/public/assets/images/illustration-article.svg b/examples/blog-preview-card/public/assets/images/illustration-article.svg new file mode 100644 index 00000000..90d8761f --- /dev/null +++ b/examples/blog-preview-card/public/assets/images/illustration-article.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/blog-preview-card/public/assets/images/image-avatar.webp b/examples/blog-preview-card/public/assets/images/image-avatar.webp new file mode 100644 index 00000000..eb276a74 Binary files /dev/null and b/examples/blog-preview-card/public/assets/images/image-avatar.webp differ diff --git a/examples/blog-preview-card/src/blogPreviewCard.ts b/examples/blog-preview-card/src/blogPreviewCard.ts new file mode 100644 index 00000000..cd49e339 --- /dev/null +++ b/examples/blog-preview-card/src/blogPreviewCard.ts @@ -0,0 +1,67 @@ +import { type Context } from "@grucloud/bau-ui/context"; + +export default function (context: Context) { + const { bau, css } = context; + const { h1, h3, div, p, article, img, figure, figcaption, span } = bau.tags; + + const className = css` + border: 1px solid var(--Black); + max-width: 400px; + margin: auto; + display: flex; + flex-direction: column; + gap: 0.6rem; + border-radius: 0.6rem; + background-color: var(--White); + padding: 1rem; + box-shadow: 10px 10px; + img { + border-radius: 0.6rem; + } + .badge { + background-color: var(--Yellow); + padding: 0.4rem; + border-radius: 0.3rem; + font-size: smaller; + font-weight: bolder; + } + .published-time { + font-size: 0.8rem; + font-weight: 500; + color: var(--Grey); + } + figure { + display: inline-flex; + align-items: center; + gap: 1rem; + img { + width: 36px; + } + h3 { + font-size: 1rem; + font-weight: bold; + } + } + `; + + return function myComponent() { + return article( + { class: className }, + img({ src: "./assets/images/illustration-article.svg" }), + div(span({ class: "badge" }, "Learning")), + div({ class: "published-time" }, "Published 21 Dec 2023"), + h1("HTML & CSS foundations"), + p( + "These languages are the backbone of every website, defining structure, content, and presentation." + ), + figure( + img({ + class: "profile-picture", + src: "./assets/images/image-avatar.webp", + alt: "Greg Hooper", + }), + figcaption(h3("Greg Hooper")) + ) + ); + }; +} diff --git a/examples/blog-preview-card/src/main.ts b/examples/blog-preview-card/src/main.ts new file mode 100644 index 00000000..47a2f86b --- /dev/null +++ b/examples/blog-preview-card/src/main.ts @@ -0,0 +1,20 @@ +import { createContext, type Context } from "@grucloud/bau-ui/context"; +import blogPreviewCard from "./blogPreviewCard"; + +import "./style.css"; + +const context = createContext(); + +const app = (context: Context) => { + const { bau } = context; + const { main } = bau.tags; + + const BlogPreviewCard = blogPreviewCard(context); + + return function () { + return main(BlogPreviewCard()); + }; +}; + +const App = app(context); +document.getElementById("app")?.replaceChildren(App()); diff --git a/examples/blog-preview-card/src/style.css b/examples/blog-preview-card/src/style.css new file mode 100644 index 00000000..a6c0f069 --- /dev/null +++ b/examples/blog-preview-card/src/style.css @@ -0,0 +1,24 @@ +@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400..700&display=swap"); + +* { + margin: 0; + box-sizing: border-box; +} + +:root { + --Yellow: hsl(47, 88%, 63%); + --White: hsl(0, 0%, 100%); + --Grey: hsl(0, 0%, 50%); + --Black: hsl(0, 0%, 7%); +} + +body { + font-family: "Inter", sans-serif; + min-height: 100vh; + display: grid; + place-items: center; + background-color: var(--Yellow); + + @media (max-width: 600px) { + } +} diff --git a/examples/blog-preview-card/src/vite-env.d.ts b/examples/blog-preview-card/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/examples/blog-preview-card/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/blog-preview-card/tsconfig.json b/examples/blog-preview-card/tsconfig.json new file mode 100644 index 00000000..75abdef2 --- /dev/null +++ b/examples/blog-preview-card/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/examples/blog-preview-card/vite.config.js b/examples/blog-preview-card/vite.config.js new file mode 100644 index 00000000..41713bec --- /dev/null +++ b/examples/blog-preview-card/vite.config.js @@ -0,0 +1,9 @@ +import { defineConfig } from "vite"; + +export default defineConfig(({ command, mode, ssrBuild }) => { + return { + server: { + open: true, + }, + }; +});