diff --git a/packages/element-tiles/README.md b/packages/element-tiles/README.md new file mode 100644 index 00000000..42117773 --- /dev/null +++ b/packages/element-tiles/README.md @@ -0,0 +1,9 @@ +# @hyperbook/element-tiles + +## Installation + +```sh +yarn add @hyperbook/element-tiles +# or +npm i @hyperbook/element-tiles +``` diff --git a/packages/element-tiles/package.json b/packages/element-tiles/package.json new file mode 100644 index 00000000..e1a41f03 --- /dev/null +++ b/packages/element-tiles/package.json @@ -0,0 +1,51 @@ +{ + "name": "@hyperbook/element-tiles", + "version": "0.0.0", + "author": "Mike Barkmin", + "homepage": "https://github.com/openpatch/hyperbook#readme", + "license": "MIT", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "sideEffects": false, + "exports": { + ".": "./dist/index.js", + "./index.css": "./dist/index.css" + }, + "files": [ + "dist" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/openpatch/hyperbook.git", + "directory": "packages/element-tiles" + }, + "bugs": { + "url": "https://github.com/openpatch/hyperbook/issues" + }, + "scripts": { + "version": "pnpm build", + "lint": "tsc --noEmit", + "build": "rimraf dist && pnpm build:pkg && pnpm build:types", + "build:pkg": "node ../../scripts/build.mjs", + "build:types": "tsc --project tsconfig.build.json --declaration --emitDeclarationOnly" + }, + "dependencies": { + "@hyperbook/provider": "workspace:*", + "@hyperbook/store": "workspace:*" + }, + "peerDependencies": { + "react": "18.x", + "react-dom": "18.x", + "react-redux": "8.x" + }, + "devDependencies": { + "@types/react": "18.0.15", + "@types/react-dom": "18.0.6", + "react": "18.2.0", + "react-dom": "18.2.0", + "vitest": "^0.26.3" + } +} diff --git a/packages/element-tiles/src/index.css b/packages/element-tiles/src/index.css new file mode 100644 index 00000000..e75dcd2d --- /dev/null +++ b/packages/element-tiles/src/index.css @@ -0,0 +1,91 @@ +.hyperbook .tiles { + display: grid; + column-gap: 0.75rem; + row-gap: 0.75rem; + grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr; + margin: 0; + padding: 0; + position: relative; + width: 100%; + list-style-type: none; +} + +.element-tiles .tile.S { + grid-column-start: span 2; +} + +.element-tiles .tile.M { + grid-column-start: span 3; +} + +.element-tiles .tile.L { + grid-column-start: span 4; +} + +@media screen and (max-width: 900px) { + .hyperbook .tiles { + grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr; + } + + .element-tiles .tile.S { + grid-column-start: span 4; + } + + .element-tiles .tile.M { + grid-column-start: span 6; + } + + .element-tiles .tile.L { + grid-column-start: span 8; + } +} + +@media screen and (max-width: 600px) { + .hyperbook .tiles { + grid-template-columns: 1fr 1fr; + } + + .element-tiles .tile.S { + grid-column-start: span 1; + } + + .element-tiles .tile.M { + grid-column-start: span 1; + } + + .element-tiles .tile.L { + grid-column-start: span 1; + } +} + +.element-tiles .tile { + line-height: 1.2em; + min-height: 6rem; + background: var(--color-nav); + transition: all 300ms; + padding: 8px; + position: relative; + border-radius: 8px; +} + +.element-tiles .tile.link:hover { + background: var(--color-brand); + color: var(--color-brand-text); +} + +.element-tiles .tile.link:hover a { + color: var(--color-brand-text); + height: 100%; + display: block; +} + +.element-tiles .tile.link a { + text-decoration: none; +} + +.element-tiles .tile-icon { + position: absolute; + width: 3rem; + bottom: 0.5rem; + right: 0.5rem; +} diff --git a/packages/element-tiles/src/index.tsx b/packages/element-tiles/src/index.tsx new file mode 100644 index 00000000..34bc9095 --- /dev/null +++ b/packages/element-tiles/src/index.tsx @@ -0,0 +1,54 @@ +import { FC, Fragment, ReactNode } from "react"; +import { createSlice } from "@hyperbook/store"; +import "./index.css"; + +type DirectiveTilesProps = { + children?: ReactNode; +}; + +const DirectiveTiles: FC = ({ children }) => { + return ( +
+ +
+ ); +}; + +type DirectiveTileProps = { + size?: "S" | "M" | "L"; + title?: string; + description?: string; + href?: string; + icon?: string; +}; + +const DirectiveTile: FC = ({ + size = "M", + title, + href, + icon, +}) => { + return ( +
  • + + {title} + + {icon && } +
  • + ); +}; + +type ElementTilesState = {}; + +const initialState: ElementTilesState = {}; + +const sliceTiles = createSlice({ + name: "element.tiles", + initialState, + reducers: {}, +}); + +export default { + directives: { tiles: DirectiveTiles, tile: DirectiveTile }, + slice: sliceTiles, +}; diff --git a/packages/element-tiles/tsconfig.build.json b/packages/element-tiles/tsconfig.build.json new file mode 100644 index 00000000..e8415085 --- /dev/null +++ b/packages/element-tiles/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "include": ["src", "../../types"], + "compilerOptions": { + "rootDir": "src", + "declarationDir": "dist" + } +} diff --git a/packages/element-tiles/tsconfig.json b/packages/element-tiles/tsconfig.json new file mode 100644 index 00000000..f068abe3 --- /dev/null +++ b/packages/element-tiles/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.base.json", + "include": ["src", "../../types", "tests"] +} diff --git a/packages/element-tiles/vite.config.ts b/packages/element-tiles/vite.config.ts new file mode 100644 index 00000000..8fb6f2dc --- /dev/null +++ b/packages/element-tiles/vite.config.ts @@ -0,0 +1,3 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({}); diff --git a/platforms/vscode/app/App.tsx b/platforms/vscode/app/App.tsx index f7322d5f..aec9d79e 100644 --- a/platforms/vscode/app/App.tsx +++ b/platforms/vscode/app/App.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useState } from "react"; import { Provider, ProviderProps } from "@hyperbook/provider"; import elementTab from "@hyperbook/element-tabs"; +import elementTiles from "@hyperbook/element-tiles"; import elementAudio from "@hyperbook/element-audio"; import elementAlert from "@hyperbook/element-alert"; import elementBitflow from "@hyperbook/element-bitflow"; @@ -152,6 +153,7 @@ export const App = () => { elementMermaid, elementScratchblock, elementExcalidraw, + elementTiles, ]} loadFile={() => async (path) => { return fetch(path).then((res) => res.text()); diff --git a/platforms/vscode/app/index.scss b/platforms/vscode/app/index.scss index ae42c0d9..77cbf17a 100644 --- a/platforms/vscode/app/index.scss +++ b/platforms/vscode/app/index.scss @@ -5,6 +5,7 @@ @import "@hyperbook/element-excalidraw/index.css"; @import "@hyperbook/element-scratchblock/index.css"; @import "@hyperbook/element-tabs/index.css"; +@import "@hyperbook/element-tiles/index.css"; @import "@hyperbook/element-audio/index.css"; @import "@hyperbook/element-alert/index.css"; @import "@hyperbook/element-term/index.css"; diff --git a/platforms/vscode/package.json b/platforms/vscode/package.json index b047b071..74ac2504 100644 --- a/platforms/vscode/package.json +++ b/platforms/vscode/package.json @@ -199,6 +199,7 @@ "@hyperbook/element-struktog": "workspace:*", "@hyperbook/element-tabs": "workspace:*", "@hyperbook/element-term": "workspace:*", + "@hyperbook/element-tiles": "workspace:*", "@hyperbook/element-youtube": "workspace:*", "@hyperbook/fs": "workspace:*", "@hyperbook/markdown": "workspace:*", diff --git a/platforms/vscode/snipptes/hyperbook.code-snippets b/platforms/vscode/snipptes/hyperbook.code-snippets index f29ce0a3..2018dc8f 100644 --- a/platforms/vscode/snipptes/hyperbook.code-snippets +++ b/platforms/vscode/snipptes/hyperbook.code-snippets @@ -90,6 +90,18 @@ ":::" ] }, + "Element Tiles": { + "prefix": [":tiles"], + "body": [ + ":::tiles", + "", + "::tile{title=\"${1:Tab 1}\" href=\"$RANDOM\"}", + "", + "$0", + "", + ":::" + ] + }, "Element YouTube": { "prefix": [":youtube"], "body": ["::youtube[${1:title}]{#$CLIPBOARD}", "$0"] diff --git a/platforms/web/package.json b/platforms/web/package.json index ce38838e..f8257c9e 100644 --- a/platforms/web/package.json +++ b/platforms/web/package.json @@ -28,6 +28,7 @@ "@hyperbook/element-struktog": "workspace:*", "@hyperbook/element-tabs": "workspace:*", "@hyperbook/element-term": "workspace:*", + "@hyperbook/element-tiles": "workspace:*", "@hyperbook/element-youtube": "workspace:*", "@hyperbook/fs": "workspace:*", "@hyperbook/markdown": "workspace:*", diff --git a/platforms/web/src/pages/_app.tsx b/platforms/web/src/pages/_app.tsx index 843ea5f0..097beff9 100644 --- a/platforms/web/src/pages/_app.tsx +++ b/platforms/web/src/pages/_app.tsx @@ -43,6 +43,8 @@ import elementBitflow from "@hyperbook/element-bitflow"; import "@hyperbook/element-bitflow/index.css"; import elementScratchblock from "@hyperbook/element-scratchblock"; import "@hyperbook/element-scratchblock/index.css"; +import elementTiles from "@hyperbook/element-tiles"; +import "@hyperbook/element-tiles/index.css"; import Link from "next/link"; import Head from "next/head"; import { Styles } from "@hyperbook/styles"; @@ -111,6 +113,7 @@ export default function MyApp({ Component, pageProps }) { elementExcalidraw, elementScratchblock, elementBitflow, + elementTiles, ]} router={router} storage={typeof window !== "undefined" ? localStorage : noopStorage} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 793fe8f4..1775b4fc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -670,6 +670,34 @@ importers: specifier: 18.2.0 version: 18.2.0(react@18.2.0) + packages/element-tiles: + dependencies: + '@hyperbook/provider': + specifier: workspace:* + version: link:../provider + '@hyperbook/store': + specifier: workspace:* + version: link:../store + react-redux: + specifier: 8.x + version: 8.1.0(@types/react-dom@18.0.6)(@types/react@18.0.15)(react-dom@18.2.0)(react@18.2.0) + devDependencies: + '@types/react': + specifier: 18.0.15 + version: 18.0.15 + '@types/react-dom': + specifier: 18.0.6 + version: 18.0.6 + react: + specifier: 18.2.0 + version: 18.2.0 + react-dom: + specifier: 18.2.0 + version: 18.2.0(react@18.2.0) + vitest: + specifier: ^0.26.3 + version: 0.26.3 + packages/element-youtube: dependencies: '@hyperbook/provider': @@ -1266,6 +1294,9 @@ importers: '@hyperbook/element-term': specifier: workspace:* version: link:../../packages/element-term + '@hyperbook/element-tiles': + specifier: workspace:* + version: link:../../packages/element-tiles '@hyperbook/element-youtube': specifier: workspace:* version: link:../../packages/element-youtube @@ -8122,6 +8153,7 @@ packages: /loupe@2.3.6: resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} + deprecated: Please upgrade to 2.3.7 which fixes GHSA-4q6p-r6v2-jvc5 dependencies: get-func-name: 2.0.0 dev: true diff --git a/website/de/book/elements/tiles.md b/website/de/book/elements/tiles.md new file mode 100644 index 00000000..dd9e1c80 --- /dev/null +++ b/website/de/book/elements/tiles.md @@ -0,0 +1,39 @@ +--- +name: Kacheln +lang: de +--- + +# Kacheln + +Kacheln sind eine schöne visuelle Möglichkeit für Startseiten oder +Übersichtsseiten, welche deinen Benutzern helfen sollen sich zurechtzufinden. + +```md +:::tiles + +::tile{title="Hallo"} + +::tile{title="Eine Kachel mit einem Link" href="openpatch.org"} + +::tile{title="Eine große Kachel" size="L"} + +::tile{title="Eine kleine Kachel" size="S"} + +::tile{title="Eine Kachel mit einem Icon" icon="https://www.inf-schule.de/assets/img/icons/icon_algorithmen.png"} + +::: +``` + +:::tiles + +::tile{title="Hallo"} + +::tile{title="Eine Kachel mit einem Link" href="openpatch.org"} + +::tile{title="Eine große Kachel" size="L"} + +::tile{title="Eine kleine Kachel" size="S"} + +::tile{title="Eine Kachel mit einem Icon" icon="https://www.inf-schule.de/assets/img/icons/icon_algorithmen.png"} + +::: diff --git a/website/en/book/elements/tiles.md b/website/en/book/elements/tiles.md new file mode 100644 index 00000000..3821b7ac --- /dev/null +++ b/website/en/book/elements/tiles.md @@ -0,0 +1,38 @@ +--- +name: Tiles +--- + +# Tiles + +Tiles are a nice visual structure for landing pages or hubs, which should give +your users an overview. + +```md +:::tiles + +::tile{title="Hallo"} + +::tile{title="A tile with a link" href="openpatch.org"} + +::tile{title="A large tile" size="L"} + +::tile{title="A small tile" size="S"} + +::tile{title="A icon tile" icon="https://www.inf-schule.de/assets/img/icons/icon_algorithmen.png"} + +::: +``` + +:::tiles + +::tile{title="Hallo"} + +::tile{title="A tile with a link" href="openpatch.org"} + +::tile{title="A large tile" size="L"} + +::tile{title="A small tile" size="S"} + +::tile{title="A icon tile" icon="https://www.inf-schule.de/assets/img/icons/icon_algorithmen.png"} + +:::