mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-15 02:11:05 +00:00
uisehll with nav finished
This commit is contained in:
parent
93b912240f
commit
614ca9d36e
10 changed files with 578 additions and 128 deletions
|
@ -1,3 +0,0 @@
|
||||||
<script>
|
|
||||||
|
|
||||||
</script>
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
import UIShell from './UIShell.svelte';
|
import UIShell from './UIShell.svelte';
|
||||||
import FormTest from './FormTest.svelte';
|
import FormTest from './FormTest.svelte';
|
||||||
import Notification20 from 'carbon-icons-svelte/lib/Notification20';
|
import SettingsAdjust20 from 'carbon-icons-svelte/lib/SettingsAdjust20';
|
||||||
import UserAvatar20 from 'carbon-icons-svelte/lib/UserAvatar20';
|
import { leftPanelActions, leftPanelTypes } from './constants';
|
||||||
|
|
||||||
const navMenu = [
|
const navMenu = [
|
||||||
{
|
{
|
||||||
|
@ -45,13 +45,15 @@
|
||||||
/*
|
/*
|
||||||
Format:
|
Format:
|
||||||
|
|
||||||
action: will be place on the aria-label, use to identify the action from the others.
|
action: will be place on the aria-label, use to identify the action from the others. Predifined actions: 'search', 'help', 'notification', 'account', 'switcher'
|
||||||
|
|
||||||
type: search-> will open an inputText to start a search.
|
type: search-> will open an inputText to start a search.
|
||||||
|
|
||||||
component-> when specifying this property, content will expect a .svelte file.
|
component-> when specifying this property, content will expect a .svelte file.
|
||||||
|
|
||||||
link-> when specifying this property, content will expect for subject objects that will contain href and link.
|
link-> when specifying this property, content will expect for just 1 href and text
|
||||||
|
|
||||||
|
links-> when specifying this property, content will expect for an array of objects with property subject and another array of objects with href and text
|
||||||
|
|
||||||
icon: you need to specify the properties specified in carbon-icons-svelte components as shown in the example below.
|
icon: you need to specify the properties specified in carbon-icons-svelte components as shown in the example below.
|
||||||
|
|
||||||
|
@ -61,29 +63,79 @@
|
||||||
*/
|
*/
|
||||||
const rightPanel = [
|
const rightPanel = [
|
||||||
{
|
{
|
||||||
action: 'search'
|
action: leftPanelActions.search.actionString,
|
||||||
|
type: leftPanelTypes.search,
|
||||||
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
action: 'userlogin',
|
action: 'customsettings',
|
||||||
type: 'component',
|
type: leftPanelTypes.component,
|
||||||
icon: [
|
icon: [
|
||||||
{
|
{
|
||||||
class: undefined,
|
class: undefined,
|
||||||
skeleton: false,
|
skeleton: false,
|
||||||
render: Notification20,
|
render: SettingsAdjust20,
|
||||||
title: 'Notification20',
|
title: 'settings',
|
||||||
tabIndex: 0,
|
tabIndex: 0,
|
||||||
focusable: false,
|
focusable: false,
|
||||||
style: undefined
|
style: undefined
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
content: FormTest
|
content: FormTest,
|
||||||
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
action: 'switcher',
|
action: leftPanelActions.help.actionString,
|
||||||
|
type: leftPanelTypes.link,
|
||||||
|
content: {
|
||||||
|
href: '#',
|
||||||
|
text: leftPanelActions.help.actionString
|
||||||
|
},
|
||||||
|
isVisible: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: leftPanelActions.notifications.actionString,
|
||||||
|
type: leftPanelTypes.links,
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
subjet: 'Switcher theme 1',
|
subjet: 'Notification subjet 1',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
href: '#',
|
||||||
|
text: 'Notification item 1'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subjet: 'Notification subjet 2',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
href: '#',
|
||||||
|
text: 'Notification item 1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: '#',
|
||||||
|
text: 'Notification item 2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: '#',
|
||||||
|
text: 'Notification item 3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: '#',
|
||||||
|
text: 'Notification item 4'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
isVisible: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: leftPanelActions.switcher.actionString,
|
||||||
|
type: leftPanelTypes.links,
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
subjet: 'Switcher subjet 1',
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
href: '#',
|
href: '#',
|
||||||
|
@ -92,7 +144,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subjet: 'Switcher theme 2',
|
subjet: 'Switcher subjet 2',
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
href: '#',
|
href: '#',
|
||||||
|
@ -113,7 +165,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subjet: 'Switcher theme 3',
|
subjet: 'Switcher subjet 3',
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
href: '#',
|
href: '#',
|
||||||
|
@ -125,23 +177,17 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
action: 'userlogin',
|
action: leftPanelActions.account.actionString,
|
||||||
type: 'component',
|
type: leftPanelTypes.link,
|
||||||
icon: [
|
content: {
|
||||||
{
|
href: '#',
|
||||||
class: undefined,
|
text: leftPanelActions.account.actionString
|
||||||
skeleton: false,
|
},
|
||||||
render: UserAvatar20,
|
isVisible: true
|
||||||
title: 'UserAvatar20',
|
|
||||||
tabIndex: 0,
|
|
||||||
focusable: false,
|
|
||||||
style: undefined
|
|
||||||
}
|
|
||||||
],
|
|
||||||
content: FormTest
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
import UIShellNavItem from './UIShellNav/UIShellNavItem.svelte';
|
import UIShellNavItem from './UIShellNav/UIShellNavItem.svelte';
|
||||||
import UIShellRightPanel from './UIShellRightPanel/UIShellRightPanel.svelte';
|
import UIShellRightPanel from './UIShellRightPanel/UIShellRightPanel.svelte';
|
||||||
|
|
||||||
$: ariaLabel = 'IBM ' + (uiShellAriaLabel || $$props['aria-label'] || platformName);
|
$: ariaLabel = company + (uiShellAriaLabel || $$props['aria-label'] || platformName);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<header aria-label={ariaLabel} class={cx('--header')} role="banner">
|
<header aria-label={ariaLabel} class={cx('--header')} role="banner">
|
||||||
|
|
|
@ -11,14 +11,14 @@
|
||||||
let listItemSubMenu = undefined;
|
let listItemSubMenu = undefined;
|
||||||
|
|
||||||
window.addEventListener('mouseup', ({ target }) => {
|
window.addEventListener('mouseup', ({ target }) => {
|
||||||
if (target !== listItemSubMenu) {
|
if (listItemSubMenu) {
|
||||||
if (expanded) {
|
if (listItemSubMenu.contains(target) || target === listItemSubMenu) {
|
||||||
console.log('entered first if');
|
expanded = !expanded;
|
||||||
expanded = false;
|
} else {
|
||||||
|
if (expanded) {
|
||||||
|
expanded = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (listItemSubMenu.contains(target) || target === listItemSubMenu) {
|
|
||||||
console.log('entered second if');
|
|
||||||
expanded = !expanded;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
<script>
|
<!-- <script>
|
||||||
// export let action = undefined;
|
export let action = undefined;
|
||||||
// export let type = undefined;
|
export let type = undefined;
|
||||||
export let icon = undefined;
|
export let icon = undefined;
|
||||||
// export let content = undefined;
|
// export let content = undefined;
|
||||||
|
|
||||||
import { cx } from '../../../lib';
|
import { cx } from '../../../lib';
|
||||||
import Icon from '../../Icon/Icon.svelte';
|
import Icon from '../../Icon/Icon.svelte';
|
||||||
|
import { leftPanelActions } from '../constants';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button aria-label="Notifications" class={cx('--header__action')} type="button">
|
<button aria-label={type} class={cx('--header__action')} type="button">
|
||||||
<Icon {...icon} render={icon[0].render} />
|
<Icon {...icon} render={icon[0].render} />
|
||||||
</button>
|
</button> -->
|
||||||
|
|
195
src/components/UIShell/UIShellRightPanel/ActionGeneric.svelte
Normal file
195
src/components/UIShell/UIShellRightPanel/ActionGeneric.svelte
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
<script>
|
||||||
|
export let action = undefined;
|
||||||
|
|
||||||
|
import { cx } from '../../../lib';
|
||||||
|
import ActionLink from './ActionLink.svelte';
|
||||||
|
import ActionComponent from './ActionComponent.svelte';
|
||||||
|
import ActionSearch from './ActionSearch.svelte';
|
||||||
|
import { leftPanelTypes, actionSearchWhiteList } from '../constants';
|
||||||
|
|
||||||
|
let typeComponent = undefined;
|
||||||
|
let componentIsActive = false;
|
||||||
|
let typeSearch = undefined;
|
||||||
|
let searchIsActive = false;
|
||||||
|
let typeLink = undefined;
|
||||||
|
let linkIsActive = false;
|
||||||
|
|
||||||
|
let isSearchFocus = false;
|
||||||
|
|
||||||
|
window.addEventListener('mouseup', ({ target }) => {
|
||||||
|
checkForClicks(target, typeComponent, leftPanelTypes.component);
|
||||||
|
checkForClicksTypeSearch(target, typeSearch, leftPanelTypes.search);
|
||||||
|
checkForClicks(target, typeLink, leftPanelTypes.link);
|
||||||
|
});
|
||||||
|
|
||||||
|
function checkForClicks(target, component, actionString) {
|
||||||
|
try {
|
||||||
|
if (component && target) {
|
||||||
|
if (component.contains(target) || target === component) {
|
||||||
|
if (actionString === leftPanelTypes.component) {
|
||||||
|
componentIsActive = !componentIsActive;
|
||||||
|
} else if (actionString === leftPanelTypes.link) {
|
||||||
|
linkIsActive = !linkIsActive;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (actionString === leftPanelTypes.component) {
|
||||||
|
if (componentIsActive) {
|
||||||
|
componentIsActive = false;
|
||||||
|
}
|
||||||
|
} else if (actionString === leftPanelTypes.link) {
|
||||||
|
if (linkIsActive) {
|
||||||
|
linkIsActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkForClicksTypeSearch(target, component, actionString) {
|
||||||
|
let parentFirstLine;
|
||||||
|
let parentSecondLine;
|
||||||
|
|
||||||
|
if (component && target) {
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
target.id !== 'right-panel-action-search' &&
|
||||||
|
target.parentNode.id !== 'right-panel-action-search' &&
|
||||||
|
target.parentNode.parentNode.id !== 'right-panel-action-search'
|
||||||
|
) {
|
||||||
|
if (component.contains(target) || target === component) {
|
||||||
|
if (actionString === leftPanelTypes.component) {
|
||||||
|
componentIsActive = !componentIsActive;
|
||||||
|
} else if (actionString === leftPanelTypes.search) {
|
||||||
|
searchIsActive = !searchIsActive;
|
||||||
|
} else if (actionString === leftPanelTypes.link) {
|
||||||
|
linkIsActive = !linkIsActive;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (actionString === leftPanelTypes.component) {
|
||||||
|
if (componentIsActive) {
|
||||||
|
componentIsActive = false;
|
||||||
|
}
|
||||||
|
} else if (actionString === leftPanelTypes.search) {
|
||||||
|
if (searchIsActive) {
|
||||||
|
searchIsActive = false;
|
||||||
|
}
|
||||||
|
} else if (actionString === leftPanelTypes.link) {
|
||||||
|
if (linkIsActive) {
|
||||||
|
linkIsActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (actionString === leftPanelTypes.component) {
|
||||||
|
if (!componentIsActive && target.id !== 'right-panel-close-search') {
|
||||||
|
componentIsActive = true;
|
||||||
|
} else if (
|
||||||
|
componentIsActive &&
|
||||||
|
(target.id === 'right-panel-close-search' ||
|
||||||
|
target.parentNode.id === 'right-panel-close-search')
|
||||||
|
) {
|
||||||
|
componentIsActive = false;
|
||||||
|
}
|
||||||
|
} else if (actionString === leftPanelTypes.search) {
|
||||||
|
if (!searchIsActive && target.id !== 'right-panel-close-search') {
|
||||||
|
searchIsActive = true;
|
||||||
|
} else if (
|
||||||
|
searchIsActive &&
|
||||||
|
(target.id === 'right-panel-close-search' ||
|
||||||
|
target.parentNode.id === 'right-panel-close-search')
|
||||||
|
) {
|
||||||
|
searchIsActive = false;
|
||||||
|
}
|
||||||
|
} else if (actionString === leftPanelTypes.link) {
|
||||||
|
if (!linkIsActive && target.id !== 'right-panel-close-search') {
|
||||||
|
linkIsActive = true;
|
||||||
|
} else if (
|
||||||
|
linkIsActive &&
|
||||||
|
(target.id === 'right-panel-close-search' ||
|
||||||
|
target.parentNode.id === 'right-panel-close-search')
|
||||||
|
) {
|
||||||
|
linkIsActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (actionString === leftPanelTypes.component) {
|
||||||
|
if (componentIsActive) {
|
||||||
|
componentIsActive = false;
|
||||||
|
}
|
||||||
|
} else if (actionString === leftPanelTypes.search) {
|
||||||
|
if (searchIsActive) {
|
||||||
|
searchIsActive = false;
|
||||||
|
}
|
||||||
|
} else if (actionString === leftPanelTypes.link) {
|
||||||
|
if (linkIsActive) {
|
||||||
|
linkIsActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.search-wrapper {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
max-width: 28rem;
|
||||||
|
width: 100%;
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
height: 3rem;
|
||||||
|
background-color: #393939;
|
||||||
|
color: #fff;
|
||||||
|
transition: max-width 0.11s cubic-bezier(0.2, 0, 0.38, 0.9),
|
||||||
|
background 0.11s cubic-bezier(0.2, 0, 0.38, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-wrapper-hidden {
|
||||||
|
max-width: 3rem;
|
||||||
|
background-color: #161616;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-focus {
|
||||||
|
outline: 2px solid #fff;
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
{#if action.type === leftPanelTypes.component}
|
||||||
|
<div bind:this={typeComponent}>
|
||||||
|
<ActionComponent
|
||||||
|
action={action.action}
|
||||||
|
icon={action.icon ? action.icon : undefined}
|
||||||
|
content={action.content}
|
||||||
|
bind:componentIsActive />
|
||||||
|
</div>
|
||||||
|
{:else if action.type === leftPanelTypes.search}
|
||||||
|
<div
|
||||||
|
bind:this={typeSearch}
|
||||||
|
class="search-wrapper"
|
||||||
|
class:search-wrapper-hidden={!searchIsActive}
|
||||||
|
class:search-focus={isSearchFocus || searchIsActive}
|
||||||
|
role="search">
|
||||||
|
<ActionSearch
|
||||||
|
action={action.action}
|
||||||
|
icon={action.icon ? action.icon : undefined}
|
||||||
|
content={action.content}
|
||||||
|
bind:searchIsActive
|
||||||
|
focusInputSearch={() => {
|
||||||
|
isSearchFocus = true;
|
||||||
|
}}
|
||||||
|
focusOutInputSearch={() => {
|
||||||
|
isSearchFocus = false;
|
||||||
|
}} />
|
||||||
|
</div>
|
||||||
|
{:else if action.type === leftPanelTypes.link || action.type === leftPanelTypes.links}
|
||||||
|
<div bind:this={typeLink}>
|
||||||
|
<ActionLink
|
||||||
|
action={action.action}
|
||||||
|
icon={action.icon ? action.icon : undefined}
|
||||||
|
content={action.content}
|
||||||
|
bind:linkIsActive />
|
||||||
|
</div>
|
||||||
|
{/if}
|
|
@ -1,38 +1,68 @@
|
||||||
<script>
|
<script>
|
||||||
export let action = undefined;
|
export let action = undefined;
|
||||||
// export let type = undefined;
|
export let type = undefined;
|
||||||
// export let icon = undefined;
|
export let icon = undefined;
|
||||||
// export let content = undefined;
|
// export let content = undefined;
|
||||||
|
export let linkIsActive = undefined;
|
||||||
|
|
||||||
// import { onMount } from 'svelte';
|
|
||||||
import { cx } from '../../../lib';
|
import { cx } from '../../../lib';
|
||||||
import AppSwitcher20 from 'carbon-icons-svelte/lib/AppSwitcher20';
|
|
||||||
import Icon from '../../Icon/Icon.svelte';
|
import Icon from '../../Icon/Icon.svelte';
|
||||||
|
import { leftPanelActions } from '../constants';
|
||||||
|
import { slide } from 'svelte/transition';
|
||||||
|
|
||||||
console.log(action);
|
let skeleton = icon ? icon.skeleton : false;
|
||||||
|
|
||||||
$: switcherIconProps =
|
if (!icon) {
|
||||||
action === 'switcher'
|
const actionsArray = Object.entries(leftPanelActions);
|
||||||
? (switcherIconProps = [
|
|
||||||
{
|
for (const definedAction of actionsArray) {
|
||||||
class: undefined,
|
for (const content of definedAction) {
|
||||||
skeleton: false,
|
if (typeof content === 'object') {
|
||||||
render: AppSwitcher20,
|
if (content.actionString === action) {
|
||||||
title: 'Switcher',
|
icon = content.iconProps;
|
||||||
tabIndex: 0,
|
|
||||||
focusable: false,
|
|
||||||
style: undefined
|
|
||||||
}
|
}
|
||||||
])
|
}
|
||||||
: (switcherIconProps = []);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if action === 'switcher'}
|
{#if action === leftPanelActions.switcher.actionString}
|
||||||
<button aria-label="Notifications" class={cx('--header__action')} type="button">
|
<button
|
||||||
<Icon {...switcherIconProps} render={switcherIconProps[0].render} />
|
aria-label={type}
|
||||||
|
class={cx('--header__action', linkIsActive && '--header__action--active')}
|
||||||
|
type="button">
|
||||||
|
<Icon {...icon} render={icon.render} />
|
||||||
</button>
|
</button>
|
||||||
{:else}
|
{:else}
|
||||||
<!-- <button aria-label="Notifications" class={cx('--header__action')} type="button">
|
<button
|
||||||
<Icon {...icon} render={icon[0].render} />
|
aria-label={type}
|
||||||
</button> -->
|
class={cx('--header__action', linkIsActive && '--header__action--active')}
|
||||||
|
type="button">
|
||||||
|
<Icon {...icon} render={icon.render} />
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{#if linkIsActive}
|
||||||
|
<div class="bx--header-panel bx--header-panel--expanded" transition:slide="{{duration: 200}}">
|
||||||
|
<ul class="bx--switcher__item">
|
||||||
|
<li class="bx--switcher__item">
|
||||||
|
<a class="bx--switcher__item-link bx--switcher__item-link--selected" href="/">Link</a>
|
||||||
|
</li>
|
||||||
|
<li class="bx--switcher__item">
|
||||||
|
<a class="bx--switcher__item-link" href="/">Link</a>
|
||||||
|
</li>
|
||||||
|
<li class="bx--switcher__item">
|
||||||
|
<a class="bx--switcher__item-link" href="/">Link</a>
|
||||||
|
</li>
|
||||||
|
<li class="bx--switcher__item">
|
||||||
|
<a class="bx--switcher__item-link" href="/">Link</a>
|
||||||
|
</li>
|
||||||
|
<li class="bx--switcher__item">
|
||||||
|
<a class="bx--switcher__item-link" href="/">Link</a>
|
||||||
|
</li>
|
||||||
|
<li class="bx--switcher__item">
|
||||||
|
<a class="bx--switcher__item-link" href="/">Link</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -1,36 +1,136 @@
|
||||||
<script>
|
<script>
|
||||||
export let action = undefined;
|
export let action = undefined;
|
||||||
// export let type = undefined;
|
|
||||||
export let icon = undefined;
|
export let icon = undefined;
|
||||||
// export let content = undefined;
|
// export let content = undefined;
|
||||||
|
export let searchIsActive = undefined;
|
||||||
|
|
||||||
// import { onMount } from 'svelte';
|
import { createEventDispatcher } from 'svelte';
|
||||||
import { cx } from '../../../lib';
|
import { cx } from '../../../lib';
|
||||||
import Search20 from 'carbon-icons-svelte/lib/Search20';
|
|
||||||
import Icon from '../../Icon/Icon.svelte';
|
import Icon from '../../Icon/Icon.svelte';
|
||||||
|
import { leftPanelActions, closeIcon } from '../constants';
|
||||||
|
|
||||||
$: searchIconProps =
|
// let searchIconProps = undefined;
|
||||||
action === 'search'
|
let searchTabIndex = 0;
|
||||||
? (searchIconProps = [
|
let closeTabIndex = -1;
|
||||||
{
|
const dispatch = createEventDispatcher();
|
||||||
class: undefined,
|
|
||||||
skeleton: false,
|
if (!icon) {
|
||||||
render: Search20,
|
const actionsArray = Object.entries(leftPanelActions);
|
||||||
title: 'Search',
|
|
||||||
tabIndex: 0,
|
for (const definedAction of actionsArray) {
|
||||||
focusable: false,
|
for (const content of definedAction) {
|
||||||
style: undefined
|
if (typeof content === 'object') {
|
||||||
|
if (content.actionString === action) {
|
||||||
|
icon = content.iconProps;
|
||||||
}
|
}
|
||||||
])
|
}
|
||||||
: (searchIconProps = []);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$: if (searchIsActive) {
|
||||||
|
searchTabIndex = -1;
|
||||||
|
closeTabIndex = 0;
|
||||||
|
} else {
|
||||||
|
searchTabIndex = 0;
|
||||||
|
closeTabIndex = -1;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if action === 'search'}
|
<style>
|
||||||
<button aria-label="Notifications" class={cx('--header__action')} type="button">
|
.search-wrapper {
|
||||||
<Icon {...searchIconProps} render={searchIconProps[0].render} />
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
border-bottom: 1px solid #393939;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-search {
|
||||||
|
width: 3rem;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
opacity: 1;
|
||||||
|
transition: background-color 0.11s cubic-bezier(0.2, 0, 0.38, 0.9),
|
||||||
|
opacity 0.11s cubic-bezier(0.2, 0, 0.38, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-search-disabled {
|
||||||
|
border: none;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-search {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.375rem;
|
||||||
|
letter-spacing: 0;
|
||||||
|
color: #fff;
|
||||||
|
caret-color: #fff;
|
||||||
|
background-color: initial;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
width: 100%;
|
||||||
|
height: 3rem;
|
||||||
|
padding: 0;
|
||||||
|
transition: opacity 0.11s cubic-bezier(0.2, 0, 0.38, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-hidden {
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-clear {
|
||||||
|
width: 3rem;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
opacity: 1;
|
||||||
|
transition: background-color 0.11s cubic-bezier(0.2, 0, 0.38, 0.9),
|
||||||
|
opacity 0.11s cubic-bezier(0.2, 0, 0.38, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-clear:hover {
|
||||||
|
background-color: #4c4c4c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-clear-hidden {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="right-panel-action-search"
|
||||||
|
class="search-wrapper"
|
||||||
|
role="combobox"
|
||||||
|
aria-expanded={searchIsActive}>
|
||||||
|
<button
|
||||||
|
tabindex={searchTabIndex}
|
||||||
|
aria-label={action}
|
||||||
|
class={cx('--header__action')}
|
||||||
|
class:btn-search={true}
|
||||||
|
class:btn-search-disabled={searchIsActive}
|
||||||
|
on:click={() => dispatch('focusInputSearch')}
|
||||||
|
type="button">
|
||||||
|
<Icon {...icon} render={icon.render} />
|
||||||
</button>
|
</button>
|
||||||
{:else}
|
<input
|
||||||
<button aria-label="Notifications" class={cx('--header__action')} type="button">
|
type="text"
|
||||||
<Icon {...icon} render={icon[0].render} />
|
autocomplete="off"
|
||||||
|
tabindex={closeTabIndex}
|
||||||
|
class="input-search"
|
||||||
|
class:input-hidden={!searchIsActive}
|
||||||
|
placeholder="Search"
|
||||||
|
on:focus={() => dispatch('focusInputSearch')}
|
||||||
|
on:focusout={() => dispatch('focusOutInputSearch')} />
|
||||||
|
<button
|
||||||
|
id="right-panel-close-search"
|
||||||
|
tabindex={closeTabIndex}
|
||||||
|
class={cx('--header__action')}
|
||||||
|
class:btn-clear={true}
|
||||||
|
class:btn-clear-hidden={!searchIsActive}
|
||||||
|
type="button"
|
||||||
|
aria-label="Clear search">
|
||||||
|
<Icon {...closeIcon} render={closeIcon.render} />
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
</div>
|
||||||
|
|
|
@ -1,51 +1,46 @@
|
||||||
<script>
|
<script>
|
||||||
export let rightPanel = undefined;
|
export let rightPanel = undefined;
|
||||||
|
|
||||||
import { onMount } from 'svelte';
|
|
||||||
import { cx } from '../../../lib';
|
import { cx } from '../../../lib';
|
||||||
import ActionSearch from './ActionSearch.svelte';
|
import ActionGeneric from './ActionGeneric.svelte';
|
||||||
import ActionComponent from './ActionComponent.svelte';
|
import { leftPanelActions } from '../constants';
|
||||||
import ActionLink from './ActionLink.svelte';
|
|
||||||
|
|
||||||
// let switcherAtLast = [];
|
let orderedRightPanel = [];
|
||||||
// let renderSwitcher = false;
|
let customActions = 1;
|
||||||
|
|
||||||
$: switcherAtLast = rightPanel.map((item, index, array) => {
|
rightPanel.forEach((item, index) => {
|
||||||
if (item.action === 'switcher') {
|
orderedRightPanel[index] = undefined;
|
||||||
if (index !== rightPanel.length) {
|
if (item.action) {
|
||||||
const newItem = array[index];
|
if (Object.keys(leftPanelActions).indexOf(item.action.charAt(0).toLowerCase() + item.action.slice(1)) === -1) {
|
||||||
return newItem;
|
orderedRightPanel[customActions] = rightPanel[index];
|
||||||
|
customActions += 1;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$: renderSwitcher = switcherAtLast ? true : false;
|
rightPanel.forEach((item, index) => {
|
||||||
|
if (item.action) {
|
||||||
|
if (item.action === leftPanelActions.search.actionString) {
|
||||||
|
orderedRightPanel[0] = rightPanel[index];
|
||||||
|
} else if (item.action === leftPanelActions.help.actionString) {
|
||||||
|
orderedRightPanel[customActions] = rightPanel[index];
|
||||||
|
} else if (item.action === leftPanelActions.notifications.actionString) {
|
||||||
|
orderedRightPanel[customActions + 1] = rightPanel[index];
|
||||||
|
} else if (item.action === leftPanelActions.account.actionString) {
|
||||||
|
orderedRightPanel[customActions + 2] = rightPanel[index];
|
||||||
|
} else if (item.action === leftPanelActions.switcher.actionString) {
|
||||||
|
orderedRightPanel[customActions + 3] = rightPanel[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
onMount(()=>{
|
orderedRightPanel = orderedRightPanel.filter(item => {
|
||||||
console.log(switcherAtLast);
|
return item;
|
||||||
console.log(renderSwitcher);
|
});
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class={cx('--header__global')}>
|
<div class={cx('--header__global')}>
|
||||||
{#each rightPanel as action, index}
|
{#each orderedRightPanel as action, index}
|
||||||
{#if action.action === 'search'}
|
<ActionGeneric {action} />
|
||||||
<ActionSearch {...action} />
|
|
||||||
{:else if action.action === 'switcher'}
|
|
||||||
{#if index === rightPanel.length}
|
|
||||||
<ActionLink {...action} />
|
|
||||||
{/if}
|
|
||||||
{:else if action.type === 'search'}
|
|
||||||
<ActionSearch {...action} />
|
|
||||||
{:else if action.type === 'component'}
|
|
||||||
<ActionComponent {...action} />
|
|
||||||
{:else if action.type === 'link'}
|
|
||||||
<ActionLink {...action} />
|
|
||||||
{/if}
|
|
||||||
{/each}
|
{/each}
|
||||||
{#if renderSwitcher}
|
|
||||||
<ActionLink {...switcherAtLast} />
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
86
src/components/UIShell/constants.js
Normal file
86
src/components/UIShell/constants.js
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
import Search20 from 'carbon-icons-svelte/lib/Search20';
|
||||||
|
import Help20 from 'carbon-icons-svelte/lib/Help20';
|
||||||
|
import Notification20 from 'carbon-icons-svelte/lib/Notification20';
|
||||||
|
import UserAvatar20 from 'carbon-icons-svelte/lib/UserAvatar20';
|
||||||
|
import AppSwitcher20 from 'carbon-icons-svelte/lib/AppSwitcher20';
|
||||||
|
import Close20 from 'carbon-icons-svelte/lib/Close20';
|
||||||
|
|
||||||
|
export const leftPanelActions = {
|
||||||
|
search: {
|
||||||
|
actionString: 'Search',
|
||||||
|
iconProps: {
|
||||||
|
class: undefined,
|
||||||
|
skeleton: false,
|
||||||
|
render: Search20,
|
||||||
|
title: 'Search',
|
||||||
|
tabIndex: 0,
|
||||||
|
focusable: false,
|
||||||
|
style: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
help: {
|
||||||
|
actionString: 'Help',
|
||||||
|
iconProps: {
|
||||||
|
class: undefined,
|
||||||
|
skeleton: false,
|
||||||
|
render: Help20,
|
||||||
|
title: 'Help',
|
||||||
|
tabIndex: 0,
|
||||||
|
focusable: false,
|
||||||
|
style: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
notifications: {
|
||||||
|
actionString: 'Notifications',
|
||||||
|
iconProps: {
|
||||||
|
class: undefined,
|
||||||
|
skeleton: false,
|
||||||
|
render: Notification20,
|
||||||
|
title: 'Notifications',
|
||||||
|
tabIndex: 0,
|
||||||
|
focusable: false,
|
||||||
|
style: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
account: {
|
||||||
|
actionString: 'Account',
|
||||||
|
iconProps: {
|
||||||
|
class: undefined,
|
||||||
|
skeleton: false,
|
||||||
|
render: UserAvatar20,
|
||||||
|
title: 'Account',
|
||||||
|
tabIndex: 0,
|
||||||
|
focusable: false,
|
||||||
|
style: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
switcher: {
|
||||||
|
actionString: 'Switcher',
|
||||||
|
iconProps: {
|
||||||
|
class: undefined,
|
||||||
|
skeleton: false,
|
||||||
|
render: AppSwitcher20,
|
||||||
|
title: 'App Switcher',
|
||||||
|
tabIndex: 0,
|
||||||
|
focusable: false,
|
||||||
|
style: undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const leftPanelTypes = {
|
||||||
|
search: 'Search',
|
||||||
|
component: 'Component',
|
||||||
|
link: 'Link',
|
||||||
|
links: 'Links'
|
||||||
|
};
|
||||||
|
|
||||||
|
export const closeIcon = {
|
||||||
|
class: undefined,
|
||||||
|
skeleton: false,
|
||||||
|
render: Close20,
|
||||||
|
title: 'Close',
|
||||||
|
tabIndex: 0,
|
||||||
|
focusable: false,
|
||||||
|
style: undefined
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue