From a1df23c46563d87d666e6e4a91a4800228d13f87 Mon Sep 17 00:00:00 2001 From: "kai.arrowood" Date: Thu, 13 Jul 2023 10:39:57 -0400 Subject: [PATCH] feat(pageheader): new component [khcp-7898] --- packages/core/app-layout/docs/page-header.md | 47 ++++++++ packages/core/app-layout/package.json | 4 +- .../sandbox/components/NavLinks.vue | 3 + packages/core/app-layout/sandbox/index.ts | 5 + .../app-layout/sandbox/pages/PageHeader.vue | 66 ++++++++++ .../components/pageHeader/PageHeader.cy.ts | 74 ++++++++++++ .../src/components/pageHeader/PageHeader.vue | 113 ++++++++++++++++++ packages/core/app-layout/src/index.ts | 12 +- pnpm-lock.yaml | 31 ++++- 9 files changed, 345 insertions(+), 10 deletions(-) create mode 100644 packages/core/app-layout/docs/page-header.md create mode 100644 packages/core/app-layout/sandbox/pages/PageHeader.vue create mode 100644 packages/core/app-layout/src/components/pageHeader/PageHeader.cy.ts create mode 100644 packages/core/app-layout/src/components/pageHeader/PageHeader.vue diff --git a/packages/core/app-layout/docs/page-header.md b/packages/core/app-layout/docs/page-header.md new file mode 100644 index 0000000000..6557871651 --- /dev/null +++ b/packages/core/app-layout/docs/page-header.md @@ -0,0 +1,47 @@ +# PageHeader.vue + +A Kong UI dynamic page header component. + +- [Features](#features) +- [Requirements](#requirements) +- [Usage](#usage) + - [Install](#install) + - [Props](#props) + - [Slots](#slots) + +## Features + +- Reactive updates based on `prop` value changes :rocket: +- Slottable areas for displaying custom content, icons, etc. + +## Requirements + +- `vue` must be initialized in the host application +- `@kong/kongponents` must be available as a `dependency` in the host application, along with the package's style imports. [See here for instructions on installing Kongponents](https://kongponents.konghq.com/#globally-install-all-kongponents). Specifically, the following Kongponents must be available: + - `KBreadcrumb` + +## Usage + +### Install + +[See instructions for installing the `@kong-ui-public/app-layout` package.](../README.md#install) + +### Props + +#### `title` + +- type: `String` +- required: `false` +- default: `''` + +The title text of the page. + +### Slots + +#### `center` + +The main slot to use for navbar content if you don't need a left/center/right navbar layout. + +--- + +[← Back to `@kong-ui-public/app-layout` docs](../README.md) diff --git a/packages/core/app-layout/package.json b/packages/core/app-layout/package.json index ff2c472cb0..a2da840871 100644 --- a/packages/core/app-layout/package.json +++ b/packages/core/app-layout/package.json @@ -38,7 +38,7 @@ "test:unit:open": "cross-env FORCE_COLOR=1 vitest --ui" }, "peerDependencies": { - "@kong/kongponents": "^8.83.5", + "@kong/kongponents": "^8.87.0", "vue": "^3.2.47", "vue-router": "^4.2.2" }, @@ -48,7 +48,7 @@ "lodash.clonedeep": "^4.5.0" }, "devDependencies": { - "@kong/kongponents": "^8.83.5", + "@kong/kongponents": "^8.87.0", "@types/lodash.clonedeep": "^4.5.7", "vue": "^3.2.47", "vue-router": "^4.2.2" diff --git a/packages/core/app-layout/sandbox/components/NavLinks.vue b/packages/core/app-layout/sandbox/components/NavLinks.vue index bf02be2bd5..0248f20bec 100644 --- a/packages/core/app-layout/sandbox/components/NavLinks.vue +++ b/packages/core/app-layout/sandbox/components/NavLinks.vue @@ -12,5 +12,8 @@ KM Example + + PageHeader + diff --git a/packages/core/app-layout/sandbox/index.ts b/packages/core/app-layout/sandbox/index.ts index 3ec532d923..c5d79218da 100644 --- a/packages/core/app-layout/sandbox/index.ts +++ b/packages/core/app-layout/sandbox/index.ts @@ -28,6 +28,11 @@ const router = createRouter({ name: 'kong-manager-example', component: () => import('./pages/KongManagerLayoutExample.vue'), }, + { + path: '/page-header', + name: 'page-header', + component: () => import('./pages/PageHeader.vue'), + }, ], }) diff --git a/packages/core/app-layout/sandbox/pages/PageHeader.vue b/packages/core/app-layout/sandbox/pages/PageHeader.vue new file mode 100644 index 0000000000..3e41313cbe --- /dev/null +++ b/packages/core/app-layout/sandbox/pages/PageHeader.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/packages/core/app-layout/src/components/pageHeader/PageHeader.cy.ts b/packages/core/app-layout/src/components/pageHeader/PageHeader.cy.ts new file mode 100644 index 0000000000..8471eb03ea --- /dev/null +++ b/packages/core/app-layout/src/components/pageHeader/PageHeader.cy.ts @@ -0,0 +1,74 @@ +// Cypress component test spec file + +import PageHeader from './PageHeader.vue' + +describe('', () => { + it('should correctly render content when using props', () => { + const title = 'Cats are Cool' + const breadcrumbTitle = 'Home' + + cy.mount(PageHeader, { + props: { + title, + breadcrumbs: [{ + key: 'home', + to: { name: 'home' }, + text: breadcrumbTitle, + icon: 'kong', + }], + }, + }) + + cy.get('.kong-ui-page-header').should('exist') + cy.getTestId('page-breadcrumbs').should('be.visible') + cy.get('.k-breadcrumb-text').should('contain.text', breadcrumbTitle) + cy.getTestId('page-title-text').should('be.visible') + cy.getTestId('page-title-text').should('contain.text', title) + }) + + it('should correctly render content when use slots', () => { + const title = 'Cats are Cool' + const breadcrumbText = 'breadcrumbs-are-cool' + const iconText = 'title-icons-are-cool' + const badgeText = 'title-badges-are-cool' + const actionsText = 'actions-are-cool' + + cy.mount(PageHeader, { + slots: { + breadcrumbs: breadcrumbText, + default: title, + 'title-icon': iconText, + 'title-badge': badgeText, + actions: actionsText, + }, + }) + + cy.get('.kong-ui-page-header').should('exist') + cy.getTestId('page-breadcrumbs').should('be.visible') + cy.getTestId('page-breadcrumbs').should('contain.text', breadcrumbText) + cy.getTestId('page-title-icon').should('be.visible') + cy.getTestId('page-title-icon').should('contain.text', iconText) + cy.getTestId('page-title-text').should('be.visible') + cy.getTestId('page-title-text').should('contain.text', title) + cy.getTestId('page-title-badge').should('be.visible') + cy.getTestId('page-title-badge').should('contain.text', badgeText) + cy.getTestId('page-actions').should('be.visible') + cy.getTestId('page-actions').should('contain.text', actionsText) + }) + + it('should not render empty slots', () => { + const title = 'Cats are Cool' + + cy.mount(PageHeader, { + props: { + title, + }, + }) + + cy.get('.kong-ui-page-header').should('exist') + cy.getTestId('page-breadcrumbs').should('not.exist') + cy.getTestId('page-title-icon').should('not.exist') + cy.getTestId('page-title-badge').should('not.exist') + cy.getTestId('page-actions').should('not.exist') + }) +}) diff --git a/packages/core/app-layout/src/components/pageHeader/PageHeader.vue b/packages/core/app-layout/src/components/pageHeader/PageHeader.vue new file mode 100644 index 0000000000..21e76cf2c3 --- /dev/null +++ b/packages/core/app-layout/src/components/pageHeader/PageHeader.vue @@ -0,0 +1,113 @@ + + + + + diff --git a/packages/core/app-layout/src/index.ts b/packages/core/app-layout/src/index.ts index a61ae6de82..20a497b010 100644 --- a/packages/core/app-layout/src/index.ts +++ b/packages/core/app-layout/src/index.ts @@ -1,11 +1,12 @@ import type { App } from 'vue' + +import AccountDropdown from './components/navbar/AccountDropdown.vue' +import AppError from './components/errors/AppError.vue' import AppLayout from './components/AppLayout.vue' import AppNavbar from './components/navbar/AppNavbar.vue' -import AccountDropdown from './components/navbar/AccountDropdown.vue' - import AppSidebar from './components/sidebar/AppSidebar.vue' +import PageHeader from './components/pageHeader/PageHeader.vue' import SidebarToggle from './components/sidebar/SidebarToggle.vue' -import AppError from './components/errors/AppError.vue' // Export Vue plugin as the default export default { @@ -18,12 +19,13 @@ export default { // Export individual Components export { + AccountDropdown, + AppError, AppLayout, AppNavbar, AppSidebar, + PageHeader, SidebarToggle, - AppError, - AccountDropdown, } export * from './types' diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4a282d25f1..cbb784fb49 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -257,8 +257,8 @@ importers: version: 4.5.0 devDependencies: '@kong/kongponents': - specifier: ^8.83.5 - version: 8.83.5(vue-router@4.2.2)(vue@3.2.47) + specifier: ^8.87.0 + version: 8.87.0(vue-router@4.2.2)(vue@3.2.47) '@types/lodash.clonedeep': specifier: ^4.5.7 version: 4.5.7 @@ -1475,6 +1475,31 @@ packages: transitivePeerDependencies: - '@popperjs/core' - debug + dev: true + + /@kong/kongponents@8.87.0(vue-router@4.2.2)(vue@3.2.47): + resolution: {integrity: sha512-J0T+qXsqlsKCwOIhPaQhiuSg1XPt0Phw9sT11g4t4U1h1EzYeWPW2hS9KhzQmMNl4d5ex4PXI4ZiUKinwz9DtQ==} + engines: {node: '>=16.19.0'} + peerDependencies: + vue: '>= 3.2.47 < 3.3' + vue-router: ^4.1.6 + dependencies: + axios: 0.27.2 + date-fns: 2.30.0 + date-fns-tz: 1.3.8(date-fns@2.30.0) + focus-trap: 7.4.3 + focus-trap-vue: 3.4.0(focus-trap@7.4.3)(vue@3.2.47) + popper.js: 1.16.1 + sortablejs: 1.15.0 + swrv: 1.0.3(vue@3.2.47) + uuid: 8.3.2 + v-calendar: 3.0.3(vue@3.2.47) + vue: 3.2.47 + vue-draggable-next: 2.2.0(sortablejs@1.15.0)(vue@3.2.47) + vue-router: 4.2.2(vue@3.2.47) + transitivePeerDependencies: + - '@popperjs/core' + - debug /@kong/swagger-ui-kong-theme-universal@4.2.5(react-dom@17.0.2)(react@17.0.2)(vue-router@4.2.2)(vue@3.2.47): resolution: {integrity: sha512-KaGay4ce/LtHvYneNhYtRmzo8TTU47LkJSpkdBMk1UQRrzqPDAAh41KS7dyrQeRU/ZA4qFJMJVsPiz1sXV9FsQ==} @@ -1482,7 +1507,7 @@ packages: react: 17.0.2 dependencies: '@braintree/sanitize-url': 2.1.0 - '@kong/kongponents': 8.83.5(vue-router@4.2.2)(vue@3.2.47) + '@kong/kongponents': 8.87.0(vue-router@4.2.2)(vue@3.2.47) '@kyleshockey/xml': 1.0.2 classnames: 2.3.2 curl-to-har: 1.0.1