diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..a7885f77 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,3 @@ +ARG VARIANT="22-bookworm" + +FROM mcr.microsoft.com/devcontainers/typescript-node:1-${VARIANT} diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..5b3da302 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,36 @@ +{ + "name": "Socialify Dev Environment", + + "build": { + "dockerfile": "Dockerfile" + }, + + "features": { + "ghcr.io/devcontainers/features/github-cli:1": { + "installDirectlyFromGitHubRelease": true, + "version": "latest" + } + }, + + "forwardPorts": [3000], + + "containerEnv": { + "NEXT_TELEMETRY_DISABLED": "1", + "PNPM_HOME": "/home/node/.local/share/pnpm", + "PNPM_STORE_DIR": "/home/node/.local/share/.pnpm-store" + }, + + "postCreateCommand": "corepack install", + + "postStartCommand": ".devcontainer/post-start.sh", + + "customizations": { + "vscode": { + "extensions": [ + "GitHub.copilot", + "biomejs.biome", + "ms-playwright.playwright" + ] + } + } +} diff --git a/.devcontainer/post-start.sh b/.devcontainer/post-start.sh new file mode 100755 index 00000000..7236cb96 --- /dev/null +++ b/.devcontainer/post-start.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +if [ ! -f /home/node/.first_run ]; then + git config --global --add safe.directory $(pwd) + git config --global core.autocrlf true + git config --global core.editor nano + + pnpm config set store-dir $PNPM_STORE_DIR + pnpm install + pnpm playwright:install + + if [ ! -f .env ]; then + cp .env.example .env + echo -e "\e[31mPlease fill in the .env file\e[0m" + fi + + touch /home/node/.first_run +fi diff --git a/.gitignore b/.gitignore index 81ff896c..89faabbb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,5 @@ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. -# Local vscode -.vscode - # Playwright /.playwright/.cache /.playwright/test-report diff --git a/.husky/prepare-commit-msg b/.husky/prepare-commit-msg index 1d00a734..102361b6 100755 --- a/.husky/prepare-commit-msg +++ b/.husky/prepare-commit-msg @@ -1,4 +1,4 @@ #!/bin/sh # gitmoji as a commit hook exec < /dev/tty -npx gitmoji-cli --hook $1 $2 +npx --yes gitmoji-cli --hook $1 $2 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..b2d79f0c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "editor.defaultFormatter": "biomejs.biome", + "editor.formatOnSave": true, + "editor.tabSize": 2, + "files.insertFinalNewline": true +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 26fba5b5..8efe5eee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # socialify +## 2.15.1 + +### Patch Changes + +- ca0cebb: Set up dev container + +## 2.15.0 + +### Minor Changes + +- c739cec: Support transparent background + +## 2.14.6 + +### Patch Changes + +- c32156a: remove unused npm packages + + Thanks to [@Sunny-64](https://github.com/Sunny-64) + ## 2.14.5 ### Patch Changes @@ -8,7 +28,7 @@ Updated scripts, hooks, and README.md Thanks to [@Keming-He](https://github.com/KemingHe) - + Update Dockerfile ## 2.14.4 diff --git a/README.md b/README.md index 2908bc30..af685e38 100644 --- a/README.md +++ b/README.md @@ -78,11 +78,18 @@ pnpm dev ### Testing and Committing +[![Open in Dev Container](https://img.shields.io/static/v1?label=Dev%20Containers&message=Click%20to%20Launch&color=blue)](https://open.vscode.dev/wei/socialify) + +If you already have VS Code and Docker installed locally, you can also click [here](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/wei/socialify) to get started. Clicking this link will cause VS Code to automatically install the Dev Containers extension if needed, clone the source code into a container volume, and spin up a dev container for use. + Socialify uses [`biomejs`](https://biomejs.dev/) as linter/formatter, [`Jest`](https://jestjs.io/) for unit testing, and [`Playwright`](https://playwright.dev/) for end-to-end testing. Make sure to run and pass the linter, unit and end-to-end tests locally before committing your code. Please let us know in case you need to update the test snapshots. More in `"scripts"` section in your `package.json` file. ```shell +# Required: Set environment variables in .env. +cp .env.example .env + # Run linter/formatter pnpm lint @@ -93,7 +100,7 @@ pnpm lint pnpm test:unit # Install Playwright dependencies (first-time) -# pnpm playwright install --with-deps chrome +# pnpm playwright:install # Run e2e tests pnpm test:e2e diff --git a/common/helpers.ts b/common/helpers.ts index 063aa9a1..fb6aab62 100644 --- a/common/helpers.ts +++ b/common/helpers.ts @@ -9,6 +9,7 @@ import { plus, signal, } from 'hero-patterns' +import type { CSSProperties } from 'react' import { type SimpleIcon, siApachegroovy, @@ -140,7 +141,7 @@ const getSimpleIconsImageURI = function (language: string, theme: Theme) { return `data:image/svg+xml,${encodeURIComponent(iconSvg)}` } -const getHeroPattern = (pattern: Pattern, theme: Theme) => { +const getHeroPattern = (pattern: Pattern, theme: Theme): CSSProperties => { const PATTERN_FUNCTIONS_MAPPING: { [key: string]: any } = { [Pattern.signal]: signal, [Pattern.charlieBrown]: charlieBrown, @@ -152,9 +153,15 @@ const getHeroPattern = (pattern: Pattern, theme: Theme) => { [Pattern.floatingCogs]: floatingCogs, [Pattern.diagonalStripes]: diagonalStripes, [Pattern.solid]: null, + [Pattern.transparent]: null, } const patternFunction = PATTERN_FUNCTIONS_MAPPING[pattern] - const themedBackgroundColor = theme === Theme.dark ? '#000' : '#fff' + const themedBackgroundColor = + pattern === Pattern.transparent + ? 'transparent' + : theme === Theme.dark + ? '#000' + : '#fff' if (!patternFunction) { return { @@ -224,11 +231,50 @@ const autoThemeCss = ` } ` +const getChessBoardPattern = (theme: Theme): CSSProperties => { + const chessPatternColors = { + light: ['#fff', '#ccc'], + dark: ['#2f2f2f', '#000'], + } + + const getSVGImage = (mode: 'light' | 'dark') => { + const [color1, color2] = chessPatternColors[mode] + return ` + + ` + } + + let svg: string + if (theme === Theme.auto) { + svg = ` + + ` + } else { + svg = getSVGImage(theme === Theme.dark ? 'dark' : 'light') + } + svg = svg.replace(/\n\s*/g, '') + + return { + backgroundImage: `url('data:image/svg+xml,${encodeURIComponent(svg.replace(/\n\s*/g, ''))}`, + backgroundRepeat: 'repeat', + } +} + const version = packageJson.version export { getSimpleIconsImageURI, getHeroPattern, + getChessBoardPattern, checkWebpSupport, HOST_PREFIX, autoThemeCss, diff --git a/common/types/configType.ts b/common/types/configType.ts index e2513200..53afc5f9 100644 --- a/common/types/configType.ts +++ b/common/types/configType.ts @@ -15,6 +15,7 @@ enum Pattern { floatingCogs = 'Floating Cogs', diagonalStripes = 'Diagonal Stripes', solid = 'Solid', + transparent = 'Transparent', } enum Font { diff --git a/package.json b/package.json index ed29c80e..a15305f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socialify", - "version": "2.14.5", + "version": "2.15.1", "description": "Socialify your project. Share with the world!", "author": "@CryogenicPlanet, @wei", "license": "MIT", @@ -16,12 +16,13 @@ "test:e2e:update-snapshot": "playwright test --update-snapshots", "test": "pnpm test:unit && pnpm test:e2e", "start": "next start", - "lint": "biome ci --max-diagnostics=999 .", - "lint:fix": "biome check --write --verbose --max-diagnostics=999 .", - "lint:fix-unsafe": "biome check --write-unsafe --verbose --max-diagnostics=999 .", + "lint": "biome ci .", + "lint:fix": "biome check --write --verbose .", + "lint:fix-unsafe": "biome check --write-unsafe --verbose .", "ncu": "npx npm-check-updates -u", "verify": "pnpm lint && pnpm test && pnpm build", "download-font": "./fonts/download-font.sh", + "playwright:install": "pnpm playwright install --with-deps chromium", "postinstall": "mkdir -p ./public && cp ./node_modules/yoga-wasm-web/dist/yoga.wasm ./public/yoga.wasm && cp ./node_modules/@resvg/resvg-wasm/index_bg.wasm ./public/resvg_bg.wasm", "prepare": "is-ci || husky" }, @@ -39,11 +40,10 @@ "next": "^14.2.8", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-error-boundary": "^4.1.2", "react-hot-toast": "^2.4.1", "react-icons": "^5.4.0", "satori": "^0.10.14", - "simple-icons": "^13.20.0", + "simple-icons": "^13.21.0", "styled-jsx": "^5.1.6", "use-debounce": "^10.0.4", "yoga-wasm-web": "^0.3.3" @@ -60,8 +60,6 @@ "@types/react": "18.3.12", "autoprefixer": "^10.4.20", "daisyui": "^4.12.14", - "graphql": "^16.9.0", - "graphql-compiler": "^1.7.0", "husky": "^9.1.7", "identity-obj-proxy": "^3.0.0", "jest": "^29.7.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c80009ea..25b10210 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,9 +38,6 @@ importers: react-dom: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) - react-error-boundary: - specifier: ^4.1.2 - version: 4.1.2(react@18.3.1) react-hot-toast: specifier: ^2.4.1 version: 2.4.1(csstype@3.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -51,8 +48,8 @@ importers: specifier: ^0.10.14 version: 0.10.14 simple-icons: - specifier: ^13.20.0 - version: 13.20.0 + specifier: ^13.21.0 + version: 13.21.0 styled-jsx: specifier: ^5.1.6 version: 5.1.6(@babel/core@7.26.0)(react@18.3.1) @@ -96,12 +93,6 @@ importers: daisyui: specifier: ^4.12.14 version: 4.12.22(postcss@8.4.49) - graphql: - specifier: ^16.9.0 - version: 16.9.0 - graphql-compiler: - specifier: ^1.7.0 - version: 1.7.0(graphql@16.9.0) husky: specifier: ^9.1.7 version: 9.1.7 @@ -757,10 +748,6 @@ packages: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} - ansi-regex@2.1.1: - resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} - engines: {node: '>=0.10.0'} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -769,10 +756,6 @@ packages: resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} engines: {node: '>=12'} - ansi-styles@2.2.1: - resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} - engines: {node: '>=0.10.0'} - ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -919,10 +902,6 @@ packages: caniuse-lite@1.0.30001688: resolution: {integrity: sha512-Nmqpru91cuABu/DTCXbM2NSRHzM2uVHfPnhJ/1zEAJx/ILBRVmz3pzH4N7DZqbdG0gWClsCC05Oj0mJ/1AWMbA==} - chalk@1.1.3: - resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} - engines: {node: '>=0.10.0'} - chalk@3.0.0: resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} engines: {node: '>=8'} @@ -1167,10 +1146,6 @@ packages: escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - escape-string-regexp@2.0.0: resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} engines: {node: '>=8'} @@ -1325,22 +1300,9 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - graphql-compiler@1.7.0: - resolution: {integrity: sha512-jC4PBo1ikFRiA2CLclNxMMFJTwhxPam1HxzIxJgWWHm26AXw0ZsN41a2t6vGfw7NxXCfnef4JCIHWFMgIm8iOQ==} - peerDependencies: - graphql: ^0.13.0 - - graphql@16.9.0: - resolution: {integrity: sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==} - engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - harmony-reflect@1.6.2: resolution: {integrity: sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==} - has-ansi@2.0.0: - resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} - engines: {node: '>=0.10.0'} - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -1399,10 +1361,6 @@ packages: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} - immutable@3.7.6: - resolution: {integrity: sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==} - engines: {node: '>=0.8.0'} - import-local@3.2.0: resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} engines: {node: '>=8'} @@ -2040,11 +1998,6 @@ packages: peerDependencies: react: ^18.3.1 - react-error-boundary@4.1.2: - resolution: {integrity: sha512-GQDxZ5Jd+Aq/qUxbCm1UtzmL/s++V7zKgE8yMktJiCQXCCFZnMZh9ng+6/Ne6PjNSXH0L9CjeOEREfRnq6Duag==} - peerDependencies: - react: '>=16.13.1' - react-hot-toast@2.4.1: resolution: {integrity: sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==} engines: {node: '>=10'} @@ -2153,8 +2106,8 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - simple-icons@13.20.0: - resolution: {integrity: sha512-8IQSSOaXhgG9fH0dJsUmlMlo0Jt0Xd1MwxsK75TlRZO0FR7P5UQ8TEaIPOwlRMHd/FzZJ0R3vFHW0kOH7PbdMw==} + simple-icons@13.21.0: + resolution: {integrity: sha512-LI5pVJPBv6oc79OMsffwb6kEqnmB8P1Cjg1crNUlhsxPETQ5UzbCKQdxU+7MW6+DD1qfPkla/vSKlLD4IfyXpQ==} engines: {node: '>=0.12.18'} sisteransi@1.0.5: @@ -2204,10 +2157,6 @@ packages: string.prototype.codepointat@0.2.1: resolution: {integrity: sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==} - strip-ansi@3.0.1: - resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} - engines: {node: '>=0.10.0'} - strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -2267,10 +2216,6 @@ packages: engines: {node: '>=16 || 14 >=14.17'} hasBin: true - supports-color@2.0.0: - resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} - engines: {node: '>=0.8.0'} - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -3336,14 +3281,10 @@ snapshots: dependencies: type-fest: 0.21.3 - ansi-regex@2.1.1: {} - ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} - ansi-styles@2.2.1: {} - ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 @@ -3502,14 +3443,6 @@ snapshots: caniuse-lite@1.0.30001688: {} - chalk@1.1.3: - dependencies: - ansi-styles: 2.2.1 - escape-string-regexp: 1.0.5 - has-ansi: 2.0.0 - strip-ansi: 3.0.1 - supports-color: 2.0.0 - chalk@3.0.0: dependencies: ansi-styles: 4.3.0 @@ -3714,8 +3647,6 @@ snapshots: escape-html@1.0.3: {} - escape-string-regexp@1.0.5: {} - escape-string-regexp@2.0.0: {} escodegen@2.1.0: @@ -3883,21 +3814,8 @@ snapshots: graceful-fs@4.2.11: {} - graphql-compiler@1.7.0(graphql@16.9.0): - dependencies: - chalk: 1.1.3 - fb-watchman: 2.0.2 - graphql: 16.9.0 - immutable: 3.7.6 - - graphql@16.9.0: {} - harmony-reflect@1.6.2: {} - has-ansi@2.0.0: - dependencies: - ansi-regex: 2.1.1 - has-flag@4.0.0: {} hasown@2.0.2: @@ -3949,8 +3867,6 @@ snapshots: ignore@5.3.2: {} - immutable@3.7.6: {} - import-local@3.2.0: dependencies: pkg-dir: 4.2.0 @@ -4743,11 +4659,6 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 - react-error-boundary@4.1.2(react@18.3.1): - dependencies: - '@babel/runtime': 7.26.0 - react: 18.3.1 - react-hot-toast@2.4.1(csstype@3.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: goober: 2.1.16(csstype@3.1.3) @@ -4851,7 +4762,7 @@ snapshots: signal-exit@4.1.0: {} - simple-icons@13.20.0: {} + simple-icons@13.21.0: {} sisteransi@1.0.5: {} @@ -4898,10 +4809,6 @@ snapshots: string.prototype.codepointat@0.2.1: {} - strip-ansi@3.0.1: - dependencies: - ansi-regex: 2.1.1 - strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -4946,8 +4853,6 @@ snapshots: pirates: 4.0.6 ts-interface-checker: 0.1.13 - supports-color@2.0.0: {} - supports-color@7.2.0: dependencies: has-flag: 4.0.0 diff --git a/src/components/preview/preview.tsx b/src/components/preview/preview.tsx index c1e97153..fb3c7299 100644 --- a/src/components/preview/preview.tsx +++ b/src/components/preview/preview.tsx @@ -5,7 +5,8 @@ import Router from 'next/router' import React, { useContext } from 'react' import { MdContentCopy, MdDownload } from 'react-icons/md' -import { checkWebpSupport } from '@/common/helpers' +import { checkWebpSupport, getChessBoardPattern } from '@/common/helpers' +import { Pattern } from '@/common/types/configType' import Card from '@/src/components/preview/card' import toaster from '@/src/components/toaster' import ConfigContext from '@/src/contexts/ConfigContext' @@ -109,6 +110,11 @@ const Preview: React.FC = () => { 'min-[640px]:w-[640px] min-[640px]:h-[320px]' )} onClick={copyImageUrl} + style={ + config.pattern === Pattern.transparent + ? getChessBoardPattern(config.theme) + : undefined + } >