Skip to content
Snippets Groups Projects
Commit 33365e83 authored by druid's avatar druid
Browse files

Merge branch 'development'

parents 491120e5 9dcd5352
No related branches found
No related tags found
No related merge requests found
Showing
with 1227 additions and 80 deletions
......@@ -5,10 +5,11 @@
* It contains typing information for all components that exist in this project.
*/
import {HTMLStencilElement, JSXBase} from '@stencil/core/internal';
import {Breadcrumb} from './components/hy-breadcrumbs/hy-breadcrumbs';
import {
AccordionVariants,
BreadcrumbVariants,
ButtonVariants,
CheckboxVariants,
ColorVariant,
CourseVariants,
CtaLinkButtonVariants,
......@@ -26,10 +27,13 @@ import {
LinkBoxVariants,
LinkVariants,
MenuType,
PaginationItemVariants,
PersonCardVariants,
ProcessFlowBoxStepStates,
ProcessFlowBoxVariants,
SiteLogoSize,
} from './utils/utils';
import {Breadcrumb} from './components/hy-breadcrumbs/hy-breadcrumbs';
import {TagValue} from './components/courses/hy-content-list-item/hy-content-list-item';
import {DesktopLinks} from './components/site-header/hy-desktop-menu-links/hy-desktop-menu-links';
import {IDropdownItem} from './components/hy-dropdown/hy-dropdown';
......@@ -54,6 +58,7 @@ export namespace Components {
}
interface HyAccordionItem {
accordiontitle?: string;
variant: AccordionVariants;
}
interface HyAdjacentImageText {
imageAlt: string;
......@@ -191,9 +196,22 @@ export namespace Components {
variant: ButtonVariants;
}
interface HyCheckbox {
/**
* Unique id for checkbox element
*/
checkboxId: string | number;
/**
* Label for input to describe
*/
checkboxLabel: string;
/**
* Value for input element
*/
checkboxValue: string | number;
/**
* Variant to deifne what style of checkbox to use
*/
variant: CheckboxVariants;
}
interface HyContentList {
dataItems: string;
......@@ -437,6 +455,14 @@ export namespace Components {
dataItems: CtaLinkValue[] | string;
listHeading: string;
}
interface HyListItem {
isExternal: boolean;
itemDescription?: string;
itemTitle?: string;
itemType?: string;
scLabel?: string;
url?: string;
}
interface HyMain {
hasSidebar: boolean;
}
......@@ -580,11 +606,34 @@ export namespace Components {
*/
size: SiteLogoSize;
}
interface HyPager {}
interface HyPagerItem {
itemLabel?: string;
itemUrl?: string;
scAriaLabel?: string;
variant: PaginationItemVariants;
}
interface HyParagraphText {
headerstyle: string;
placement: string;
variant: string;
}
interface HyPersonCard {
categoryTitle?: string;
department?: string;
email?: string;
field?: string;
firstName?: string;
imageAlt?: string;
imageUrl?: string;
isExternal: boolean;
lastName?: string;
phone?: string;
positionTitle?: string;
scLabel?: string;
url?: string;
variant: PersonCardVariants;
}
interface HyProcess {
dataItems: ProcessFlowBoxValue[] | string;
numberTerm: string;
......@@ -988,6 +1037,11 @@ declare global {
prototype: HTMLHyLinkListElement;
new (): HTMLHyLinkListElement;
};
interface HTMLHyListItemElement extends Components.HyListItem, HTMLStencilElement {}
var HTMLHyListItemElement: {
prototype: HTMLHyListItemElement;
new (): HTMLHyListItemElement;
};
interface HTMLHyMainElement extends Components.HyMain, HTMLStencilElement {}
var HTMLHyMainElement: {
prototype: HTMLHyMainElement;
......@@ -1038,11 +1092,26 @@ declare global {
prototype: HTMLHyMenuSidebarElement;
new (): HTMLHyMenuSidebarElement;
};
interface HTMLHyPagerElement extends Components.HyPager, HTMLStencilElement {}
var HTMLHyPagerElement: {
prototype: HTMLHyPagerElement;
new (): HTMLHyPagerElement;
};
interface HTMLHyPagerItemElement extends Components.HyPagerItem, HTMLStencilElement {}
var HTMLHyPagerItemElement: {
prototype: HTMLHyPagerItemElement;
new (): HTMLHyPagerItemElement;
};
interface HTMLHyParagraphTextElement extends Components.HyParagraphText, HTMLStencilElement {}
var HTMLHyParagraphTextElement: {
prototype: HTMLHyParagraphTextElement;
new (): HTMLHyParagraphTextElement;
};
interface HTMLHyPersonCardElement extends Components.HyPersonCard, HTMLStencilElement {}
var HTMLHyPersonCardElement: {
prototype: HTMLHyPersonCardElement;
new (): HTMLHyPersonCardElement;
};
interface HTMLHyProcessElement extends Components.HyProcess, HTMLStencilElement {}
var HTMLHyProcessElement: {
prototype: HTMLHyProcessElement;
......@@ -1184,6 +1253,7 @@ declare global {
'hy-link-box': HTMLHyLinkBoxElement;
'hy-link-box-list': HTMLHyLinkBoxListElement;
'hy-link-list': HTMLHyLinkListElement;
'hy-list-item': HTMLHyListItemElement;
'hy-main': HTMLHyMainElement;
'hy-main-content-wrapper': HTMLHyMainContentWrapperElement;
'hy-menu': HTMLHyMenuElement;
......@@ -1194,7 +1264,10 @@ declare global {
'hy-menu-level-container': HTMLHyMenuLevelContainerElement;
'hy-menu-mobile-breadcrumb': HTMLHyMenuMobileBreadcrumbElement;
'hy-menu-sidebar': HTMLHyMenuSidebarElement;
'hy-pager': HTMLHyPagerElement;
'hy-pager-item': HTMLHyPagerItemElement;
'hy-paragraph-text': HTMLHyParagraphTextElement;
'hy-person-card': HTMLHyPersonCardElement;
'hy-process': HTMLHyProcessElement;
'hy-process-flow-box': HTMLHyProcessFlowBoxElement;
'hy-prominent-image': HTMLHyProminentImageElement;
......@@ -1222,6 +1295,7 @@ declare namespace LocalJSX {
}
interface HyAccordionItem {
accordiontitle?: string;
variant?: AccordionVariants;
}
interface HyAdjacentImageText {
imageAlt?: string;
......@@ -1359,9 +1433,22 @@ declare namespace LocalJSX {
variant?: ButtonVariants;
}
interface HyCheckbox {
/**
* Unique id for checkbox element
*/
checkboxId?: string | number;
/**
* Label for input to describe
*/
checkboxLabel?: string;
/**
* Value for input element
*/
checkboxValue?: string | number;
/**
* Variant to deifne what style of checkbox to use
*/
variant?: CheckboxVariants;
}
interface HyContentList {
dataItems?: string;
......@@ -1605,6 +1692,14 @@ declare namespace LocalJSX {
dataItems?: CtaLinkValue[] | string;
listHeading?: string;
}
interface HyListItem {
isExternal?: boolean;
itemDescription?: string;
itemTitle?: string;
itemType?: string;
scLabel?: string;
url?: string;
}
interface HyMain {
hasSidebar?: boolean;
}
......@@ -1758,11 +1853,34 @@ declare namespace LocalJSX {
*/
size?: SiteLogoSize;
}
interface HyPager {}
interface HyPagerItem {
itemLabel?: string;
itemUrl?: string;
scAriaLabel?: string;
variant?: PaginationItemVariants;
}
interface HyParagraphText {
headerstyle?: string;
placement?: string;
variant?: string;
}
interface HyPersonCard {
categoryTitle?: string;
department?: string;
email?: string;
field?: string;
firstName?: string;
imageAlt?: string;
imageUrl?: string;
isExternal?: boolean;
lastName?: string;
phone?: string;
positionTitle?: string;
scLabel?: string;
url?: string;
variant?: PersonCardVariants;
}
interface HyProcess {
dataItems?: ProcessFlowBoxValue[] | string;
numberTerm?: string;
......@@ -1963,6 +2081,7 @@ declare namespace LocalJSX {
'hy-link-box': HyLinkBox;
'hy-link-box-list': HyLinkBoxList;
'hy-link-list': HyLinkList;
'hy-list-item': HyListItem;
'hy-main': HyMain;
'hy-main-content-wrapper': HyMainContentWrapper;
'hy-menu': HyMenu;
......@@ -1973,7 +2092,10 @@ declare namespace LocalJSX {
'hy-menu-level-container': HyMenuLevelContainer;
'hy-menu-mobile-breadcrumb': HyMenuMobileBreadcrumb;
'hy-menu-sidebar': HyMenuSidebar;
'hy-pager': HyPager;
'hy-pager-item': HyPagerItem;
'hy-paragraph-text': HyParagraphText;
'hy-person-card': HyPersonCard;
'hy-process': HyProcess;
'hy-process-flow-box': HyProcessFlowBox;
'hy-prominent-image': HyProminentImage;
......@@ -2052,6 +2174,7 @@ declare module '@stencil/core' {
'hy-link-box': LocalJSX.HyLinkBox & JSXBase.HTMLAttributes<HTMLHyLinkBoxElement>;
'hy-link-box-list': LocalJSX.HyLinkBoxList & JSXBase.HTMLAttributes<HTMLHyLinkBoxListElement>;
'hy-link-list': LocalJSX.HyLinkList & JSXBase.HTMLAttributes<HTMLHyLinkListElement>;
'hy-list-item': LocalJSX.HyListItem & JSXBase.HTMLAttributes<HTMLHyListItemElement>;
'hy-main': LocalJSX.HyMain & JSXBase.HTMLAttributes<HTMLHyMainElement>;
'hy-main-content-wrapper': LocalJSX.HyMainContentWrapper &
JSXBase.HTMLAttributes<HTMLHyMainContentWrapperElement>;
......@@ -2065,7 +2188,10 @@ declare module '@stencil/core' {
'hy-menu-mobile-breadcrumb': LocalJSX.HyMenuMobileBreadcrumb &
JSXBase.HTMLAttributes<HTMLHyMenuMobileBreadcrumbElement>;
'hy-menu-sidebar': LocalJSX.HyMenuSidebar & JSXBase.HTMLAttributes<HTMLHyMenuSidebarElement>;
'hy-pager': LocalJSX.HyPager & JSXBase.HTMLAttributes<HTMLHyPagerElement>;
'hy-pager-item': LocalJSX.HyPagerItem & JSXBase.HTMLAttributes<HTMLHyPagerItemElement>;
'hy-paragraph-text': LocalJSX.HyParagraphText & JSXBase.HTMLAttributes<HTMLHyParagraphTextElement>;
'hy-person-card': LocalJSX.HyPersonCard & JSXBase.HTMLAttributes<HTMLHyPersonCardElement>;
'hy-process': LocalJSX.HyProcess & JSXBase.HTMLAttributes<HTMLHyProcessElement>;
'hy-process-flow-box': LocalJSX.HyProcessFlowBox & JSXBase.HTMLAttributes<HTMLHyProcessFlowBoxElement>;
'hy-prominent-image': LocalJSX.HyProminentImage & JSXBase.HTMLAttributes<HTMLHyProminentImageElement>;
......
......@@ -22,6 +22,39 @@
}
}
.hy-accordion__item.mini {
margin-bottom: 1rem;
margin-top: 1rem;
}
.hy-accordion__item__is-open.mini {
margin-bottom: 0;
margin-top: 0;
.hy-accordion__item--container {
border-bottom: 1px solid var(--grayscale-medium-dark);
border-top: 1px solid var(--grayscale-medium-dark);
padding-top: 16px;
padding-bottom: 32px;
margin-top: -1px;
transition: padding 0.5s ease-in-out;
@include breakpoint($narrow) {
padding-top: 28px;
padding-bottom: 30px;
}
@include breakpoint($wide) {
padding-top: 32px;
padding-bottom: 40px;
}
}
}
.hy-accordion__item.hy-accordion__item__is-open.mini {
background-color: var(--grayscale-white);
border: none;
box-shadow: 0 -10px 10px -10px rgba(0, 49, 70, 0.05);
}
.hy-accordion--heading {
justify-content: flex-start;
letter-spacing: -0.69px;
......@@ -87,6 +120,55 @@
}
}
.hy-accordion--heading.mini {
// accordion clickable header
.hy-accordion__button {
@include font-size(18px, 22px);
background-color: var(--grayscale-white);
color: var(--link-blue);
letter-spacing: -0.56px;
padding: 0;
@include breakpoint($narrow) {
@include font-size(22px, 28px);
letter-spacing: -0.69px;
padding: 0;
}
&[aria-expanded='true'] {
color: var(--grayscale-black);
margin-bottom: 20px;
@include breakpoint($narrow) {
margin-bottom: 28px;
}
@include breakpoint($wide) {
margin-bottom: 32px;
}
}
}
//accordion arrow
.hy-accordion--heading__icon {
margin-right: 0.5rem;
z-index: 0;
@include breakpoint($narrow) {
margin-right: 10px;
}
svg {
fill: var(--brand-main-light);
height: 14px;
width: 14px;
@include breakpoint($narrow) {
height: 16px;
width: 16px;
}
}
}
}
.hy-accordion__content {
display: block;
height: 0;
......@@ -104,3 +186,9 @@
}
}
}
.hy-accordion__content.mini {
hy-box {
padding: 0;
}
}
import {Component, Listen, Prop, State, Element, h} from '@stencil/core';
import {AccordionVariants} from '../../utils/utils';
let keys = {
enter: 'Enter', //13
tab: 'Tab', //9
pageUp: 'PageUp', //33
pageDown: 'PageDown', //34
arrowUp: 'ArrowUp', // 38
arrowDown: 'ArrowDown', //40
home: 'Home', //36
end: 'End', //35
};
@Component({
tag: 'hy-accordion-item',
......@@ -8,6 +20,7 @@ import {Component, Listen, Prop, State, Element, h} from '@stencil/core';
export class AccordionItem {
@Element() el: HTMLElement;
@Prop() accordiontitle?: string;
@Prop() variant: AccordionVariants = AccordionVariants.default;
@State() ready: boolean = false;
componentDidLoad() {
......@@ -34,31 +47,28 @@ export class AccordionItem {
const triggers = Array.prototype.slice.call(accordion.querySelectorAll('.hy-accordion__button'));
let target = event.target as HTMLButtonElement;
const key = event.which.toString();
const key = event.code;
// 33 = Page Up, 34 = Page Down
const ctrlModifier = event.ctrlKey && key.match(/33|34/);
const ctrlModifier = event.ctrlKey && [keys.pageDown, keys.pageUp].includes(key); //key.match(/33|34/);
if (target.classList.contains('hy-accordion__button')) {
// Up/ Down arrow and Control + Page Up/ Page Down keyboard operations
// 38 = Up, 40 = Down
if (key.match(/38|40/) || ctrlModifier) {
if ([keys.arrowDown, keys.arrowUp].includes(key) || ctrlModifier) {
const index = triggers.indexOf(target);
const direction = key.match(/34|40/) ? 1 : -1;
const direction = [keys.arrowDown, keys.pageDown].includes(key) ? 1 : -1;
const length = triggers.length;
const newIndex = (index + length + direction) % length;
triggers[newIndex].focus();
event.preventDefault();
} else if (key.match(/35|36/)) {
// 35 = End, 36 = Home keyboard operations
} else if ([keys.home, keys.end].includes(key)) {
switch (key) {
// Go to first accordion
case '36':
case keys.home:
triggers[0].focus();
break;
// Go to last accordion
case '35':
case keys.end:
triggers[triggers.length - 1].focus();
break;
}
......@@ -179,40 +189,46 @@ export class AccordionItem {
});
}
const classAttributes = ['hy-accordion__item'];
const classAttributes = ['hy-accordion__item', this.variant].join(' ');
const classInnerWrapper = ['hy-accordion__item--container', this.variant].join(' ');
const classHeadingAttributes = ['hy-accordion--heading', this.variant].join(' ');
const classContentAttributes = ['hy-accordion__content', this.variant].join(' ');
const titleAsId = this.accordiontitle.toLowerCase().replace(/\W/g, '-');
const accordionItemHref = '#' + titleAsId + '--title';
return (
<div class={classAttributes.join(' ')}>
<div class="hy-accordion--heading">
<a href={accordionItemHref} class="hy-accordion__link" tabindex="-1">
<button
aria-expanded="false"
aria-controls={`${titleAsId}--content`}
class="hy-accordion__button"
id={`${titleAsId}--title`}
>
<span class="hy-accordion--heading__icon">
<hy-icon icon={'hy-icon-caret-down'} size={20} />
</span>
{this.accordiontitle}
</button>
</a>
</div>
<div
aria-labelledBy={`${titleAsId}--title`}
class="hy-accordion__content"
id={`${titleAsId}--content`}
role="region"
aria-hidden="true"
style={{display: 'none'}}
>
<hy-box pt="0" pb="0" pl="0.75" pr="0.75">
<div class="hy-accordion__content--inner-wrapper">
<slot></slot>
</div>
</hy-box>
<div class={classAttributes}>
<div class={classInnerWrapper}>
<div class={classHeadingAttributes}>
<a href={accordionItemHref} class="hy-accordion__link" tabindex="-1">
<button
aria-expanded="false"
aria-controls={`${titleAsId}--content`}
class="hy-accordion__button"
id={`${titleAsId}--title`}
>
<span class="hy-accordion--heading__icon">
<hy-icon icon={'hy-icon-caret-down'} size={20} />
</span>
{this.accordiontitle}
</button>
</a>
</div>
<div
aria-labelledBy={`${titleAsId}--title`}
class={classContentAttributes}
id={`${titleAsId}--content`}
role="region"
aria-hidden="true"
style={{display: 'none'}}
>
<hy-box pt="0" pb="0" pl="0.75" pr="0.75">
<div class="hy-accordion__content--inner-wrapper">
<slot></slot>
</div>
</hy-box>
</div>
</div>
</div>
);
......
......@@ -39,9 +39,10 @@ Accordion component
## Properties
| Property | Attribute | Description | Type | Default |
| ---------------- | ---------------- | ----------- | -------- | ----------- |
| `accordiontitle` | `accordiontitle` | | `string` | `undefined` |
| Property | Attribute | Description | Type | Default |
| ---------------- | ---------------- | ----------- | ----------------------------------------------------- | --------------------------- |
| `accordiontitle` | `accordiontitle` | | `string` | `undefined` |
| `variant` | `variant` | | `AccordionVariants.default \| AccordionVariants.mini` | `AccordionVariants.default` |
## Dependencies
......
......@@ -81,3 +81,113 @@
}
}
}
.hy-checkbox--button {
display: inline-block;
margin-right: 4px;
position: relative;
&__label {
@include font-size(12px, 14px);
align-items: center;
border: 0.5px solid var(--grayscale-medium-dark);
color: var(--link-blue);
display: inline-flex;
font-family: var(--main-font-family);
font-weight: 600;
letter-spacing: -0.3px;
padding: 12px 15px 12px 13px;
z-index: 1;
@include breakpoint($wide) {
@include font-size(14px, 18px);
letter-spacing: -0.4px;
padding: 9px 8px 9px 8px;
}
}
&__checkmark {
position: absolute;
right: 12px;
top: 0;
bottom: 0;
@include breakpoint($wide) {
right: 10px;
bottom: calc(50% + 10px);
}
svg {
bottom: 0;
left: 0;
position: absolute;
visibility: hidden;
}
}
&__label-icon {
height: 13px;
position: absolute;
width: 12px;
@include breakpoint($wide) {
padding: 10px;
right: -6px;
top: calc(50% + 5px);
}
svg {
background: var(--grayscale-white);
height: 12px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 12px;
}
}
&__checkbox {
height: 100%;
margin: 0;
opacity: 0;
position: absolute;
width: 100%;
z-index: 10;
&:checked {
& + label {
border: 1px solid var(--grayscale-black);
color: var(--grayscale-black);
padding: 12px 15px 12px 13px;
@include breakpoint($wide) {
border: 2px solid var(--grayscale-black);
padding: 8px 26px 8px 7px;
}
.hy-checkbox--button__checkmark {
.hy-checkbox--button__label-icon {
background: var(--grayscale-white);
}
svg {
visibility: visible;
}
}
}
}
&:hover {
cursor: pointer;
}
&:focus {
& + label {
outline-offset: 1px;
outline: 1px solid var(--link-blue);
}
}
}
}
import {Component, Host, h, Prop} from '@stencil/core';
import {CheckboxVariants} from '../../utils/utils';
@Component({
tag: 'hy-checkbox',
......@@ -6,25 +7,60 @@ import {Component, Host, h, Prop} from '@stencil/core';
shadow: false,
})
export class HyCheckbox {
/**
* Unique id for checkbox element
*/
@Prop() checkboxId: string | number;
/**
* Value for input element
*/
@Prop() checkboxValue: string | number;
/**
* Label for input to describe
*/
@Prop() checkboxLabel: string;
/**
* Variant to deifne what style of checkbox to use
*/
@Prop() variant: CheckboxVariants = CheckboxVariants.default;
render() {
return (
<Host class="hy-checkbox">
<input
type="checkbox"
class="hy-checkbox__checkbox"
id={`${this.checkboxId}`}
value={`${this.checkboxValue}`}
/>
<label class="hy-checkbox__label" htmlFor={`${this.checkboxId}`}>
<span class="hy-checkbox__checkmark">
<hy-icon class="hy-checkbox__label-icon" icon={'hy-icon-done'} size={23} aria-hidden="true" />
</span>
{this.checkboxLabel}
</label>
</Host>
);
switch (this.variant) {
case 'button':
return (
<Host class="hy-checkbox--button">
<input
type="checkbox"
class="hy-checkbox--button__checkbox"
id={`${this.checkboxId}`}
value={`${this.checkboxValue}`}
/>
<label class="hy-checkbox--button__label" htmlFor={`${this.checkboxId}`}>
{this.checkboxLabel}
<span class="hy-checkbox--button__checkmark">
<hy-icon class="hy-checkbox--button__label-icon" icon={'hy-icon-done'} size={14} aria-hidden="true" />
</span>
</label>
</Host>
);
default:
return (
<Host class="hy-checkbox">
<input
type="checkbox"
class="hy-checkbox__checkbox"
id={`${this.checkboxId}`}
value={`${this.checkboxValue}`}
/>
<label class="hy-checkbox__label" htmlFor={`${this.checkboxId}`}>
<span class="hy-checkbox__checkmark">
<hy-icon class="hy-checkbox__label-icon" icon={'hy-icon-done'} size={23} aria-hidden="true" />
</span>
{this.checkboxLabel}
</label>
</Host>
);
}
}
}
......@@ -4,11 +4,12 @@
## Properties
| Property | Attribute | Description | Type | Default |
| --------------- | ---------------- | ----------- | ------------------ | ----------- |
| `checkboxId` | `checkbox-id` | | `number \| string` | `undefined` |
| `checkboxLabel` | `checkbox-label` | | `string` | `undefined` |
| `checkboxValue` | `checkbox-value` | | `number \| string` | `undefined` |
| Property | Attribute | Description | Type | Default |
| --------------- | ---------------- | ----------------------------------------------- | ----------------------------------------------------- | -------------------------- |
| `checkboxId` | `checkbox-id` | Unique id for checkbox element | `number \| string` | `undefined` |
| `checkboxLabel` | `checkbox-label` | Label for input to describe | `string` | `undefined` |
| `checkboxValue` | `checkbox-value` | Value for input element | `number \| string` | `undefined` |
| `variant` | `variant` | Variant to deifne what style of checkbox to use | `CheckboxVariants.button \| CheckboxVariants.default` | `CheckboxVariants.default` |
## Dependencies
......
:host {
display: block;
}
.hy-list-item {
display: flex;
font-family: var(--main-font-family);
margin-bottom: 28px;
text-decoration: none;
@include breakpoint($wide) {
margin-bottom: 32px;
}
&__info-container {
&__header {
@include font-size(12px, 14px);
color: var(--grayscale-dark);
letter-spacing: 0;
margin-bottom: 4px;
@include breakpoint($narrow) {
@include font-size(14px, 18px);
margin-bottom: 2px;
}
}
&__title {
@include font-size(18px, 22px);
@include font-weight($bold);
color: var(--brand-main-light);
letter-spacing: -0.56px;
margin-bottom: 6px;
@include breakpoint($narrow) {
@include font-size(22px, 28px);
letter-spacing: -0.69px;
margin-bottom: 10px;
}
@include breakpoint($fullhd) {
@include font-size(26px, 32px);
letter-spacing: -0.8px;
margin-bottom: 8px;
}
}
&__link-container {
align-items: center;
display: flex;
margin-bottom: 6px;
@include breakpoint($narrow) {
margin-bottom: 8px;
}
}
&__link {
@include font-size(12px, 16px);
color: var(--grayscale-dark);
letter-spacing: -0.07px;
margin-left: 4px;
@include breakpoint($narrow) {
margin-left: 5px;
}
&__icon {
svg {
fill: var(--grayscale-dark);
}
}
}
&__description {
@include font-size(14px, 20px);
color: var(--grayscale-black);
letter-spacing: 0;
@include breakpoint($narrow) {
@include font-size(16px, 24px);
}
}
}
}
import {Component, h, Prop} from '@stencil/core';
@Component({
tag: 'hy-list-item',
styleUrl: 'hy-list-item.scss',
shadow: false,
})
export class HyListItem {
@Prop() itemType?: string;
@Prop() itemTitle?: string;
@Prop() itemDescription?: string;
@Prop() url?: string;
@Prop() isExternal: boolean = false;
@Prop() scLabel?: string;
render() {
const classAttributes = ['hy-list-item'].join(' ');
const target = this.isExternal ? '_blank' : '_self';
return (
<article>
<a class={classAttributes} href={this.url} target={target} aria-label={this.scLabel}>
<div class="hy-list-item__info-container">
<div class="hy-list-item__info-container__header">{this.itemType}</div>
<div class="hy-list-item__info-container__title">{this.itemTitle}</div>
<div class="hy-list-item__info-container__link-container">
<span class="hy-list-item__info-container__link__icon">
<hy-icon icon={'hy-icon-link'} size={15} />
</span>
<div class="hy-list-item__info-container__link">{this.url}</div>
</div>
{this.itemDescription && (
<div class="hy-list-item__info-container__description">{this.itemDescription}</div>
)}
</div>
</a>
</article>
);
}
}
# hy-list-item
<!-- Auto Generated Below -->
## Properties
| Property | Attribute | Description | Type | Default |
| ----------------- | ------------------ | ----------- | --------- | ----------- |
| `isExternal` | `is-external` | | `boolean` | `false` |
| `itemDescription` | `item-description` | | `string` | `undefined` |
| `itemTitle` | `item-title` | | `string` | `undefined` |
| `itemType` | `item-type` | | `string` | `undefined` |
| `scLabel` | `sc-label` | | `string` | `undefined` |
| `url` | `url` | | `string` | `undefined` |
## Dependencies
### Depends on
- [hy-icon](../icon)
### Graph
```mermaid
graph TD;
hy-list-item --> hy-icon
style hy-list-item fill:#f9f,stroke:#333,stroke-width:4px
```
---
Helsinki University Design System
:host {
display: block;
}
.hy-person-card-container {
font-family: var(--main-font-family);
margin-bottom: 28px;
@include breakpoint($wide) {
margin-bottom: 32px;
}
&__category-title {
@include font-size(12px, 14px);
color: var(--grayscale-dark);
letter-spacing: 0;
margin-bottom: 8px;
@include breakpoint($narrow) {
@include font-size(14px, 18px);
}
@include breakpoint($fullhd) {
@include font-size(14px, 18px); //>1920 desktop
}
}
&__link {
text-decoration: none;
}
}
.hy-person-card {
display: flex;
flex-direction: row;
font-family: var(--main-font-family);
&__image-container {
margin-right: 12px;
@include breakpoint($narrow) {
margin-right: 16px;
}
&__image {
height: 70px;
width: 70px;
@include breakpoint($narrow) {
height: 112px;
width: 112px;
}
@include breakpoint($fullhd) {
//1920
height: 140px;
width: 140px;
}
img {
height: 70px;
width: 70px;
object-fit: cover;
@include breakpoint($narrow) {
height: 112px;
width: 112px;
}
@include breakpoint($fullhd) {
height: 140px;
width: 140px;
}
}
}
&__no-image {
height: 70px;
width: 70px;
align-items: center;
background-color: var(--brand-main-light);
display: flex;
justify-content: center;
@include breakpoint($narrow) {
height: 112px;
width: 112px;
}
@include breakpoint($fullhd) {
height: 140px;
width: 140px;
}
&__initials {
@include font-size(18px, 24px);
@include font-weight($bold);
color: var(--grayscale-white);
letter-spacing: -0.56px;
@include breakpoint($narrow) {
@include font-size(32px, 32px);
letter-spacing: 0.96px;
}
}
}
}
&__info-container {
&__full-name {
@include font-size(18px, 24px);
@include font-weight($bold);
color: var(--brand-main-light);
letter-spacing: -0.56px;
margin-bottom: 4px;
@include breakpoint($narrow) {
@include font-size(22px, 28px);
letter-spacing: -0.69px;
margin-bottom: 3px;
}
@include breakpoint($fullhd) {
@include font-size(26px, 28px);
letter-spacing: -0.81px;
margin-bottom: 5px;
}
}
&__position-title {
@include font-size(14px, 19px);
@include font-weight($bold);
color: var(--brand-main-nearly-black);
letter-spacing: 0;
margin-bottom: 3px;
@include breakpoint($narrow) {
@include font-size(16px, 20px);
letter-spacing: -0.5px;
margin-bottom: 4px;
}
@include breakpoint($fullhd) {
@include font-size(18px, 24px);
letter-spacing: -0.56px;
margin-bottom: 8px;
}
}
&__department {
@include font-size(12px, 17px);
color: var(--brand-main-nearly-black);
letter-spacing: 0;
margin-bottom: 3px;
text-transform: uppercase;
@include breakpoint($narrow) {
@include font-size(14px, 19px);
margin-bottom: 6px;
}
@include breakpoint($fullhd) {
@include font-size(14px, 16px);
margin-bottom: 9px;
}
}
&__field {
@include font-size(12px, 17px);
color: var(--brand-main-nearly-black);
letter-spacing: 0;
margin-bottom: 4px;
@include breakpoint($narrow) {
@include font-size(14px, 19px);
margin-bottom: 6px;
}
@include breakpoint($fullhd) {
@include font-size(14px, 16px);
margin-bottom: 9px;
}
}
&__email-container {
align-items: center;
display: flex;
margin-bottom: 4px;
}
&__email {
@include font-size(12px, 17px);
color: var(--brand-main-nearly-black);
letter-spacing: 0;
margin-left: 11px;
@include breakpoint($narrow) {
@include font-size(14px, 19px);
margin-left: 8px;
}
&__icon {
svg {
height: 15px;
width: 16px;
@include breakpoint($narrow) {
height: 12px;
width: 16px;
}
}
}
}
&__phone-container {
align-items: center;
display: flex;
}
&__phone {
@include font-size(12px, 17px);
color: var(--brand-main-nearly-black);
letter-spacing: 0;
margin-left: 11px;
@include breakpoint($narrow) {
@include font-size(14px, 19px);
margin-left: 8px;
}
&__icon {
svg {
height: 13px;
width: 13px;
@include breakpoint($narrow) {
height: 14px;
width: 14px;
}
}
}
}
}
&.search-panel {
margin-bottom: 12px;
@include breakpoint($narrow) {
margin-bottom: 14px;
}
.hy-person-card__info-container__full-name {
@include font-size(14px, 20px);
@include font-weight($semibold);
color: var(--grayscale-dark);
letter-spacing: 0;
margin-bottom: 0;
@include breakpoint($narrow) {
letter-spacing: -0.3px;
}
@include breakpoint($fullhd) {
@include font-size(16px, 24px);
letter-spacing: 0;
}
}
.hy-person-card__info-container__position-title {
@include font-size(12px, 16px);
color: var(--grayscale-dark);
letter-spacing: -0.07px;
margin-bottom: 0;
}
.hy-person-card__image-container {
margin-right: 12px;
&__image {
height: 60px;
width: 60px;
img {
height: 60px;
width: 60px;
}
}
&__no-image {
height: 60px;
width: 60px;
&__initials {
color: var(--grayscale-white);
@include font-size(16px, 32px);
@include font-weight($bold);
letter-spacing: 0.48px;
}
}
}
}
}
import {Component, h, Prop} from '@stencil/core';
import {PersonCardVariants} from '../../utils/utils';
@Component({
tag: 'hy-person-card',
styleUrl: 'hy-person-card.scss',
shadow: false,
})
export class HyPersonCard {
@Prop() variant: PersonCardVariants = PersonCardVariants.default;
@Prop() categoryTitle?: string;
@Prop() imageUrl?: string;
@Prop() imageAlt?: string;
@Prop() firstName?: string;
@Prop() lastName?: string;
@Prop() url?: string;
@Prop() isExternal: boolean = false;
@Prop() scLabel?: string;
@Prop() positionTitle?: string;
@Prop() department?: string;
@Prop() field?: string;
@Prop() email?: string;
@Prop() phone?: string;
private _fullName: string;
private _initials: string;
componentWillLoad() {
this._fullName = this.firstName && this.lastName ? `${this.firstName} ${this.lastName}` : '';
this._initials =
this.imageUrl && this.firstName && this.lastName ? '' : `${this.firstName.charAt(0)}${this.lastName.charAt(0)}`;
if (!this.imageAlt) {
this.imageAlt = this._fullName;
}
if (!this.scLabel) {
this.scLabel = 'Link to the person profile';
}
}
render() {
const classLinkAttributes = ['hy-person-card-container__link', this.variant].join(' ');
const classAttributes = ['hy-person-card', this.variant].join(' ');
const target = this.isExternal ? '_blank' : '_self';
return (
<article class="hy-person-card-container">
<a class={classLinkAttributes} href={this.url} target={target} aria-label={this.scLabel}>
{this.categoryTitle && this.variant == PersonCardVariants.default && (
<div class="hy-person-card-container__category-title">{this.categoryTitle}</div>
)}
<div class={classAttributes}>
<div class="hy-person-card__image-container">
{this.imageUrl ? (
<div class="hy-person-card__image-container__image">
<img aria-hidden="true" src={this.imageUrl} alt={this.imageAlt} />
</div>
) : (
<div class="hy-person-card__image-container__no-image">
<div class="hy-person-card__image-container__no-image__initials">{this._initials}</div>
</div>
)}
</div>
<div class="hy-person-card__info-container">
<div class="hy-person-card__info-container__full-name">{this._fullName}</div>
{this.positionTitle && (
<div class="hy-person-card__info-container__position-title">{this.positionTitle}</div>
)}
{this.department && this.variant == PersonCardVariants.default && (
<div class="hy-person-card__info-container__department">{this.department}</div>
)}
{this.field && this.variant == PersonCardVariants.default && (
<div class="hy-person-card__info-container__field">{this.field}</div>
)}
{this.email &&
this.variant == PersonCardVariants.default && [
<div class="hy-person-card__info-container__email-container">
<span class="hy-person-card__info-container__email__icon">
<hy-icon icon={'hy-icon-email'} size={16} />
</span>
<span class="hy-person-card__info-container__email">{this.email}</span>
</div>,
]}
{this.phone &&
this.variant == PersonCardVariants.default && [
<div class="hy-person-card__info-container__phone-container">
<span class="hy-person-card__info-container__phone__icon">
<hy-icon icon={'hy-icon-phone'} size={14} />
</span>
<span class="hy-person-card__info-container__phone">{this.phone}</span>
</div>,
]}
</div>
</div>
</a>
</article>
);
}
}
# hy-person-card
<!-- Auto Generated Below -->
## Properties
| Property | Attribute | Description | Type | Default |
| --------------- | ---------------- | ----------- | -------------------------------------------------------------- | ---------------------------- |
| `categoryTitle` | `category-title` | | `string` | `undefined` |
| `department` | `department` | | `string` | `undefined` |
| `email` | `email` | | `string` | `undefined` |
| `field` | `field` | | `string` | `undefined` |
| `firstName` | `first-name` | | `string` | `undefined` |
| `imageAlt` | `image-alt` | | `string` | `undefined` |
| `imageUrl` | `image-url` | | `string` | `undefined` |
| `isExternal` | `is-external` | | `boolean` | `false` |
| `lastName` | `last-name` | | `string` | `undefined` |
| `phone` | `phone` | | `string` | `undefined` |
| `positionTitle` | `position-title` | | `string` | `undefined` |
| `scLabel` | `sc-label` | | `string` | `undefined` |
| `url` | `url` | | `string` | `undefined` |
| `variant` | `variant` | | `PersonCardVariants.default \| PersonCardVariants.searchPanel` | `PersonCardVariants.default` |
## Dependencies
### Depends on
- [hy-icon](../icon)
### Graph
```mermaid
graph TD;
hy-person-card --> hy-icon
style hy-person-card fill:#f9f,stroke:#333,stroke-width:4px
```
---
Helsinki University Design System
......@@ -16,9 +16,12 @@ const iconNames: IconName = {
'hy-icon-dot-arrow-right': (p) => <icons.DotArrowRight {...p} />,
'hy-icon-done': (p) => <icons.Done {...p} />,
'hy-icon-euro': (p) => <icons.Euro {...p} />,
'hy-icon-link': (p) => <icons.Url {...p} />,
'hy-icon-globe': (p) => <icons.Globe {...p} />,
'hy-icon-hamburger': (p) => <icons.Hamburger {...p} />,
'hy-icon-home': (p) => <icons.Home {...p} />,
'hy-icon-email': (p) => <icons.Mail {...p} />,
'hy-icon-phone': (p) => <icons.Phone {...p} />,
'hy-icon-hy-logo': (p) => <icons.HyLogo {...p} />,
'hy-icon-image-gallery': (p) => <icons.ImageGallery {...p} />,
'hy-icon-link-arrow-down': (p) => <icons.LinkArrowDown {...p} />,
......
......@@ -32,12 +32,15 @@
- [hy-footer-link-item](../footer/hy-footer-link-item)
- [hy-introduction](../hy-introduction)
- [hy-link-box](../link-box)
- [hy-list-item](../hy-list-item)
- [hy-menu-item](../navigation/menu-item)
- [hy-menu-item-sidebar](../navigation/menu-item-sidebar)
- [hy-menu-language](../navigation/menu-language)
- [hy-menu-level-container](../navigation/menu-level-container)
- [hy-menu-mobile-breadcrumb](../navigation/menu-mobile-breadcrumb)
- [hy-menu-sidebar](../navigation/menu-sidebar)
- [hy-pager-item](../pagination/hy-pager-item)
- [hy-person-card](../hy-person-card)
- [hy-quote](../hy-quote)
- [hy-search-field](../hy-search-field)
- [hy-shortcuts](../hy-shortcuts)
......@@ -69,12 +72,15 @@ graph TD;
hy-footer-link-item --> hy-icon
hy-introduction --> hy-icon
hy-link-box --> hy-icon
hy-list-item --> hy-icon
hy-menu-item --> hy-icon
hy-menu-item-sidebar --> hy-icon
hy-menu-language --> hy-icon
hy-menu-level-container --> hy-icon
hy-menu-mobile-breadcrumb --> hy-icon
hy-menu-sidebar --> hy-icon
hy-pager-item --> hy-icon
hy-person-card --> hy-icon
hy-quote --> hy-icon
hy-search-field --> hy-icon
hy-shortcuts --> hy-icon
......
......@@ -67,7 +67,7 @@
}
&.is-open,
&.active-trail-panel {
height: fit-content;
height: 100vh;
min-height: var(--minHeight);
}
}
......
......@@ -72,6 +72,7 @@
animation-name: sidepanel-movein;
display: flex;
height: auto;
min-height: 100vh;
width: 100%;
// Open sidenav panels. Set background color to non-active items
......
......@@ -86,26 +86,32 @@ export class MenuSidebar {
componentWillLoad() {
const sideBar = document.querySelector('.layout-sidebar-first');
if (this.menuIsOpen) {
sideBar.classList.add('menu-is-open');
} else if (sideBar.classList.contains('menu-is-open')) {
sideBar.classList.remove('menu-is-open');
if (sideBar) {
if (this.menuIsOpen) {
sideBar.classList.add('menu-is-open');
} else if (sideBar.classList.contains('menu-is-open')) {
sideBar.classList.remove('menu-is-open');
}
}
}
componentDidLoad() {
const sidebarContainer = document.querySelector('.hy-menu-sidebar--container');
sidebarContainer.addEventListener('click', (e) => {
if ((e.target as HTMLElement).classList.contains('sidebar-open')) {
this.closeWholeTree();
}
});
if (sidebarContainer) {
sidebarContainer.addEventListener('click', (e) => {
if ((e.target as HTMLElement).classList.contains('sidebar-open')) {
this.closeWholeTree();
}
});
}
const sidepanelContainer = document.querySelector('.hy-menu-sidepanel--container');
sidepanelContainer.addEventListener('click', (e) => {
if ((e.target as HTMLElement).classList.contains('sidepanel-open')) {
this.panelToggle(e);
}
});
if (sidepanelContainer) {
sidepanelContainer.addEventListener('click', (e) => {
if ((e.target as HTMLElement).classList.contains('sidepanel-open')) {
this.panelToggle(e);
}
});
}
const panels = document.querySelectorAll('.hy-menu-level-container');
if (panels) {
......
:host {
display: block;
}
.hy-pager__item {
@include font-size(14px, 24px);
@include font-weight($bold);
align-items: center;
background-color: var(--brand-main-light);
color: var(--grayscale-white);
display: flex;
flex-direction: row;
font-family: var(--main-font-family);
justify-content: center;
letter-spacing: -0.4px;
margin-bottom: 4px;
margin-right: 8px;
min-height: 36px;
min-width: 36px;
text-align: center;
@include breakpoint($wide) {
margin-right: 6px;
min-height: 40px;
min-width: 40px;
}
a {
@include font-size(14px, 24px);
@include font-weight($bold);
align-items: center;
color: var(--grayscale-white);
display: flex;
flex-direction: row;
justify-content: center;
letter-spacing: -0.4px;
min-height: 36px;
min-width: 36px;
text-decoration: none;
@include breakpoint($wide) {
@include font-size(16px, 24px);
letter-spacing: -0.5px;
min-height: 40px;
min-width: 40px;
}
}
&__current {
background-color: var(--grayscale-white);
box-sizing: border-box;
border: 2px solid var(--grayscale-black);
a {
color: var(--brand-main-nearly-black);
@include breakpoint($wide) {
@include font-size(18px, 24px);
letter-spacing: -0.56px;
}
}
}
&__next,
&__previous {
a {
padding: 7px 12px 5px 12px;
@include breakpoint($wide) {
padding: 8px 12px;
}
}
.hy-icon-wrapper {
margin: 0 4px;
@include breakpoint($wide) {
margin: 0 6px;
}
svg {
fill: var(--grayscale-white);
}
}
}
}
import {Component, h, Prop} from '@stencil/core';
import {PaginationItemVariants} from '../../../utils/utils';
@Component({
tag: 'hy-pager-item',
styleUrl: 'hy-pager-item.scss',
shadow: true,
})
export class HyPagerItem {
@Prop() variant: PaginationItemVariants = PaginationItemVariants.default;
@Prop() itemLabel?: string;
@Prop() itemUrl?: string;
@Prop() scAriaLabel?: string;
render() {
let classAttributes = ['hy-pager__item'].join(' ');
switch (this.variant) {
case PaginationItemVariants.current: {
classAttributes = ['hy-pager__item', 'hy-pager__item__current'].join(' ');
return (
<li class={classAttributes}>
<a href={this.itemUrl} aria-current="true">
{this.itemLabel}
</a>
</li>
);
}
case PaginationItemVariants.next: {
classAttributes = ['hy-pager__item', 'hy-pager__item__next'].join(' ');
const iconClassAttributes = ['link-icon'].join(' ');
return (
<li class={classAttributes}>
<a href={this.itemUrl} aria-label={this.scAriaLabel}>
{this.itemLabel}
<span class={'hy-icon-wrapper'}>
<div class={iconClassAttributes}>
<hy-icon icon={'hy-icon-arrow-to-right'} size={12} />
</div>
</span>
</a>
</li>
);
}
case PaginationItemVariants.previous: {
classAttributes = ['hy-pager__item', 'hy-pager__item__previous'].join(' ');
const iconClassAttributes = ['link-icon'].join(' ');
return (
<li class={classAttributes}>
<a href={this.itemUrl} aria-label={this.scAriaLabel}>
<span class={'hy-icon-wrapper'}>
<div class={iconClassAttributes}>
<hy-icon icon={'hy-icon-arrow-left'} size={12} />
</div>
</span>
{this.itemLabel}
</a>
</li>
);
}
case PaginationItemVariants.ellipsis: {
classAttributes = ['hy-pager__item', 'hy-pager__item__ellipsis'].join(' ');
return <li class={classAttributes}>...</li>;
}
default: {
classAttributes = ['hy-pager__item'].join(' ');
return (
<li class={classAttributes}>
<a href={this.itemUrl} aria-label={this.scAriaLabel}>
{this.itemLabel}
</a>
</li>
);
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment