diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..1f3e3d7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,62 @@ +name: Bug report +description: Something does not work, or does not work the way the docs say. +labels: ['bug'] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time. You do not need to diagnose the problem — "I expected X and + got Y" is a complete report. Fill in what you know and leave the rest blank. + + - type: textarea + id: what-happened + attributes: + label: What happened? + description: What did you expect, and what did you get instead? + placeholder: | + I set columnWidth="260" and expected four columns on a 1200px screen, but got three. + validations: + required: true + + - type: input + id: reproduction + attributes: + label: Reproduction + description: > + A StackBlitz is the fastest way to get this fixed. Fork the starter and break it: + https://stackblitz.com/github/MeAkib/masonry-angular/tree/main/examples/stackblitz + If that is not practical, paste the relevant template and component code below instead. + placeholder: https://stackblitz.com/edit/... + + - type: textarea + id: code + attributes: + label: Code + description: The template and options you used. Formatted automatically, no backticks needed. + render: html + + - type: input + id: versions + attributes: + label: Versions + description: Output of `npx ng version`, or just the Angular and masonry-angular versions. + placeholder: Angular 19.2.0, masonry-angular 0.0.1 + validations: + required: true + + - type: input + id: browser + attributes: + label: Browser and OS + placeholder: Safari 26.4 on macOS, Chrome 141 on Windows, Chrome on Android 15 + + - type: checkboxes + id: context + attributes: + label: Anything that applies + options: + - label: It happens with server-side rendering (SSR) + - label: It happens only after items are added, removed or reordered + - label: It happens only at certain window sizes + - label: 'I am using `native: true`' + - label: I found a workaround (please describe it above — the workaround is a clue) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..26a8521 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: true +contact_links: + - name: Getting started guide + url: https://github.com/MeAkib/masonry-angular/blob/main/projects/masonry-angular/GETTING-STARTED.md + about: Install to a responsive gallery, with the common mistakes called out. + - name: Full reference + url: https://github.com/MeAkib/masonry-angular/blob/main/projects/masonry-angular/DOCS.md + about: Every option, spans, stamps, testing, and migrating from ngx-masonry. + - name: Try it in StackBlitz + url: https://stackblitz.com/github/MeAkib/masonry-angular/tree/main/examples/stackblitz + about: A running grid you can fork to reproduce a problem. diff --git a/.github/ISSUE_TEMPLATE/experience_report.yml b/.github/ISSUE_TEMPLATE/experience_report.yml new file mode 100644 index 0000000..83ec75e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/experience_report.yml @@ -0,0 +1,45 @@ +name: Experience report +description: You used it, or tested it somewhere new. Nothing is necessarily broken. +labels: ['feedback'] +body: + - type: markdown + attributes: + value: | + At version 0.0.1 this is the most useful thing anyone can file. It does not have to be a + bug, and it does not have to be polished. + + - type: textarea + id: what + attributes: + label: What did you build or test? + placeholder: | + A photo gallery in a side panel, Angular 20, Safari 26.4 on macOS. + validations: + required: true + + - type: textarea + id: friction + attributes: + label: What was harder than it should have been? + description: > + Anything you had to read twice, guess at, or find by trial and error. Docs that did not + answer your question count. So does an option whose name did not mean what you assumed. + + - type: textarea + id: worked + attributes: + label: What worked well? (optional) + description: Useful for knowing what not to change. + + - type: checkboxes + id: coverage + attributes: + label: If you tested somewhere we have not, tick it + options: + - label: Safari + - label: Firefox + - label: A mobile browser + - label: Right-to-left layout + - label: Screen reader or keyboard-only navigation + - label: A low-end or older device + - label: 'Native CSS masonry (`display: grid-lanes`) in a browser that supports it' diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..62b9f55 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,42 @@ +name: Feature request +description: Something the library cannot do yet. +labels: ['enhancement'] +body: + - type: markdown + attributes: + value: | + Open one of these before writing code. Not for permission — sometimes the answer is + "that already works, here is how", which saves you the work. + + - type: textarea + id: problem + attributes: + label: What are you trying to build? + description: > + Describe the situation rather than the API you have in mind. The underlying problem often + has a solution the requested feature would not have covered. + placeholder: | + I have a feed where new posts arrive at the top while the user is scrolled down, and ... + validations: + required: true + + - type: textarea + id: workaround + attributes: + label: What have you tried? + description: Which options or approaches did you look at, and where did they fall short? + + - type: textarea + id: proposal + attributes: + label: What would it look like? (optional) + description: An API sketch, if you have one in mind. + render: html + + - type: markdown + attributes: + value: | + One thing worth knowing: every byte ships to everyone who installs this, so a new option + has to earn its size. A feature that can be built on top of the existing API, or lives in + your own code, is usually the better outcome — and if that is the answer, the issue will + explain how. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..973b18c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,24 @@ + + +## What does this change? + + + +## How to see it + + + +## Checks + +- [ ] `npm test` passes +- [ ] `npm run format` run on the files I touched +- [ ] Added a test, if this fixes a bug — one that fails before the change and passes after +- [ ] `npm run verify:compat`, if I changed anything public (builds a real app on Angular 17–22) + + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..f812ed9 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,146 @@ +name: CI + +# Everything here runs on every pull request, and must pass before merging. +# The slow Angular-version matrix lives in compat.yml, which does not run here. +on: + pull_request: + push: + branches: [main] + +# A new push to a branch makes the previous run irrelevant. +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + # Formatting, unit tests, and both builds. Fast enough to be the gate. + verify: + name: Tests and build + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 + with: + node-version: 24 + cache: npm + - run: npm ci + + - name: Formatting + run: npx prettier --check "projects/**/*.{ts,html,css,json}" + + - name: Unit tests + run: npm test + + - name: Build the library + run: npm run build:lib + + # Also exercises the command Vercel runs, and the llms.txt sync step. + - name: Build the demo + run: npm run build + + - name: Bundle size + run: npm run size + + # The server-rendering claim, checked on a real server rather than in jsdom — + # which defines `window` and so could never catch a stray browser call. + ssr: + name: Server rendering + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 + with: + node-version: 24 + cache: npm + - run: npm ci + - run: npm run verify:ssr + + # Native CSS masonry in a real browser engine. Playwright is deliberately not + # a dependency of the package, so it is installed here instead. + native: + name: Native CSS masonry + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 + with: + node-version: 24 + cache: npm + - run: npm ci + - run: npm run build:lib + + # Both are needed: the npm package, which the script imports, and the + # browser binary. Installing only the browser leaves the script unable to + # import playwright — and it would then skip and exit 0. + - name: Install Playwright and Chromium + run: | + npm i --no-save playwright + npx playwright install --with-deps chromium + + # The script exits 0 when it cannot run, which is right on a contributor's + # machine and wrong here: a skipped check that reports success is worse + # than no check. A missing browser is CI's fault and fails the job. A + # Chromium that simply has no masonry implementation is not, so that one + # only warns. + - name: Native CSS masonry + run: | + set -o pipefail + npm run verify:native 2>&1 | tee native.log + if grep -qE 'skipped: (playwright is not installed|could not launch)' native.log; then + echo "::error::verify:native could not run. CI must exercise the native path, not skip it." + exit 1 + fi + if grep -q 'skipped:' native.log; then + echo "::warning::This Chromium has no masonry implementation, so the native path went unchecked." + fi + + # Compiles the examples in the README, the getting-started guide and llms.txt. + # Two examples once shipped to npm that could not compile at all; this is what + # stops that happening again. + docs: + name: Documentation examples + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 + with: + node-version: 24 + cache: npm + - run: npm ci + - run: npm run verify:docs + + # One check to require in the branch protection rule, so that adding or + # renaming a job above never means editing repository settings — and a job + # that silently stops running can never leave a rule waiting on a name that + # no longer reports. + # + # `always()` is what makes it work: without it this job would itself be + # skipped when something upstream fails, and a skipped required check blocks + # the pull request rather than failing it. + gate: + name: All checks passed + if: always() + needs: [verify, ssr, native, docs] + runs-on: ubuntu-latest + timeout-minutes: 2 + steps: + - name: Check the results + run: | + echo "verify: ${{ needs.verify.result }}" + echo "ssr: ${{ needs.ssr.result }}" + echo "native: ${{ needs.native.result }}" + echo "docs: ${{ needs.docs.result }}" + if [ "${{ contains(needs.*.result, 'failure') }}" = "true" ] \ + || [ "${{ contains(needs.*.result, 'cancelled') }}" = "true" ] \ + || [ "${{ contains(needs.*.result, 'skipped') }}" = "true" ]; then + echo "::error::At least one check did not pass." + exit 1 + fi + echo "All checks passed." diff --git a/.github/workflows/compat.yml b/.github/workflows/compat.yml new file mode 100644 index 0000000..5626ae6 --- /dev/null +++ b/.github/workflows/compat.yml @@ -0,0 +1,46 @@ +name: Angular compatibility + +# `npm run verify:compat` installs a full Angular toolchain and builds a real +# application once per supported major. That is minutes per version, which is +# too slow to sit in front of every pull request — but it is the only thing that +# actually tests the peer range, because the Angular linker runs during a +# consumer's build and nowhere else. +# +# So it runs when the promise itself could have changed, on a weekly schedule to +# catch a new Angular release breaking us, and on demand. +on: + pull_request: + paths: + - 'projects/masonry-angular/package.json' # the peer range itself + - 'projects/masonry-angular/src/**' # anything a consumer's build compiles + - 'scripts/verify-compat.mjs' + schedule: + - cron: '0 6 * * 1' # Mondays, 06:00 UTC + workflow_dispatch: + inputs: + majors: + description: 'Majors to check, space separated (blank = all)' + required: false + default: '' + +concurrency: + group: compat-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + compat: + name: Build a real app on each supported major + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 + with: + node-version: 24 + cache: npm + - run: npm ci + - name: verify:compat + run: npm run verify:compat -- ${{ github.event.inputs.majors }} diff --git a/projects/demo/src/styles.css b/projects/demo/src/styles.css index 4e34c9c..843dd0c 100644 --- a/projects/demo/src/styles.css +++ b/projects/demo/src/styles.css @@ -47,7 +47,7 @@ h3 { /* ---- Shared example chrome ------------------------------------------------ */ .lede { - max-width: 68ch; + /* max-width: 68ch; */ margin: 0 0 22px; color: var(--muted); line-height: 1.6;