From 5eef97deb644285d56fa5fa6d1aac2f044d06226 Mon Sep 17 00:00:00 2001 From: Maksym Portianoi Date: Tue, 17 Oct 2023 16:37:35 -0400 Subject: [PATCH] feat(klabel): component reskinning [KHCP-8987] (#1764) * chore(sandbox): set up component sandbox [KHCP-8987] * fix(klabel): remove unneeded props [KHCP-8987] * feat(klabel): reskin component [KHCP-8987] * test(klabel): fix component tests [KHCP-8987] * fix(*): fix components affected by klabel [KHCP-8987] * fix(*): misc fixes [KHCP-8987] * docs(label): update component docs [KHCP-8987] * fix(klabel): address PR feedback [KHCP-8987] * fix: minor fix [KHCP-8987] * chore(sandbox): minor fix [KHCP-8987] * fix(ktooltip): make tooltip trigger focusable [KHCP-8987] * fix(klabel): address PR feedback [KHCP-8987] * fix(deps): bump @kong/design-tokens [KHCP-8987] --- docs/components/input.md | 6 +- docs/components/label.md | 50 ++++------- docs/guide/migrating-to-version-9.md | 10 +++ package.json | 2 +- sandbox/components/SandboxNavComponent.vue | 5 +- .../components/SandboxSectionComponent.vue | 11 +++ sandbox/components/SandboxTitleComponent.vue | 15 ++++ sandbox/pages/SandboxInput.vue | 6 +- sandbox/pages/SandboxLabel.vue | 64 ++++++++++++++ sandbox/router.ts | 26 +++--- src/components/KButton/KButton.vue | 12 --- src/components/KFileUpload/KFileUpload.cy.ts | 8 +- src/components/KInput/KInput.cy.ts | 12 +-- src/components/KInput/KInput.vue | 2 +- src/components/KLabel/KLabel.cy.ts | 41 ++------- src/components/KLabel/KLabel.vue | 83 +++++++++---------- .../KMultiselect/KMultiselect.cy.ts | 8 +- src/components/KSelect/KSelect.cy.ts | 8 +- src/components/KStepper/KStep.vue | 4 +- src/components/KTextArea/KTextArea.cy.ts | 8 +- src/components/KTooltip/KTooltip.vue | 4 +- src/types/input.ts | 1 - yarn.lock | 8 +- 23 files changed, 221 insertions(+), 173 deletions(-) create mode 100644 sandbox/pages/SandboxLabel.vue diff --git a/docs/components/input.md b/docs/components/input.md index b9730bb9c4..7f5b27f21a 100644 --- a/docs/components/input.md +++ b/docs/components/input.md @@ -48,7 +48,7 @@ Use the `labelAttributes` prop to configure the KLabel's [props](/components/lab You can add `tooltipAttributes` to configure the KTooltip's [props](/components/tooltip) - @@ -56,7 +56,7 @@ maxWidth: '150px' Input Title - -```html -Input Title -``` - -Long Input Title - -```html - - Long Input Title - -``` - ### info Use the `info` prop to display information help text. -Input Title +Input title ```html -Input Title +Input title ``` ### required -Use the `required` prop to indicate requiredness of a field by displaying an `*` after the label. +Use this prop on labels for required fields. Adds a red dot in front of a label. Name @@ -50,14 +32,14 @@ Use the `required` prop to indicate requiredness of a field by displaying an `*` ### tooltipAttributes -Use the `tooltipAttributes` prop to configure the **KTooltip's** [props](/components/tooltip) if using the `help` or `info` props. +Use the `tooltipAttributes` prop to configure the KTooltip's [props](/components/tooltip) if using the `info` prop. -With Tooltip Attributes +With Tooltip Attributes ```html With Tooltip Attributes @@ -69,30 +51,28 @@ Use the `tooltipAttributes` prop to configure the **KTooltip's** [props](/compon Use the `for` attribute to bind a label to an input element for accessibility. -Service Name +Service name ```html -Service Name +Service name ``` ## Slots -- `tooltip` - Rather than using the `help` or `info` props, if you need to utilize HTML in the tooltip, you may use the `tooltip` slot. +### tooltip -:::tip Note: -When utilizing the `label-tooltip` slot, the `info` `KIcon` will be shown by default. To utilize the the `help` icon instead, set the `label-attributes` `help` property to any non-empty string value. -::: +Should you need to utilize HTML in the tooltip, you may use the `tooltip` slot. - + My Tooltip ```html - + My Tooltip diff --git a/docs/guide/migrating-to-version-9.md b/docs/guide/migrating-to-version-9.md index d0c839169a..e17787f8bf 100644 --- a/docs/guide/migrating-to-version-9.md +++ b/docs/guide/migrating-to-version-9.md @@ -153,6 +153,16 @@ Kongponents styles are no longer designed to be utilized standalone, separately ### KLabel +#### Structure + +* `k-input-label` class has been renamed to `k-label` + +#### Constants, Types & Interfaces + +#### Props + +* `help` prop has been removed +* `testMode` prop has been removed ### KMenu diff --git a/package.json b/package.json index 47a7d04350..9099a06573 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "@cypress/vite-dev-server": "^5.0.6", "@digitalroute/cz-conventional-changelog-for-jira": "^8.0.1", "@evilmartians/lefthook": "^1.5.1", - "@kong/design-tokens": "^1.11.3", + "@kong/design-tokens": "^1.11.4", "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", "@types/inquirer": "^9.0.3", diff --git a/sandbox/components/SandboxNavComponent.vue b/sandbox/components/SandboxNavComponent.vue index 1534002499..6e29088296 100644 --- a/sandbox/components/SandboxNavComponent.vue +++ b/sandbox/components/SandboxNavComponent.vue @@ -32,9 +32,10 @@ const links = computed((): SandboxNavItem[] => ( { name: 'KButton', to: { name: 'button' } }, { name: 'KCatalog', to: { name: 'catalog' } }, { name: 'KInput', to: { name: 'input' } }, - { name: 'KTabs', to: { name: 'tabs' } }, - { name: 'KTable', to: { name: 'table' } }, + { name: 'KLabel', to: { name: 'label' } }, { name: 'KMultiselect', to: { name: 'multiselect' } }, + { name: 'KTable', to: { name: 'table' } }, + { name: 'KTabs', to: { name: 'tabs' } }, ] )) diff --git a/sandbox/components/SandboxSectionComponent.vue b/sandbox/components/SandboxSectionComponent.vue index 5244163a0e..43dda6645f 100644 --- a/sandbox/components/SandboxSectionComponent.vue +++ b/sandbox/components/SandboxSectionComponent.vue @@ -55,10 +55,21 @@ const hasDescription = computed((): boolean => !!(props.description || slots.des .section-title { color: $kui-color-text; margin: $kui-space-0; + margin-left: $kui-space-50; + position: relative; & + .section-description { margin-top: $kui-space-50; } + + &::before { + bottom: 2px; + color: $kui-color-text-neutral; + content: '#'; + font-size: $kui-font-size-20; + left: -12px; + position: absolute; + } } .section-description { diff --git a/sandbox/components/SandboxTitleComponent.vue b/sandbox/components/SandboxTitleComponent.vue index 04fee45e3c..d0eef2f7c6 100644 --- a/sandbox/components/SandboxTitleComponent.vue +++ b/sandbox/components/SandboxTitleComponent.vue @@ -3,6 +3,7 @@ {{ title }} @@ -52,6 +53,20 @@ const hasDescription = computed((): boolean => !!(props.description || slots.des & + .description { margin-top: $kui-space-50; } + + &.subtitle { + margin-left: $kui-space-50; + position: relative; + + &::before { + bottom: 2px; + color: $kui-color-text-primary; + content: '#'; + font-size: $kui-font-size-30; + left: -12px; + position: absolute; + } + } } .description { diff --git a/sandbox/pages/SandboxInput.vue b/sandbox/pages/SandboxInput.vue index 6007fda84a..d1247d9f3e 100644 --- a/sandbox/pages/SandboxInput.vue +++ b/sandbox/pages/SandboxInput.vue @@ -159,7 +159,11 @@ - + + + +
+ + + + + + This is a label + + + + + + + Label + + + + + Required label + + + + + Required label + + + + + + + + +
+ + + diff --git a/sandbox/router.ts b/sandbox/router.ts index a74156f355..1382aa78d2 100644 --- a/sandbox/router.ts +++ b/sandbox/router.ts @@ -28,12 +28,6 @@ export default createRouter({ meta: { title: 'Catalog Sandbox' }, component: () => import('./pages/SandboxCatalog.vue'), }, - { - path: 'tabs', - name: 'tabs', - meta: { title: 'Tabs Sandbox' }, - component: () => import('./pages/SandboxTabs.vue'), - }, { path: 'input', name: 'input', @@ -41,10 +35,10 @@ export default createRouter({ component: () => import('./pages/SandboxInput.vue'), }, { - path: 'table', - name: 'table', - meta: { title: 'Table Sandbox' }, - component: () => import('./pages/SandboxTable.vue'), + path: 'label', + name: 'label', + meta: { title: 'Label Sandbox' }, + component: () => import('./pages/SandboxLabel.vue'), }, { path: 'multiselect', @@ -52,6 +46,18 @@ export default createRouter({ meta: { title: 'Multiselect Sandbox' }, component: () => import('./pages/SandboxMultiselect.vue'), }, + { + path: 'table', + name: 'table', + meta: { title: 'Table Sandbox' }, + component: () => import('./pages/SandboxTable.vue'), + }, + { + path: 'tabs', + name: 'tabs', + meta: { title: 'Tabs Sandbox' }, + component: () => import('./pages/SandboxTabs.vue'), + }, ], }, ], diff --git a/src/components/KButton/KButton.vue b/src/components/KButton/KButton.vue index 22a05dede1..c978ad545f 100644 --- a/src/components/KButton/KButton.vue +++ b/src/components/KButton/KButton.vue @@ -170,16 +170,12 @@ export default { // TODO: [beta] remove :deep(.kong-icon) once once we remove the icon prop & slot // enforce icon size exported by @kong/icons because it's defined by the design system :deep(#{$kongponentsKongIconSelector}), :deep(.kong-icon) { - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ height: var(--kui-icon-size-40, $kui-icon-size-40) !important; - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ width: var(--kui-icon-size-40, $kui-icon-size-40) !important; // TODO: [beta] remove this once once we remove the icon prop & slot svg { - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ height: var(--kui-icon-size-40, $kui-icon-size-40) !important; - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ width: var(--kui-icon-size-40, $kui-icon-size-40) !important; } } @@ -324,16 +320,12 @@ export default { // TODO: [beta] remove :deep(.kong-icon) once once we remove the icon prop & slot // enforce icon size exported by @kong/icons because it's defined by the design system :deep(#{$kongponentsKongIconSelector}), :deep(.kong-icon) { - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ height: var(--kui-icon-size-50, $kui-icon-size-50) !important; - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ width: var(--kui-icon-size-50, $kui-icon-size-50) !important; // TODO: [beta] remove this once once we remove the icon prop & slot svg { - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ height: var(--kui-icon-size-50, $kui-icon-size-50) !important; - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ width: var(--kui-icon-size-50, $kui-icon-size-50) !important; } } @@ -358,16 +350,12 @@ export default { // TODO: [beta] remove :deep(.kong-icon) once once we remove the icon prop & slot // enforce icon size exported by @kong/icons because it's defined by the design system :deep(#{$kongponentsKongIconSelector}), :deep(.kong-icon) { - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ height: var(--kui-icon-size-30, $kui-icon-size-30) !important; - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ width: var(--kui-icon-size-30, $kui-icon-size-30) !important; // TODO: [beta] remove this once once we remove the icon prop & slot svg { - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ height: var(--kui-icon-size-30, $kui-icon-size-30) !important; - /* stylelint-disable-next-line @kong/design-tokens/use-proper-token */ width: var(--kui-icon-size-30, $kui-icon-size-30) !important; } } diff --git a/src/components/KFileUpload/KFileUpload.cy.ts b/src/components/KFileUpload/KFileUpload.cy.ts index 77f6ba976f..0956cd4b7c 100644 --- a/src/components/KFileUpload/KFileUpload.cy.ts +++ b/src/components/KFileUpload/KFileUpload.cy.ts @@ -11,7 +11,7 @@ describe('KFileUpload', () => { }, }) - cy.get('.k-input-label').should('contain.text', text) + cy.get('.k-label').should('contain.text', text) }) it('remove-button should not exist if there is no selected file', () => { @@ -42,13 +42,13 @@ describe('KFileUpload', () => { testMode: true, label: labelText, labelAttributes: { - help: 'random text', + info: 'random text', }, }, }) - cy.get('.k-input-label').should('contain.text', labelText) - cy.get('.k-input-label .kong-icon-help').should('be.visible') + cy.get('.k-label').should('contain.text', labelText) + cy.get('.k-label .tooltip-trigger-icon').should('be.visible') }) it('does not render cancel button, if removable is false', () => { diff --git a/src/components/KInput/KInput.cy.ts b/src/components/KInput/KInput.cy.ts index 196b74b701..c6169733dc 100644 --- a/src/components/KInput/KInput.cy.ts +++ b/src/components/KInput/KInput.cy.ts @@ -47,7 +47,7 @@ describe('KInput', () => { }, }) - cy.get('.k-input-label').should('contain.text', label) + cy.get('.k-label').should('contain.text', label) }) it('renders label with labelAttributes applied', () => { @@ -57,13 +57,13 @@ describe('KInput', () => { props: { label, labelAttributes: { - help: 'some help text', + info: 'some info text', }, }, }) - cy.get('.k-input-label').should('contain.text', label) - cy.get('.k-input-label .kong-icon-help').should('exist').and('be.visible') + cy.get('.k-label').should('contain.text', label) + cy.get('.k-label .tooltip-trigger-icon').should('exist').and('be.visible') }) it('renders label and tooltip with `label-tooltip` slot applied', () => { @@ -78,8 +78,8 @@ describe('KInput', () => { }, }) - cy.get('.k-input-label').should('contain.text', label) - cy.get('.k-input-label .kong-icon-infoFilled').should('exist').and('be.visible') + cy.get('.k-label').should('contain.text', label) + cy.get('.k-label .tooltip-trigger-icon').should('exist').and('be.visible') }) it.skip('renders label with required symbol when `required` attribute is set', () => { diff --git a/src/components/KInput/KInput.vue b/src/components/KInput/KInput.vue index e96d89a07e..fcb012080b 100644 --- a/src/components/KInput/KInput.vue +++ b/src/components/KInput/KInput.vue @@ -122,7 +122,7 @@ const attrs = useAttrs() const isRequired = computed((): boolean => attrs?.required !== undefined && String(attrs?.required) !== 'false') const inputId = computed((): string => attrs.id ? String(attrs.id) : uuidv4()) const strippedLabel = computed((): string => stripRequiredLabel(props.label, isRequired.value)) -const hasLabelTooltip = computed((): boolean => !!(props.labelAttributes?.help || props.labelAttributes?.info || slots['label-tooltip'])) +const hasLabelTooltip = computed((): boolean => !!(props.labelAttributes?.info || slots['label-tooltip'])) // we need this so we can create a watcher for programmatic changes to the modelValue const value = computed({ diff --git a/src/components/KLabel/KLabel.cy.ts b/src/components/KLabel/KLabel.cy.ts index 926b76acac..5d0cdc345c 100644 --- a/src/components/KLabel/KLabel.cy.ts +++ b/src/components/KLabel/KLabel.cy.ts @@ -2,47 +2,23 @@ import { mount } from 'cypress/vue' import KLabel from '@/components/KLabel/KLabel.vue' import { h } from 'vue' -/** - * ALL TESTS MUST USE testMode: true - * We generate unique IDs for reference by aria properties. Test mode strips these out - * allowing for successful snapshot verification. - * props: { - * testMode: true - * } - */ describe('KLabel', () => { it('renders a plain label by default', () => { const text = 'Full Name' mount(KLabel, { props: { - testMode: true, }, slots: { default: () => text, }, }) - cy.get('.k-input-label').should('have.text', text) + cy.get('.k-label').should('have.text', text) }) - it('renders a tooltip when `help` is provided', () => { + it('renders a red dot when `required` is true', () => { mount(KLabel, { props: { - help: 'This is a tooltip', - testMode: true, - }, - slots: { - default: () => 'Full Name', - }, - }) - - cy.get('.k-input-label .label-tooltip').should('not.be.empty') - }) - - it('renders an asterisk when `required` is true', () => { - mount(KLabel, { - props: { - testMode: true, required: true, }, slots: { @@ -50,27 +26,25 @@ describe('KLabel', () => { }, }) - cy.get('.k-input-label .is-required').should('exist') + cy.get('.k-label.is-required').should('exist') }) - it('renders a tooltip when `info` is provided', () => { + it('renders a tooltip when `info` prop is provided', () => { mount(KLabel, { props: { info: 'This is a tooltip', - testMode: true, }, slots: { default: () => 'Full Name', }, }) - cy.get('.k-input-label .label-tooltip').should('not.be.empty') + cy.get('.k-label .label-tooltip').should('not.be.empty') }) it('renders a tooltip when `tooltip` slot is used', () => { mount(KLabel, { props: { - testMode: true, }, slots: { default: () => 'Full Name', @@ -78,7 +52,7 @@ describe('KLabel', () => { }, }) - cy.get('.k-input-label .label-tooltip').should('not.be.empty') + cy.get('.k-label .label-tooltip').should('not.be.empty') }) it('passes the `for` attribute to label when `for` is provided', () => { @@ -86,13 +60,12 @@ describe('KLabel', () => { mount(KLabel, { props: { for: id, - testMode: true, }, slots: { default: () => 'Full Name', }, }) - cy.get('.k-input-label').invoke('attr', 'for').should('eq', id) + cy.get('.k-label').invoke('attr', 'for').should('eq', id) }) }) diff --git a/src/components/KLabel/KLabel.vue b/src/components/KLabel/KLabel.vue index 41ccd4f347..e94b8a2c3c 100644 --- a/src/components/KLabel/KLabel.vue +++ b/src/components/KLabel/KLabel.vue @@ -1,25 +1,21 @@