diff --git a/packages/elements/src/components.d.ts b/packages/elements/src/components.d.ts index 14150448be..e1274daec8 100644 --- a/packages/elements/src/components.d.ts +++ b/packages/elements/src/components.d.ts @@ -840,7 +840,7 @@ export namespace Components { */ "open"?: boolean; /** - * The variant to use for the drawer Possible values: `docked` (default), `dismissible`, `modal`. + * The variant to use for the drawer. */ "variant"?: NavDrawerVariant; } @@ -2724,7 +2724,7 @@ declare namespace LocalJSX { */ "open"?: boolean; /** - * The variant to use for the drawer Possible values: `docked` (default), `dismissible`, `modal`. + * The variant to use for the drawer. */ "variant"?: NavDrawerVariant; } diff --git a/packages/elements/src/components/ino-nav-drawer/ino-nav-drawer.scss b/packages/elements/src/components/ino-nav-drawer/ino-nav-drawer.scss index ef4d2ab7d4..4642999d7d 100644 --- a/packages/elements/src/components/ino-nav-drawer/ino-nav-drawer.scss +++ b/packages/elements/src/components/ino-nav-drawer/ino-nav-drawer.scss @@ -1,8 +1,9 @@ @use '../base/mdc-customize'; @use '@material/drawer/mdc-drawer'; -@use "@material/drawer"; -@use "@material/list"; -@use '../base/theme'; +@use '@material/drawer'; +@use '@material/list'; +@use '../base/theme' as theme; +@use '../base/new-theme' as new-theme; @include drawer.core-styles; @include drawer.dismissible-core-styles; @@ -13,6 +14,7 @@ /** * @prop --ino-nav-drawer-width-open: The width of the open drawer. * @prop --ino-nav-drawer-width-closed: Docked variant only! The width of the collapsed drawer. + * @prop --ino-nav-drawer-mobile-width-open: Mobile variant only! The width of the open drawer. * @prop --ino-nav-drawer-background: Background of the drawer. * @prop --ino-nav-drawer-height: Height of the drawer. * @prop --ino-nav-drawer-text-color: Color of text inside the drawer. @@ -22,12 +24,16 @@ --nav-drawer-width-open: var(--ino-nav-drawer-width-open, 250px); --nav-drawer-width-closed: var(--ino-nav-drawer-width-closed, 72px); + --nav-drawer-mobile-width-open: var( + --ino-nav-drawer-mobile-width-open, + 171px + ); --nav-drawer-height: var(--ino-nav-drawer-height, 100%); --nav-drawer-background: var( --ino-nav-drawer-background, #{theme.color(primary, contrast)} ); - --nav-drawer-text-color: var(--ino-nav-drawer-text-color, theme.$brand); + --nav-drawer-text-color: var(--ino-nav-drawer-text-color, #{new-theme.$p-7}); --nav-drawer-transition-duration: var( --ino-nav-drawer-transition-duration, 0.25s @@ -117,6 +123,7 @@ justify-content: center; align-items: center; text-align: center; + white-space: normal; .mdc-drawer__subtitle { font-size: 12px; @@ -223,4 +230,40 @@ top: 0; } } + + // Styles for mobile nav drawer + .mdc-drawer.mobile-drawer { + @include drawer.width(var(--nav-drawer-mobile-width-open)); + + .mdc-drawer__content { + margin-top: 87px; + } + .mdc-drawer__header { + font-size: 12px; + ::slotted(div) { + display: flex; + align-items: center; + gap: 13px; + } + } + + & + .mdc-drawer-app-content { + box-shadow: none; + } + + & + .mdc-drawer-scrim { + backdrop-filter: blur(4.5px); + background: rgba(167, 183, 212, 0.41); + } + } + + .visually-hidden { + position: absolute; + clip-path: inset(50%); + padding: 0; + border: 0; + height: 1px; + width: 1px; + overflow: hidden; + } } diff --git a/packages/elements/src/components/ino-nav-drawer/ino-nav-drawer.tsx b/packages/elements/src/components/ino-nav-drawer/ino-nav-drawer.tsx index 79ad22538f..e07bd95fcf 100644 --- a/packages/elements/src/components/ino-nav-drawer/ino-nav-drawer.tsx +++ b/packages/elements/src/components/ino-nav-drawer/ino-nav-drawer.tsx @@ -33,7 +33,6 @@ export class NavDrawer implements ComponentInterface { */ private drawerInstance: MDCDrawer; private drawerEl: HTMLElement; - @Element() el!: HTMLInoNavDrawerElement; /** @@ -55,8 +54,7 @@ export class NavDrawer implements ComponentInterface { @Prop() anchor?: NavDrawerAnchor = 'left'; /** - * The variant to use for the drawer - * Possible values: `docked` (default), `dismissible`, `modal`. + * The variant to use for the drawer. */ @Prop() variant?: NavDrawerVariant = 'docked'; @@ -67,9 +65,17 @@ export class NavDrawer implements ComponentInterface { @Prop() a11yLabels?: NavDrawerLabels = { content: 'Main Navigation', footer: 'Footer Navigation', - toggleBtn: 'Toggle Navigation' + toggleBtn: 'Toggle Navigation', }; + @Watch('variant') + variantChanged(newVariant: NavDrawerVariant) { + if (newVariant === 'mobile') { + this.activateMobileMode(); + } else { + this.deactivateMobileMode(); + } + } componentDidLoad() { this.drawerInstance = new MDCDrawer( @@ -79,10 +85,16 @@ export class NavDrawer implements ComponentInterface { if (this.drawerInstance) { this.drawerInstance.open = this.open || false; } - this.drawerEl.addEventListener('MDCDrawer:closed', this.closeDrawer); this.initTabindex('content'); this.initTabindex('footer'); + + // set initial mobile or desktop mode + if (this.variant === 'mobile') { + this.activateMobileMode(); + } else { + this.deactivateMobileMode(); + } } disconnectedCallback() { @@ -90,6 +102,19 @@ export class NavDrawer implements ComponentInterface { this.drawerInstance?.destroy(); } + private activateMobileMode() { + const navItems = this.el.querySelectorAll('ino-nav-item'); + navItems.forEach((item) => { + item.classList.add('mobile-nav-item'); + }); + } + + private deactivateMobileMode() { + const navItems = this.el.querySelectorAll('ino-nav-item'); + navItems.forEach((item) => { + item.classList.remove('mobile-nav-item'); + }); + } // This listener ensures that only the most recently clicked/selected list item appears as "activated" @Listen('clickEl') handleListItemClick(event: CustomEvent) { @@ -127,21 +152,24 @@ export class NavDrawer implements ComponentInterface { private initTabindex(slotName: string) { const contentElements = this.el.querySelector(`[slot="${slotName}"]`); - const contenListItems = contentElements.querySelectorAll('ino-list-item'); - contenListItems[0].attrs = {tabIndex:0} + const contentListItems = contentElements.querySelectorAll('ino-list-item'); + contentListItems[0].attrs = { tabIndex: 0 }; } render() { const { anchor, variant } = this; + const isMobile = variant === 'mobile'; + const classDrawer = classNames({ 'mdc-drawer': true, 'mdc-drawer--docked': variant === 'docked', 'mdc-drawer--dismissible': variant === 'dismissible' || variant === 'docked', // docked is a modifier of MDC's dismissible inoVariant - 'mdc-drawer--modal': variant === 'modal', + 'mdc-drawer--modal': variant === 'modal' || isMobile, 'mdc-drawer--anchor-left': anchor === 'left', 'mdc-drawer--anchor-right': anchor === 'right', + 'mobile-drawer': isMobile, // custom class for mobile drawer }); const classAppContent = classNames({ @@ -169,11 +197,16 @@ export class NavDrawer implements ComponentInterface { @@ -189,7 +222,9 @@ export class NavDrawer implements ComponentInterface { return ( {nav} - {variant === 'modal' &&
} + {(isMobile || variant === 'modal') && ( +
+ )} {main}
); diff --git a/packages/elements/src/components/ino-nav-drawer/readme.md b/packages/elements/src/components/ino-nav-drawer/readme.md index 1e0f56e27d..c33a82cfab 100644 --- a/packages/elements/src/components/ino-nav-drawer/readme.md +++ b/packages/elements/src/components/ino-nav-drawer/readme.md @@ -118,12 +118,12 @@ class MyComponent extends Component { ## Properties -| Property | Attribute | Description | Type | Default | -| ------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | -| `a11yLabels` | -- | The aria-labels used for content and footer nav elements. https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/navigation_role. | `{ content: string; footer: string; toggleBtn: string; }` | `{ content: 'Main Navigation', footer: 'Footer Navigation', toggleBtn: 'Toggle Navigation' }` | -| `anchor` | `anchor` | Side from which the drawer will appear. Possible values: `left` (default), `right`. | `"left" \| "right"` | `'left'` | -| `open` | `open` | Marks this element as open. (**unmanaged**) | `boolean` | `false` | -| `variant` | `variant` | The variant to use for the drawer Possible values: `docked` (default), `dismissible`, `modal`. | `"dismissible" \| "docked" \| "modal"` | `'docked'` | +| Property | Attribute | Description | Type | Default | +| ------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | +| `a11yLabels` | -- | The aria-labels used for content and footer nav elements. https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/navigation_role. | `{ content: string; footer: string; toggleBtn: string; }` | `{ content: 'Main Navigation', footer: 'Footer Navigation', toggleBtn: 'Toggle Navigation', }` | +| `anchor` | `anchor` | Side from which the drawer will appear. Possible values: `left` (default), `right`. | `"left" \| "right"` | `'left'` | +| `open` | `open` | Marks this element as open. (**unmanaged**) | `boolean` | `false` | +| `variant` | `variant` | The variant to use for the drawer. | `"dismissible" \| "docked" \| "mobile" \| "modal"` | `'docked'` | ## Events @@ -145,19 +145,6 @@ class MyComponent extends Component { | `"subtitle"` | For the element just below the logo (cannot be used with the `header` slot) | -## CSS Custom Properties - -| Name | Description | -| -------------------------------------- | ------------------------------------------------------- | -| `--ino-nav-drawer-background` | Background of the drawer. | -| `--ino-nav-drawer-height` | Height of the drawer. | -| `--ino-nav-drawer-text-color` | Color of text inside the drawer. | -| `--ino-nav-drawer-timing-function` | Timing function of the slide animation of the drawer. | -| `--ino-nav-drawer-transition-duration` | Duration of the slide animation of the drawer. | -| `--ino-nav-drawer-width-closed` | Docked variant only! The width of the collapsed drawer. | -| `--ino-nav-drawer-width-open` | The width of the open drawer. | - - ## Dependencies ### Depends on diff --git a/packages/elements/src/components/ino-nav-item/ino-nav-item.scss b/packages/elements/src/components/ino-nav-item/ino-nav-item.scss index 56f5d662d9..d8090c9144 100644 --- a/packages/elements/src/components/ino-nav-item/ino-nav-item.scss +++ b/packages/elements/src/components/ino-nav-item/ino-nav-item.scss @@ -1,8 +1,9 @@ @use '../base/mdc-customize'; @use '@material/list/mdc-list'; @use '../base/theme'; +@use '../base/typography-new' as typography; -ino-nav-item  { +ino-nav-item { /** * @prop --ino-nav-item-color: Inactive color of icon. * @prop --ino-nav-item-color-active: Active color of icon. @@ -69,4 +70,24 @@ ino-nav-item  { } } } + + // Styles for mobile-nav-item + &.mobile-nav-item { + .mdc-deprecated-list-item, + ino-list-item .mdc-deprecated-list-item { + @include typography.typo(label-s); + + &__graphic { + margin-right: 0px; + } + + // icon + ::slotted(ino-icon), + ino-icon, + .ino-list-item__icon { + --icon-width: 16px; + --icon-height: 16px; + } + } + } } diff --git a/packages/elements/src/components/types.ts b/packages/elements/src/components/types.ts index e827449dda..eba74d9d2c 100644 --- a/packages/elements/src/components/types.ts +++ b/packages/elements/src/components/types.ts @@ -9,7 +9,7 @@ export type HorizontalLocation = 'left' | 'right'; export type ImageDecodingTypes = 'async' | 'auto' | 'sync'; export type Locations = HorizontalLocation | VerticalLocation; export type NavDrawerAnchor = 'left' | 'right'; -export type NavDrawerVariant = 'docked' | 'dismissible' | 'modal'; +export type NavDrawerVariant = 'docked' | 'dismissible' | 'modal' | 'mobile'; export type SnackbarType = 'info' | 'success' | 'error'; export type SpinnerType = 'tile' | 'bounce' | 'circle'; export type SurfaceType = 'filled' | 'outlined' | 'text'; diff --git a/packages/storybook/elements-stencil-docs.json b/packages/storybook/elements-stencil-docs.json index 4904b65ca9..5636000d12 100644 --- a/packages/storybook/elements-stencil-docs.json +++ b/packages/storybook/elements-stencil-docs.json @@ -5056,7 +5056,7 @@ "reflectToAttr": false, "docs": "The aria-labels used for content and footer nav elements.\nhttps://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/navigation_role.", "docsTags": [], - "default": "{\n content: 'Main Navigation',\n footer: 'Footer Navigation',\n toggleBtn: 'Toggle Navigation'\n }", + "default": "{\n content: 'Main Navigation',\n footer: 'Footer Navigation',\n toggleBtn: 'Toggle Navigation',\n }", "values": [ { "type": "{ content: string; footer: string; toggleBtn: string; }" @@ -5106,11 +5106,11 @@ }, { "name": "variant", - "type": "\"dismissible\" | \"docked\" | \"modal\"", + "type": "\"dismissible\" | \"docked\" | \"mobile\" | \"modal\"", "mutable": false, "attr": "variant", "reflectToAttr": false, - "docs": "The variant to use for the drawer\nPossible values: `docked` (default), `dismissible`, `modal`.", + "docs": "The variant to use for the drawer.", "docsTags": [], "default": "'docked'", "values": [ @@ -5122,6 +5122,10 @@ "value": "docked", "type": "string" }, + { + "value": "mobile", + "type": "string" + }, { "value": "modal", "type": "string" @@ -5143,43 +5147,7 @@ "docsTags": [] } ], - "styles": [ - { - "name": "--ino-nav-drawer-background", - "annotation": "prop", - "docs": "Background of the drawer." - }, - { - "name": "--ino-nav-drawer-height", - "annotation": "prop", - "docs": "Height of the drawer." - }, - { - "name": "--ino-nav-drawer-text-color", - "annotation": "prop", - "docs": "Color of text inside the drawer." - }, - { - "name": "--ino-nav-drawer-timing-function", - "annotation": "prop", - "docs": "Timing function of the slide animation of the drawer." - }, - { - "name": "--ino-nav-drawer-transition-duration", - "annotation": "prop", - "docs": "Duration of the slide animation of the drawer." - }, - { - "name": "--ino-nav-drawer-width-closed", - "annotation": "prop", - "docs": "Docked variant only! The width of the collapsed drawer." - }, - { - "name": "--ino-nav-drawer-width-open", - "annotation": "prop", - "docs": "The width of the open drawer." - } - ], + "styles": [], "slots": [ { "name": "app", diff --git a/packages/storybook/src/assets/images/elements.svg b/packages/storybook/src/assets/images/elements.svg new file mode 100644 index 0000000000..b362a4aca2 --- /dev/null +++ b/packages/storybook/src/assets/images/elements.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/storybook/src/stories/ino-nav-drawer/ino-nav-drawer.scss b/packages/storybook/src/stories/ino-nav-drawer/ino-nav-drawer.scss index d089e1b47a..127371a403 100644 --- a/packages/storybook/src/stories/ino-nav-drawer/ino-nav-drawer.scss +++ b/packages/storybook/src/stories/ino-nav-drawer/ino-nav-drawer.scss @@ -2,7 +2,7 @@ .story-nav-drawer__docked_anchor--right, .story-nav-drawer__dismissible { position: relative; - height: 500px; + height: 700px; border: 1px solid grey; border-radius: 4px; overflow: hidden; @@ -17,4 +17,4 @@ .button__label { pointer-events: none; -} +} \ No newline at end of file diff --git a/packages/storybook/src/stories/ino-nav-drawer/ino-nav-drawer.stories.ts b/packages/storybook/src/stories/ino-nav-drawer/ino-nav-drawer.stories.ts index 919037f400..5ef547c085 100644 --- a/packages/storybook/src/stories/ino-nav-drawer/ino-nav-drawer.stories.ts +++ b/packages/storybook/src/stories/ino-nav-drawer/ino-nav-drawer.stories.ts @@ -3,10 +3,10 @@ import { Meta } from '@storybook/web-components'; import { html } from 'lit-html'; import { TemplateGenerator } from '../template-generator'; import { Components } from '@inovex.de/elements'; -import jamesLogo from '../../assets/images/james-logo.png'; +import inovexElementsLogo from '../../assets/images/elements.svg'; import './ino-nav-drawer.scss'; -const openChangeHandle = function (e) { +const openChangeHandle = function(e) { const el = e.target; if (el.tagName.toLowerCase() !== 'ino-nav-drawer') { return; @@ -14,7 +14,7 @@ const openChangeHandle = function (e) { el.setAttribute('open', !!e.detail); }; -const clickHandler = (e) => { +const clickHandler = e => { e.preventDefault(); e.stopPropagation(); const el = e.target.parentElement; @@ -36,7 +36,7 @@ const clickHandler = (e) => { const parentDrawer = el.closest('ino-nav-drawer'); const navItemNodes = parentDrawer.querySelectorAll('ino-list-item'); navItemNodes && - navItemNodes.forEach((link) => { + navItemNodes.forEach(link => { link.activated = false; }); el.activated = true; @@ -57,7 +57,7 @@ export default { }, }, decorators: [ - (story) => { + story => { useEffect(() => { document.addEventListener('openChange', openChangeHandle); document.addEventListener('click', clickHandler); @@ -72,6 +72,14 @@ export default { return story(); }, ], + argTypes: { + variant: { + control: { + type: 'select', + options: ['docked', 'dismissible', 'modal', 'mobile'], + }, + }, + }, args: { open: true, anchor: 'left', @@ -86,51 +94,80 @@ export default { const template = new TemplateGenerator( 'ino-nav-drawer', - args => html` -
- -
- -

inovex

-
- - - - - - - - - - - - - - -
- ${args.a11yLabels?.toggleBtn} { + return html` +
+ -
-
- Your App goes here 🤘 -

-
-
-
-`); +
+ +

inovex Elements

+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ ${args.a11yLabels?.toggleBtn} +
+
+ Your App goes here 🤘 +

+
+ + + `; + } +); export const Playground = template.generatePlaygroundStory(); export const AnchorRight = template.generateStoryForProp('anchor', 'right'); -export const Modal = template.generateStoryForProp('variant', 'modal', {open: false}); -export const Dismissible = template.generateStoryForProp('variant', 'dismissible'); +export const Modal = template.generateStoryForProp('variant', 'modal', { + open: false, +}); +export const Dismissible = template.generateStoryForProp( + 'variant', + 'dismissible' +); +export const Mobile = template.generateStoryForProp('variant', 'mobile', { + open: false, +});