Skip to content

Commit

Permalink
Merge pull request #169 from Neovici/feat/use-tabs-next
Browse files Browse the repository at this point in the history
feat: cosmoz-tabs-next
  • Loading branch information
megheaiulian authored May 19, 2022
2 parents 39783c0 + 0c051b4 commit 622b24c
Show file tree
Hide file tree
Showing 28 changed files with 6,338 additions and 8,871 deletions.
34 changes: 0 additions & 34 deletions .storybook/preview.js

This file was deleted.

14,834 changes: 6,041 additions & 8,793 deletions package-lock.json

Large diffs are not rendered by default.

28 changes: 17 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,19 @@
},
"license": "Apache-2.0",
"author": "Neovici Development <dev@neovici.se>",
"main": "cosmoz-tabs.js",
"main": "src/index.js",
"directories": {
"test": "test"
},
"files": [
"cosmoz-*.js",
"lib/**/*.js"
"src/**/*.js"
],
"scripts": {
"lint": "eslint --cache --ext .js .",
"lint-tsc": "tsc",
"start": "npm run storybook",
"start": "wds",
"test": "wtr --coverage",
"test:watch": "wtr --watch",
"storybook": "start-storybook --node-resolve --watch --open",
"storybook:build": "build-storybook",
"storybook:deploy": "storybook-to-ghpages",
"prepare": "husky install"
Expand All @@ -53,8 +51,16 @@
"@commitlint/config-conventional"
]
},
"exports": {
".": "./src/index.js",
"./cosmoz-tabs": "./src/cosmoz-tabs.js",
"./cosmoz-tab": "./src/cosmoz-tab.js",
"./cosmoz-tab-card": "./src/cosmoz-tab-card.js",
"./cosmoz-tab-card.js": "./src/cosmoz-tab-card.js",
"./next/*": "./src/next/*"
},
"dependencies": {
"@neovici/cosmoz-page-router": "^7.0.0",
"@neovici/cosmoz-page-router": "^8.0.0",
"@neovici/cosmoz-utils": "^3.25.0",
"@polymer/iron-icon": "^3.0.0",
"@polymer/iron-icons": "^3.0.0",
Expand All @@ -63,19 +69,19 @@
"lit-html": "^1.4.0"
},
"devDependencies": {
"@commitlint/cli": "^16.0.0",
"@commitlint/config-conventional": "^16.0.0",
"@commitlint/cli": "^17.0.0",
"@commitlint/config-conventional": "^17.0.0",
"@neovici/cfg": "^1.11.0",
"@open-wc/demoing-storybook": "^2.4.0",
"@open-wc/testing": "^2.5.0",
"@polymer/iron-list": "^3.1.0",
"@semantic-release/changelog": "^6.0.0",
"@semantic-release/git": "^10.0.0",
"@storybook/storybook-deployer": "^2.8.0",
"@web/dev-server-storybook": "^0.5.0",
"@web/test-runner": "^0.13.18",
"husky": "^7.0.0",
"husky": "^8.0.0",
"semantic-release": "^19.0.0",
"sinon": "^13.0.0",
"sinon": "^14.0.0",
"typescript": "^4.4.0"
}
}
File renamed without changes.
2 changes: 1 addition & 1 deletion cosmoz-tab.js → src/cosmoz-tab.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
html,
component
} from 'haunted';
import { useTab } from './lib/use-tab';
import { useTab } from './use-tab';

/**
Expand Down
4 changes: 2 additions & 2 deletions cosmoz-tabs.js → src/cosmoz-tabs.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @license Copyright (C) 2015 Neovici AB - Apache 2 License
import { html, component } from 'haunted';
import { useTabs } from './lib/use-tabs';
import { style, renderTab } from './lib/render';
import { useTabs } from './use-tabs';
import { style, renderTab } from './render';
import './cosmoz-tab.js';
import '@polymer/iron-icon';
import '@polymer/iron-icons';
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import './cosmoz-tabs';
68 changes: 68 additions & 0 deletions src/next/cosmoz-tab.css.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { tagged as css } from '@neovici/cosmoz-utils';

export default css`
:host {
position: relative;
display: flex;
box-sizing: border-box;
align-items: center;
justify-content: center;
flex: 1;
padding: 11px 24px;
color: inherit;
text-decoration: none;
text-align: center;
letter-spacing: 0.3px;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
/* TODO(accessibility): focused tab should be outlined */
outline: 0;
}
:host([active]) {
color: var(--cosmoz-tabs-accent-color, #508aef);
box-shadow: inset 0 -3px 0px 0px var(--cosmoz-tabs-accent-color, #508aef);
font-weight: 700;
letter-spacing: 0;
}
:host([disabled]) {
opacity: 0.4;
pointer-events: none;
}
#iconSlot::slotted(*) {
flex-shrink: 0;
}
#contentSlot::slotted(*) {
flex: auto;
}
.badge {
font-family: var(--cosmoz-font-base, 'Verdana, Arial, sans-serif');
font-weight: normal;
font-size: 11px;
line-height: 1;
border-radius: 0.90909em;
box-sizing: border-box;
transform: translateY(-50%);
vertical-align: top;
min-width: 1.81818em;
padding: 0.40909em 0.36363em;
max-width: 80px;
text-overflow: ellipsis;
overflow: hidden;
background-color: var(--accent-color, #ff4081);
color: #ffffff;
text-align: center;
}
a {
display: contents;
}
`;
53 changes: 53 additions & 0 deletions src/next/cosmoz-tab.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { component, useEffect, useLayoutEffect } from 'haunted';
import { html, nothing } from 'lit-html';
import { ifDefined } from 'lit-html/directives/if-defined';
import computeScroll from 'compute-scroll-into-view';

import style from './cosmoz-tab.css';

const Tab = (host) => {
const { active, badge, href } = host;

useEffect(() => {
if (!host.getAttribute('tabindex')) {
host.setAttribute('tabindex', '-1');
}
host.setAttribute('role', 'tab');
}, []);

useLayoutEffect(() => {
const el = host;
el.toggleAttribute('aria-selected', !!active);

if (!active) {
return;
}
computeScroll(el, {
block: 'nearest',
inline: 'center',
boundary: el.parentElement,
}).forEach(({ el, top, left }) =>
el.scroll({ top, left, behavior: 'smooth' })
);
}, [active]);

return html`
<style>
${style}
</style>
<a part="link" href=${ifDefined(href)}>
<slot id="iconSlot" name="icon"></slot>
<slot id="contentSlot"></slot>
${badge
? html`<span class="badge" part="badge">${badge}</span>`
: nothing}
</a>
`;
};

customElements.define(
'cosmoz-tab-next',
component(Tab, {
observedAttributes: ['active', 'badge', 'href'],
})
);
22 changes: 22 additions & 0 deletions src/next/cosmoz-tabs.css.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { tagged as css } from '@neovici/cosmoz-utils';

export default css`
:host {
background-color: var(--cosmoz-tabs-bg-color, #fff);
color: var(--cosmoz-tabs-text-color, #606c7e);
font-family: var(--cosmoz-tabs-font-family, inherit);
font-size: var(--cosmoz-tabs-font-size, 13px);
line-height: var(--cosmoz-tabs-line-height, 19px);
box-shadow: var(--cosmoz-tabs-shadow, inset 0 -1px 0 0 #e5e6eb);
flex: none;
display: flex;
align-items: center;
overflow-x: auto;
-webkit-overflow-scrolling: auto;
scrollbar-width: none;
padding-bottom: 1px;
}
:host::-webkit-scrollbar {
display: none;
}
`;
17 changes: 17 additions & 0 deletions src/next/cosmoz-tabs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { html, component, useEffect } from 'haunted';
import style from './cosmoz-tabs.css';

const Tabs = (host) => {
useEffect(() => {
host.setAttribute('role', 'tablist');
}, []);

return html`
<style>
${style}
</style>
<slot></slot>
`;
};

customElements.define('cosmoz-tabs-next', component(Tabs));
4 changes: 4 additions & 0 deletions src/next/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import './cosmoz-tabs';
import './cosmoz-tab';

export * from './use-tabs';
50 changes: 50 additions & 0 deletions src/next/use-tabs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* eslint-disable import/group-exports */
import { html, useMemo, useCallback, useRef } from 'haunted';
import { useHashParam } from '@neovici/cosmoz-page-router/lib/use-hash-param';

const isValid = (tab) => !tab.hidden && !tab.disabled,
valid = (tabs) => tabs.find(isValid),
choose = (tabs, name) => {
const tab = name && tabs.find((tab) => tab.name === name);
return tab && isValid(tab) ? tab : valid(tabs);
};

export const useTabs = (tabs, { hashParam }) => {
const [name, activate] = useHashParam(hashParam),
ref = useRef([]),
active = useMemo(() => choose(tabs, name), [tabs, name]),
activated = useMemo(() => {
const name = active.name;
return (ref.current = [...ref.current.filter((i) => i !== name), name]);
}, [active]),
onActivate = useCallback(
(e) => {
if (e.button !== 0 || e.metaKey || e.ctrlKey) {
return;
}
const { name } = e.currentTarget;
activate(name);
},
[activate]
);

return {
tabs,
active,
activated,
activate,
onActivate,
};
};

export const renderTabs = ({ tabs, active, onActivate }) =>
tabs.map(
(tab) => html`<cosmoz-tab-next
name=${tab.name}
?active=${active.name === tab.name}
?hidden=${tab.hidden}
?disabled=${tab.disabled}
@click=${onActivate}
>${tab.title}</cosmoz-tab-next
>`
);
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion lib/use-tabs.js → src/use-tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const useTabSelectedEffect = (host, selectedTab) => {
selected, hashParam
} = host,
[tabs, setTabs] = useState([]),
param = useHashParam(hashParam),
[param] = useHashParam(hashParam),
selection = hashParam == null || param == null && selected != null ? selected : param,
selectedTab = useMemo(() => choose(tabs, selection), [tabs, selection]);

Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion stories/cosmoz-tab-card.stories.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { html } from 'haunted';

import '../cosmoz-tabs';
import '../src/cosmoz-tabs';

export default {
title: 'Card',
Expand Down
2 changes: 1 addition & 1 deletion stories/cosmoz-tab.stories.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { html } from 'haunted';

import '../cosmoz-tabs';
import '../src/cosmoz-tabs';

export default {
title: 'Tab',
Expand Down
22 changes: 22 additions & 0 deletions stories/cosmoz-tabs-next.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { html } from 'haunted';

import '../src/next';

export default {
title: 'Tabs (next)',
component: 'cosmoz-tabs-next',
};

const basics = () => html`
<cosmoz-tabs-next>
<cosmoz-tab-next disabled>Tab1</cosmoz-tab-next>
<cosmoz-tab-next disabled badge="2">Tab2</cosmoz-tab-next>
<cosmoz-tab-next hidden badge="3">Tab3</cosmoz-tab-next>
<cosmoz-tab-next badge="4" active href="#123">Tab4</cosmoz-tab-next>
${Array(6)
.fill()
.map((_, i) => html`<cosmoz-tab-next>Tab ${5 + i}</cosmoz-tab-next>`)}
</cosmoz-tabs-next>
`;

export { basics };
Loading

0 comments on commit 622b24c

Please sign in to comment.