diff --git a/.github/scripts/addCalcitePackageLabel.js b/.github/scripts/addCalcitePackageLabel.js index 6e24ed308ec..92f4873e04a 100644 --- a/.github/scripts/addCalcitePackageLabel.js +++ b/.github/scripts/addCalcitePackageLabel.js @@ -1,12 +1,14 @@ +// @ts-check const { createLabelIfMissing } = require("./support/utils"); +/** @param {import('github-script').AsyncFunctionArguments} AsyncFunctionArguments */ module.exports = async ({ github, context }) => { + const { repo, owner } = context.repo; + + const payload = /** @type {import('@octokit/webhooks-types').IssuesEvent} */ (context.payload); const { - repo: { owner, repo }, - payload: { - issue: { body, number: issue_number }, - }, - } = context; + issue: { body, number: issue_number }, + } = payload; if (!body) { console.log("could not determine the issue body"); diff --git a/.github/scripts/addEsriProductLabel.js b/.github/scripts/addEsriProductLabel.js index b7aa973e8e6..16f1080e9b9 100644 --- a/.github/scripts/addEsriProductLabel.js +++ b/.github/scripts/addEsriProductLabel.js @@ -1,13 +1,15 @@ +// @ts-check const { createLabelIfMissing } = require("./support/utils"); +/** @param {import('github-script').AsyncFunctionArguments} AsyncFunctionArguments */ module.exports = async ({ github, context }) => { + const { repo, owner } = context.repo; + + const payload = /** @type {import('@octokit/webhooks-types').IssuesEvent} */ (context.payload); const { - repo: { owner, repo }, - payload: { - action, - issue: { body, number: issue_number }, - }, - } = context; + action, + issue: { body, number: issue_number }, + } = payload; if (!body) { console.log("could not determine the issue body"); @@ -28,7 +30,7 @@ module.exports = async ({ github, context }) => { const product = (productRegexMatch && productRegexMatch[0] ? productRegexMatch[0] : "").trim(); - if (product && product !== "N/A") { + if (product !== "N/A") { await createLabelIfMissing({ github, context, diff --git a/.github/scripts/addPriorityLabel.js b/.github/scripts/addPriorityLabel.js index cdf79e04ae6..abe30b4138e 100644 --- a/.github/scripts/addPriorityLabel.js +++ b/.github/scripts/addPriorityLabel.js @@ -1,13 +1,15 @@ +// @ts-check const { createLabelIfMissing } = require("./support/utils"); +/** @param {import('github-script').AsyncFunctionArguments} AsyncFunctionArguments */ module.exports = async ({ github, context }) => { + const { repo, owner } = context.repo; + + const payload = /** @type {import('@octokit/webhooks-types').IssuesEvent} */ (context.payload); const { - repo: { owner, repo }, - payload: { - action, - issue: { body, number: issue_number }, - }, - } = context; + action, + issue: { body, number: issue_number }, + } = payload; if (!body) { console.log("could not determine the issue body"); diff --git a/.github/scripts/assignForVerification.js b/.github/scripts/assignForVerification.js index 1a3cca231e4..173fe3731ea 100644 --- a/.github/scripts/assignForVerification.js +++ b/.github/scripts/assignForVerification.js @@ -1,25 +1,38 @@ +// @ts-check const { handoff, issueWorkflow } = require("./support/resources"); const { removeLabel } = require("./support/utils"); +/** @param {import('github-script').AsyncFunctionArguments} AsyncFunctionArguments */ module.exports = async ({ github, context }) => { + const { repo, owner } = context.repo; + + const payload = /** @type {import('@octokit/webhooks-types').IssuesLabeledEvent} */ (context.payload); + const { + label, + issue: { number }, + } = payload; + const { ISSUE_VERIFIERS, CALCITE_DESIGNERS } = process.env; - const { label } = context.payload; - if (label && label.name === issueWorkflow.installed) { + if (label?.name === issueWorkflow.installed) { const issueProps = { - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, + owner, + repo, + issue_number: number, }; const { data: issue } = await github.rest.issues.get(issueProps); await removeLabel({ github, context, label: issueWorkflow.inDevelopment }); - const assignees = ISSUE_VERIFIERS.split(",").map((v) => v.trim()); + const assignees = ISSUE_VERIFIERS?.split(",").map((v) => v.trim()); // assign designers if figma updates are required - if (issue.labels.map((label) => label.name).includes(handoff.figmaChanges)) { + if ( + assignees && + CALCITE_DESIGNERS && + issue.labels.map((label) => (typeof label === "string" ? label : label.name)).includes(handoff.figmaChanges) + ) { assignees.push(...CALCITE_DESIGNERS.split(",").map((v) => v.trim())); } diff --git a/.github/scripts/assignPullRequestAuthor.js b/.github/scripts/assignPullRequestAuthor.js index 2d9f5be2255..7e72b3f29b8 100644 --- a/.github/scripts/assignPullRequestAuthor.js +++ b/.github/scripts/assignPullRequestAuthor.js @@ -1,17 +1,24 @@ +// @ts-check +/** @param {import('github-script').AsyncFunctionArguments} AsyncFunctionArguments */ module.exports = async ({ github, context }) => { + const { repo, owner } = context.repo; + + const payload = /** @type {import('@octokit/webhooks-types').PullRequestEvent} */ (context.payload); const { - assignees, - number, - user: { login: author }, - } = context.payload.pull_request; + pull_request: { + assignees, + number, + user: { login: author }, + }, + } = payload; const updatedAssignees = assignees && assignees.length ? [...assignees.map((a) => a.login).filter((a) => a !== author), author] : [author]; try { await github.rest.issues.addAssignees({ - owner: context.repo.owner, - repo: context.repo.repo, + owner, + repo, issue_number: number, assignees: updatedAssignees, }); diff --git a/.github/scripts/labelPullRequestWithCommitType.js b/.github/scripts/labelPullRequestWithCommitType.js index ed6fe6a247f..f443ce21546 100644 --- a/.github/scripts/labelPullRequestWithCommitType.js +++ b/.github/scripts/labelPullRequestWithCommitType.js @@ -1,7 +1,14 @@ +// @ts-check const { issueType } = require("./support/resources"); +/** @param {import('github-script').AsyncFunctionArguments} AsyncFunctionArguments */ module.exports = async ({ github, context }) => { - const { title, number } = context.payload.pull_request; + const { repo, owner } = context.repo; + + const payload = /** @type {import('@octokit/webhooks-types').PullRequestEvent} */ (context.payload); + const { + pull_request: { title, number }, + } = payload; const conventionalCommitRegex = /^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\([\w ,-]+\))?(!?:\s+)([\w ]+[\s\S]*)/i; @@ -23,9 +30,9 @@ module.exports = async ({ github, context }) => { try { await github.rest.issues.addLabels({ + owner, + repo, issue_number: number, - owner: context.repo.owner, - repo: context.repo.repo, labels: [typeLabel], }); } catch (e) { @@ -33,6 +40,9 @@ module.exports = async ({ github, context }) => { } }; +/** + * @param {string} type + */ function getLabelName(type) { switch (type) { case "feat": diff --git a/.github/scripts/notifyAboutNewComponent.js b/.github/scripts/notifyAboutNewComponent.js index ac27c2be3f5..d407970a88e 100644 --- a/.github/scripts/notifyAboutNewComponent.js +++ b/.github/scripts/notifyAboutNewComponent.js @@ -1,16 +1,32 @@ +// @ts-check // If the "new component" label is added to an issue, generates a notification to the Calcite designer lead(s) // The secret is formatted like so: designer1, designer2, designer3 // Note the script automatically adds the "@" character in to notify the designer lead(s) + +/** @param {import('github-script').AsyncFunctionArguments} AsyncFunctionArguments */ module.exports = async ({ github, context }) => { - const { designers } = process.env; + const { repo, owner } = context.repo; + + const payload = /** @type {import('@octokit/webhooks-types').IssuesLabeledEvent} */ (context.payload); + const { + issue: { number }, + } = payload; + + const { DESIGNERS } = process.env; + // Add a "@" character to notify the user - const calcite_designers = designers.split(",").map((v) => " @" + v.trim()); + const calcite_designers = DESIGNERS?.split(",").map((v) => " @" + v.trim()); + + if (!calcite_designers?.length) { + console.error("unable to determine designers"); + process.exit(1); + } // Add a comment to issues with the 'new component' label to notify the designer(s) await github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, + owner, + repo, + issue_number: number, body: `cc ${calcite_designers}`, }); }; diff --git a/.github/scripts/notifyWhenReadyForDev.js b/.github/scripts/notifyWhenReadyForDev.js index 2c790ea531f..3b7d8c73ed3 100644 --- a/.github/scripts/notifyWhenReadyForDev.js +++ b/.github/scripts/notifyWhenReadyForDev.js @@ -1,3 +1,4 @@ +// @ts-check // When the "ready for dev" label is added to an issue: // 1. Modifies the labels, // 2. Updates the assignees and milestone, and @@ -9,18 +10,26 @@ const { issueWorkflow, planning } = require("./support/resources"); const { removeLabel } = require("./support/utils"); +/** @param {import('github-script').AsyncFunctionArguments} AsyncFunctionArguments */ module.exports = async ({ github, context }) => { - const { managers } = process.env; - const { label } = context.payload; + const { repo, owner } = context.repo; - if (label && label.name === "ready for dev") { + const payload = /** @type {import('@octokit/webhooks-types').IssuesLabeledEvent} */ (context.payload); + const { + issue: { number }, + label, + } = payload; + + const { MANAGERS } = process.env; + + if (label?.name === "ready for dev") { // Add a "@" character to notify the user - const calcite_managers = managers.split(",").map((v) => " @" + v.trim()); + const calcite_managers = MANAGERS?.split(",").map((v) => " @" + v.trim()); const issueProps = { - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, + owner, + repo, + issue_number: number, }; /* Modify labels */ diff --git a/.github/scripts/notifyWhenSpikeComplete.js b/.github/scripts/notifyWhenSpikeComplete.js index d8364583aa4..7189509f2d0 100644 --- a/.github/scripts/notifyWhenSpikeComplete.js +++ b/.github/scripts/notifyWhenSpikeComplete.js @@ -1,3 +1,4 @@ +// @ts-check // When the "spike complete" label is added to an issue: // 1. Modifies the labels, // 2. Updates the assignees and milestone, and @@ -9,18 +10,26 @@ const { issueWorkflow, planning } = require("./support/resources"); const { removeLabel } = require("./support/utils"); +/** @param {import('github-script').AsyncFunctionArguments} AsyncFunctionArguments */ module.exports = async ({ github, context }) => { - const { managers } = process.env; - const { label } = context.payload; + const { repo, owner } = context.repo; - if (label && label.name === planning.spikeComplete) { + const payload = /** @type {import('@octokit/webhooks-types').IssuesLabeledEvent} */ (context.payload); + const { + issue: { number }, + label, + } = payload; + + const { MANAGERS } = process.env; + + if (label?.name === planning.spikeComplete) { // Add a "@" character to notify the user - const calcite_managers = managers.split(",").map((v) => " @" + v.trim()); + const calcite_managers = MANAGERS?.split(",").map((v) => " @" + v.trim()); const issueProps = { - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, + owner, + repo, + issue_number: number, }; /* Modify labels */ diff --git a/.github/scripts/support/utils.js b/.github/scripts/support/utils.js index 01016c1b357..4150a44ef26 100644 --- a/.github/scripts/support/utils.js +++ b/.github/scripts/support/utils.js @@ -1,4 +1,13 @@ +// @ts-check module.exports = { + /** + * @typedef {object} removeLabelParam + * @property {InstanceType} github + * @property {import('@actions/github/lib/context').Context} context + * @property {string} label + * + * @param {removeLabelParam} obj + **/ removeLabel: async ({ github, context, label }) => { const { owner, repo } = context.repo; const issue_number = context.issue.number; @@ -15,6 +24,16 @@ module.exports = { } }, + /** + * @typedef {object} createLabelIfMissingParam + * @property {InstanceType} github + * @property {import('@actions/github/lib/context').Context} context + * @property {string} label + * @property {string} color + * @property {string} description + * + * @param {createLabelIfMissingParam} obj + **/ createLabelIfMissing: async ({ github, context, label, color, description }) => { const { owner, repo } = context.repo; try { diff --git a/.github/scripts/validatePullRequestTitle.js b/.github/scripts/validatePullRequestTitle.js index f76fbae63bb..e67ba100b95 100644 --- a/.github/scripts/validatePullRequestTitle.js +++ b/.github/scripts/validatePullRequestTitle.js @@ -1,4 +1,9 @@ +// @ts-check +/** @param {import('github-script').AsyncFunctionArguments} AsyncFunctionArguments */ module.exports = async ({ context, core }) => { + const payload = /** @type {import('@octokit/webhooks-types').PullRequestEvent} */ (context.payload); + const { title } = payload.pull_request; + const REGEX = new RegExp("^[^…]+$"); // Title must match this regex const MIN_LENGTH = 1; // Min length of the title const MAX_LENGTH = -1; // Max length of the title (-1 is no max) @@ -6,10 +11,13 @@ module.exports = async ({ context, core }) => { const DISALLOWED_PREFIXES = []; // Title cannot start with one of these prefixes const PREFIX_CASE_SENSITIVE = false; // Whether the prefix is case sensitive + /** + * @param {string} title + * @param {string} prefix + */ const validateTitlePrefix = (title, prefix) => PREFIX_CASE_SENSITIVE ? title.startsWith(prefix) : title.toLowerCase().startsWith(prefix.toLowerCase()); - const { title } = context.payload.pull_request; if (!REGEX.test(title)) { core.setFailed(`Pull Request title "${title}" failed to match regex - ${REGEX}`); return; @@ -28,7 +36,7 @@ module.exports = async ({ context, core }) => { core.info(`Allowed Prefixes: ${ALLOWED_PREFIXES}`); if (ALLOWED_PREFIXES.length && !ALLOWED_PREFIXES.some((prefix) => validateTitlePrefix(title, prefix))) { core.setFailed( - `Pull Request title "${title}" did not start with any of the required prefixes - ${ALLOWED_PREFIXES}` + `Pull Request title "${title}" did not start with any of the required prefixes - ${ALLOWED_PREFIXES}`, ); return; } @@ -36,7 +44,7 @@ module.exports = async ({ context, core }) => { core.info(`Disallowed Prefixes: ${DISALLOWED_PREFIXES}`); if (DISALLOWED_PREFIXES.length && DISALLOWED_PREFIXES.some((prefix) => validateTitlePrefix(title, prefix))) { core.setFailed( - `Pull Request title "${title}" started with one of the disallowed prefixes - ${DISALLOWED_PREFIXES}` + `Pull Request title "${title}" started with one of the disallowed prefixes - ${DISALLOWED_PREFIXES}`, ); return; } diff --git a/package-lock.json b/package-lock.json index fea3e48db7c..a5fa78727e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "@cspell/eslint-plugin": "8.9.1", "@esri/calcite-base": "1.2.0", "@esri/calcite-colors": "6.1.0", + "@octokit/webhooks-types": "7.5.1", "@prettier/sync": "0.5.2", "@rollup/plugin-node-resolve": "15.2.3", "@rollup/plugin-replace": "5.0.7", @@ -42,6 +43,7 @@ "@types/dedent": "0.7.2", "@types/eslint": "8.56.10", "@types/estree": "1.0.5", + "@types/github-script": "github:actions/github-script#pull/482", "@types/jest": "29.5.12", "@types/jest-axe": "3.5.9", "@types/jsdom": "21.1.7", @@ -112,6 +114,264 @@ "@nx/nx-win32-x64-msvc": "19.5.1" } }, + "node_modules/@actions/core": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", + "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", + "dev": true, + "dependencies": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } + }, + "node_modules/@actions/core/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "dev": true, + "dependencies": { + "@actions/io": "^1.0.1" + } + }, + "node_modules/@actions/github": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.0.tgz", + "integrity": "sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==", + "dev": true, + "dependencies": { + "@actions/http-client": "^2.2.0", + "@octokit/core": "^5.0.1", + "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/plugin-rest-endpoint-methods": "^10.0.0" + } + }, + "node_modules/@actions/github/node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "dev": true, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@actions/github/node_modules/@octokit/core": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz", + "integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==", + "dev": true, + "dependencies": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@actions/github/node_modules/@octokit/endpoint": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz", + "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==", + "dev": true, + "dependencies": { + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@actions/github/node_modules/@octokit/graphql": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz", + "integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==", + "dev": true, + "dependencies": { + "@octokit/request": "^8.3.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@actions/github/node_modules/@octokit/openapi-types": { + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz", + "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==", + "dev": true + }, + "node_modules/@actions/github/node_modules/@octokit/plugin-paginate-rest": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz", + "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==", + "dev": true, + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@actions/github/node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "dev": true + }, + "node_modules/@actions/github/node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@actions/github/node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", + "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", + "dev": true, + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@actions/github/node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "dev": true + }, + "node_modules/@actions/github/node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@actions/github/node_modules/@octokit/request": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.0.tgz", + "integrity": "sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==", + "dev": true, + "dependencies": { + "@octokit/endpoint": "^9.0.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@actions/github/node_modules/@octokit/request-error": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz", + "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==", + "dev": true, + "dependencies": { + "@octokit/types": "^13.1.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@actions/github/node_modules/@octokit/types": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.5.0.tgz", + "integrity": "sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^22.2.0" + } + }, + "node_modules/@actions/glob": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.4.0.tgz", + "integrity": "sha512-+eKIGFhsFa4EBwaf/GMyzCdWrXWymGXfFmZU3FHQvYS8mPcHtTtZONbkcqqUMzw9mJ/pImEBFET1JNifhqGsAQ==", + "dev": true, + "dependencies": { + "@actions/core": "^1.9.1", + "minimatch": "^3.0.4" + } + }, + "node_modules/@actions/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@actions/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@actions/http-client": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.1.tgz", + "integrity": "sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==", + "dev": true, + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" + } + }, + "node_modules/@actions/http-client/node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dev": true, + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", + "dev": true + }, "node_modules/@adobe/css-tools": { "version": "4.3.3", "dev": true, @@ -3233,6 +3493,15 @@ "resolved": "packages/eslint-plugin-calcite-components", "link": true }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@floating-ui/core": { "version": "1.6.2", "license": "MIT", @@ -5834,6 +6103,12 @@ "@octokit/openapi-types": "^18.0.0" } }, + "node_modules/@octokit/webhooks-types": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-7.5.1.tgz", + "integrity": "sha512-1dozxWEP8lKGbtEu7HkRbK1F/nIPuJXNfT0gd96y6d3LcHZTtRtlf8xz3nicSJfesADxJyDh+mWBOsdLkqgzYw==", + "dev": true + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "dev": true, @@ -7504,6 +7779,168 @@ "@types/send": "*" } }, + "node_modules/@types/github-script": { + "name": "github-script", + "version": "7.0.1", + "resolved": "git+ssh://git@github.com/actions/github-script.git#c44be22d0bdc111a630a891945557ae7fcedc80b", + "dev": true, + "dependencies": { + "@actions/core": "^1.10.1", + "@actions/exec": "^1.1.1", + "@actions/github": "^6.0.0", + "@actions/glob": "^0.4.0", + "@actions/io": "^1.1.3", + "@octokit/core": "^5.0.1", + "@octokit/plugin-request-log": "^4.0.0", + "@octokit/plugin-retry": "^6.0.1", + "@types/node": "^20.9.0" + }, + "engines": { + "node": ">=20.0.0 <21.0.0" + } + }, + "node_modules/@types/github-script/node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "dev": true, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@types/github-script/node_modules/@octokit/core": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz", + "integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==", + "dev": true, + "dependencies": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@types/github-script/node_modules/@octokit/endpoint": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz", + "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==", + "dev": true, + "dependencies": { + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@types/github-script/node_modules/@octokit/graphql": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz", + "integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==", + "dev": true, + "dependencies": { + "@octokit/request": "^8.3.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@types/github-script/node_modules/@octokit/openapi-types": { + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz", + "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==", + "dev": true + }, + "node_modules/@types/github-script/node_modules/@octokit/plugin-request-log": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.1.tgz", + "integrity": "sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==", + "dev": true, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@types/github-script/node_modules/@octokit/plugin-retry": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.0.1.tgz", + "integrity": "sha512-SKs+Tz9oj0g4p28qkZwl/topGcb0k0qPNX/i7vBKmDsjoeqnVfFUquqrE/O9oJY7+oLzdCtkiWSXLpLjvl6uog==", + "dev": true, + "dependencies": { + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^12.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=5" + } + }, + "node_modules/@types/github-script/node_modules/@octokit/plugin-retry/node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "dev": true + }, + "node_modules/@types/github-script/node_modules/@octokit/plugin-retry/node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@types/github-script/node_modules/@octokit/request": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.0.tgz", + "integrity": "sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==", + "dev": true, + "dependencies": { + "@octokit/endpoint": "^9.0.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@types/github-script/node_modules/@octokit/request-error": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz", + "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==", + "dev": true, + "dependencies": { + "@octokit/types": "^13.1.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@types/github-script/node_modules/@octokit/types": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.5.0.tgz", + "integrity": "sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^22.2.0" + } + }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "dev": true, @@ -9697,6 +10134,12 @@ "dev": true, "license": "ISC" }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "dev": true + }, "node_modules/brace-expansion": { "version": "2.0.1", "dev": true, @@ -31526,6 +31969,15 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -33953,7 +34405,7 @@ }, "packages/calcite-components": { "name": "@esri/calcite-components", - "version": "2.11.0-next.21", + "version": "2.11.0-next.23", "license": "SEE LICENSE.md", "dependencies": { "@esri/calcite-ui-icons": "3.29.0", @@ -37150,10 +37602,10 @@ }, "packages/calcite-components-angular/projects/component-library": { "name": "@esri/calcite-components-angular", - "version": "2.11.0-next.21", + "version": "2.11.0-next.23", "license": "SEE LICENSE.md", "dependencies": { - "@esri/calcite-components": "^2.11.0-next.21", + "@esri/calcite-components": "^2.11.0-next.23", "tslib": "2.6.3" }, "peerDependencies": { @@ -37163,10 +37615,10 @@ }, "packages/calcite-components-react": { "name": "@esri/calcite-components-react", - "version": "2.11.0-next.21", + "version": "2.11.0-next.23", "license": "SEE LICENSE.md", "dependencies": { - "@esri/calcite-components": "^2.11.0-next.21" + "@esri/calcite-components": "^2.11.0-next.23" }, "peerDependencies": { "react": ">=16.7", diff --git a/package.json b/package.json index f0d7a3cdc94..cf9fecefe45 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "@cspell/eslint-plugin": "8.9.1", "@esri/calcite-base": "1.2.0", "@esri/calcite-colors": "6.1.0", + "@octokit/webhooks-types": "7.5.1", "@prettier/sync": "0.5.2", "@rollup/plugin-node-resolve": "15.2.3", "@rollup/plugin-replace": "5.0.7", @@ -57,6 +58,7 @@ "@types/dedent": "0.7.2", "@types/eslint": "8.56.10", "@types/estree": "1.0.5", + "@types/github-script": "github:actions/github-script#pull/482", "@types/jest": "29.5.12", "@types/jest-axe": "3.5.9", "@types/jsdom": "21.1.7", diff --git a/packages/calcite-components-angular/projects/component-library/CHANGELOG.md b/packages/calcite-components-angular/projects/component-library/CHANGELOG.md index 180a89f4fd9..7d847ca61ac 100644 --- a/packages/calcite-components-angular/projects/component-library/CHANGELOG.md +++ b/packages/calcite-components-angular/projects/component-library/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.11.0-next.23](https://github.com/Esri/calcite-design-system/compare/@esri/calcite-components-angular@2.11.0-next.22...@esri/calcite-components-angular@2.11.0-next.23) (2024-07-25) + +**Note:** Version bump only for package @esri/calcite-components-angular + +## [2.11.0-next.22](https://github.com/Esri/calcite-design-system/compare/@esri/calcite-components-angular@2.11.0-next.21...@esri/calcite-components-angular@2.11.0-next.22) (2024-07-25) + +**Note:** Version bump only for package @esri/calcite-components-angular + ## [2.11.0-next.21](https://github.com/Esri/calcite-design-system/compare/@esri/calcite-components-angular@2.11.0-next.20...@esri/calcite-components-angular@2.11.0-next.21) (2024-07-23) **Note:** Version bump only for package @esri/calcite-components-angular diff --git a/packages/calcite-components-angular/projects/component-library/package.json b/packages/calcite-components-angular/projects/component-library/package.json index df262dafdc8..b62da298cfd 100644 --- a/packages/calcite-components-angular/projects/component-library/package.json +++ b/packages/calcite-components-angular/projects/component-library/package.json @@ -1,6 +1,6 @@ { "name": "@esri/calcite-components-angular", - "version": "2.11.0-next.21", + "version": "2.11.0-next.23", "description": "A set of Angular components that wrap Esri's Calcite Components.", "homepage": "https://developers.arcgis.com/calcite-design-system/", "bugs": { @@ -17,7 +17,7 @@ }, "sideEffects": false, "dependencies": { - "@esri/calcite-components": "^2.11.0-next.21", + "@esri/calcite-components": "^2.11.0-next.23", "tslib": "2.6.3" }, "peerDependencies": { diff --git a/packages/calcite-components-react/CHANGELOG.md b/packages/calcite-components-react/CHANGELOG.md index bbe29dbe3ee..1b3be4dbb44 100644 --- a/packages/calcite-components-react/CHANGELOG.md +++ b/packages/calcite-components-react/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.11.0-next.23](https://github.com/Esri/calcite-design-system/compare/@esri/calcite-components-react@2.11.0-next.22...@esri/calcite-components-react@2.11.0-next.23) (2024-07-25) + +**Note:** Version bump only for package @esri/calcite-components-react + +## [2.11.0-next.22](https://github.com/Esri/calcite-design-system/compare/@esri/calcite-components-react@2.11.0-next.21...@esri/calcite-components-react@2.11.0-next.22) (2024-07-25) + +**Note:** Version bump only for package @esri/calcite-components-react + ## [2.11.0-next.21](https://github.com/Esri/calcite-design-system/compare/@esri/calcite-components-react@2.11.0-next.20...@esri/calcite-components-react@2.11.0-next.21) (2024-07-23) **Note:** Version bump only for package @esri/calcite-components-react diff --git a/packages/calcite-components-react/package.json b/packages/calcite-components-react/package.json index 2783f5cb4ba..5707a517a25 100644 --- a/packages/calcite-components-react/package.json +++ b/packages/calcite-components-react/package.json @@ -1,6 +1,6 @@ { "name": "@esri/calcite-components-react", - "version": "2.11.0-next.21", + "version": "2.11.0-next.23", "description": "A set of React components that wrap calcite components", "homepage": "https://developers.arcgis.com/calcite-design-system/", "repository": { @@ -28,7 +28,7 @@ "tsc": "tsc" }, "dependencies": { - "@esri/calcite-components": "^2.11.0-next.21" + "@esri/calcite-components": "^2.11.0-next.23" }, "peerDependencies": { "react": ">=16.7", diff --git a/packages/calcite-components/CHANGELOG.md b/packages/calcite-components/CHANGELOG.md index 818fc0f2fe9..959743843b2 100644 --- a/packages/calcite-components/CHANGELOG.md +++ b/packages/calcite-components/CHANGELOG.md @@ -3,6 +3,19 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.11.0-next.23](https://github.com/Esri/calcite-design-system/compare/@esri/calcite-components@2.11.0-next.22...@esri/calcite-components@2.11.0-next.23) (2024-07-25) + +### Bug Fixes + +- **carousel:** Prevent duplicate animation when navigating via keyboard ([#9848](https://github.com/Esri/calcite-design-system/issues/9848)) ([37229a5](https://github.com/Esri/calcite-design-system/commit/37229a5de4a6338c6d921d2def6afc38300bf636)), closes [#9471](https://github.com/Esri/calcite-design-system/issues/9471) + +## [2.11.0-next.22](https://github.com/Esri/calcite-design-system/compare/@esri/calcite-components@2.11.0-next.21...@esri/calcite-components@2.11.0-next.22) (2024-07-25) + +### Bug Fixes + +- **shell:** fix resizing a slotted shell-panel when clicking to resize ([#9846](https://github.com/Esri/calcite-design-system/issues/9846)) ([2318905](https://github.com/Esri/calcite-design-system/commit/23189059dd8a0efa4e665c5a10d2dc1568e0d6ef)), closes [#9807](https://github.com/Esri/calcite-design-system/issues/9807) +- **tabs:** Update tab title indicator display ([#9666](https://github.com/Esri/calcite-design-system/issues/9666)) ([d570023](https://github.com/Esri/calcite-design-system/commit/d570023ab447b6ba6694c38b611efae4db2cc0eb)), closes [#8800](https://github.com/Esri/calcite-design-system/issues/8800) [#8772](https://github.com/Esri/calcite-design-system/issues/8772) + ## [2.11.0-next.21](https://github.com/Esri/calcite-design-system/compare/@esri/calcite-components@2.11.0-next.20...@esri/calcite-components@2.11.0-next.21) (2024-07-23) ### Features diff --git a/packages/calcite-components/package.json b/packages/calcite-components/package.json index dd456a195ec..567db28c352 100644 --- a/packages/calcite-components/package.json +++ b/packages/calcite-components/package.json @@ -1,6 +1,6 @@ { "name": "@esri/calcite-components", - "version": "2.11.0-next.21", + "version": "2.11.0-next.23", "homepage": "https://developers.arcgis.com/calcite-design-system/", "description": "Web Components for Esri's Calcite Design System.", "main": "dist/index.cjs.js", diff --git a/packages/calcite-components/src/components.d.ts b/packages/calcite-components/src/components.d.ts index 1c920006dcc..1c2de4bd221 100644 --- a/packages/calcite-components/src/components.d.ts +++ b/packages/calcite-components/src/components.d.ts @@ -4873,8 +4873,6 @@ export namespace Components { } interface CalciteTabNav { "bordered": boolean; - "indicatorOffset": number; - "indicatorWidth": number; "layout": TabLayout; /** * Use this property to override individual strings used by the component. @@ -12878,8 +12876,6 @@ declare namespace LocalJSX { } interface CalciteTabNav { "bordered"?: boolean; - "indicatorOffset"?: number; - "indicatorWidth"?: number; "layout"?: TabLayout; /** * Use this property to override individual strings used by the component. diff --git a/packages/calcite-components/src/components/carousel/carousel.tsx b/packages/calcite-components/src/components/carousel/carousel.tsx index fb15ae06c3b..3185becb26b 100644 --- a/packages/calcite-components/src/components/carousel/carousel.tsx +++ b/packages/calcite-components/src/components/carousel/carousel.tsx @@ -494,6 +494,8 @@ export class Carousel return; } + const lastItem = this.items.length - 1; + switch (event.key) { case " ": case "Enter": @@ -512,13 +514,19 @@ export class Carousel break; case "Home": event.preventDefault(); + if (this.selectedIndex === 0) { + return; + } this.direction = "backward"; this.setSelectedItem(0, true); break; case "End": event.preventDefault(); + if (this.selectedIndex === lastItem) { + return; + } this.direction = "forward"; - this.setSelectedItem(this.items.length - 1, true); + this.setSelectedItem(lastItem, true); break; } }; diff --git a/packages/calcite-components/src/components/tab-nav/resources.ts b/packages/calcite-components/src/components/tab-nav/resources.ts index 451228247f6..010d3306dfa 100644 --- a/packages/calcite-components/src/components/tab-nav/resources.ts +++ b/packages/calcite-components/src/components/tab-nav/resources.ts @@ -4,7 +4,6 @@ export const ICON = { } as const; export const CSS = { - activeIndicatorContainer: "tab-nav-active-indicator-container", container: "tab-nav", containerHasEndTabTitleOverflow: "tab-nav--end-overflow", containerHasStartTabTitleOverflow: "tab-nav--start-overflow", diff --git a/packages/calcite-components/src/components/tab-nav/tab-nav.e2e.ts b/packages/calcite-components/src/components/tab-nav/tab-nav.e2e.ts index e9d2be1069d..df4fe3bfd73 100644 --- a/packages/calcite-components/src/components/tab-nav/tab-nav.e2e.ts +++ b/packages/calcite-components/src/components/tab-nav/tab-nav.e2e.ts @@ -48,48 +48,6 @@ describe("calcite-tab-nav", () => { expect(activeEventSpy).toHaveReceivedEventTimes(2); }); - describe("selected indicator", () => { - const tabTitles = html` - Tab 1 Title - Tab 2 Title - Tab 3 Title - Tab 4 Title - `; - - it("has its active indicator positioned from left if LTR", async () => { - const page = await newE2EPage(); - await page.setContent(`${tabTitles}`); - const element = await page.find("calcite-tab-nav >>> .tab-nav-active-indicator"); - const style = await element.getComputedStyle(); - expect(style["left"]).toBe("0px"); - expect(style["right"]).not.toBe("0px"); - expect(style["width"]).not.toBe("0px"); - }); - - it("has its active indicator positioned from right if RTL", async () => { - const page = await newE2EPage(); - await page.setContent(`${tabTitles}`); - const element = await page.find("calcite-tab-nav >>> .tab-nav-active-indicator"); - const style = await element.getComputedStyle(); - expect(style["right"]).toBe("0px"); - expect(style["left"]).not.toBe("0px"); - expect(style["width"]).not.toBe("0px"); - }); - - it("updates position when made visible", async () => { - const page = await newE2EPage(); - await page.setContent(``); - const tabNav = await page.find("calcite-tab-nav"); - const indicator = await page.find("calcite-tab-nav >>> .tab-nav-active-indicator"); - - tabNav.setProperty("hidden", false); - await page.waitForChanges(); - - const style = await indicator.getComputedStyle(); - expect(style["width"]).not.toBe("0px"); - }); - }); - it("focuses on keyboard interaction", async () => { const page = await newE2EPage(); await page.setContent( diff --git a/packages/calcite-components/src/components/tab-nav/tab-nav.scss b/packages/calcite-components/src/components/tab-nav/tab-nav.scss index ff0279df298..aedd6d89ffb 100644 --- a/packages/calcite-components/src/components/tab-nav/tab-nav.scss +++ b/packages/calcite-components/src/components/tab-nav/tab-nav.scss @@ -28,7 +28,6 @@ $last-mask-color-stop-position: 51%; // we go beyond the half point to ensure the mask color stops overlap when both start and end are overflowing .tab-nav--start-overflow { - .tab-nav-active-indicator-container, .tab-titles-slot-wrapper { mask-image: linear-gradient( to var(--calcite-internal-tab-nav-gradient-end-side), @@ -41,7 +40,6 @@ $last-mask-color-stop-position: 51%; // we go beyond the half point to ensure th } .tab-nav--end-overflow { - .tab-nav-active-indicator-container, .tab-titles-slot-wrapper { mask-image: linear-gradient( to var(--calcite-internal-tab-nav-gradient-start-side), @@ -54,7 +52,6 @@ $last-mask-color-stop-position: 51%; // we go beyond the half point to ensure th } .tab-nav--start-overflow.tab-nav--end-overflow { - .tab-nav-active-indicator-container, .tab-titles-slot-wrapper { mask-image: linear-gradient( to var(--calcite-internal-tab-nav-gradient-end-side), @@ -126,26 +123,6 @@ $last-mask-color-stop-position: 51%; // we go beyond the half point to ensure th overflow-hidden; } -// prevent indicator overflow in horizontal scrolling situations -.tab-nav-active-indicator-container { - @apply absolute - bottom-0 - h-0.5 - inset-x-0 - overflow-hidden - w-full; -} - -.tab-nav-active-indicator { - @apply absolute - bg-brand - bottom-0 - block - h-0.5 - ease-out - transition-all; -} - .scroll-button-container { @apply absolute bottom-0 top-0; @@ -195,29 +172,4 @@ $last-mask-color-stop-position: 51%; // we go beyond the half point to ensure th } } -:host .position-bottom .tab-nav-active-indicator { - inset-block-end: unset; - @apply top-0; -} - -:host .position-bottom .tab-nav-active-indicator-container { - inset-block-end: unset; - @apply top-0; -} - -:host([bordered]) .tab-nav-active-indicator-container { - inset-block-end: unset; // display active blue line above instead of below -} - -:host([bordered]) .position-bottom .tab-nav-active-indicator-container { - inset-block-end: 0; // display active blue line below instead of above - inset-block-start: unset; -} - -@media (forced-colors: active) { - .tab-nav-active-indicator { - background-color: highlight; - } -} - @include base-component(); diff --git a/packages/calcite-components/src/components/tab-nav/tab-nav.tsx b/packages/calcite-components/src/components/tab-nav/tab-nav.tsx index adaccde7ceb..ab5d5f1c958 100644 --- a/packages/calcite-components/src/components/tab-nav/tab-nav.tsx +++ b/packages/calcite-components/src/components/tab-nav/tab-nav.tsx @@ -79,7 +79,6 @@ export class TabNav implements LocalizedComponent, T9nComponent { this.calciteInternalTabChange.emit({ tab: this.selectedTabId, }); - this.updateActiveIndicator(); } /** @@ -106,16 +105,6 @@ export class TabNav implements LocalizedComponent, T9nComponent { */ @Prop({ reflect: true, mutable: true }) bordered = false; - /** - * @internal - */ - @Prop({ mutable: true }) indicatorOffset: number; - - /** - * @internal - */ - @Prop({ mutable: true }) indicatorWidth: number; - /** * Made into a prop for testing purposes only. * @@ -167,10 +156,6 @@ export class TabNav implements LocalizedComponent, T9nComponent { this.layout = parentTabsEl?.layout; this.bordered = parentTabsEl?.bordered; this.effectiveDir = getElementDir(this.el); - - if (this.selectedTitle) { - this.updateActiveIndicator(); - } } componentDidRender(): void { @@ -201,11 +186,6 @@ export class TabNav implements LocalizedComponent, T9nComponent { //-------------------------------------------------------------------------- render(): VNode { - const width = `${this.indicatorWidth}px`; - const offset = `${this.indicatorOffset}px`; - const indicatorStyle = - this.effectiveDir !== "rtl" ? { width, left: offset } : { width, right: offset }; - return (
{this.renderScrollButton("start")}
-
(this.activeIndicatorContainerEl = el)} - > -
(this.activeIndicatorEl = el as HTMLElement)} - style={indicatorStyle} - /> -
{this.renderScrollButton("end")}
@@ -367,11 +334,6 @@ export class TabNav implements LocalizedComponent, T9nComponent { event.stopPropagation(); } - @Listen("calciteInternalTabIconChanged") - iconStartChangeHandler(): void { - this.updateActiveIndicator(); - } - //-------------------------------------------------------------------------- // // Events @@ -432,12 +394,6 @@ export class TabNav implements LocalizedComponent, T9nComponent { }); } - private activeIndicatorEl: HTMLElement; - - private activeIndicatorContainerEl: HTMLDivElement; - - private containerEl: HTMLDivElement; - private effectiveDir: Direction = "ltr"; private lastScrollWheelAxis: "x" | "y" = "x"; @@ -450,12 +406,6 @@ export class TabNav implements LocalizedComponent, T9nComponent { private resizeObserver = createObserver("resize", () => { this.updateScrollingState(); - - if (!this.activeIndicatorEl) { - return; - } - - this.updateActiveIndicator(); }); private get scrollerButtonWidth(): number { @@ -469,20 +419,6 @@ export class TabNav implements LocalizedComponent, T9nComponent { // //-------------------------------------------------------------------------- - private updateActiveIndicator(): void { - const tabTitleScrollLeft = this.tabTitleContainerEl?.scrollLeft; - const containerScrollLeft = this.containerEl?.scrollLeft; - const navWidth = this.activeIndicatorContainerEl?.offsetWidth; - const tabLeft = this.selectedTitle?.offsetLeft; - const tabWidth = this.selectedTitle?.offsetWidth; - const offsetRight = navWidth - tabLeft - tabWidth; - const offsetBase = this.effectiveDir === "ltr" ? tabLeft : offsetRight; - const multiplier = this.effectiveDir === "ltr" ? -1 : 1; - - this.indicatorOffset = offsetBase + multiplier * (containerScrollLeft + tabTitleScrollLeft); - this.indicatorWidth = this.selectedTitle?.offsetWidth; - } - private onTabTitleWheel = (event: WheelEvent): void => { event.preventDefault(); @@ -504,7 +440,6 @@ export class TabNav implements LocalizedComponent, T9nComponent { const scrollByX = (this.effectiveDir === "rtl" ? -1 : 1) * scrollBy; (event.currentTarget as HTMLDivElement).scrollBy(scrollByX, 0); - requestAnimationFrame(() => this.updateActiveIndicator()); }; private onSlotChange = (event: Event): void => { @@ -517,8 +452,6 @@ export class TabNav implements LocalizedComponent, T9nComponent { this.calciteInternalTabNavSlotChange.emit(slottedElements); }; - private storeContainerRef = (el: HTMLDivElement) => (this.containerEl = el); - private storeTabTitleWrapperRef = (el: HTMLDivElement) => { this.tabTitleContainerEl = el; this.intersectionObserver = createObserver("intersection", () => this.updateScrollingState(), { @@ -646,7 +579,6 @@ export class TabNav implements LocalizedComponent, T9nComponent { } private onTabTitleScroll = (): void => { - this.updateActiveIndicator(); this.updateScrollingState(); }; @@ -699,7 +631,6 @@ export class TabNav implements LocalizedComponent, T9nComponent { } requestAnimationFrame(() => { - this.updateActiveIndicator(); tabTitles[this.selectedTabId].focus(); }); } diff --git a/packages/calcite-components/src/components/tab-title/resources.ts b/packages/calcite-components/src/components/tab-title/resources.ts index f0d85f55681..a2891547cb3 100644 --- a/packages/calcite-components/src/components/tab-title/resources.ts +++ b/packages/calcite-components/src/components/tab-title/resources.ts @@ -1,12 +1,17 @@ +import { Scale } from "../interfaces"; + export const CSS = { closeButton: "close-button", container: "container", + containerBottom: "container--bottom", content: "content", contentHasText: "content--has-text", iconEnd: "icon-end", iconPresent: "icon-present", iconStart: "icon-start", titleIcon: "calcite-tab-title--icon", + scale: (scale: Scale) => `scale-${scale}` as const, + selectedIndicator: "selected-indicator", }; export const ICONS = { diff --git a/packages/calcite-components/src/components/tab-title/tab-title.e2e.ts b/packages/calcite-components/src/components/tab-title/tab-title.e2e.ts index d9ad2e31879..3146dba8ca5 100644 --- a/packages/calcite-components/src/components/tab-title/tab-title.e2e.ts +++ b/packages/calcite-components/src/components/tab-title/tab-title.e2e.ts @@ -343,54 +343,4 @@ describe("calcite-tab-title", () => { await page.keyboard.press("Enter"); expect(activeEventSpy).toHaveReceivedEventTimes(2); }); - - describe("when the active tab-title changes", () => { - it("should move the active tab nav indicator", async () => { - const page = await newE2EPage({ - html: ` - - - Tab 1 Title - Tab 2 Title - Tab 3 Title - Tab 4 Title - - Tab 1 Content - Tab 2 Content - Tab 3 Content - Tab 4 Content - - `, - }); - const tabTitle1 = await page.find(".title-1"); - const tabTitle2 = await page.find(".title-2"); - - expect(await (await page.find("calcite-tab-title[selected]")).innerText).toEqual("Tab 2 Title"); - expect( - await page.evaluate(() => { - return ( - document - .querySelector("calcite-tab-nav") - .shadowRoot.querySelector(".tab-nav-active-indicator") as HTMLDivElement - ).style.left; - }), - ).not.toEqual("0px"); - - // toggle new selected tab-title - await tabTitle2.removeAttribute("selected"); - await tabTitle1.setAttribute("selected", true); - await page.waitForChanges(); - - expect(await (await page.find("calcite-tab-title[selected]")).innerText).toEqual("Tab 1 Title"); - expect( - await page.evaluate(() => { - return ( - document - .querySelector("calcite-tab-nav") - .shadowRoot.querySelector(".tab-nav-active-indicator") as HTMLDivElement - ).style.left; - }), - ).toEqual("0px"); - }); - }); }); diff --git a/packages/calcite-components/src/components/tab-title/tab-title.scss b/packages/calcite-components/src/components/tab-title/tab-title.scss index f995706fe33..9be58245133 100644 --- a/packages/calcite-components/src/components/tab-title/tab-title.scss +++ b/packages/calcite-components/src/components/tab-title/tab-title.scss @@ -12,29 +12,38 @@ } .content { - @apply flex items-center justify-center; + @apply flex items-center justify-center h-full mb-0.5 relative box-border; } .scale-s { .content { @apply text-n2h py-1; } + .close-button { + @apply w-5; + } } .scale-m { .content { @apply text-n1h py-2; } + .close-button { + @apply w-7; + } } .scale-l { .content { @apply text-0h py-2.5; } + .close-button { + @apply w-8; + } } :host([closable]) .content { - @apply h-full box-border border-b-color-transparent; + @apply border-b-color-transparent; } :host([layout="inline"]), @@ -55,8 +64,7 @@ } .container { - @apply border-b-2 - border-b-color-transparent + @apply relative box-border content-center cursor-pointer @@ -69,15 +77,82 @@ text-n1h transition-default w-full; +} + +.selected-indicator { + @apply absolute + block + w-full + h-0.5 + transition-default; + inset-block-end: 0; + inset-inline-start: 0; + inset-inline-end: 0; + inline-size: 100%; +} + +.container--bottom .selected-indicator { + inset-block-end: unset; + inset-block-start: 0; +} + +:host([bordered]) .selected-indicator { + inset-block-start: 0; + inset-block-end: unset; + inset-inline-start: -1px; + inset-inline-end: 0; + inline-size: calc(100% + var(--calcite-spacing-base)); +} + +:host([bordered][selected]) .container::after { + @apply absolute + block + w-full + h-0.5 + transition-default; + inset-block-end: 0; + inset-inline-start: 0; + inset-inline-end: 0; + inline-size: 100%; + background: var(--calcite-color-foreground-1); + content: ""; +} - border-block-end-style: solid; +:host([bordered][selected]) .container.container--bottom::after { + inset-block-start: -1px; } -:host([position="bottom"]) .container { - @apply border-t-color-transparent - border-b-0 - border-t-2; - border-block-start-style: solid; +:host([bordered][selected]:hover) .container::after { + background: var(--calcite-color-foreground-2); +} + +:host([bordered][selected]:focus) .container::after { + background: transparent; +} + +:host([bordered]) .container--bottom .selected-indicator { + inset-block-start: unset; + inset-block-end: 0; +} + +:host([selected]) .selected-indicator, +:host([selected]:hover) .selected-indicator { + @apply bg-brand; +} + +:host(:hover) .selected-indicator { + background-color: var(--calcite-color-border-3); +} + +:host(:focus) .selected-indicator, +:host(:active) .selected-indicator { + background-color: var(--calcite-color-brand); +} + +@media (forced-colors: active) { + .selected-indicator { + background-color: highlight; + } } :host([closed]) { @@ -125,11 +200,11 @@ } .content--has-text .calcite-tab-title--icon.icon-start { - margin-inline-end: theme("margin.2"); + margin-inline-end: var(--calcite-spacing-sm); } .content--has-text .calcite-tab-title--icon.icon-end { - margin-inline-start: theme("margin.2"); + margin-inline-start: var(--calcite-spacing-sm); } .close-button { @@ -142,25 +217,29 @@ focus-base items-center justify-center - p-1 + h-full self-center text-color-3 transition-default; - background-color: var(--calcite-button-transparent-1); - margin-inline-start: auto; + // compensate for the added border on parent and ensure focus alignment + margin-inline-end: var(--calcite-spacing-px); + box-shadow: + var(--calcite-spacing-px) 0 0 0 transparent, + 0 var(--calcite-spacing-xxs) 0 0 transparent; + block-size: calc(100% - var(--calcite-spacing-xxs)); + &:hover { + box-shadow: var(--calcite-spacing-px) 0 0 0 var(--calcite-color-foreground-3); + } &:focus { - @apply focus-inset; - - // ⚠️overriding outline-offset should be avoided as it won't honor --calcite-color-focus-offset-invert - outline-offset: -1px; + @apply focus-normal; } &:focus, &:hover { @apply text-color-1; - background-color: var(--calcite-color-foreground-2); + background-color: var(--calcite-color-foreground-3); } &:active { @@ -176,7 +255,7 @@ // compensate for spacing when no hastext and two icons :host([icon-start][icon-end]) { .calcite-tab-title--icon:first-child { - margin-inline-end: theme("margin.2"); + margin-inline-end: var(--calcite-spacing-sm); } } @@ -186,33 +265,28 @@ } :host([bordered][selected]) { - box-shadow: inset 0 -2px var(--calcite-color-foreground-1); + box-shadow: inset 0 -1px var(--calcite-color-foreground-1); } :host([bordered][selected][position="bottom"]) { - box-shadow: inset 0 2px 0 var(--calcite-color-foreground-1); + box-shadow: inset 0 var(--calcite-spacing-base) 0 var(--calcite-color-foreground-1); } :host([bordered]:hover) { .container { - background-color: var(--calcite-color-transparent-hover); + background-color: var(--calcite-color-foreground-2); } } :host([closable]) .container, :host([bordered]) .container { - border-inline-start: 1px solid transparent; - border-inline-end: 1px solid transparent; + border-inline-start: var(--calcite-spacing-px) solid transparent; + border-inline-end: var(--calcite-spacing-px) solid transparent; .close-button { - margin-inline: 0; + margin-inline-start: var(--calcite-spacing-sm); } } -:host([closable][position="bottom"]) .container, -:host([bordered][position="bottom"]) .container { - border-block-start-style: unset; -} - :host([selected][bordered]) .container { border-inline-start-color: var(--calcite-color-border-1); border-inline-end-color: var(--calcite-color-border-1); @@ -263,7 +337,7 @@ border-block-end-style: solid; } - :host([bordered][position="bottom"]) .container { + :host([bordered]) .container--bottom { border-block-start-style: solid; } @@ -271,7 +345,7 @@ border-block-end-style: none; } - :host([bordered][position="bottom"][selected]) .container { + :host([bordered][selected]) .container--bottom { border-block-start-style: none; } diff --git a/packages/calcite-components/src/components/tab-title/tab-title.tsx b/packages/calcite-components/src/components/tab-title/tab-title.tsx index 7ff878514d5..8d79c1d504d 100644 --- a/packages/calcite-components/src/components/tab-title/tab-title.tsx +++ b/packages/calcite-components/src/components/tab-title/tab-title.tsx @@ -220,9 +220,10 @@ export class TabTitle implements InteractiveComponent, LocalizedComponent, T9nCo {this.renderCloseButton()} +
diff --git a/packages/calcite-components/src/components/tabs/tabs.e2e.ts b/packages/calcite-components/src/components/tabs/tabs.e2e.ts index 98bd01bf3f2..819afba39c5 100644 --- a/packages/calcite-components/src/components/tabs/tabs.e2e.ts +++ b/packages/calcite-components/src/components/tabs/tabs.e2e.ts @@ -172,44 +172,6 @@ describe("calcite-tabs", () => { expect(await page.find("calcite-tab-title")).toEqualAttribute("bordered", ""); expect(await page.find("calcite-tab")).toEqualAttribute("bordered", null); }); - - it("should render tab-nav's blue active indicator on top", async () => { - const page = await newE2EPage({ - html: ` - - - Tab 1 Title - Tab 2 Title - - Tab 1 Content - Tab 2 Content - - `, - }); - const indicator = await page.find("calcite-tab-nav >>> .tab-nav-active-indicator-container"); - const indicatorStyles = await indicator.getComputedStyle(); - expect(indicatorStyles.top).toEqual("0px"); - expect(indicatorStyles.bottom).not.toEqual("0px"); - }); - - it("should render tab-nav's blue active indicator on bottom when position is bottom", async () => { - const page = await newE2EPage({ - html: ` - - - Tab 1 Title - Tab 2 Title - - Tab 1 Content - Tab 2 Content - - `, - }); - const indicator = await page.find("calcite-tab-nav >>> .tab-nav-active-indicator-container"); - const indicatorStyles = await indicator.getComputedStyle(); - expect(indicatorStyles.bottom).toEqual("0px"); - expect(indicatorStyles.top).not.toEqual("0px"); - }); }); it("should not ignore bordered attribute when layout is center", async () => { diff --git a/packages/calcite-components/src/components/tabs/tabs.stories.ts b/packages/calcite-components/src/components/tabs/tabs.stories.ts index 853d6f4924d..ee41fdb436a 100644 --- a/packages/calcite-components/src/components/tabs/tabs.stories.ts +++ b/packages/calcite-components/src/components/tabs/tabs.stories.ts @@ -364,26 +364,6 @@ Tab200PercentHeightWithVerticalScroll.parameters = { chromatic: { delay: 1000 }, }; -export const updateIndicatorOffset_TestOnly = (): string => - html` - - Boats - Ships - Yachts - - Tab 1 content - Tab 2 content - Tab 3 content - - `; - -updateIndicatorOffset_TestOnly.parameters = { - chromatic: { delay: 1000 }, -}; - export const fixedHeightNoVerticalScrollbar_TestOnly = (): string => html` diff --git a/packages/calcite-components/src/demos/tabs.html b/packages/calcite-components/src/demos/tabs.html index c1170a0952a..866245228a4 100644 --- a/packages/calcite-components/src/demos/tabs.html +++ b/packages/calcite-components/src/demos/tabs.html @@ -71,6 +71,7 @@ Tab 1 Title Tab 2 Title Tab 3 Title + Tab 4 Title
@@ -85,6 +86,7 @@ Tab 1 Title Tab 2 Title Tab 3 Title + Tab 4 Title Tab 1 Content Tab 2 Content @@ -129,6 +131,7 @@ Tab 1 Title Tab 2 Title Tab 3 Title + Tab 4 Title Tab 1 Content Tab 2 Content @@ -291,16 +294,80 @@ + +
+
icon end closable
+ +
+ + + Tab 1 Title + Tab 2 Title + Tab 3 Title + Tab 4 Title + Tab 5 Title + Tab 6 Title + + + Tab 1 Content + Tab 2 Content + +
+ +
+ + + Tab 1 Title + Tab 2 Title + Tab 3 Title + Tab 4 Title + Tab 5 Title + Tab 6 Title + + + Tab 1 Content + Tab 2 Content + +
+ +
+ + + Tab 1 Title + Tab 2 Title + Tab 3 Title + Tab 4 Title + Tab 5 Title + Tab 6 Title + + + Tab 1 Content + Tab 2 Content + +
+
with border + icon-start + icon end
- + - Tab 1 Title + Tab 1 Title Tab 2 Title + Tab 3 Title + Tab 4 Title + Tab 5 Title + Tab 6 Title Tab 1 content Tab 2 Content @@ -308,10 +375,16 @@
- + - Tab 1 Title + Tab 1 Title Tab 2 Title + Tab 3 Title + Tab 4 Title + Tab 5 Title + Tab 6 Title Tab 1 content Tab 2 Content @@ -319,10 +392,72 @@
- + - Tab 1 Title + Tab 1 Title Tab 2 Title + Tab 3 Title + Tab 4 Title + Tab 5 Title + Tab 6 Title + + Tab 1 content + Tab 2 Content + +
+
+ + +
+
with border + icon-start + icon end closable
+ +
+ + + Tab 1 Title + Tab 2 Title + Tab 3 Title + Tab 4 Title + Tab 5 Title + Tab 6 Title + + Tab 1 content + Tab 2 Content + +
+ +
+ + + Tab 1 Title + Tab 2 Title + Tab 3 Title + Tab 4 Title + Tab 5 Title + Tab 6 Title + + Tab 1 content + Tab 2 Content + +
+ +
+ + + Tab 1 Title + Tab 2 Title + Tab 3 Title + Tab 4 Title + Tab 5 Title + Tab 6 Title Tab 1 content Tab 2 Content @@ -350,6 +485,7 @@ Tab 1 Title Tab 2 Title + Tab 3 Title Tab 1 content Tab 2 Content @@ -361,6 +497,51 @@ Tab 1 Title Tab 2 Title + Tab 3 Title + + Tab 1 content + Tab 2 Content + +
+
+ + +
+
tab position: bottom with border + icon-start + icon end closable
+ +
+ + + Tab 1 Title + Tab 2 Title + + Tab 1 content + Tab 2 Content + +
+ +
+ + + Tab 1 Title + Tab 2 Title + + Tab 1 content + Tab 2 Content + +
+ +
+ + + Tab 1 Title + Tab 2 Title Tab 1 content Tab 2 Content