├── deploy ├── vite.config.main.js └── vite.config.gh-pages.js ├── images ├── gphg.png ├── favicon.ico ├── favicon-16x16.png ├── favicon-32x32.png ├── apple-touch-icon.png ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── github-profile-header-generator-demo.webm ├── github-profile-header-generator-demo-poster.png ├── icons │ ├── center-align.svg │ ├── left-align.svg │ └── right-align.svg ├── gphg.svg ├── github-logo-40.svg └── github-logo-20.svg ├── social ├── social-preview.png ├── examples │ ├── example-1.png │ ├── example-2.png │ ├── example-3.png │ ├── example-4.png │ └── example-5.png ├── repo-header-image.png └── social-preview-small.png ├── public ├── images │ ├── decorations │ │ ├── js.png │ │ ├── apple.png │ │ ├── code.png │ │ ├── css.png │ │ ├── dino.png │ │ ├── html.png │ │ ├── idea.png │ │ ├── tabs.png │ │ ├── coding.png │ │ ├── octocat.png │ │ ├── rocket.png │ │ ├── dev-badge.png │ │ ├── dev-white.png │ │ ├── my-octocat.png │ │ ├── terminal.png │ │ ├── binary-code.png │ │ ├── dev-rainbow.png │ │ ├── dino-border.png │ │ ├── github-mark.png │ │ ├── programming.png │ │ ├── apple-thumbnail.png │ │ ├── code-thumbnail.png │ │ ├── coding-screen.png │ │ ├── idea-thumbnail.png │ │ ├── tabs-thumbnail.png │ │ ├── terminal-circle.png │ │ ├── coding-thumbnail.png │ │ ├── headphones-cat-1.png │ │ ├── headphones-cat-2.png │ │ ├── octocat-thumbnail.png │ │ ├── rocket-thumbnail.png │ │ ├── dev-badge-thumbnail.png │ │ ├── dev-white-thumbnail.png │ │ ├── my-octocat-thumbnail.png │ │ ├── terminal-thumbnail.png │ │ ├── binary-code-thumbnail.png │ │ ├── dev-rainbow-thumbnail.png │ │ ├── github-mark-thumbnail.png │ │ ├── programming-thumbnail.png │ │ ├── coding-screen-thumbnail.png │ │ └── terminal-circle-thumbnail.png │ ├── icons │ │ ├── loading.gif │ │ ├── info.svg │ │ ├── close.svg │ │ ├── product-hunt.svg │ │ ├── heart.svg │ │ ├── heart-circle.svg │ │ ├── moon.svg │ │ ├── light-dark.svg │ │ ├── light-dark-black.svg │ │ ├── download.svg │ │ ├── download-black.svg │ │ ├── sun.svg │ │ ├── random.svg │ │ ├── random-black.svg │ │ ├── reset.svg │ │ └── reset-black.svg │ ├── theme-previews │ │ ├── theme-0-preview.png │ │ ├── theme-1-preview.png │ │ ├── theme-10-preview.png │ │ ├── theme-11-preview.png │ │ ├── theme-12-preview.png │ │ ├── theme-13-preview.png │ │ ├── theme-14-preview.png │ │ ├── theme-15-preview.png │ │ ├── theme-16-preview.png │ │ ├── theme-17-preview.png │ │ ├── theme-18-preview.png │ │ ├── theme-19-preview.png │ │ ├── theme-2-preview.png │ │ ├── theme-20-preview.png │ │ ├── theme-21-preview.png │ │ ├── theme-22-preview.png │ │ ├── theme-23-preview.png │ │ ├── theme-3-preview.png │ │ ├── theme-4-preview.png │ │ ├── theme-5-preview.png │ │ ├── theme-6-preview.png │ │ ├── theme-7-preview.png │ │ ├── theme-8-preview.png │ │ └── theme-9-preview.png │ └── patterns │ │ ├── honeycomb-thumbnail.svg │ │ ├── 4-point-stars-thumbnail.svg │ │ ├── aztec-thumbnail.svg │ │ ├── falling-triangles-thumbnail.svg │ │ ├── overlapping-circles-thumbnail.svg │ │ ├── squares-thumbnail.svg │ │ ├── random-shapes-thumbnail.svg │ │ ├── bubbles-thumbnail.svg │ │ ├── squares-in-squares-thumbnail.svg │ │ ├── bathroom-floor-thumbnail.svg │ │ ├── brick-wall-thumbnail.svg │ │ ├── temple-thumbnail.svg │ │ ├── leaf-thumbnail.svg │ │ ├── hideout-thumbnail.svg │ │ ├── github-thumbnail.svg │ │ ├── graph-paper-thumbnail.svg │ │ ├── dalmatian-spots-thumbnail.svg │ │ ├── jigsaw-thumbnail.svg │ │ ├── lisbon-thumbnail.svg │ │ ├── glamorous-thumbnail.svg │ │ ├── circuit-board-thumbnail.svg │ │ └── endless-constellation-thumbnail.svg ├── robots.txt ├── sitemap.xml └── site.webmanifest ├── styles ├── index.scss ├── reset.scss ├── how-to.scss ├── toolbox-presets.scss ├── variables.scss ├── modals.scss ├── toolbox-decorations.scss ├── tabs.scss ├── toolbox-background.scss ├── toolbox-test-fonts.scss └── toolbox-main.scss ├── vite.config.js ├── Dockerfile ├── .gitignore ├── docker-compose.yml ├── .github ├── SECURITY.md ├── pull_request_template.md ├── ISSUE_TEMPLATE │ └── bug_report.md ├── workflows │ └── gh-pages.yml ├── CONTRIBUTING.md └── CODE_OF_CONDUCT.md ├── conf └── default.conf ├── partials ├── toolbox │ ├── presets.html │ ├── result.html │ ├── test-fonts.html │ └── decorations.html ├── scripts.html ├── header.html ├── modals │ ├── feedback.html │ ├── special-message.html │ └── info.html ├── how-to.html ├── footer.html └── head.html ├── js ├── presets.js ├── helpers │ ├── helpers.js │ └── elements.js ├── toolbox-presets.js ├── toolbox-decorations.js ├── toolbox-background.js ├── toolbox-main.js └── main.js ├── package.json ├── LICENSE ├── index.html └── README.md /deploy/vite.config.main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | build: { 3 | emptyOutDir: true 4 | } 5 | } -------------------------------------------------------------------------------- /images/gphg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/images/gphg.png -------------------------------------------------------------------------------- /images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/images/favicon.ico -------------------------------------------------------------------------------- /images/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/images/favicon-16x16.png -------------------------------------------------------------------------------- /images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/images/favicon-32x32.png -------------------------------------------------------------------------------- /social/social-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/social/social-preview.png -------------------------------------------------------------------------------- /images/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/images/apple-touch-icon.png -------------------------------------------------------------------------------- /social/examples/example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/social/examples/example-1.png -------------------------------------------------------------------------------- /social/examples/example-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/social/examples/example-2.png -------------------------------------------------------------------------------- /social/examples/example-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/social/examples/example-3.png -------------------------------------------------------------------------------- /social/examples/example-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/social/examples/example-4.png -------------------------------------------------------------------------------- /social/examples/example-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/social/examples/example-5.png -------------------------------------------------------------------------------- /social/repo-header-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/social/repo-header-image.png -------------------------------------------------------------------------------- /public/images/decorations/js.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/js.png -------------------------------------------------------------------------------- /public/images/icons/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/icons/loading.gif -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-Agent: * 2 | Allow: / 3 | 4 | Sitemap: https://leviarista.github.io/github-profile-header-generator/sitemap.xml 5 | -------------------------------------------------------------------------------- /social/social-preview-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/social/social-preview-small.png -------------------------------------------------------------------------------- /images/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/images/android-chrome-192x192.png -------------------------------------------------------------------------------- /images/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/images/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/images/decorations/apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/apple.png -------------------------------------------------------------------------------- /public/images/decorations/code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/code.png -------------------------------------------------------------------------------- /public/images/decorations/css.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/css.png -------------------------------------------------------------------------------- /public/images/decorations/dino.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/dino.png -------------------------------------------------------------------------------- /public/images/decorations/html.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/html.png -------------------------------------------------------------------------------- /public/images/decorations/idea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/idea.png -------------------------------------------------------------------------------- /public/images/decorations/tabs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/tabs.png -------------------------------------------------------------------------------- /public/images/decorations/coding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/coding.png -------------------------------------------------------------------------------- /public/images/decorations/octocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/octocat.png -------------------------------------------------------------------------------- /public/images/decorations/rocket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/rocket.png -------------------------------------------------------------------------------- /public/images/decorations/dev-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/dev-badge.png -------------------------------------------------------------------------------- /public/images/decorations/dev-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/dev-white.png -------------------------------------------------------------------------------- /public/images/decorations/my-octocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/my-octocat.png -------------------------------------------------------------------------------- /public/images/decorations/terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/terminal.png -------------------------------------------------------------------------------- /public/images/decorations/binary-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/binary-code.png -------------------------------------------------------------------------------- /public/images/decorations/dev-rainbow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/dev-rainbow.png -------------------------------------------------------------------------------- /public/images/decorations/dino-border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/dino-border.png -------------------------------------------------------------------------------- /public/images/decorations/github-mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/github-mark.png -------------------------------------------------------------------------------- /public/images/decorations/programming.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/programming.png -------------------------------------------------------------------------------- /public/images/decorations/apple-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/apple-thumbnail.png -------------------------------------------------------------------------------- /public/images/decorations/code-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/code-thumbnail.png -------------------------------------------------------------------------------- /public/images/decorations/coding-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/coding-screen.png -------------------------------------------------------------------------------- /public/images/decorations/idea-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/idea-thumbnail.png -------------------------------------------------------------------------------- /public/images/decorations/tabs-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/tabs-thumbnail.png -------------------------------------------------------------------------------- /public/images/decorations/terminal-circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/terminal-circle.png -------------------------------------------------------------------------------- /public/images/decorations/coding-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/coding-thumbnail.png -------------------------------------------------------------------------------- /public/images/decorations/headphones-cat-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/headphones-cat-1.png -------------------------------------------------------------------------------- /public/images/decorations/headphones-cat-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/headphones-cat-2.png -------------------------------------------------------------------------------- /public/images/decorations/octocat-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/octocat-thumbnail.png -------------------------------------------------------------------------------- /public/images/decorations/rocket-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/rocket-thumbnail.png -------------------------------------------------------------------------------- /images/github-profile-header-generator-demo.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/images/github-profile-header-generator-demo.webm -------------------------------------------------------------------------------- /public/images/decorations/dev-badge-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/dev-badge-thumbnail.png -------------------------------------------------------------------------------- /public/images/decorations/dev-white-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/dev-white-thumbnail.png -------------------------------------------------------------------------------- /public/images/decorations/my-octocat-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/my-octocat-thumbnail.png -------------------------------------------------------------------------------- /public/images/decorations/terminal-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/terminal-thumbnail.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-0-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-0-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-1-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-1-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-10-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-10-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-11-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-11-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-12-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-12-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-13-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-13-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-14-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-14-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-15-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-15-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-16-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-16-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-17-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-17-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-18-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-18-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-19-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-19-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-2-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-2-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-20-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-20-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-21-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-21-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-22-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-22-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-23-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-23-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-3-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-3-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-4-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-4-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-5-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-5-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-6-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-6-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-7-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-7-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-8-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-8-preview.png -------------------------------------------------------------------------------- /public/images/theme-previews/theme-9-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/theme-previews/theme-9-preview.png -------------------------------------------------------------------------------- /public/images/decorations/binary-code-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/binary-code-thumbnail.png -------------------------------------------------------------------------------- /public/images/decorations/dev-rainbow-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/dev-rainbow-thumbnail.png -------------------------------------------------------------------------------- /public/images/decorations/github-mark-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/github-mark-thumbnail.png -------------------------------------------------------------------------------- /public/images/decorations/programming-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/programming-thumbnail.png -------------------------------------------------------------------------------- /images/github-profile-header-generator-demo-poster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/images/github-profile-header-generator-demo-poster.png -------------------------------------------------------------------------------- /public/images/decorations/coding-screen-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/coding-screen-thumbnail.png -------------------------------------------------------------------------------- /public/images/decorations/terminal-circle-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leviarista/github-profile-header-generator/HEAD/public/images/decorations/terminal-circle-thumbnail.png -------------------------------------------------------------------------------- /images/icons/center-align.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /images/icons/left-align.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /images/icons/right-align.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /public/images/icons/info.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/index.scss: -------------------------------------------------------------------------------- 1 | @use "reset"; 2 | @use "variables"; 3 | @use "main"; 4 | @use "how-to"; 5 | @use "toolbox-presets"; 6 | @use "toolbox-main"; 7 | @use "toolbox-background"; 8 | @use "toolbox-decorations"; 9 | @use "toolbox-test-fonts"; 10 | @use "tabs"; 11 | @use "modals"; -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import injectHTML from 'vite-plugin-html-inject'; 3 | 4 | export default defineConfig({ 5 | build: { 6 | emptyOutDir: true 7 | }, 8 | plugins: [ 9 | injectHTML(), 10 | ], 11 | }); 12 | -------------------------------------------------------------------------------- /public/images/icons/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /deploy/vite.config.gh-pages.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import injectHTML from 'vite-plugin-html-inject'; 3 | 4 | export default defineConfig({ 5 | base: '/github-profile-header-generator/', 6 | build: { 7 | emptyOutDir: true 8 | }, 9 | plugins: [ 10 | injectHTML(), 11 | ], 12 | }); 13 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Build 2 | FROM node:20-alpine AS build 3 | 4 | WORKDIR /usr/src/app 5 | 6 | COPY package.json package-lock.json ./ 7 | 8 | RUN npm install 9 | 10 | COPY . . 11 | 12 | RUN npm run build 13 | 14 | # Setup nginx 15 | FROM nginx:1.21.6-alpine 16 | COPY conf/default.conf /etc/nginx/conf.d/ 17 | COPY --from=build /usr/src/app/dist /usr/share/nginx/html 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | web: 5 | build: 6 | dockerfile: Dockerfile 7 | context: . 8 | image: github-profile-header-generator:latest 9 | container_name: github-profile-header-generator 10 | ports: 11 | - 8008:80 12 | restart: always 13 | mem_limit: 256m 14 | logging: 15 | options: 16 | "max-size": 2048m 17 | 18 | -------------------------------------------------------------------------------- /public/images/patterns/honeycomb-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | 2.0.0 | :white_check_mark: | 8 | | < 2.0.0 | :x: | 9 | 10 | ## Reporting a Vulnerability 11 | 12 | Please create a new issue with all the information you can share and assign it to me @leviarista 13 | 14 | Thanks for contributing to the project's security. I appreciate it. 15 | -------------------------------------------------------------------------------- /public/images/icons/product-hunt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/images/icons/heart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/images/patterns/4-point-stars-thumbnail.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/images/icons/heart-circle.svg: -------------------------------------------------------------------------------- 1 | ionicons-v5-f -------------------------------------------------------------------------------- /styles/reset.scss: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | font-size: 14px; 4 | } 5 | 6 | * { 7 | border: none; 8 | } 9 | 10 | *, 11 | *:before, 12 | *:after { 13 | box-sizing: inherit; 14 | } 15 | 16 | body, 17 | h1, 18 | h2, 19 | h3, 20 | h4, 21 | h5, 22 | h6, 23 | p, 24 | ol, 25 | ul { 26 | margin: 0; 27 | padding: 0; 28 | font-weight: normal; 29 | } 30 | 31 | html, body { 32 | min-height: 100%; 33 | height: 100%; 34 | } 35 | @media (max-width: 768px) { 36 | body { 37 | height: auto; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /public/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | https://leviarista.github.io/github-profile-header-generator/ 12 | 2025-10-27T02:50:07+00:00 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /public/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Github Profile Header Generator", 3 | "short_name": "A simple but nice header image generator for your Github profile", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } -------------------------------------------------------------------------------- /public/images/patterns/aztec-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | -------------------------------------------------------------------------------- /conf/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | sendfile on; 4 | default_type application/octet-stream; 5 | gzip on; 6 | gzip_http_version 1.1; 7 | gzip_disable "MSIE [1-6]\."; 8 | gzip_min_length 1100; 9 | gzip_vary on; 10 | gzip_proxied expired no-cache no-store private auth; 11 | gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; 12 | gzip_comp_level 9; 13 | 14 | root /usr/share/nginx/html; 15 | 16 | location / { 17 | try_files $uri $uri/ /index.html =404; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /partials/toolbox/presets.html: -------------------------------------------------------------------------------- 1 |
2 |

Choose a preset theme or customize your own with the options above.

3 |

You can use it for your repo banners too!

4 |
5 |
6 |
7 | Customize 8 |
9 | 13 |
14 |
-------------------------------------------------------------------------------- /js/presets.js: -------------------------------------------------------------------------------- 1 | import presets from "./data/presets.json"; 2 | import { updateBanner, updateUIOptions } from "./banner"; 3 | 4 | function getAllPresets() { 5 | return presets; 6 | } 7 | 8 | function getPreset(index) { 9 | return presets[index]; 10 | } 11 | 12 | function getRandomPreset() { 13 | let random = Math.floor(Math.random() * presets.length); 14 | return presets[random]; 15 | } 16 | 17 | function setPreset(preset, ignoreSave = null) { 18 | updateUIOptions(preset); 19 | updateBanner({ ...preset, ignoreSave }); 20 | } 21 | 22 | export { 23 | getAllPresets, 24 | getPreset, 25 | getRandomPreset, 26 | setPreset, 27 | }; 28 | -------------------------------------------------------------------------------- /partials/scripts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /public/images/icons/moon.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /partials/header.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Github logo
4 | Github Profile
5 | Header Generator 6 |

7 |

8 | A simple but nice header image generator
for your Github profile or project. 9 |

10 |

11 | 14 | Star 15 | 16 |

17 |
-------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Pull Request Title 2 | 3 | ## Description 4 | 5 | > Summary why you opened this PR, you may add the benefits this PR provides. 6 | 7 | ## Changes 8 | 9 | > Please describe your changes, if needed attach screenshots. 10 | 1. Fix ... 11 | 2. Refactor ... 12 | 3. Update ... 13 | 4. Implement ... 14 | 15 | ## Screenshots 16 | (_If applicable_) 17 | 18 | | Picture Name | 19 | | :-------------------------: | 20 | | _Insert your picture link_ | 21 | 22 | ## Related Issues 23 | 24 | > Please add any related issue(s): 25 | 26 | This PR: 27 | - Fixes [Issue ticket name](Issue ticket link) 28 | - Implements [Issue ticket name](Issue ticket link) 29 | 30 | ## Aditional information 31 | 32 | > Provide any additional information that might be useful. 33 | -------------------------------------------------------------------------------- /js/helpers/helpers.js: -------------------------------------------------------------------------------- 1 | const isLocalDevelopment = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1'; 2 | 3 | const queryString = window.location.search; 4 | const urlParams = new URLSearchParams(queryString); 5 | const isDevOptions = urlParams.get('devOptions'); 6 | 7 | function saveImageOnLocalStorage(img) { 8 | var canvas = document.createElement('canvas'); 9 | var ctx = canvas.getContext('2d'); 10 | 11 | canvas.width = img.width; 12 | canvas.height = img.height; 13 | ctx.drawImage(img, 0, 0, img.width, img.height); 14 | 15 | var dataURL = canvas.toDataURL('image/png'); 16 | localStorage.setItem('savedImage', dataURL); 17 | } 18 | 19 | export { 20 | isLocalDevelopment, 21 | isDevOptions, 22 | saveImageOnLocalStorage 23 | }; 24 | -------------------------------------------------------------------------------- /images/gphg.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/images/patterns/falling-triangles-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /public/images/patterns/overlapping-circles-thumbnail.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /partials/modals/feedback.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /js/helpers/elements.js: -------------------------------------------------------------------------------- 1 | function getMainElements() { 2 | const bannerImageContainer = document.querySelector('.header-image-container'); 3 | const bannerImage = document.querySelector('#github-header-image'); 4 | const bannerTitle = bannerImage.querySelector('.title'); 5 | const bannerSubtitle = bannerImage.querySelector('.subtitle'); 6 | 7 | const toolbox = document.querySelector('.toolbox'); 8 | const toolboxBackground = document.querySelector('.toolbox-background'); 9 | const toolboxDecorations = document.querySelector('.toolbox-decorations'); 10 | const toolboxPresets = document.querySelector('.toolbox-presets'); 11 | 12 | return { 13 | bannerImageContainer, 14 | bannerImage, 15 | bannerTitle, 16 | bannerSubtitle, 17 | toolbox, 18 | toolboxDecorations, 19 | toolboxBackground, 20 | toolboxPresets 21 | } 22 | } 23 | 24 | export { getMainElements }; -------------------------------------------------------------------------------- /styles/how-to.scss: -------------------------------------------------------------------------------- 1 | .how-to-section { 2 | margin-top: 2rem; 3 | margin-bottom: 25px; 4 | text-align: center; 5 | flex-grow: 1; 6 | 7 | .title { 8 | font-family: "Kalam", sans-serif; 9 | } 10 | 11 | li { 12 | list-style-position: inside; 13 | margin-top: 10px; 14 | 15 | .demo { 16 | margin-top: 10px; 17 | } 18 | 19 | a { 20 | text-decoration: underline; 21 | } 22 | 23 | .code { 24 | margin: auto; 25 | margin-top: 5px; 26 | width: fit-content; 27 | padding: 5px 10px; 28 | background-color: #22272e; 29 | border-radius: 5px; 30 | 31 | code { 32 | font-size: 0.9rem; 33 | } 34 | } 35 | } 36 | } 37 | 38 | @media (max-width: 768px) { 39 | .how-to-section { 40 | margin-top: 25px; 41 | margin-bottom: 25px; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "github-profile-header-generator", 3 | "version": "2.1.0", 4 | "description": "A simple but nice header image generator for your Github profile", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build", 8 | "preview": "vite preview", 9 | "build:gh-pages": "cp deploy/vite.config.gh-pages.js vite.config.js && vite build" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/leviarista/github-profile-header-generator.git" 14 | }, 15 | "author": "Leví Arista", 16 | "license": "MIT", 17 | "bugs": { 18 | "url": "https://github.com/leviarista/github-profile-header-generator/issues" 19 | }, 20 | "homepage": "https://github.com/leviarista/github-profile-header-generator#readme", 21 | "devDependencies": { 22 | "sass": "^1.89.2", 23 | "vite": "^7.0.3", 24 | "vite-plugin-html-inject": "^1.1.2" 25 | }, 26 | "dependencies": { 27 | "@zumer/snapdom": "^1.9.7" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report any bug you find 4 | title: "[Bug] " 5 | labels: bug 6 | assignees: leviarista 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to 'x' section 16 | 2. Select these options: ... 17 | 3. Click on 'x' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, please add screenshots to help explain your problem. 25 | Also, if possible, a screenshot of your browser console will help. 26 | 27 | ** Device information** 28 | - Device type (desktop, mobile phone, tablet, ...) 29 | - Operating System 30 | - Browser (if you include your version will be helpful) 31 | - Any relevant browser extension installed? 32 | 33 | **Additional context** 34 | Add any other context about the problem here. 35 | -------------------------------------------------------------------------------- /public/images/patterns/squares-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Leví Arista 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /js/toolbox-presets.js: -------------------------------------------------------------------------------- 1 | import { getAllPresets, setPreset } from "./presets"; 2 | import { getMainElements } from "./helpers/elements" 3 | 4 | const themes = getAllPresets(); 5 | const { toolboxPresets } = getMainElements(); 6 | 7 | document.addEventListener('DOMContentLoaded', function () { 8 | if (toolboxPresets) { 9 | toolboxPresets.querySelectorAll('.theme-button-white')[0].addEventListener('click', (e) => { 10 | document.querySelector('.tab .tablinks[data-name="main-section"]').click(); 11 | }) 12 | 13 | themes.forEach(theme => { 14 | const div = document.createElement('div'); 15 | div.classList.add('theme-button'); 16 | div.setAttribute('role', 'button') 17 | 18 | const img = document.createElement('img'); 19 | img.src = './images/theme-previews/' + theme.previewImage; 20 | img.alt = 'Theme image'; 21 | 22 | img.addEventListener('click', (e) => { 23 | setPreset(theme); 24 | }); 25 | 26 | div.appendChild(img); 27 | 28 | toolboxPresets.appendChild(div); 29 | }) 30 | } 31 | }); -------------------------------------------------------------------------------- /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: Build and Deploy for GH Pages 2 | on: 3 | push: 4 | branches: 5 | - main 6 | paths-ignore: 7 | - '**/*.md' 8 | pull_request: 9 | types: [opened, synchronize, reopened, closed] 10 | branches: 11 | - main 12 | paths-ignore: 13 | - '**/*.md' 14 | jobs: 15 | build-and-deploy: 16 | concurrency: ci-${{ github.ref }} # Recommended if you intend to make multiple deployments in quick succession. 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout 🛎️ 20 | uses: actions/checkout@v3 21 | 22 | - name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. 23 | run: | 24 | npm ci 25 | npm run build:gh-pages 26 | 27 | - name: Deploy 🚀 28 | uses: JamesIves/github-pages-deploy-action@v4.2.5 29 | with: 30 | branch: gh-pages # The branch the action should deploy to. 31 | folder: dist # The folder the action should deploy. 32 | -------------------------------------------------------------------------------- /public/images/patterns/random-shapes-thumbnail.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/images/patterns/bubbles-thumbnail.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /partials/how-to.html: -------------------------------------------------------------------------------- 1 |
2 |

How to use it?

3 |
    4 |
  1. 5 | Create a nice github header image.
    6 | 10 |
  2. 11 |
  3. 12 | Create your GitHub profile README
    following 13 | 15 | this guide. 16 | 17 |
  4. 18 |
  5. Upload your header to your profile/projecy repo.
  6. 19 |
  7. 20 | Add this line to your README: 21 |

    ![Header](./your-header-image-name.png)

    22 |
  8. 23 |
24 |
25 |

You can use it for your repo banners too!

26 |
-------------------------------------------------------------------------------- /partials/modals/special-message.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/images/patterns/squares-in-squares-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /public/images/patterns/bathroom-floor-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /images/github-logo-40.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /images/github-logo-20.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/images/icons/light-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /public/images/icons/light-dark-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /styles/toolbox-presets.scss: -------------------------------------------------------------------------------- 1 | #presets-section { 2 | text-align: center; 3 | padding: 0; 4 | 5 | .toolbox-presets { 6 | padding: 10px; 7 | display: flex; 8 | justify-content: center; 9 | flex-wrap: wrap; 10 | gap: 1rem; 11 | 12 | .theme-button { 13 | width: 185px; 14 | display: flex; 15 | cursor: pointer; 16 | 17 | img { 18 | max-width: 100%; 19 | object-fit: contain; 20 | transition: all ease-in-out 300ms; 21 | 22 | &:hover { 23 | filter: drop-shadow(0px 0px 5px rgba(255, 255, 255, 0.5)); 24 | } 25 | } 26 | 27 | &-white { 28 | min-height: 45px; 29 | display: flex; 30 | justify-content: center; 31 | align-items: center; 32 | background: rgba(255, 255, 255, 0.15); 33 | border: 1px solid rgb(255, 255, 255, 0.5); 34 | border-radius: 5px; 35 | 36 | &:hover { 37 | filter: drop-shadow(0px 0px 5px rgba(255, 255, 255, 0.5)); 38 | } 39 | } 40 | } 41 | } 42 | } 43 | 44 | @media (max-width: 768px) { 45 | #presets-section { 46 | 47 | .toolbox-presets { 48 | padding: 0; 49 | gap: 10px; 50 | 51 | .theme-button { 52 | width: 165px; 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /partials/modals/info.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /partials/toolbox/result.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
Hey! I am ...
5 |
Fullstack developer
6 |
7 |
8 |
9 |
10 |
11 |
12 | 13 | Dark 14 |
15 |
16 | 17 | Random 18 |
19 |
20 | 21 | Reset 22 |
23 |
24 |
25 | 29 | 33 |
34 |
35 | 36 | Download 37 |
38 |
39 |
-------------------------------------------------------------------------------- /styles/variables.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | --button-border-radius: 7px; 3 | --input-border-radius: 7px; 4 | --background-color: linear-gradient(180deg, 5 | #675494 0%, 6 | #605fa1 32.6%, 7 | #4e6db3 68.54%, 8 | #4078c0 100%); 9 | --text-color: white; 10 | --paddings: 3rem; 11 | --github-dark-mode-color: #0d1117; 12 | --github-light-mode-color: white; 13 | --main-font-familiy: "Red Hat Display", Arial, Helvetica, sans-serif; 14 | 15 | 16 | } 17 | 18 | [data-theme="dark"] { 19 | // --background-color: linear-gradient(180deg, #2A2142 0%, #2F3E6F 50%, #1A2A54 100%); 20 | // --background-color: linear-gradient(180deg, #201932 0%, #222c50 50%, #131e3c 100%); 21 | // --background-color: linear-gradient(180deg, #1B1B2F 0%, #121224 60%, #0A0A1A 100%); 22 | // --background-color: linear-gradient(180deg, #111110 0%, #1A1A1A 40%, #2E2E3A 100%); 23 | // --background-color: linear-gradient(180deg, #0d0a14 0%, #151b31 75%, #131e3c 100%); 24 | // --background-color: linear-gradient(180deg, #3b2e5a 0%, #4b3b7a 40%, #1a1a1a 100%); 25 | // --background-color: linear-gradient(180deg, #1e1436 0%, #2a1e4a 40%, #0a0a0a 100%); 26 | // --background-color: linear-gradient(180deg, #1A1924 0%, #2A2D40 50%, #0F1017 100%); 27 | // --background-color: linear-gradient(180deg, #121212 0%, #2F3E50 50%, #10192a 100%); 28 | --background-color: linear-gradient(180deg, #111110 0%, #1e2732 50%, #111110 100%); 29 | 30 | // --text-color: white; 31 | --text-color: #f5f5f5; 32 | 33 | .tab { 34 | background-color: #1b3050; 35 | } 36 | } 37 | 38 | @media (max-width: 768px) { 39 | :root { 40 | --paddings: 1rem; 41 | } 42 | } -------------------------------------------------------------------------------- /public/images/patterns/brick-wall-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /partials/footer.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/images/patterns/temple-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /styles/modals.scss: -------------------------------------------------------------------------------- 1 | .modal { 2 | position: fixed; 3 | background-color: rgba(0, 0, 0, 0.7); 4 | top: 0; 5 | right: 0; 6 | bottom: 0; 7 | left: 0; 8 | z-index: 999; 9 | visibility: hidden; 10 | opacity: 0; 11 | pointer-events: none; 12 | transition: all 0.25s; 13 | 14 | &:target { 15 | visibility: visible; 16 | opacity: 1; 17 | pointer-events: auto; 18 | } 19 | 20 | &>div { 21 | width: 450px; 22 | margin-top: 15px; 23 | max-width: calc(100% - 30px); 24 | position: absolute; 25 | top: 50%; 26 | left: 50%; 27 | transform: translate(-50%, -50%); 28 | padding: 2em; 29 | background: var(--background-color); 30 | box-shadow: 0px 0px 5px rgba(255, 255, 255, 0.5), 0px 0px 10px rgba(0, 0, 0, 0.25); 31 | border-radius: var(--button-border-radius); 32 | } 33 | 34 | .modal-title { 35 | font-size: 1.2rem; 36 | } 37 | 38 | .modal-info-text { 39 | border-top: solid 1px rgba(255, 255, 255, 0.5); 40 | font-size: 12px; 41 | } 42 | 43 | a { 44 | font-weight: 700; 45 | } 46 | } 47 | 48 | .modal-close { 49 | position: absolute; 50 | right: 15px; 51 | top: 15px; 52 | } 53 | 54 | #feedback-modal { 55 | input { 56 | width: calc(50% - 2px); 57 | margin-bottom: 5px; 58 | } 59 | textarea{ 60 | width: 100%; 61 | 62 | &::-webkit-scrollbar { 63 | width: 14px; 64 | cursor: pointer; 65 | } 66 | 67 | &::-webkit-scrollbar-track { 68 | background: rgba(0, 0, 0, 0.1); 69 | // -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.1); 70 | } 71 | 72 | &::-webkit-scrollbar-thumb { 73 | border-radius: var(--input-border-radius); 74 | background-color: rgba(255, 255, 255, 0.75); 75 | // 76 | } 77 | } 78 | button { 79 | display: block; 80 | margin-left: auto 81 | } 82 | } -------------------------------------------------------------------------------- /styles/toolbox-decorations.scss: -------------------------------------------------------------------------------- 1 | .toolbox-decorations { 2 | box-sizing: border-box; 3 | max-width: 550px; 4 | margin: auto; 5 | 6 | > div { 7 | display: flex; 8 | align-items: center; 9 | justify-content: center; 10 | flex-wrap: wrap; 11 | 12 | &:not(:last-child) { 13 | margin-bottom: 15px; 14 | } 15 | } 16 | 17 | .decorations-buttons { 18 | button { 19 | width: 70px; 20 | height: 70px; 21 | padding: 0; 22 | margin-left: 5px; 23 | margin-bottom: 5px; 24 | display: flex; 25 | align-items: center; 26 | justify-content: center; 27 | transition: all ease-in-out 300ms; 28 | 29 | img { 30 | max-width: 50px; 31 | max-height: 50px; 32 | // border-radius: var(--input-border-radius); 33 | } 34 | 35 | &:hover { 36 | box-shadow: 0px 0px 5px 2px rgba(255, 255, 255, 0.25); 37 | } 38 | 39 | &.selected { 40 | border: solid white 2px; 41 | } 42 | } 43 | } 44 | 45 | .decorations-upload { 46 | flex-direction: column; 47 | 48 | input { 49 | margin-top: 5px; 50 | } 51 | 52 | .myoctocats-tip { 53 | margin-top: 10px; 54 | margin-bottom: 10px; 55 | padding: 20px; 56 | // border: 2px solid rgb(255, 255, 255, 0.5); 57 | border-radius: var(--input-border-radius); 58 | font-size: 0.9rem; 59 | // text-transform: uppercase; 60 | // text-align: center; 61 | line-height: 1.5; 62 | background: rgba(255, 255, 255, 0.15); 63 | 64 | a { 65 | font-weight: 700; 66 | text-decoration: underline; 67 | } 68 | } 69 | } 70 | } 71 | 72 | @media (max-width: 768px) { 73 | .toolbox-decorations { 74 | .decorations-buttons { 75 | button { 76 | margin-bottom: 5px; 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | Glad to hear you're interested in contributing to the project!. Thank you so much. 4 | These are some ways how you can help: 5 | 6 | > ℹ️ After cloning the repo, please add `/?devOptions=1` in the URL, so you can see additional options for development mode 7 | > Also the hostname should be either `localhost`or `127.0.0.1`. 8 | 9 | #### Issues 10 | You can check the [Issues](https://github.com/rails/rails/issues) section and start working on some of the existing tickets. 11 | 12 | #### Bugs 13 | If you find a bug, please [create a new issue](https://github.com/leviarista/github-profile-header-generator/issues/new/choose). 14 | 15 | #### Presets 16 | Create more presets/themes: 17 | - Open the browser console. 18 | - Create your theme and copy the printed theme values from the console. 19 | - Click the "miniature" option and save the image, add it to `public/images/theme-previews/`. 20 | - Use the previuos console values to insert a new item on `/js/data/presets.json`. 21 | - Add a property called `"previewImage"` with the name of the miniature image. 22 | - For example: `"previewImage": "my-theme-preview.png"` 23 | - That's it! 24 | 25 | #### Add Background patterns 26 | - Go to `/js/data/patterns.js`, add a new case block with an appropriate name in the `getPattern` function. 27 | - After choosing a new pattern in SVG format, paste the SVG code of the image into the return value. 28 | - Change the `fill` and `fill-opacity` values ​​that the function receives, for example: 29 | - `fill="#F12AA34"` -> `fill='%23${color}'` 30 | - `fill-opacity=0.5` -> `fill-opacity='${opacity}'` 31 | - [Optional] Add a predefined size in the getPatternDefaultSize function. 32 | - Create an appropriate thumbnail file and add it to `/public/images/patterns/`. 33 | - Go to `/partials/toolbox/background.html` and add a new button element in the `"patterns-buttons"` div section. 34 | 35 | #### Add new decorations 36 | - Place an image on `/public/images/decorations/`. 37 | - Go to `/partials/toolbox/decorations.html` and add a new button element in the `"decorations-buttons"` div section. 38 | 39 | #### Ideas or suggestions 40 | - Share them in the [discussions](https://github.com/leviarista/github-profile-header-generator/discussions) section. 41 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |
9 |
10 | light-mode-btn 11 |
12 |
13 | dark-mode-btn 14 |
15 |
16 | 17 | 18 | 19 |
20 | 21 |
22 | 23 | 24 |
25 | 32 | 33 | 34 | 35 | 36 |
37 | 38 |
39 | 40 | 41 | 42 | 43 | 44 |
45 |
46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /js/toolbox-decorations.js: -------------------------------------------------------------------------------- 1 | import { updateBanner } from "./banner"; 2 | import { getMainElements } from "./helpers/elements"; 3 | import { saveImageOnLocalStorage } from "./helpers/helpers"; 4 | 5 | /* ************** Elements ************** */ 6 | 7 | const { 8 | toolboxDecorations, 9 | } = getMainElements(); 10 | 11 | /* ************** Decorations inputs ************** */ 12 | 13 | function setDecorationSize() { 14 | let selectedDecorationSize = toolboxDecorations.querySelector('.decorations-size-inputs input#decoration-size-input').value; 15 | 16 | updateBanner({ 17 | decorationSize: selectedDecorationSize, 18 | }); 19 | } 20 | 21 | toolboxDecorations.querySelectorAll('.decorations-size-inputs input[type="range"]') 22 | .forEach(input => { 23 | input.addEventListener('input', (e) => { 24 | e.target.nextElementSibling.value = e.target.value 25 | setDecorationSize(); 26 | }); 27 | }) 28 | 29 | /* ************** Decorations ************** */ 30 | 31 | toolboxDecorations.querySelectorAll('.decorations-buttons button') 32 | .forEach(button => { 33 | button.addEventListener('click', (e) => { 34 | const element = e.target.tagName.toLowerCase() === 'img' ? 35 | e.target.parentNode : 36 | e.target; 37 | const decorationValue = element.getAttribute('data-decoration-value'); 38 | updateBanner({ 39 | decoration: decorationValue, 40 | decorationLocal: false 41 | }); 42 | setDecorationSize(); 43 | }); 44 | }) 45 | 46 | /* ************** Upload decoration ************** */ 47 | 48 | toolboxDecorations.querySelector('#decoration-upload-input') 49 | .addEventListener('change', () => { 50 | const file = toolboxDecorations.querySelector('#decoration-upload-input').files[0]; 51 | 52 | let reader = new FileReader(); 53 | reader.readAsDataURL(file); 54 | reader.onload = function (e) { 55 | updateBanner({ 56 | decoration: this.result, 57 | decorationLocal: true 58 | }); 59 | 60 | const decoration = document.querySelector('.img-decoration'); 61 | saveImageOnLocalStorage(decoration); 62 | } 63 | }) 64 | 65 | /* ************** ************** ************** */ 66 | -------------------------------------------------------------------------------- /public/images/icons/download.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | -------------------------------------------------------------------------------- /public/images/icons/download-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | -------------------------------------------------------------------------------- /public/images/patterns/leaf-thumbnail.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # Github Profile Header Generator 4 | 5 | ## What is it? 6 | 7 | A simple but nice header image generator for your __Github profile Readme__. 8 | You can use it for your __repo banners__ too! 9 | 10 | [Create my banner!](https://leviarista.github.io/github-profile-header-generator/) 11 | 12 | ## How to use it? 13 | 14 | 1. Create a nice github header image. 15 | 2. Create your GitHub profile README following [this guide](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/managing-your-profile-readme). 16 | 3. Upload your header to your profile repo. 17 | 4. Add this line to your README: 18 | ```Markdown 19 | ![Header](./[Your header image]) 20 | ``` 21 | 22 | ## Examples 23 | 24 | ![Example 1](https://raw.githubusercontent.com/leviarista/github-profile-header-generator/main/social/examples/example-1.png) 25 | ![Example 2](https://raw.githubusercontent.com/leviarista/github-profile-header-generator/main/social/examples/example-2.png) 26 | ![Example 3](https://raw.githubusercontent.com/leviarista/github-profile-header-generator/main/social/examples/example-3.png) 27 | ![Example 4](https://raw.githubusercontent.com/leviarista/github-profile-header-generator/main/social/examples/example-4.png) 28 | ![Example 5](https://raw.githubusercontent.com/leviarista/github-profile-header-generator/main/social/examples/example-5.png) 29 | 30 | ## Features list 31 | 32 | - Edit title and subtitle texts. 33 | - Choose colors for text, background and borders. 34 | - Set dimensions and padding. 35 | - Align text and decorations. 36 | - Change fonts. 37 | - Set the size and radius of the border. 38 | - Set background pattern image, its color, size and opacity. 39 | - Add decorations. 40 | - Upload your own decoration, octocat or profile pic. 41 | - Toogle between Github dark and light mode. 42 | - Download image as png. 43 | - Choose from predefined presets or get a random one. 44 | 45 | ## Tech used 46 | 47 | - [Vite](https://vitejs.dev/) 48 | - [snapdom](https://zumerlab.github.io/snapdom/) 49 | 50 | ## Get started 51 | 52 | - `npm run dev`- starts dev server 53 | - `npm run build` - builds for production 54 | - `npm run preview` - locally previews production build 55 | 56 | ## Get started with Docker 57 | 58 | ```bash 59 | docker-compose up -d --build --force-recreate 60 | ``` 61 | 62 | ## Contributing 63 | 64 | Check out our [Contributing guide](https://github.com/leviarista/github-profile-header-generator/blob/main/.github/CONTRIBUTING.md) 65 | -------------------------------------------------------------------------------- /public/images/icons/sun.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /public/images/icons/random.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /public/images/icons/random-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /public/images/patterns/hideout-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 11 | 14 | 17 | 20 | 23 | 26 | 29 | 32 | 35 | 38 | 41 | 42 | -------------------------------------------------------------------------------- /public/images/patterns/github-thumbnail.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/images/patterns/graph-paper-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /partials/toolbox/test-fonts.html: -------------------------------------------------------------------------------- 1 | 5 |
6 |
Hey! I'm Leví Arista. username/project - red-hat-display
7 | 8 | 9 | 10 | 11 |
Hey! I'm Leví Arista. username/project - ubuntu
12 | 13 | 14 |
Hey! I'm Leví Arista. username/project - poppins
15 |
Hey! I'm Leví Arista. username/project - anonymous-pro
16 |
Hey! I'm Leví Arista. username/project - source-code-pro
17 | 18 | 19 | 20 |
Hey! I'm Leví Arista. username/project - quattrocento
21 |
Hey! I'm Leví Arista. username/project - della-respira
22 |
Hey! I'm Leví Arista. username/project - lancelot
23 |
Hey! I'm Leví Arista. username/project - life-savers
24 |
Hey! I'm Leví Arista. username/project - athiti
25 |
Hey! I'm Leví Arista. username/project - electrolize
26 |
Hey! I'm Leví Arista. username/project - passero-one
27 |
Hey! I'm Leví Arista. username/project - pixelify-sans
28 |
Hey! I'm Leví Arista. username/project - kalam
29 |
Hey! I'm Leví Arista. username/project - playball
30 |
Hey! I'm Leví Arista. username/project - orbitron
31 | 32 | 33 |
-------------------------------------------------------------------------------- /styles/tabs.scss: -------------------------------------------------------------------------------- 1 | /* Style the tab */ 2 | .tab { 3 | position: fixed; 4 | left: 50%; 5 | transform: translateX(calc(-50% + 190px)); 6 | padding: 0 2px 2px 2px; 7 | width: fit-content; 8 | margin: 0 auto; 9 | display: grid; 10 | grid-template-columns: repeat(4, auto); 11 | gap: 2px; 12 | justify-content: center; 13 | color: var(--text-color); 14 | background: #6E5494; 15 | border-radius: 0 0 10px 10px; 16 | box-shadow: 0px 0px 5px 2px rgba(255, 255, 255, 0.25); 17 | // overflow: hidden; 18 | z-index: 10; 19 | user-select: none; 20 | } 21 | 22 | /* Style the buttons that are used to open the tab content */ 23 | .tab button { 24 | background-color: inherit; 25 | border: none; 26 | outline: none; 27 | cursor: pointer; 28 | padding: 1rem 2rem; 29 | transition: 0.3s; 30 | color: rgb(240, 240, 240); 31 | border-radius: 0 0 9px 9px; 32 | font-weight: bold; 33 | } 34 | 35 | /* Change background color of buttons on hover */ 36 | .tab button:hover { 37 | background-color: rgba(255, 255, 255, 0.15); 38 | } 39 | 40 | /* Create an active/current tablink class */ 41 | .tab button.active { 42 | background-color: rgba(255, 255, 255, 0.15); 43 | // border-top-left-radius: 7px; 44 | // border-top-right-radius: 7px; 45 | } 46 | 47 | /* Style the tab content */ 48 | .tabcontent { 49 | width: 100%; 50 | // max-width: calc(1280px - 296px - 24px); 51 | margin: auto; 52 | margin-top: calc(1rem + 2rem + 0.5rem); 53 | max-width: calc(850px); 54 | padding: 0.5rem 1rem 0.5rem 1rem; 55 | overflow: auto; 56 | } 57 | 58 | .tabcontent { 59 | animation: fadeEffect 1s; 60 | /* Fading effect takes 1 second */ 61 | } 62 | 63 | /* Go from zero to full opacity */ 64 | @keyframes fadeEffect { 65 | from { 66 | opacity: 0; 67 | } 68 | 69 | to { 70 | opacity: 1; 71 | } 72 | } 73 | 74 | @media (max-width: 850px) { 75 | .tab { 76 | button { 77 | padding: 10px 1rem; 78 | } 79 | } 80 | } 81 | 82 | @media (max-width: 768px) { 83 | .tab { 84 | position: static; 85 | width: 100%; 86 | transform: translateX(calc(0)); 87 | display: grid; 88 | grid-template-columns: repeat(4, auto); 89 | gap: 1px; 90 | border-radius: 0; 91 | padding: 1px; 92 | overflow: auto; 93 | 94 | button { 95 | padding: 10px; 96 | border-radius: 0; 97 | } 98 | } 99 | 100 | .tabcontent { 101 | height: auto; 102 | margin-top: 1rem; 103 | } 104 | } 105 | 106 | @media (max-width: 360px) { 107 | .tab { 108 | width: 100%; 109 | margin: 0; 110 | left: 0; 111 | transform: translateX(calc(0)); 112 | display: grid; 113 | grid-template-columns: repeat(4, auto); 114 | border-radius: 0; 115 | padding: 1px; 116 | overflow: auto; 117 | 118 | button { 119 | padding: 10px; 120 | border-radius: 0; 121 | } 122 | } 123 | 124 | } -------------------------------------------------------------------------------- /styles/toolbox-background.scss: -------------------------------------------------------------------------------- 1 | .toolbox-background { 2 | box-sizing: border-box; 3 | 4 | > div { 5 | display: flex; 6 | align-items: center; 7 | justify-content: center; 8 | flex-wrap: wrap; 9 | 10 | &:not(:last-child) { 11 | margin-bottom: 15px; 12 | } 13 | } 14 | 15 | .bg-color-selectors { 16 | > div { 17 | display: flex; 18 | align-items: center; 19 | 20 | &:not(:last-child) { 21 | margin-right: 15px; 22 | } 23 | } 24 | 25 | input { 26 | margin-left: 5px; 27 | cursor: pointer; 28 | padding: 0; 29 | } 30 | } 31 | 32 | .border-inputs { 33 | div { 34 | display: flex; 35 | align-items: flex-start; 36 | 37 | &:not(:last-child) { 38 | margin-right: 15px; 39 | } 40 | 41 | input { 42 | cursor: pointer; 43 | } 44 | } 45 | } 46 | 47 | .pattern-inputs { 48 | div { 49 | display: flex; 50 | align-items: flex-start; 51 | 52 | &:not(:last-child) { 53 | margin-right: 15px; 54 | } 55 | 56 | &:first-child { 57 | align-items: center; 58 | } 59 | 60 | #pattern-color-selector { 61 | padding: 0; 62 | } 63 | 64 | input { 65 | margin-left: 5px; 66 | cursor: pointer; 67 | } 68 | } 69 | } 70 | 71 | .patterns-buttons { 72 | max-width: 550px; 73 | margin: auto; 74 | display: grid; 75 | grid-template-columns: repeat(auto-fill, 70px); 76 | gap: 5px; 77 | 78 | button { 79 | width: 70px; 80 | height: 70px; 81 | padding: 0; 82 | display: flex; 83 | align-items: center; 84 | justify-content: center; 85 | transition: all ease-in-out 300ms; 86 | 87 | img { 88 | width: 100%; 89 | max-width: 55px; 90 | max-height: 55px; 91 | } 92 | 93 | &:hover { 94 | box-shadow: 0px 0px 5px 2px rgba(255, 255, 255, 0.25); 95 | } 96 | 97 | &.selected { 98 | border: solid white 2px; 99 | } 100 | } 101 | } 102 | } 103 | 104 | @media (max-width: 768px) { 105 | .toolbox-background { 106 | .border-inputs { 107 | > div { 108 | &:not(:last-child) { 109 | margin-bottom: 10px; 110 | } 111 | } 112 | } 113 | 114 | .pattern-inputs { 115 | input { 116 | &:not(:last-child) { 117 | margin-bottom: 15px; 118 | } 119 | } 120 | } 121 | 122 | // .patterns-buttons { 123 | // button { 124 | // margin-bottom: 5px; 125 | // } 126 | // } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /public/images/patterns/dalmatian-spots-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /public/images/patterns/jigsaw-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /public/images/patterns/lisbon-thumbnail.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/toolbox-test-fonts.scss: -------------------------------------------------------------------------------- 1 | .tablinks[data-name="test-fonts-section"] { 2 | position: fixed; 3 | right: 0; 4 | transform: translateX(100%); 5 | z-index: 100 6 | } 7 | 8 | #test-fonts-section { 9 | font-size: 20px; 10 | padding: 50px 0 100px 50px; 11 | background-color: #222; 12 | color: white; 13 | } 14 | 15 | .red-hat-display { 16 | font-family: "Red Hat Display", sans-serif; 17 | font-optical-sizing: auto; 18 | font-weight: 400; 19 | font-style: normal; 20 | } 21 | 22 | .kalam { 23 | font-family: "Kalam", cursive; 24 | font-weight: 400; 25 | font-style: normal; 26 | } 27 | 28 | .poppins { 29 | font-family: "Poppins", sans-serif; 30 | font-weight: 400; 31 | font-style: normal; 32 | } 33 | 34 | 35 | .maven-pro { 36 | font-family: "Maven Pro", sans-serif; 37 | font-optical-sizing: auto; 38 | font-weight: 400; 39 | font-style: normal; 40 | } 41 | 42 | .athiti { 43 | font-family: "Athiti", sans-serif; 44 | font-weight: 400; 45 | font-style: normal; 46 | } 47 | 48 | .ubuntu-sans { 49 | font-family: "Ubuntu Sans", sans-serif; 50 | font-optical-sizing: auto; 51 | font-weight: 400; 52 | font-style: normal; 53 | font-variation-settings: 54 | "wdth" 100; 55 | } 56 | 57 | .ubuntu { 58 | font-family: "Ubuntu", sans-serif; 59 | font-weight: 400; 60 | font-style: normal; 61 | } 62 | 63 | .istok-web { 64 | font-family: "Istok Web", sans-serif; 65 | font-weight: 400; 66 | font-style: normal; 67 | } 68 | 69 | 70 | .courgette { 71 | font-family: "Courgette", cursive; 72 | font-weight: 400; 73 | font-style: normal; 74 | } 75 | 76 | .quattrocento { 77 | font-family: "Quattrocento", serif; 78 | font-weight: 400; 79 | font-style: normal; 80 | } 81 | 82 | .della-respira { 83 | font-family: "Della Respira", serif; 84 | font-weight: 400; 85 | font-style: normal; 86 | } 87 | 88 | .lato { 89 | font-family: "Lato", sans-serif; 90 | font-weight: 400; 91 | font-style: normal; 92 | } 93 | 94 | .martel { 95 | font-family: "Martel", serif; 96 | font-weight: 400; 97 | font-style: normal; 98 | } 99 | 100 | .lancelot { 101 | font-family: "Lancelot", serif; 102 | font-weight: 400; 103 | font-style: normal; 104 | } 105 | 106 | .playball { 107 | font-family: "Playball", cursive; 108 | font-weight: 400; 109 | font-style: normal; 110 | } 111 | 112 | 113 | .life-savers { 114 | font-family: "Life Savers", serif; 115 | font-weight: 400; 116 | font-style: normal; 117 | } 118 | 119 | .anonymous-pro { 120 | font-family: "Anonymous Pro", monospace; 121 | font-weight: 400; 122 | font-style: normal; 123 | } 124 | 125 | .inconsolata { 126 | font-family: "Inconsolata", monospace; 127 | font-optical-sizing: auto; 128 | font-weight: 400; 129 | font-style: normal; 130 | font-variation-settings: 131 | "wdth" 100; 132 | } 133 | 134 | .fira-code { 135 | font-family: "Fira Code", monospace; 136 | font-optical-sizing: auto; 137 | font-weight: 400; 138 | font-style: normal; 139 | } 140 | 141 | .open-sans { 142 | font-family: "Open Sans", sans-serif; 143 | font-optical-sizing: auto; 144 | font-weight: 400; 145 | font-style: normal; 146 | font-variation-settings: 147 | "wdth" 100; 148 | } 149 | 150 | .playwrite-hu { 151 | font-family: "Playwrite HU", cursive; 152 | font-optical-sizing: auto; 153 | font-weight: 400; 154 | font-style: normal; 155 | } 156 | 157 | 158 | .dancing-script { 159 | font-family: "Dancing Script", cursive; 160 | font-optical-sizing: auto; 161 | font-weight: 400; 162 | font-style: normal; 163 | } 164 | 165 | .passero-one { 166 | font-family: "Passero One", sans-serif; 167 | font-weight: 400; 168 | font-style: normal; 169 | } 170 | 171 | .pixelify-sans { 172 | font-family: "Pixelify Sans", sans-serif; 173 | font-optical-sizing: auto; 174 | font-weight: 400; 175 | font-style: normal; 176 | } 177 | 178 | .electrolize { 179 | font-family: "Electrolize", sans-serif; 180 | font-weight: 400; 181 | font-style: normal; 182 | } 183 | 184 | .source-code-pro { 185 | font-family: "Source Code Pro", monospace; 186 | font-optical-sizing: auto; 187 | font-weight: 400; 188 | font-style: normal; 189 | } -------------------------------------------------------------------------------- /public/images/icons/reset.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /public/images/icons/reset-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /js/toolbox-background.js: -------------------------------------------------------------------------------- 1 | import { getSavedThemeProp, updateBanner } from './banner'; 2 | import { getPatternDefaultSize } from './data/patterns'; 3 | import { getMainElements } from './helpers/elements'; 4 | 5 | /* ************** Elements ************** */ 6 | 7 | const { 8 | toolboxBackground, 9 | } = getMainElements(); 10 | 11 | let selectedPattern = getSavedThemeProp('pattern'); 12 | let selectedPatternOpacity; 13 | let selectedPatternColor; 14 | let selectedPatternSize; 15 | 16 | /* ************** Color selectors ************** */ 17 | 18 | function setBgColorValues() { 19 | let bgColorSelector = toolboxBackground.querySelector('.bg-color-selectors input#background-bg-color-selector'); 20 | let borderColorSelector = toolboxBackground.querySelector('.bg-color-selectors input#border-color-selector'); 21 | 22 | updateBanner({ 23 | background: bgColorSelector.value, 24 | borderColor: borderColorSelector.value, 25 | }); 26 | 27 | let mainTabBgColorSelector = document.querySelector('.color-selectors-container input#main-bg-color-selector'); 28 | mainTabBgColorSelector.value = bgColorSelector.value; 29 | } 30 | 31 | toolboxBackground.querySelectorAll('.bg-color-selectors input') 32 | .forEach(input => { 33 | input.addEventListener('input', (e) => { 34 | setBgColorValues(); 35 | }); 36 | }) 37 | 38 | /* ************** Border Inputs ************** */ 39 | 40 | function setBorderValues() { 41 | let borderInput = toolboxBackground.querySelector('.border-inputs input#border-input'); 42 | let borderRadiusInput = toolboxBackground.querySelector('.border-inputs input#border-radius-input'); 43 | let borderColorSelector = toolboxBackground.querySelector('.bg-color-selectors input#border-color-selector'); 44 | 45 | updateBanner({ 46 | borderColor: borderColorSelector.value, 47 | borderSize: borderInput.value, 48 | borderRadius: borderRadiusInput.value 49 | }); 50 | } 51 | 52 | toolboxBackground.querySelectorAll('.border-inputs input') 53 | .forEach(input => { 54 | input.addEventListener('input', (e) => { 55 | e.target.nextElementSibling.value = e.target.value 56 | setBorderValues(); 57 | }); 58 | }) 59 | 60 | /* ************** Pattern inputs ************** */ 61 | 62 | function setPatternValues() { 63 | selectedPatternOpacity = toolboxBackground.querySelector('.pattern-inputs input#pattern-opacity-input').value; 64 | selectedPatternSize = toolboxBackground.querySelector('.pattern-inputs input#pattern-size-input').value; 65 | } 66 | 67 | toolboxBackground.querySelectorAll('.pattern-inputs input[type="range"]') 68 | .forEach(input => { 69 | input.addEventListener('input', (e) => { 70 | e.target.nextElementSibling.value = e.target.value 71 | setPatternValues(); 72 | setPatternBackground(); 73 | }); 74 | }) 75 | 76 | toolboxBackground.querySelectorAll('.pattern-inputs input[type="color"]') 77 | .forEach(input => { 78 | input.addEventListener('input', (e) => { 79 | setPatternBackground(); 80 | }); 81 | }) 82 | 83 | /* ************** Patterns ************** */ 84 | 85 | function setPatternBackground() { 86 | const selectedPatternColor = toolboxBackground.querySelector('.pattern-inputs input#pattern-color-selector').value; 87 | 88 | updateBanner({ 89 | pattern: selectedPattern, 90 | patternColor: selectedPatternColor, 91 | patternOpacity: selectedPatternOpacity, 92 | patternSize: selectedPatternSize 93 | }); 94 | } 95 | 96 | toolboxBackground.querySelectorAll('.patterns-buttons button') 97 | .forEach(button => { 98 | button.addEventListener('click', (e) => { 99 | const element = e.target.tagName.toLowerCase() === 'img' ? 100 | e.target.parentNode : 101 | e.target; 102 | const patternValue = element.getAttribute('data-pattern-value'); 103 | selectedPattern = patternValue; 104 | setPatternDefaultSize(patternValue); 105 | setPatternValues(); 106 | setPatternBackground(); 107 | }); 108 | }) 109 | 110 | function setPatternDefaultSize(patternValue) { 111 | selectedPatternSize = getPatternDefaultSize(patternValue); 112 | toolboxBackground.querySelector('.pattern-inputs #pattern-size-input').value = selectedPatternSize; 113 | toolboxBackground.querySelector('.pattern-inputs #pattern-size-input').nextElementSibling.innerHTML = selectedPatternSize; 114 | } 115 | 116 | /* ************** ************** ************** */ -------------------------------------------------------------------------------- /public/images/patterns/glamorous-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 11 | 13 | 15 | 18 | 21 | 24 | 26 | 28 | 31 | 34 | 37 | 38 | -------------------------------------------------------------------------------- /public/images/patterns/circuit-board-thumbnail.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /js/toolbox-main.js: -------------------------------------------------------------------------------- 1 | import { updateBanner } from './banner'; 2 | import { getMainElements } from './helpers/elements'; 3 | 4 | /* ************** Elements ************** */ 5 | 6 | const { 7 | bannerImageContainer, 8 | bannerImage, 9 | toolbox, 10 | } = getMainElements(); 11 | 12 | /* ************** Info text inputs ************** */ 13 | 14 | toolbox.querySelectorAll('.text-inputs input') 15 | .forEach(input => { 16 | input.addEventListener('click', () => input.select()); 17 | 18 | input.addEventListener('keyup', (e) => { 19 | let titleInput = toolbox.querySelector('.text-inputs input#title-input'); 20 | let subtitleInput = toolbox.querySelector('.text-inputs input#subtitle-input'); 21 | 22 | updateBanner({ 23 | title: titleInput.value, 24 | subtitle: subtitleInput.value 25 | }); 26 | }); 27 | }) 28 | 29 | /* ************** Color selectors ************** */ 30 | 31 | function setColorValues() { 32 | let bgColorSelector = toolbox.querySelector('.color-selectors-container input#main-bg-color-selector'); 33 | let titleColorSelector = toolbox.querySelector('.color-selectors-container input#title-color-selector'); 34 | let subtitleColorSelector = toolbox.querySelector('.color-selectors-container input#subtitle-color-selector'); 35 | 36 | updateBanner({ 37 | background: bgColorSelector.value, 38 | titleColor: titleColorSelector.value, 39 | subtitleColor: subtitleColorSelector.value, 40 | }); 41 | 42 | let backgroundTabBgColorSelector = document.querySelector('.bg-color-selectors input#background-bg-color-selector'); 43 | backgroundTabBgColorSelector.value = bgColorSelector.value; 44 | } 45 | 46 | toolbox.querySelectorAll('.color-selectors-container input') 47 | .forEach(input => { 48 | input.addEventListener('input', (e) => { 49 | setColorValues(); 50 | }); 51 | }) 52 | 53 | /* ************** Size inputs ************** */ 54 | 55 | function setSizeValues() { 56 | let widthInput = toolbox.querySelector('.size-inputs input#width-input'); 57 | let heightInput = toolbox.querySelector('.size-inputs input#height-input'); 58 | 59 | if (Number(widthInput.value) > bannerImageContainer.clientWidth) { 60 | bannerImage.style.zoom = bannerImageContainer.clientWidth / widthInput.value; 61 | } else { 62 | bannerImage.style.zoom = 1; 63 | } 64 | bannerImage.style.width = `${widthInput.value}px`; 65 | bannerImage.style.height = `${heightInput.value}px`; 66 | } 67 | 68 | function setPaddingValues() { 69 | let paddingInput = toolbox.querySelector('.size-inputs input#paddings-input'); 70 | 71 | updateBanner({ padding: paddingInput.value }); 72 | } 73 | 74 | toolbox.querySelectorAll('.size-inputs input') 75 | .forEach(input => { 76 | if (['width-input', 'height-input'].includes(input.id)) { 77 | input.addEventListener('click', () => input.select()); 78 | 79 | input.addEventListener('keyup', (e) => { 80 | setSizeValues(); 81 | }); 82 | } else if (input.id = 'paddings-input') { 83 | input.addEventListener('input', (e) => { 84 | e.target.nextElementSibling.value = e.target.value 85 | setPaddingValues(); 86 | }); 87 | } 88 | }) 89 | 90 | /* ************** Align buttons ************** */ 91 | 92 | toolbox.querySelectorAll('.align-buttons button') 93 | .forEach(button => { 94 | button.addEventListener('click', (e) => { 95 | const element = e.target.tagName.toLowerCase() === 'img' ? 96 | e.target.parentNode : 97 | e.target; 98 | const alignValue = element.getAttribute('data-align-value'); 99 | 100 | updateBanner({ 101 | textAlign: alignValue 102 | }); 103 | 104 | }); 105 | }) 106 | 107 | /* ************** Font Selectors ************** */ 108 | 109 | toolbox.querySelectorAll('.font-selectors-container') 110 | .forEach(button => { 111 | button.addEventListener('change', (e) => { 112 | let titleFontSelect = toolbox.querySelector('.font-selectors-container #title-font-selector'); 113 | let subtitleFontSelect = toolbox.querySelector('.font-selectors-container #subtitle-font-selector'); 114 | 115 | updateBanner({ 116 | titleFont: titleFontSelect.value, 117 | subtitleFont: subtitleFontSelect.value, 118 | }); 119 | }); 120 | }) 121 | 122 | /* ************** Font Size inputs ************** */ 123 | 124 | function setFontSizeValues() { 125 | let titleFontSizeInput = toolbox.querySelector('.font-size-inputs input#title-font-size-input'); 126 | let subtitleFontSizeInput = toolbox.querySelector('.font-size-inputs input#subtitle-font-size-input'); 127 | 128 | updateBanner({ 129 | titleFontSize: titleFontSizeInput.value, 130 | subtitleFontSize: subtitleFontSizeInput.value, 131 | }); 132 | } 133 | 134 | toolbox.querySelectorAll('.font-size-inputs input') 135 | .forEach(input => { 136 | input.addEventListener('input', (e) => { 137 | e.target.nextElementSibling.value = e.target.value 138 | setFontSizeValues(); 139 | }); 140 | }) 141 | 142 | /* ************** ************** ************** */ 143 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of any condition. 7 | 8 | We pledge to act and interact in ways that contribute to an open, welcoming, inclusive, and healthy community. 9 | 10 | ## Our Standards 11 | 12 | Examples of behavior that contributes to a positive environment for our 13 | community include: 14 | 15 | * Demonstrating empathy and kindness toward other people 16 | * Being respectful of differing opinions, viewpoints, and experiences 17 | * Giving and gracefully accepting constructive feedback 18 | * Accepting responsibility and apologizing to those affected by our mistakes, 19 | and learning from the experience 20 | * Focusing on what is best not just for us as individuals, but for the 21 | overall community 22 | 23 | Examples of unacceptable behavior include: 24 | 25 | * The use of sexualized language or imagery, and sexual attention or 26 | advances of any kind 27 | * Trolling, insulting or derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or email 30 | address, without their explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Enforcement Responsibilities 35 | 36 | Community leaders are responsible for clarifying and enforcing our standards of 37 | acceptable behavior and will take appropriate and fair corrective action in 38 | response to any behavior that they deem inappropriate, threatening, offensive, 39 | or harmful. 40 | 41 | Community leaders have the right and responsibility to remove, edit, or reject 42 | comments, commits, code, wiki edits, issues, and other contributions that are 43 | not aligned to this Code of Conduct, and will communicate reasons for moderation 44 | decisions when appropriate. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies within all community spaces, and also applies when 49 | an individual is officially representing the community in public spaces. 50 | Examples of representing our community include using an official e-mail address, 51 | posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. 53 | 54 | ## Enforcement 55 | 56 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 57 | reported to the community leaders responsible for enforcement at 58 | levi.arista@gmail.com. 59 | All complaints will be reviewed and investigated promptly and fairly. 60 | 61 | All community leaders are obligated to respect the privacy and security of the 62 | reporter of any incident. 63 | 64 | ## Enforcement Guidelines 65 | 66 | Community leaders will follow these Community Impact Guidelines in determining 67 | the consequences for any action they deem in violation of this Code of Conduct: 68 | 69 | ### 1. Correction 70 | 71 | **Community Impact**: Use of inappropriate language or other behavior deemed 72 | unprofessional or unwelcome in the community. 73 | 74 | **Consequence**: A private, written warning from community leaders, providing 75 | clarity around the nature of the violation and an explanation of why the 76 | behavior was inappropriate. A public apology may be requested. 77 | 78 | ### 2. Warning 79 | 80 | **Community Impact**: A violation through a single incident or series 81 | of actions. 82 | 83 | **Consequence**: A warning with consequences for continued behavior. No 84 | interaction with the people involved, including unsolicited interaction with 85 | those enforcing the Code of Conduct, for a specified period of time. This 86 | includes avoiding interactions in community spaces as well as external channels 87 | like social media. Violating these terms may lead to a temporary or 88 | permanent ban. 89 | 90 | ### 3. Temporary Ban 91 | 92 | **Community Impact**: A serious violation of community standards, including 93 | sustained inappropriate behavior. 94 | 95 | **Consequence**: A temporary ban from any sort of interaction or public 96 | communication with the community for a specified period of time. No public or 97 | private interaction with the people involved, including unsolicited interaction 98 | with those enforcing the Code of Conduct, is allowed during this period. 99 | Violating these terms may lead to a permanent ban. 100 | 101 | ### 4. Permanent Ban 102 | 103 | **Community Impact**: Demonstrating a pattern of violation of community 104 | standards, including sustained inappropriate behavior, harassment of an 105 | individual, or aggression toward or disparagement of classes of individuals. 106 | 107 | **Consequence**: A permanent ban from any sort of public interaction within 108 | the community. 109 | 110 | ## Attribution 111 | 112 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 113 | version 2.0, available at 114 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 115 | 116 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 117 | enforcement ladder](https://github.com/mozilla/diversity). 118 | 119 | [homepage]: https://www.contributor-covenant.org 120 | 121 | For answers to common questions about this code of conduct, see the FAQ at 122 | https://www.contributor-covenant.org/faq. Translations are available at 123 | https://www.contributor-covenant.org/translations. 124 | -------------------------------------------------------------------------------- /partials/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Github Profile Header Generator 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 27 | 28 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 41 | 43 | 45 | 46 | 48 | 49 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 66 | 67 | 68 | 93 | -------------------------------------------------------------------------------- /public/images/patterns/endless-constellation-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /partials/toolbox/decorations.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 6 | 8 | 100 9 |
10 |
11 |
Decorations:
12 |
13 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 43 | 47 | 51 | 54 | 58 | 62 | 66 | 69 | 72 | 75 | 78 | 82 | 85 | 88 | 91 | 94 | 97 | 100 |
101 |
102 | 103 | 104 |
105 | 106 | 💡Use an octocat from the 107 | Github 108 | Octodex 109 |
110 | 💡Or build your own at 111 | MyOctocat.com 112 | 114 |
115 |
116 |
117 |
-------------------------------------------------------------------------------- /styles/toolbox-main.scss: -------------------------------------------------------------------------------- 1 | .toolbox-container { 2 | .result-box { 3 | // height: 300px; 4 | padding: 2rem 2rem 0.5rem 2rem; 5 | background: var(--github-dark-mode-color); 6 | transition: 0.5s ease; 7 | user-select: none; 8 | position: relative; 9 | z-index: 20; 10 | border-bottom: solid 1px #373737; 11 | 12 | &.light-mode { 13 | background: var(--github-light-mode-color); 14 | 15 | .dark-mode-button, 16 | .randomize-button, 17 | .reset-button { 18 | color: black !important; 19 | 20 | &:hover { 21 | // box-shadow: 0px 0px 5px 2px rgba(255, 255, 255, 0.25); 22 | text-shadow: 0px 0px 10px #929292 !important; 23 | } 24 | } 25 | } 26 | 27 | .header-image-container { 28 | width: 100%; 29 | flex-grow: 1; 30 | // max-width: calc(1280px - 296px - 24px); 31 | max-width: calc(850px); 32 | margin: auto; 33 | width: 100%; 34 | filter: drop-shadow(0px 0px 5px rgba(125, 125, 125, 0.5)); 35 | } 36 | 37 | #github-header-image { 38 | width: 100%; 39 | height: 230px; 40 | padding: 25px; 41 | position: relative; 42 | display: flex; 43 | align-items: flex-start; 44 | justify-content: center; 45 | flex-direction: column; 46 | background-color: #62518d; 47 | color: white; 48 | border-radius: 7px; 49 | margin: 0 auto; 50 | border: none; 51 | overflow: hidden; 52 | background-size: 200px; 53 | transition: 0.25s ease; 54 | 55 | .title, 56 | .subtitle { 57 | transition: 0.25s ease; 58 | white-space: nowrap; 59 | } 60 | 61 | // Ensure Electrolize font loads properly 62 | .title[style*="Electrolize"], 63 | .subtitle[style*="Electrolize"] { 64 | font-family: "Electrolize", monospace !important; 65 | } 66 | 67 | img { 68 | transition: 0.15s; 69 | } 70 | } 71 | 72 | .options-container { 73 | max-width: calc(850px); 74 | margin: auto; 75 | user-select: none; 76 | display: flex; 77 | align-items: center; 78 | gap: 35px; 79 | justify-content: space-between; 80 | // flex-wrap: wrap; 81 | padding: 1rem 0 0.5rem 0; 82 | overflow: auto; 83 | 84 | >div:first-child { 85 | display: flex; 86 | gap: 2rem; 87 | } 88 | 89 | .dark-mode-button, 90 | .randomize-button, 91 | .download-button, 92 | .reset-button { 93 | background-color: transparent; 94 | display: flex; 95 | gap: 7px; 96 | justify-content: center; 97 | align-items: center; 98 | width: fit-content; 99 | height: 35px; 100 | // border: 1px solid #ffffff; 101 | // border-radius: var(--button-border-radius); 102 | color: var(--text-color); 103 | // text-transform: uppercase; 104 | text-align: center; 105 | font-weight: 600; 106 | white-space: nowrap; 107 | transition: all 0.25s ease-in-out; 108 | cursor: pointer; 109 | 110 | img { 111 | transition: all ease 500ms; 112 | } 113 | 114 | &:hover { 115 | // box-shadow: 0px 0px 5px 2px rgba(255, 255, 255, 0.25); 116 | text-shadow: 0px 0px 10px rgb(255, 255, 255); 117 | 118 | img { 119 | transform: scale(1.2); 120 | } 121 | } 122 | } 123 | 124 | .download-button, 125 | .display-button, 126 | .miniature-button { 127 | background-color: #2D8655 !important; 128 | // border: 1px solid #ffffff; 129 | border-radius: var(--button-border-radius); 130 | padding: 5px 15px; 131 | } 132 | } 133 | } 134 | 135 | .toolbox-tools { 136 | height: calc(100vh - 230px - 3rem - 35px - 1rem); 137 | overflow: auto; 138 | padding: 1rem 1rem 4rem 1rem; 139 | } 140 | 141 | .toolbox { 142 | box-sizing: border-box; 143 | 144 | >div { 145 | display: flex; 146 | align-items: center; 147 | justify-content: center; 148 | flex-wrap: wrap; 149 | 150 | &:not(:last-child) { 151 | margin-bottom: 15px; 152 | } 153 | } 154 | 155 | .text-inputs { 156 | justify-content: space-between; 157 | 158 | input { 159 | text-align: center; 160 | width: calc(50% - 7.5px); 161 | } 162 | } 163 | 164 | .color-selectors-container { 165 | div { 166 | display: flex; 167 | align-items: center; 168 | 169 | &:not(:last-child) { 170 | margin-right: 15px; 171 | } 172 | 173 | input { 174 | margin-left: 5px; 175 | cursor: pointer; 176 | padding: 0; 177 | } 178 | } 179 | } 180 | 181 | .size-inputs { 182 | >div { 183 | &:not(:last-child) { 184 | margin-right: 15px; 185 | } 186 | 187 | input { 188 | width: 70px; 189 | margin-left: 5px; 190 | } 191 | } 192 | 193 | .paddings-input { 194 | width: 100px; 195 | } 196 | } 197 | 198 | .align-buttons { 199 | button { 200 | margin-left: 5px; 201 | } 202 | } 203 | 204 | .font-selectors-container { 205 | column-gap: 1rem; 206 | row-gap: 0.5rem; 207 | 208 | select { 209 | cursor: pointer; 210 | margin-left: 5px; 211 | 212 | option { 213 | color: black; 214 | } 215 | } 216 | } 217 | 218 | .font-size-inputs { 219 | display: flex; 220 | 221 | div { 222 | display: flex; 223 | align-items: flex-start; 224 | 225 | &:not(:last-child) { 226 | margin-right: 15px; 227 | } 228 | 229 | input { 230 | cursor: pointer; 231 | } 232 | } 233 | } 234 | } 235 | } 236 | 237 | @media (max-width: 768px) { 238 | .toolbox-container { 239 | input { 240 | margin-bottom: 5px; 241 | } 242 | 243 | .result-box { 244 | padding: 2rem 1rem 0.5rem 1rem; 245 | 246 | #github-header-image { 247 | height: 230px; 248 | } 249 | 250 | .options-container { 251 | gap: 10px; 252 | 253 | >div:first-child { 254 | gap: 10px; 255 | } 256 | } 257 | } 258 | 259 | .toolbox-tools { 260 | height: calc(100vh - 230px - 3rem - 35px - 2rem - 2rem); 261 | min-height: 300px; 262 | } 263 | 264 | .toolbox { 265 | .text-inputs { 266 | input { 267 | width: 100%; 268 | // &:not(:last-child) { 269 | // margin-bottom: 10px; 270 | // } 271 | } 272 | } 273 | 274 | .font-size-inputs { 275 | input { 276 | &:not(:last-child) { 277 | margin-bottom: 15px; 278 | } 279 | } 280 | } 281 | } 282 | } 283 | } 284 | 285 | @media (max-width: 410px) { 286 | .toolbox-container { 287 | .result-box { 288 | .options-container { 289 | flex-wrap: wrap; 290 | gap: 10px; 291 | justify-content: center; 292 | 293 | >div:first-child { 294 | gap: 10px; 295 | } 296 | } 297 | } 298 | } 299 | 300 | } -------------------------------------------------------------------------------- /js/main.js: -------------------------------------------------------------------------------- 1 | import { snapdom } from '@zumer/snapdom'; 2 | import { getMainElements } from './helpers/elements'; 3 | import { isDevOptions, isLocalDevelopment } from './helpers/helpers'; 4 | import { getAllPresets, getRandomPreset, setPreset } from './presets'; 5 | 6 | /* ************** Elements ************** */ 7 | 8 | const { 9 | bannerImageContainer, 10 | bannerImage, 11 | toolbox, 12 | } = getMainElements(); 13 | 14 | /* ************** Options ************** */ 15 | 16 | const initialTheme = { 17 | textAlign: "center", 18 | ...getAllPresets()[15], 19 | background: "#62518d", 20 | borderSize: 5, 21 | decoration: 'dino-border.png', 22 | subtitleColor: "#FFF2B3", 23 | titleFont: 'Red Hat Display', 24 | subtitleFont: 'Kalam' 25 | } 26 | 27 | // Init 28 | toolbox.querySelector('.size-inputs input#width-input').value = bannerImageContainer.clientWidth; 29 | document.addEventListener("DOMContentLoaded", (event) => { 30 | const theme = localStorage.getItem('theme'); 31 | if (theme) 32 | setPreset(JSON.parse(theme), true); 33 | else 34 | setPreset(initialTheme); 35 | }); 36 | 37 | // Demo reset after ended 38 | document.querySelector('.how-to-section video.demo').onended = (e) => e.target.currentTime = 0; 39 | 40 | // Decoration 41 | 42 | const imageDecorationContainer = document.querySelector('.img-decoration-container'); 43 | const imgDecorationElement = document.createElement('img'); 44 | imgDecorationElement.className = 'img-decoration'; 45 | imgDecorationElement.style.position = 'absolute'; 46 | imgDecorationElement.style.bottom = 'calc(50%)'; 47 | imgDecorationElement.style.transform = 'translateY(50%)' 48 | imgDecorationElement.style.left = 'auto'; 49 | imgDecorationElement.style.right = '25px'; 50 | imgDecorationElement.style.width = '0px'; 51 | imgDecorationElement.alt = 'Header image decoration' 52 | imageDecorationContainer.appendChild(imgDecorationElement) 53 | 54 | /* ************** Header image options ************** */ 55 | 56 | // Download button 57 | document.querySelector('.download-button') 58 | .addEventListener('click', async () => { 59 | document.querySelector('.download-button img').src = './images/icons/loading.gif' 60 | 61 | try { 62 | await snapdom.download( 63 | bannerImage, 64 | { 65 | embedFonts: true, 66 | format: 'png', 67 | filename: 'github-header-banner', 68 | scale: 2 69 | }); 70 | document.querySelector('.download-button img').src = './images/icons/download.svg' 71 | } catch (error) { 72 | console.error('Image capture or download failed:', error); 73 | } 74 | }) 75 | 76 | // For local development 77 | document.addEventListener("DOMContentLoaded", (event) => { 78 | const displayButton = document.querySelector('.display-button'); 79 | const miniatureButton = document.querySelector('.miniature-button'); 80 | const testFontsTab = document.querySelector('.tablinks[data-name="test-fonts-section"]'); 81 | 82 | if (isLocalDevelopment && isDevOptions == 1) { 83 | const el = document.querySelector('#github-header-image'); 84 | const container = document.querySelector('.header-image-container') 85 | 86 | if (displayButton) { 87 | displayButton.style.display = "block"; 88 | 89 | displayButton.addEventListener('click', async () => { 90 | const png = await snapdom.toPng(el, { embedFonts: true }); 91 | 92 | const prevImage = container.children[1]; 93 | if (prevImage) container.removeChild(prevImage); 94 | 95 | container.appendChild(png); 96 | document.querySelector('.toolbox-container .toolbox-tools').style.height = 'calc(100vh - 230px - 3rem - 35px - 1rem - 230px)' 97 | }) 98 | } 99 | if (miniatureButton) { 100 | miniatureButton.style.display = "block"; 101 | // console.log('Running on localhost! display appending image option ...'); 102 | 103 | miniatureButton.addEventListener('click', async () => { 104 | const png = await snapdom.toPng(el, { embedFonts: true, scale: 0.25 }); 105 | 106 | const prevImage = container.children[1]; 107 | if (prevImage) container.removeChild(prevImage); 108 | 109 | container.appendChild(png); 110 | document.querySelector('.toolbox-container .toolbox-tools').style.height = 'calc(100vh - 230px - 3rem - 35px - 1rem - 46px)' 111 | }) 112 | } 113 | if (testFontsTab) { 114 | // testFontsTab.style.display = "block" 115 | } 116 | } 117 | }); 118 | 119 | // Toogle Dark Mode button 120 | document.querySelector('.dark-mode-button') 121 | .addEventListener('click', (e) => { 122 | let resultBox = document.querySelector('.result-box'); 123 | const toogleDarkModeButton = document.querySelector('.dark-mode-button'); 124 | const toogleRandomizeButton = document.querySelector('.randomize-button'); 125 | const toogleResetButton = document.querySelector('.reset-button'); 126 | const toogleDownloadButton = document.querySelector('.download-button'); 127 | 128 | const size = 20; 129 | 130 | resultBox.classList.toggle('light-mode'); 131 | if (resultBox.className.includes('light')) { 132 | toogleDarkModeButton.innerHTML = `Light` 133 | toogleRandomizeButton.innerHTML = `Random` 134 | toogleResetButton.innerHTML = `Reset` 135 | toogleDownloadButton.innerHTML = `Download` 136 | } else { 137 | toogleDarkModeButton.innerHTML = `Dark` 138 | toogleRandomizeButton.innerHTML = `Random` 139 | toogleResetButton.innerHTML = `Reset` 140 | toogleDownloadButton.innerHTML = `Download` 141 | } 142 | }); 143 | 144 | // Randomize 145 | document.querySelector('.randomize-button') 146 | .addEventListener('click', (e) => { 147 | const theme = getRandomPreset(); 148 | setPreset(theme); 149 | }); 150 | 151 | document.querySelector('.reset-button') 152 | .addEventListener('click', (e) => { 153 | const darkMode = localStorage.getItem('darkMode'); 154 | localStorage.clear(); 155 | localStorage.setItem('darkMode', darkMode); 156 | setPreset(initialTheme); 157 | }); 158 | 159 | /* ************** Tabs ************** */ 160 | 161 | function openTab(e, name) { 162 | let i, tabcontent, tablinks; 163 | 164 | tabcontent = document.getElementsByClassName("tabcontent"); 165 | for (i = 0; i < tabcontent.length; i++) { 166 | tabcontent[i].style.display = "none"; 167 | } 168 | 169 | tablinks = document.getElementsByClassName("tablinks"); 170 | for (i = 0; i < tablinks.length; i++) { 171 | tablinks[i].className = tablinks[i].className.replace(" active", ""); 172 | } 173 | 174 | document.getElementById(name).style.display = "block"; 175 | e.currentTarget.className += " active"; 176 | } 177 | 178 | document.querySelectorAll('.tab .tablinks') 179 | .forEach(button => { 180 | button.addEventListener('click', (e) => { 181 | const name = e.target.getAttribute('data-name'); 182 | localStorage.setItem('openTab', name) 183 | openTab(e, name); 184 | }); 185 | }) 186 | 187 | // Saved tab 188 | document.addEventListener("DOMContentLoaded", (event) => { 189 | const openTab = localStorage.getItem('openTab'); 190 | if (openTab) { 191 | document.querySelector(`[data-name="${openTab}"]`).click(); 192 | } else { 193 | document.getElementById("defaultOpenTag").click(); 194 | } 195 | }); 196 | 197 | /* ************** Dark Mode ************** */ 198 | 199 | function setLightMode() { 200 | localStorage.setItem('darkMode', 0); 201 | document.documentElement.setAttribute("data-theme", "light"); 202 | document.querySelector('#light-mode-btn').classList.add('selected'); 203 | document.querySelector('#dark-mode-btn').classList.remove('selected'); 204 | } 205 | function setDarkMode() { 206 | localStorage.setItem('darkMode', 1); 207 | document.documentElement.setAttribute("data-theme", "dark"); 208 | document.querySelector('#light-mode-btn').classList.remove('selected'); 209 | document.querySelector('#dark-mode-btn').classList.add('selected'); 210 | } 211 | 212 | document.addEventListener("DOMContentLoaded", (event) => { 213 | const localDarkMode = localStorage.getItem('darkMode'); 214 | if (localDarkMode && localDarkMode == 1){ 215 | document.querySelector('#dark-mode-btn').classList.add('selected'); 216 | } else { 217 | document.querySelector('#light-mode-btn').classList.add('selected'); 218 | } 219 | document.querySelector('#light-mode-btn').onclick = setLightMode; 220 | document.querySelector('#dark-mode-btn').onclick = setDarkMode; 221 | }); 222 | 223 | /* ************** ************** ************** */ 224 | --------------------------------------------------------------------------------