diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ae2cf6294d..ad1804bfc5 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -16,6 +16,7 @@ /src/components/views/dialogs/devtools/Crypto.tsx @element-hq/element-crypto-web-reviewers /playwright/e2e/crypto/ @element-hq/element-crypto-web-reviewers /playwright/e2e/settings/encryption-user-tab/ @element-hq/element-crypto-web-reviewers +/packages/shared-components/src/crypto/ @element-hq/element-crypto-web-reviewers /src/models/Call.ts @element-hq/element-call-reviewers @@ -25,7 +26,10 @@ # Ignore translations as those will be updated by GHA for Localazy download /src/i18n/strings -/src/i18n/strings/en_EN.json @element-hq/element-web-reviewers +/packages/shared-components/src/i18n/strings +/src/i18n/strings/en_EN.json @element-hq/element-web-reviewers +/packages/shared-components/src/i18n/strings/en_EN.json @element-hq/element-web-reviewers + # Ignore the synapse & mas plugins as this is updated by GHA for docker image updating /playwright/testcontainers/synapse.ts /playwright/testcontainers/mas.ts diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 759266d4e0..86ab82944a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,7 +2,7 @@ ## Checklist -- [ ] I have read through [review guidelines](../docs/review.md) and [CONTRIBUTING.md](../CONTRIBUTING.md). +- [ ] I have read through [review guidelines](https://github.com/element-hq/element-web/blob/develop/docs/review.md) and [CONTRIBUTING.md](https://github.com/element-hq/element-web/blob/develop/CONTRIBUTING.md). - [ ] Tests written for new code (and old code if feasible). - [ ] New or updated `public`/`exported` symbols have accurate [TSDoc](https://tsdoc.org/) documentation. - [ ] Linter and other CI checks pass. diff --git a/.github/labels.yml b/.github/labels.yml index 649e1a7407..8cf5613f92 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -173,6 +173,12 @@ color: "bfd4f2" - name: "A-Welcome-Page" color: "bfd4f2" +- name: "A-Install" + color: "72A447" +- name: "A-Seshat" + color: "8262BE" +- name: "A-Update" + color: "17BE67" - name: "backport staging" description: "Label to automatically backport PR to staging branch" color: "B60205" @@ -282,3 +288,23 @@ - name: "Z-Skip-Coverage" description: "Skip SonarQube coverage for this PR" color: "ededed" +- name: "Z-Arch" + color: "D601BE" +- name: "Z-ARM" + color: "5DEC5B" +- name: "Z-Flatpak" + color: "0CA856" +- name: "Z-Linux" + color: "7B4A9C" +- name: "Z-macOS" + color: "500605" +- name: "Z-Official" + color: "1D2B20" +- name: "Z-Snap" + color: "29CD95" +- name: "Z-Suse" + color: "79D07B" +- name: "Z-Wayland" + color: "94C519" +- name: "Z-Windows" + color: "0632DE" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 74425f25b4..5d863a6a32 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,7 +44,7 @@ jobs: steps: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: # Disable cache on Windows as it is slower than not caching # https://github.com/actions/setup-node/issues/975 @@ -66,7 +66,7 @@ jobs: run: VERSION=$(scripts/get-version-from-git.sh) yarn build - name: Upload Artifact - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 with: name: webapp-${{ matrix.image }} path: webapp diff --git a/.github/workflows/build_debian.yaml b/.github/workflows/build_debian.yaml index 48c21c9dc5..6ad62f85aa 100644 --- a/.github/workflows/build_debian.yaml +++ b/.github/workflows/build_debian.yaml @@ -62,7 +62,7 @@ jobs: dpkg-gencontrol -v"$VERSION" -ldebian/tmp/DEBIAN/changelog dpkg-deb -Zxz --root-owner-group --build debian/tmp element-web.deb - - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 with: name: element-web.deb path: element-web.deb diff --git a/.github/workflows/build_develop.yml b/.github/workflows/build_develop.yml index a923e1db1d..72ebd40d25 100644 --- a/.github/workflows/build_develop.yml +++ b/.github/workflows/build_develop.yml @@ -28,7 +28,7 @@ jobs: steps: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: cache: "yarn" node-version: "lts/*" @@ -53,7 +53,7 @@ jobs: - run: mv dist/element-*.tar.gz dist/develop.tar.gz - - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 with: name: webapp path: dist/develop.tar.gz @@ -104,7 +104,7 @@ jobs: running-workflow-name: "Build & Deploy develop.element.io" repo-token: ${{ secrets.GITHUB_TOKEN }} wait-interval: 10 - check-regexp: ^((?!SonarCloud|SonarQube|issue|board|label|Release|prepare|GitHub Pages).)*$ + check-regexp: ^((?!SonarCloud|SonarQube|issue|board|label|Release|prepare|GitHub Pages|Upload).)*$ # We keep the latest develop.tar.gz on R2 instead of relying on the github artifact uploaded earlier # as the expires after 24h and requires auth to download. diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 5c2e989e28..a11da471f9 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -32,25 +32,10 @@ jobs: uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 with: install: true - - name: Login to Docker Hub - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3 - if: github.event_name != 'pull_request' - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Login to GitHub Container Registry - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3 - if: github.event_name != 'pull_request' - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Build and load id: test-build uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6 @@ -102,12 +87,64 @@ jobs: images: | vectorim/element-web ghcr.io/element-hq/element-web + oci-push.vpn.infra.element.io/element-web tags: | type=ref,event=branch type=ref,event=tag flavor: | latest=${{ contains(github.ref_name, '-rc.') && 'false' || 'auto' }} + - name: Login to Docker Hub + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 + if: github.event_name != 'pull_request' + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 + if: github.event_name != 'pull_request' + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Connect to Tailscale + uses: tailscale/github-action@53acf823325fe9ca47f4cdaa951f90b4b0de5bb9 # v4 + if: github.event_name != 'pull_request' + with: + oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }} + audience: ${{ secrets.TS_AUDIENCE }} + tags: tag:github-actions + + - name: Compute vault jwt role name + id: vault-jwt-role + if: github.event_name != 'pull_request' + run: | + echo "role_name=github_service_management_$( echo "${{ github.repository }}" | sed -r 's|[/-]|_|g')" | tee -a "$GITHUB_OUTPUT" + + - name: Get team registry token + id: import-secrets + uses: hashicorp/vault-action@4c06c5ccf5c0761b6029f56cfb1dcf5565918a3b # v3 + if: github.event_name != 'pull_request' + with: + url: https://vault.infra.ci.i.element.dev + role: ${{ steps.vault-jwt-role.outputs.role_name }} + path: service-management/github-actions + jwtGithubAudience: https://vault.infra.ci.i.element.dev + method: jwt + secrets: | + services/web-repositories/secret/data/oci.element.io username | OCI_USERNAME ; + services/web-repositories/secret/data/oci.element.io password | OCI_PASSWORD ; + + - name: Login to oci.element.io Registry + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 + if: github.event_name != 'pull_request' + with: + registry: oci-push.vpn.infra.element.io + username: ${{ steps.import-secrets.outputs.OCI_USERNAME }} + password: ${{ steps.import-secrets.outputs.OCI_PASSWORD }} + - name: Build and push id: build-and-push uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6 @@ -139,16 +176,3 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} repository: vectorim/element-web - - - name: Repository Dispatch - uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4 - if: github.event_name != 'pull_request' - with: - repository: element-hq/element-web-pro - token: ${{ secrets.ELEMENT_BOT_TOKEN }} - event-type: image-built - # Stable way to determine the :version - client-payload: |- - { - "base-ref": "${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}" - } diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 9020f7914b..a3e9e40247 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -33,7 +33,7 @@ jobs: repository: matrix-org/matrix-js-sdk path: matrix-js-sdk - - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: cache: "yarn" cache-dependency-path: element-web/yarn.lock diff --git a/.github/workflows/end-to-end-tests-netlify.yaml b/.github/workflows/end-to-end-tests-netlify.yaml index 049f4ea343..a08efa220b 100644 --- a/.github/workflows/end-to-end-tests-netlify.yaml +++ b/.github/workflows/end-to-end-tests-netlify.yaml @@ -25,7 +25,7 @@ jobs: actions: read steps: - name: Download HTML report - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id }} diff --git a/.github/workflows/end-to-end-tests.yaml b/.github/workflows/end-to-end-tests.yaml index 1b366333b6..304e4468e2 100644 --- a/.github/workflows/end-to-end-tests.yaml +++ b/.github/workflows/end-to-end-tests.yaml @@ -54,7 +54,7 @@ jobs: with: repository: element-hq/element-web - - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: cache: "yarn" node-version: "lts/*" @@ -74,7 +74,7 @@ jobs: run: VERSION=$(scripts/get-version-from-git.sh) yarn build - name: Upload Artifact - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 with: name: webapp path: webapp @@ -128,12 +128,12 @@ jobs: repository: element-hq/element-web - name: 📥 Download artifact - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 with: name: webapp path: webapp - - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: cache: "yarn" cache-dependency-path: yarn.lock @@ -147,7 +147,7 @@ jobs: run: echo "version=$(yarn list --pattern @playwright/test --depth=0 --json --non-interactive --no-progress | jq -r '.data.trees[].name')" >> $GITHUB_OUTPUT - name: Cache playwright binaries - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5 id: playwright-cache with: path: ~/.cache/ms-playwright @@ -172,7 +172,7 @@ jobs: - name: Upload blob report to GitHub Actions Artifacts if: always() - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 with: name: all-blob-reports-${{ matrix.project }}-${{ matrix.runner }} path: blob-report @@ -200,7 +200,7 @@ jobs: persist-credentials: false repository: element-hq/element-web - - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 if: inputs.skip != true with: cache: "yarn" @@ -212,7 +212,7 @@ jobs: - name: Download blob reports from GitHub Actions Artifacts if: inputs.skip != true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 with: pattern: all-blob-reports-* path: all-blob-reports @@ -228,7 +228,7 @@ jobs: # Upload the HTML report even if one of our reporters fails, this can happen when stale screenshots are detected - name: Upload HTML report if: always() && inputs.skip != true - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 with: name: html-report path: playwright-report diff --git a/.github/workflows/localazy_upload.yaml b/.github/workflows/localazy_upload.yaml index 8cb7743968..ad23f350f7 100644 --- a/.github/workflows/localazy_upload.yaml +++ b/.github/workflows/localazy_upload.yaml @@ -4,6 +4,7 @@ on: branches: [develop] paths: - "src/i18n/strings/en_EN.json" + - "packages/shared-components/src/i18n/strings/en_EN.json" permissions: {} # No permissions needed jobs: upload: diff --git a/.github/workflows/netlify.yaml b/.github/workflows/netlify.yaml index ab2433c267..9507567ef6 100644 --- a/.github/workflows/netlify.yaml +++ b/.github/workflows/netlify.yaml @@ -28,7 +28,7 @@ jobs: Exercise caution. Use test accounts. - name: 📥 Download artifact - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id }} diff --git a/.github/workflows/playwright-image-updates.yaml b/.github/workflows/playwright-image-updates.yaml index 1ce3d767a7..d0cd242884 100644 --- a/.github/workflows/playwright-image-updates.yaml +++ b/.github/workflows/playwright-image-updates.yaml @@ -32,7 +32,7 @@ jobs: - name: Create Pull Request id: cpr - uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7 + uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8 with: token: ${{ secrets.ELEMENT_BOT_TOKEN }} branch: actions/playwright-image-updates diff --git a/.github/workflows/shared-component-publish.yaml b/.github/workflows/shared-component-publish.yaml index 6869c17660..a1b6a0c882 100644 --- a/.github/workflows/shared-component-publish.yaml +++ b/.github/workflows/shared-component-publish.yaml @@ -16,7 +16,7 @@ jobs: uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - name: 🔧 Set up node environment - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: cache: "yarn" node-version-file: ".node-version" @@ -37,4 +37,4 @@ jobs: - name: 🚀 Publish to npm working-directory: packages/shared-components - run: npm publish --access public --tag test --provenance + run: npm publish --access public --provenance diff --git a/.github/workflows/shared-component-storybook-publish.yaml b/.github/workflows/shared-component-storybook-publish.yaml new file mode 100644 index 0000000000..620f7a48e8 --- /dev/null +++ b/.github/workflows/shared-component-storybook-publish.yaml @@ -0,0 +1,41 @@ +name: Publish shared component storybook +on: + workflow_dispatch: {} + push: + branches: + - "develop" + paths: + - "packages/shared-components/**/*" + +permissions: {} + +jobs: + doc: + name: Publish storybook + runs-on: ubuntu-latest + environment: SharedComponents + steps: + - name: 🧮 Checkout code + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 + + - name: 🔧 Yarn cache + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + with: + cache: "yarn" + node-version-file: package.json + + - name: 🔨 Install dependencies + working-directory: packages/shared-components + run: "yarn install --pure-lockfile" + + - name: 📖 Build Storybook + working-directory: packages/shared-components + run: yarn build:storybook + + - name: 🚀 Deploy to Cloudflare Pages + uses: cloudflare/wrangler-action@9681c2997648301493e78cacbfb790a9f19c833f # v3 + with: + apiToken: ${{ secrets.CF_PAGES_TOKEN }} + accountId: ${{ secrets.CF_PAGES_ACCOUNT_ID }} + workingDirectory: "packages/shared-components" + command: pages deploy storybook-static --project-name=shared-components-storybook diff --git a/.github/workflows/shared-component-visual-tests-netlify.yaml b/.github/workflows/shared-component-visual-tests-netlify.yaml index 816d899836..950dd8febf 100644 --- a/.github/workflows/shared-component-visual-tests-netlify.yaml +++ b/.github/workflows/shared-component-visual-tests-netlify.yaml @@ -27,7 +27,7 @@ jobs: run: "sudo apt-get install -y tree" - name: Download Diffs - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id }} diff --git a/.github/workflows/shared-component-visual-tests.yaml b/.github/workflows/shared-component-visual-tests.yaml index 8f9cbdae31..b2015f0a08 100644 --- a/.github/workflows/shared-component-visual-tests.yaml +++ b/.github/workflows/shared-component-visual-tests.yaml @@ -26,14 +26,11 @@ jobs: persist-credentials: false repository: element-hq/element-web - - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: cache: "yarn" node-version: "lts/*" - - name: Install element web dependencies - run: yarn install --frozen-lockfile - - name: Install dependencies working-directory: packages/shared-components run: yarn install --frozen-lockfile @@ -44,7 +41,7 @@ jobs: run: echo "version=$(yarn list --pattern @playwright/test --depth=0 --json --non-interactive --no-progress | jq -r '.data.trees[].name')" >> $GITHUB_OUTPUT - name: Cache playwright binaries - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5 id: playwright-cache with: path: ~/.cache/ms-playwright @@ -56,11 +53,18 @@ jobs: run: "yarn playwright install --with-deps --only-shell" - name: Run Visual tests - run: "yarn --cwd packages/shared-components test:storybook:ci" + working-directory: packages/shared-components + run: "yarn test:storybook --run" + + # Workaround for vis silently adding new baselines if they didn't exist + # Can be removed once https://github.com/repobuddy/visual-testing/issues/516 is released + - run: | + git add -N . + git diff --exit-code - name: Upload received images & diffs if: always() - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 with: name: received-images - path: packages/shared-components/playwright/shared-component-received + path: packages/shared-components/__vis__/linux diff --git a/.github/workflows/static_analysis.yaml b/.github/workflows/static_analysis.yaml index 9f90572371..c26ee1b487 100644 --- a/.github/workflows/static_analysis.yaml +++ b/.github/workflows/static_analysis.yaml @@ -24,7 +24,7 @@ jobs: steps: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: cache: "yarn" node-version: "lts/*" @@ -41,8 +41,8 @@ jobs: - name: Typecheck Shared Components run: "yarn --cwd packages/shared-components run lint:types" - i18n_lint: - name: "i18n Check" + i18n_lint_ew: + name: "i18n Check (Element Web)" uses: matrix-org/matrix-web-i18n/.github/workflows/i18n_check.yml@main permissions: pull-requests: read @@ -59,6 +59,15 @@ jobs: devtools|settings|elementCallUrl labs|sliding_sync_description + i18n_lint_shared_components: + name: "i18n Check (Shared Components)" + uses: matrix-org/matrix-web-i18n/.github/workflows/i18n_check.yml@main + permissions: + pull-requests: read + with: + path: "packages/shared-components" + hardcoded-words: "Element" + rethemendex_lint: name: "Rethemendex Check" runs-on: ubuntu-24.04 @@ -75,7 +84,7 @@ jobs: steps: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: cache: "yarn" node-version: "lts/*" @@ -99,7 +108,7 @@ jobs: steps: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: cache: "yarn" node-version: "lts/*" @@ -117,7 +126,7 @@ jobs: steps: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: cache: "yarn" node-version: "lts/*" @@ -135,7 +144,7 @@ jobs: steps: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: cache: "yarn" node-version: "lts/*" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 95382b180c..4b90ca2cb5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -44,7 +44,7 @@ jobs: repository: ${{ inputs.matrix-js-sdk-sha && 'element-hq/element-web' || github.repository }} - name: Yarn cache - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: node-version: "lts/*" cache: "yarn" @@ -55,7 +55,7 @@ jobs: JS_SDK_GITHUB_BASE_REF: ${{ inputs.matrix-js-sdk-sha }} - name: Jest Cache - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5 with: path: /tmp/jest_cache key: ${{ hashFiles('**/yarn.lock') }} @@ -84,7 +84,7 @@ jobs: - name: Upload Artifact if: env.ENABLE_COVERAGE == 'true' - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 with: name: coverage-${{ matrix.runner }} path: | @@ -93,18 +93,18 @@ jobs: complete: name: jest-tests - needs: jest_ew + needs: [jest_ew, vitest_sc] if: always() runs-on: ubuntu-24.04 permissions: statuses: write steps: - - if: needs.jest_ew.result != 'skipped' && needs.jest_ew.result != 'success' + - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') run: exit 1 - name: Skip SonarCloud in merge queue if: github.event_name == 'merge_group' || inputs.disable_coverage == 'true' - uses: guibranco/github-status-action-v2@5530c593759f489bba08272e96986ffc571c1ea1 + uses: guibranco/github-status-action-v2@9bfa8773cdbdc6c185747fd43cd7faa9d7c32f09 with: authToken: ${{ secrets.GITHUB_TOKEN }} state: success @@ -113,8 +113,8 @@ jobs: sha: ${{ github.sha }} target_url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} - jest_sc: - name: Jest (Shared Components) + vitest_sc: + name: Vitest (Shared Components) runs-on: ubuntu-24.04 steps: - name: Checkout code @@ -123,43 +123,47 @@ jobs: repository: ${{ inputs.matrix-js-sdk-sha && 'element-hq/element-web' || github.repository }} - name: Yarn cache - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: node-version: "lts/*" cache: "yarn" - - name: Install EW Deps - run: "yarn install" - - name: Install Shared Component Deps working-directory: "packages/shared-components" run: "yarn install" - - name: Jest Cache - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + - name: Cache storybook & vitest + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5 with: - path: /tmp/jest_cache - key: ${{ hashFiles('**/yarn.lock') }} + path: | + packages/shared-components/node_modules/.cache + packages/shared-components/node_modules/.vite/vitest + key: ${{ hashFiles('packages/shared-components/yarn.lock') }} - - name: Get number of CPU cores - id: cpu-cores - uses: SimenB/github-actions-cpu-cores@97ba232459a8e02ff6121db9362b09661c875ab8 # v2 + - name: Get installed Playwright version + working-directory: packages/shared-components + id: playwright + run: echo "version=$(yarn list --pattern @playwright/test --depth=0 --json --non-interactive --no-progress | jq -r '.data.trees[].name')" >> $GITHUB_OUTPUT + + - name: Cache playwright binaries + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5 + id: playwright-cache + with: + path: ~/.cache/ms-playwright + key: ${{ runner.os }}-${{ runner.arch }}-playwright-${{ steps.playwright.outputs.version }}-onlyshell + + - name: Install Playwright browsers + working-directory: packages/shared-components + if: steps.playwright-cache.outputs.cache-hit != 'true' + run: "yarn playwright install --with-deps --only-shell" - name: Run tests working-directory: "packages/shared-components" - run: | - yarn test \ - --coverage=${{ env.ENABLE_COVERAGE }} \ - --ci \ - --max-workers ${{ steps.cpu-cores.outputs.count }} \ - --cacheDirectory /tmp/jest_cache - env: - # tell jest to use coloured output - FORCE_COLOR: true + run: yarn test:unit --coverage=${{ env.ENABLE_COVERAGE }} - name: Upload Artifact if: env.ENABLE_COVERAGE == 'true' - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 with: name: coverage-sharedcomponents path: | diff --git a/.github/workflows/triage-move-review-requests.yml b/.github/workflows/triage-move-review-requests.yml index 4d8745f4bd..6933233c0a 100644 --- a/.github/workflows/triage-move-review-requests.yml +++ b/.github/workflows/triage-move-review-requests.yml @@ -9,7 +9,7 @@ jobs: name: Move PRs asking for design review to the design board runs-on: ubuntu-24.04 steps: - - uses: octokit/graphql-action@abaeca7ba4f0325d63b8de7ef943c2418d161b93 # v3.0.0 + - uses: octokit/graphql-action@ddde8ebb2493e79f390e6449c725c21663a67505 # v3.0.2 id: find_team_members with: headers: '{"GraphQL-Features": "projects_next_graphql"}' @@ -52,7 +52,7 @@ jobs: fi env: TEAM: "design" - - uses: octokit/graphql-action@abaeca7ba4f0325d63b8de7ef943c2418d161b93 # v3.0.0 + - uses: octokit/graphql-action@ddde8ebb2493e79f390e6449c725c21663a67505 # v3.0.2 id: add_to_project if: steps.any_matching_reviewers.outputs.match == 'true' with: @@ -76,7 +76,7 @@ jobs: name: Move PRs asking for design review to the design board runs-on: ubuntu-24.04 steps: - - uses: octokit/graphql-action@abaeca7ba4f0325d63b8de7ef943c2418d161b93 # v3.0.0 + - uses: octokit/graphql-action@ddde8ebb2493e79f390e6449c725c21663a67505 # v3.0.2 id: find_team_members with: headers: '{"GraphQL-Features": "projects_next_graphql"}' @@ -119,7 +119,7 @@ jobs: fi env: TEAM: "product" - - uses: octokit/graphql-action@abaeca7ba4f0325d63b8de7ef943c2418d161b93 # v3.0.0 + - uses: octokit/graphql-action@ddde8ebb2493e79f390e6449c725c21663a67505 # v3.0.2 id: add_to_project if: steps.any_matching_reviewers.outputs.match == 'true' with: diff --git a/.github/workflows/update-jitsi.yml b/.github/workflows/update-jitsi.yml index 67e3fb19c5..b37a2967d4 100644 --- a/.github/workflows/update-jitsi.yml +++ b/.github/workflows/update-jitsi.yml @@ -11,7 +11,7 @@ jobs: steps: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: cache: "yarn" node-version: "lts/*" @@ -23,7 +23,7 @@ jobs: run: "yarn update:jitsi" - name: Create Pull Request - uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7 + uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8 with: token: ${{ secrets.ELEMENT_BOT_TOKEN }} branch: actions/jitsi-update diff --git a/.gitignore b/.gitignore index 3d6d723ac3..870489a7bd 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ electron/pub /index.html # version file and tarball created by `npm pack` / `yarn pack` /git-revision.txt +jest-sonar.xml *storybook.log storybook-static @@ -37,3 +38,6 @@ storybook-static /packages/shared-components/node_modules /packages/shared-components/dist /packages/shared-components/src/i18nKeys.d.ts + +# TSC incremental compilation information +*.tsbuildinfo diff --git a/.stylelintrc.js b/.stylelintrc.js index 3244d122c5..2cbebc0472 100644 --- a/.stylelintrc.js +++ b/.stylelintrc.js @@ -56,7 +56,6 @@ module.exports = { { from: "res/css/views/rooms/_EditMessageComposer.pcss", type: "css" }, { from: "res/css/views/right_panel/_BaseCard.pcss", type: "css" }, { from: "res/css/views/messages/_MessageTimestamp.pcss", type: "css" }, - { from: "res/css/views/messages/_EventTileBubble.pcss", type: "css" }, { from: "res/css/views/messages/_MessageActionBar.pcss", type: "css" }, { from: "res/css/views/voip/LegacyCallView/_LegacyCallViewButtons.pcss", type: "css" }, { from: "res/css/views/elements/_ToggleSwitch.pcss", type: "css" }, diff --git a/CHANGELOG.md b/CHANGELOG.md index 43546c1817..4128a2b75f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,84 @@ +Changes in [1.12.9](https://github.com/element-hq/element-web/releases/tag/v1.12.9) (2026-01-27) +================================================================================================ +## ✨ Features + +* Allow local log downloads when a rageshake URL is not configured. ([#31716](https://github.com/element-hq/element-web/pull/31716)). Contributed by @Half-Shot. +* Improve icon rendering accessibility ([#31776](https://github.com/element-hq/element-web/pull/31776)). Contributed by @t3chguy. +* Show "Bob shared this message" on messages shared via MSC4268 ([#31684](https://github.com/element-hq/element-web/pull/31684)). Contributed by @richvdh. +* Update the way we render icons for accessibility ([#31731](https://github.com/element-hq/element-web/pull/31731)). Contributed by @t3chguy. +* Switch from css masks to rendering svg ([#31681](https://github.com/element-hq/element-web/pull/31681)). Contributed by @t3chguy. +* Support for stable MSC4191 account management action parameter ([#31701](https://github.com/element-hq/element-web/pull/31701)). Contributed by @hughns. +* Support for stable m.oauth UIA stage from MSC4312 ([#31704](https://github.com/element-hq/element-web/pull/31704)). Contributed by @hughns. +* Switch to Compound icons to replace old icons ([#31667](https://github.com/element-hq/element-web/pull/31667)). Contributed by @t3chguy. +* Switch from svg masks to svg rendering in more places ([#31652](https://github.com/element-hq/element-web/pull/31652)). Contributed by @t3chguy. +* Switch from svg masks to svg rendering in more places ([#31650](https://github.com/element-hq/element-web/pull/31650)). Contributed by @t3chguy. +* Update notification icons using Compound icons ([#31671](https://github.com/element-hq/element-web/pull/31671)). Contributed by @t3chguy. +* Memoise ListView context ([#31668](https://github.com/element-hq/element-web/pull/31668)). Contributed by @t3chguy. +* Switch emoji picker to use emoji for header icons ([#31645](https://github.com/element-hq/element-web/pull/31645)). Contributed by @t3chguy. +* Replace icons with Compound alternatives ([#31642](https://github.com/element-hq/element-web/pull/31642)). Contributed by @t3chguy. + +## 🐛 Bug Fixes + +* Fix avatar decorations in thread activity centre not being atop avatar ([#31789](https://github.com/element-hq/element-web/pull/31789)). Contributed by @t3chguy. +* Fix room settings roles tab getting confused if power level change fails ([#31768](https://github.com/element-hq/element-web/pull/31768)). Contributed by @t3chguy. +* Custom themes now import highlights in css ([#31758](https://github.com/element-hq/element-web/pull/31758)). Contributed by @Philldomd. +* Use correct translation for url preview settings ([#31740](https://github.com/element-hq/element-web/pull/31740)). Contributed by @florianduros. +* Fix error shown if accepting a 3pid invite ([#31735](https://github.com/element-hq/element-web/pull/31735)). Contributed by @dbkr. +* Ensure correct focus configuration for Element Call before allowing users to call. ([#31490](https://github.com/element-hq/element-web/pull/31490)). Contributed by @Half-Shot. +* Fix emoji font in emoji picker header buttons ([#31679](https://github.com/element-hq/element-web/pull/31679)). Contributed by @t3chguy. +* fix flaky test by waiting for chat panel before counting messages ([#31633](https://github.com/element-hq/element-web/pull/31633)). Contributed by @BillCarsonFr. + + +Changes in [1.12.8](https://github.com/element-hq/element-web/releases/tag/v1.12.8) (2026-01-13) +================================================================================================ +## 🦖 Deprecations + +* Remove `element_call.participant_limit` config and associated code. ([#31638](https://github.com/element-hq/element-web/pull/31638)). Contributed by @Half-Shot. + +## ✨ Features + +* Switch to rendering svg icons rather than masking them ([#31557](https://github.com/element-hq/element-web/pull/31557)). Contributed by @t3chguy. +* Update history visibility UX ([#31635](https://github.com/element-hq/element-web/pull/31635)). Contributed by @langleyd. +* Show correct call icon for joining a call. ([#31489](https://github.com/element-hq/element-web/pull/31489)). Contributed by @Half-Shot. +* Update StopGapWidgetDriver to support sticky events ([#31205](https://github.com/element-hq/element-web/pull/31205)). Contributed by @Half-Shot. +* Remove release announcements for new sounds \& room list ([#31544](https://github.com/element-hq/element-web/pull/31544)). Contributed by @t3chguy. +* Add button to restore from backup into /devtools ([#31581](https://github.com/element-hq/element-web/pull/31581)). Contributed by @mxandreas. +* Switch to non-solid compound icons for room settings \& composer ([#31561](https://github.com/element-hq/element-web/pull/31561)). Contributed by @t3chguy. +* Support encrypted state events MSC4362 ([#31513](https://github.com/element-hq/element-web/pull/31513)). Contributed by @andybalaam. +* Update prop type \& documentation for HistoryVisibleBanner and VM. ([#31545](https://github.com/element-hq/element-web/pull/31545)). Contributed by @kaylendog. +* Switch to Compound icons in more places ([#31560](https://github.com/element-hq/element-web/pull/31560)). Contributed by @t3chguy. +* Switch to rendering svg icons rather than masking them ([#31550](https://github.com/element-hq/element-web/pull/31550)). Contributed by @t3chguy. +* Make AccessibleButton contrast control compatible ([#31308](https://github.com/element-hq/element-web/pull/31308)). Contributed by @t3chguy. +* Switch to compound-design-tokens for platform icons ([#31543](https://github.com/element-hq/element-web/pull/31543)). Contributed by @t3chguy. +* Switch to rendering svg icons rather than masking them ([#31531](https://github.com/element-hq/element-web/pull/31531)). Contributed by @t3chguy. +* Switch to rendering svg icons rather than css masking ([#31517](https://github.com/element-hq/element-web/pull/31517)). Contributed by @t3chguy. +* Auto approve matrix rtc member event (`m.rtc.member`) (sticky events) ([#31452](https://github.com/element-hq/element-web/pull/31452)). Contributed by @toger5. +* Size Autocomplete relative to the RoomView height rather than the viewport height ([#31425](https://github.com/element-hq/element-web/pull/31425)). Contributed by @langleyd. +* Implement UI for history visibility acknowledgement. ([#31156](https://github.com/element-hq/element-web/pull/31156)). Contributed by @kaylendog. +* Export disposing hook from package ([#31498](https://github.com/element-hq/element-web/pull/31498)). Contributed by @MidhunSureshR. +* Change `header-panel-bg-hover` to use `var(--cpd-color-bg-action-secondary-hovered)` for better custom theming ([#31457](https://github.com/element-hq/element-web/pull/31457)). Contributed by @th0mcat. +* Improve icon rendering in iconized context menu ([#31458](https://github.com/element-hq/element-web/pull/31458)). Contributed by @t3chguy. + +## 🐛 Bug Fixes + +* [Backport staging] Fix space settings visibility tab crashing ([#31705](https://github.com/element-hq/element-web/pull/31705)). Contributed by @RiotRobot. +* Fix expand/collapse reply preview not showing in some cases ([#31639](https://github.com/element-hq/element-web/pull/31639)). Contributed by @t3chguy. +* Fix bundled font or custom font not applied after theme switch ([#31591](https://github.com/element-hq/element-web/pull/31591)). Contributed by @florianduros. +* Add ol override CSS for markdown-body ([#31618](https://github.com/element-hq/element-web/pull/31618)). Contributed by @niamu. +* Fix reaction left margin in timeline card ([#31625](https://github.com/element-hq/element-web/pull/31625)). Contributed by @t3chguy. +* Open right panel timeline when jumping to event with maximised widget ([#31626](https://github.com/element-hq/element-web/pull/31626)). Contributed by @t3chguy. +* Fix Compound Link elements not having an underline. ([#31583](https://github.com/element-hq/element-web/pull/31583)). Contributed by @Half-Shot. +* Recalculate mentions metadata of forwarded messages based on message body ([#31193](https://github.com/element-hq/element-web/pull/31193)). Contributed by @twassman. +* Fix Room Preview Card Layout ([#31611](https://github.com/element-hq/element-web/pull/31611)). Contributed by @germain-gg. +* Fix: WidgetMessaging not properly closed causing side effects and bugs ([#31598](https://github.com/element-hq/element-web/pull/31598)). Contributed by @BillCarsonFr. +* Handle cross-signing keys missing locally and/or from secret storage ([#31367](https://github.com/element-hq/element-web/pull/31367)). Contributed by @uhoreg. +* fix: Allow wrapping in `Banner` component. ([#31532](https://github.com/element-hq/element-web/pull/31532)). Contributed by @kaylendog. +* Update algorithm for history visible banner. ([#31577](https://github.com/element-hq/element-web/pull/31577)). Contributed by @kaylendog. +* Fix styling issue when using EW modules ([#31533](https://github.com/element-hq/element-web/pull/31533)). Contributed by @florianduros. +* Prevent history visible banner from displaying in threads. ([#31535](https://github.com/element-hq/element-web/pull/31535)). Contributed by @kaylendog. +* Make the feedback icon be the right color in dark theme ([#31527](https://github.com/element-hq/element-web/pull/31527)). Contributed by @robintown. + + Changes in [1.12.7](https://github.com/element-hq/element-web/releases/tag/v1.12.7) (2025-12-16) ================================================================================================ ## ✨ Features diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ec59b2eff..e269853d7f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -184,6 +184,16 @@ Please ensure your changes match the cosmetic style of the existing project, and **_never_** mix cosmetic and functional changes in the same commit, as it makes it horribly hard to review otherwise. +## Shared Components + +When creating new UI components, consider whether they should be added to the shared components package (`packages/shared-components`) rather than directly in the main `src/` directory. Components should be placed in shared components if they: + +- Are reusable across different parts of the application +- Could potentially be used by other Element projects (Element Desktop, Aurora, Element modules...) +- Follow established patterns and don't have tight coupling to specific application logic + +For more details, see the [shared components README](./packages/shared-components/README.md). + ## Attribution Everyone who contributes anything to Matrix is welcome to be listed in the diff --git a/Dockerfile b/Dockerfile index 5ce43a7c4f..9b418ac7fc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ -# syntax=docker.io/docker/dockerfile:1.20-labs@sha256:dbcde2ebc4abc8bb5c3c499b9c9a6876842bf5da243951cd2697f921a7aeb6a9 +# syntax=docker.io/docker/dockerfile:1.21-labs@sha256:2e681d22e86e738a057075f930b81b2ab8bc2a34cd16001484a7453cfa7a03fb # Builder -FROM --platform=$BUILDPLATFORM node:24-bullseye@sha256:5583cbe5d3347db372d9a9100eba272b548ca1f53246b9b769334bcd0eef2c26 AS builder +FROM --platform=$BUILDPLATFORM node:24-bullseye@sha256:8036dbe5b1f465e3acb8b866031cd06e4f84c31b0e83dabbdc59397a40dbe288 AS builder # Support custom branch of the js-sdk. This also helps us build images of element-web develop. ARG USE_CUSTOM_SDKS=false @@ -19,7 +19,7 @@ RUN /src/scripts/docker-package.sh RUN cp /src/config.sample.json /src/webapp/config.json # App -FROM nginxinc/nginx-unprivileged:alpine-slim@sha256:a6bec37058b9047ece799c01d98dc6d5aa0542b6583cc69f187652f91331a752 +FROM nginxinc/nginx-unprivileged:alpine-slim@sha256:9ac6a908ed07ba7d23cbf6048090453a081abf663c53a7c3f3bf96abc16c0799 # Need root user to install packages & manipulate the usr directory USER root diff --git a/README.md b/README.md index 6f6e3172fa..bf0e10551d 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,17 @@ To add a new translation, head to the [translating doc](docs/translating.md). For a developer guide, see the [translating dev doc](docs/translating-dev.md). +# Extending Element Web with Modules + +Element Web supports a module system that allows you to extend or modify functionality at runtime. Modules are loaded dynamically and provide a safe, predictable API for customization. + +## What are modules? + +Modules are extensions that can add or modify Element Web's functionality. They are: + +- Built using the [`@element-hq/element-web-module-api`](https://github.com/element-hq/element-modules/tree/main/packages/element-web-module-api) +- Loaded in EW via [config.json](docs/config.md#modules) + # Triaging issues Issues are triaged by community members and the Web App Team, following the [triage process](https://github.com/element-hq/element-meta/wiki/Triage-process). diff --git a/code_style.md b/code_style.md index 6e7289d22e..bd1fb4371c 100644 --- a/code_style.md +++ b/code_style.md @@ -272,20 +272,44 @@ Inheriting all the rules of TypeScript, the following additionally apply: 18. Components should serve a single, or near-single, purpose. 19. Prefer to derive information from component properties rather than establish state. 20. Do not use `React.Component::forceUpdate`. +21. Prefer to use [compound typography components](https://compound.element.io/?path=/docs/compound-web_typography--docs) instead of raw HTML elements for text. This ensures consistent font usage and letter spacing across the app. +22. If you can't use 21, don't forget to apply the correct CSS classes for font and letter spacing. +23. Prefer to use `Flex` or `Box` components from shared-components for layout instead of raw HTML elements with CSS flexbox styles. -## Stylesheets (\*.pcss = PostCSS + Plugins) +## Stylesheets -Note: We use PostCSS + some plugins to process our styles. It looks like SCSS, but actually it is not. +1. Keep indentation/nesting to a minimum. Maximum suggested nesting is 5 layers. +2. Components should render only within the bounding box of their outermost DOM element. Page-absolute positioning and negative CSS margins and similar are generally not cool and stop the component from being reused easily in different places. -1. The view's CSS file MUST have the same name as the component (e.g. `view/rooms/_MessageTile.css` for `MessageTile.tsx` component). +### PostCSS (\*.pcss = PostCSS + Plugins) + +> [!NOTE] +> We use PostCSS + some plugins to process our styles. It looks like SCSS, but actually it is not. + +**PostCSS should be use when working in the main Element Web codebase (not shared-components).** + +#### Naming and file structure + +1. The view's CSS file MUST have the same name as the component (e.g. `res/css/components/views/rooms/_RoomTile.pcss` for `RoomTile.tsx` component). 2. Per-view CSS is optional - it could choose to inherit all its styling from the context of the rest of the app, although this is unusual. -3. Class names must be prefixed with "mx\_". +3. Class names must be prefixed with `mx_`. 4. Class names must strictly denote the component which defines them. For example: `mx_MyFoo` for `MyFoo` component. -5. Class names for DOM elements within a view which aren't components are named by appending a lower camel case identifier to the view's class name - e.g. .mx_MyFoo_randomDiv is how you'd name the class of an arbitrary div within the MyFoo view. -6. Use the `$font` variables instead of manual values. -7. Keep indentation/nesting to a minimum. Maximum suggested nesting is 5 layers. -8. Use the whole class name instead of shortcuts: +5. Class names for DOM elements within a view which aren't components are named by appending a lower camel case identifier to the view's class name. + For example: `.mx_MyFoo_randomDiv` is how you'd name the class of an arbitrary div within the MyFoo view. + +#### Variables + +6. Use the `$font-*` variables instead of manual font-size values (e.g., `$font-12px`, `$font-15px`). + - Note: These are deprecated. Prefer Compound typography tokens like `var(--cpd-font-body-md-regular)` for new code. +7. Use theme color variables like `$primary-content`, `$secondary-content`, `$accent`, `$alert` for colors. + - Prefer Compound color tokens like `var(--cpd-color-text-primary)` for new code. +8. Use spacing variables like `$spacing-8`, `$spacing-12`, `$spacing-16` where available. + - Prefer Compound spacing tokens like `var(--cpd-space-2x)` for new code. + +#### Syntax and formatting + +10. Use the whole class name instead of shortcuts: ```scss .mx_MyFoo { @@ -296,7 +320,7 @@ Note: We use PostCSS + some plugins to process our styles. It looks like SCSS, b } ``` -9. Break multiple selectors over multiple lines this way: +11. Break multiple selectors over multiple lines this way: ```scss .mx_MyFoo, @@ -306,8 +330,7 @@ Note: We use PostCSS + some plugins to process our styles. It looks like SCSS, b } ``` -10. Non-shared variables should use $lowerCamelCase. Shared variables use $dashed-naming. -11. Overrides to Z indexes, adjustments of dimensions/padding with pixels, and so on should all be +12. Overrides to Z indexes, adjustments of dimensions/padding with pixels, and so on should all be [documented](#comments) for what the values mean: ```scss @@ -318,9 +341,81 @@ Note: We use PostCSS + some plugins to process our styles. It looks like SCSS, b } ``` -12. Avoid the use of `!important`. If `!important` is necessary, add a [comment](#comments) explaining why. -13. The CSS for a component can override the rules for child components. For instance, .mxRoomList .mx_RoomTile {} would be the selector to override styles of RoomTiles when viewed in the context of a RoomList view. Overrides must be scoped to the View's CSS class - i.e. don't just define .mx_RoomTile {} in RoomList.css - only RoomTile.css is allowed to define its own CSS. Instead, say .mx_RoomList .mx_RoomTile {} to scope the override only to the context of RoomList views. N.B. overrides should be relatively rare as in general CSS inheritance should be enough. -14. Components should render only within the bounding box of their outermost DOM element. Page-absolute positioning and negative CSS margins and similar are generally not cool and stop the component from being reused easily in different places. +13. Avoid the use of `!important`. If `!important` is necessary, add a [comment](#comments) explaining why. + +#### Component overrides + +14. The CSS for a component can override the rules for child components. For instance, `.mx_RoomList .mx_RoomTile {}` would be the selector to override styles of RoomTiles when viewed in the context of a RoomList view. Overrides must be scoped to the View's CSS class - i.e. don't just define `.mx_RoomTile {}` in RoomList.pcss - only RoomTile.pcss is allowed to define its own CSS. Instead, say `.mx_RoomList .mx_RoomTile {}` to scope the override only to the context of RoomList views. N.B. overrides should be relatively rare as in general CSS inheritance should be enough. + +### CSS module (\*.module.css) + +**CSS modules provide locally-scoped class names and are the preferred approach for new shared components.** + +#### Naming and file structure + +1. The CSS module file MUST have the same name as the component with `.module.css` extension. + For example: `PlayPauseButton.module.css` for `PlayPauseButton.tsx`. +2. Place the CSS module file in the same directory as the component. +3. Class names should be semantic and describe their purpose, NOT prefixed with `mx_`. + For example: `.button`, `.label`, `.content`, `.title`. +4. Use camelCase for multi-word class names: `.playButton`, `.primaryAction`, `.errorMessage`. + +#### Importing and usage + +5. Import the CSS module as `styles`: + + ```tsx + import styles from "./MyComponent.module.css"; + ``` + +6. Apply classes using the styles object: + + ```tsx +