diff --git a/src/components.d.ts b/src/components.d.ts index 9ef7f9f8ab2ab6299e9ac5eb23b42444a6b466e9..e3f7fb4a3c57cae77811cd701bc919f36d0af33a 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -5,11 +5,14 @@ * 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 { + BreadcrumbVariants, ButtonVariants, ColorVariant, CtaLinkButtonVariants, CtaLinkVariants, + FooterLinkItemColor, GridAlignVariants, GridColumns, GridColumnsLg, @@ -26,6 +29,8 @@ import { ProcessFlowBoxVariants, SiteLogoSize, } from './utils/utils'; +import {FooterBaseLinks, FooterBaseSome} from './components/footer/hy-footer-base/hy-footer-base'; +import {FooterInfoLinks} from './components/footer/hy-footer-info/hy-footer-info'; import {KeyFigureValue} from './components/hy-key-figure-group/hy-key-figure-group'; import {KeyHighlightValue} from './components/hy-key-highlight-group/hy-key-highlight-group'; import {ProcessFlowValue} from './components/hy-large-process-flow/hy-large-process-flow'; @@ -126,6 +131,11 @@ export namespace Components { */ wrap: boolean; } + interface HyBreadcrumbs { + dataItems: Breadcrumb[] | string; + headerstyle: string; + variant: BreadcrumbVariants; + } interface HyButton { /** * Aria label for the element @@ -187,6 +197,81 @@ export namespace Components { variant: CtaLinkVariants; } interface HyDocsContainer {} + interface HyFooter {} + interface HyFooterAction { + /** + * Up button label. + */ + upButtonLabel: string; + /** + * String of text for updated text to be displayed. + */ + updatedText: string; + } + interface HyFooterBase { + /** + * Link item color + */ + color: FooterLinkItemColor; + /** + * Copyright text + */ + copyrightText: string; + /** + * Footer links to be displayed + */ + dataFooterBaseLinks: FooterBaseLinks[] | string; + /** + * Footer some links + */ + dataFooterBaseSome: FooterBaseSome[] | string; + /** + * Logo label + */ + logoLabel?: string; + /** + * Logo url + */ + logoUrl?: string; + /** + * Logo size + */ + size: SiteLogoSize; + /** + * Label for some links + */ + someLabel?: string; + } + interface HyFooterInfo { + /** + * Data for links to be displayed. + */ + dataFooterInfoLinks: FooterInfoLinks[] | string; + /** + * Content area link button text. + */ + linkText: string; + /** + * Content area link button url. + */ + linkUrl: string; + /** + * Content area text. + */ + textDescription: string; + /** + * Content area title. + */ + textTitle: string; + } + interface HyFooterLinkItem { + color: FooterLinkItemColor; + isMobile: boolean; + items: Array<any>; + label: string; + mainLink: boolean; + url: string; + } interface HyGridContainer {} interface HyGridItem { columns: GridColumns; @@ -479,6 +564,11 @@ declare global { prototype: HTMLHyBoxContainerElement; new (): HTMLHyBoxContainerElement; }; + interface HTMLHyBreadcrumbsElement extends Components.HyBreadcrumbs, HTMLStencilElement {} + var HTMLHyBreadcrumbsElement: { + prototype: HTMLHyBreadcrumbsElement; + new (): HTMLHyBreadcrumbsElement; + }; interface HTMLHyButtonElement extends Components.HyButton, HTMLStencilElement {} var HTMLHyButtonElement: { prototype: HTMLHyButtonElement; @@ -499,6 +589,31 @@ declare global { prototype: HTMLHyDocsContainerElement; new (): HTMLHyDocsContainerElement; }; + interface HTMLHyFooterElement extends Components.HyFooter, HTMLStencilElement {} + var HTMLHyFooterElement: { + prototype: HTMLHyFooterElement; + new (): HTMLHyFooterElement; + }; + interface HTMLHyFooterActionElement extends Components.HyFooterAction, HTMLStencilElement {} + var HTMLHyFooterActionElement: { + prototype: HTMLHyFooterActionElement; + new (): HTMLHyFooterActionElement; + }; + interface HTMLHyFooterBaseElement extends Components.HyFooterBase, HTMLStencilElement {} + var HTMLHyFooterBaseElement: { + prototype: HTMLHyFooterBaseElement; + new (): HTMLHyFooterBaseElement; + }; + interface HTMLHyFooterInfoElement extends Components.HyFooterInfo, HTMLStencilElement {} + var HTMLHyFooterInfoElement: { + prototype: HTMLHyFooterInfoElement; + new (): HTMLHyFooterInfoElement; + }; + interface HTMLHyFooterLinkItemElement extends Components.HyFooterLinkItem, HTMLStencilElement {} + var HTMLHyFooterLinkItemElement: { + prototype: HTMLHyFooterLinkItemElement; + new (): HTMLHyFooterLinkItemElement; + }; interface HTMLHyGridContainerElement extends Components.HyGridContainer, HTMLStencilElement {} var HTMLHyGridContainerElement: { prototype: HTMLHyGridContainerElement; @@ -724,10 +839,16 @@ declare global { 'hy-baseline': HTMLHyBaselineElement; 'hy-box': HTMLHyBoxElement; 'hy-box-container': HTMLHyBoxContainerElement; + 'hy-breadcrumbs': HTMLHyBreadcrumbsElement; 'hy-button': HTMLHyButtonElement; 'hy-cta-button': HTMLHyCtaButtonElement; 'hy-cta-link': HTMLHyCtaLinkElement; 'hy-docs-container': HTMLHyDocsContainerElement; + 'hy-footer': HTMLHyFooterElement; + 'hy-footer-action': HTMLHyFooterActionElement; + 'hy-footer-base': HTMLHyFooterBaseElement; + 'hy-footer-info': HTMLHyFooterInfoElement; + 'hy-footer-link-item': HTMLHyFooterLinkItemElement; 'hy-grid-container': HTMLHyGridContainerElement; 'hy-grid-item': HTMLHyGridItemElement; 'hy-grid-row': HTMLHyGridRowElement; @@ -863,6 +984,11 @@ declare namespace LocalJSX { */ wrap?: boolean; } + interface HyBreadcrumbs { + dataItems?: Breadcrumb[] | string; + headerstyle?: string; + variant?: BreadcrumbVariants; + } interface HyButton { /** * Aria label for the element @@ -924,6 +1050,81 @@ declare namespace LocalJSX { variant?: CtaLinkVariants; } interface HyDocsContainer {} + interface HyFooter {} + interface HyFooterAction { + /** + * Up button label. + */ + upButtonLabel?: string; + /** + * String of text for updated text to be displayed. + */ + updatedText?: string; + } + interface HyFooterBase { + /** + * Link item color + */ + color?: FooterLinkItemColor; + /** + * Copyright text + */ + copyrightText?: string; + /** + * Footer links to be displayed + */ + dataFooterBaseLinks?: FooterBaseLinks[] | string; + /** + * Footer some links + */ + dataFooterBaseSome?: FooterBaseSome[] | string; + /** + * Logo label + */ + logoLabel?: string; + /** + * Logo url + */ + logoUrl?: string; + /** + * Logo size + */ + size?: SiteLogoSize; + /** + * Label for some links + */ + someLabel?: string; + } + interface HyFooterInfo { + /** + * Data for links to be displayed. + */ + dataFooterInfoLinks?: FooterInfoLinks[] | string; + /** + * Content area link button text. + */ + linkText?: string; + /** + * Content area link button url. + */ + linkUrl?: string; + /** + * Content area text. + */ + textDescription?: string; + /** + * Content area title. + */ + textTitle?: string; + } + interface HyFooterLinkItem { + color?: FooterLinkItemColor; + isMobile?: boolean; + items?: Array<any>; + label?: string; + mainLink?: boolean; + url?: string; + } interface HyGridContainer {} interface HyGridItem { columns?: GridColumns; @@ -1185,10 +1386,16 @@ declare namespace LocalJSX { 'hy-baseline': HyBaseline; 'hy-box': HyBox; 'hy-box-container': HyBoxContainer; + 'hy-breadcrumbs': HyBreadcrumbs; 'hy-button': HyButton; 'hy-cta-button': HyCtaButton; 'hy-cta-link': HyCtaLink; 'hy-docs-container': HyDocsContainer; + 'hy-footer': HyFooter; + 'hy-footer-action': HyFooterAction; + 'hy-footer-base': HyFooterBase; + 'hy-footer-info': HyFooterInfo; + 'hy-footer-link-item': HyFooterLinkItem; 'hy-grid-container': HyGridContainer; 'hy-grid-item': HyGridItem; 'hy-grid-row': HyGridRow; @@ -1247,10 +1454,16 @@ declare module '@stencil/core' { 'hy-baseline': LocalJSX.HyBaseline & JSXBase.HTMLAttributes<HTMLHyBaselineElement>; 'hy-box': LocalJSX.HyBox & JSXBase.HTMLAttributes<HTMLHyBoxElement>; 'hy-box-container': LocalJSX.HyBoxContainer & JSXBase.HTMLAttributes<HTMLHyBoxContainerElement>; + 'hy-breadcrumbs': LocalJSX.HyBreadcrumbs & JSXBase.HTMLAttributes<HTMLHyBreadcrumbsElement>; 'hy-button': LocalJSX.HyButton & JSXBase.HTMLAttributes<HTMLHyButtonElement>; 'hy-cta-button': LocalJSX.HyCtaButton & JSXBase.HTMLAttributes<HTMLHyCtaButtonElement>; 'hy-cta-link': LocalJSX.HyCtaLink & JSXBase.HTMLAttributes<HTMLHyCtaLinkElement>; 'hy-docs-container': LocalJSX.HyDocsContainer & JSXBase.HTMLAttributes<HTMLHyDocsContainerElement>; + 'hy-footer': LocalJSX.HyFooter & JSXBase.HTMLAttributes<HTMLHyFooterElement>; + 'hy-footer-action': LocalJSX.HyFooterAction & JSXBase.HTMLAttributes<HTMLHyFooterActionElement>; + 'hy-footer-base': LocalJSX.HyFooterBase & JSXBase.HTMLAttributes<HTMLHyFooterBaseElement>; + 'hy-footer-info': LocalJSX.HyFooterInfo & JSXBase.HTMLAttributes<HTMLHyFooterInfoElement>; + 'hy-footer-link-item': LocalJSX.HyFooterLinkItem & JSXBase.HTMLAttributes<HTMLHyFooterLinkItemElement>; 'hy-grid-container': LocalJSX.HyGridContainer & JSXBase.HTMLAttributes<HTMLHyGridContainerElement>; 'hy-grid-item': LocalJSX.HyGridItem & JSXBase.HTMLAttributes<HTMLHyGridItemElement>; 'hy-grid-row': LocalJSX.HyGridRow & JSXBase.HTMLAttributes<HTMLHyGridRowElement>; diff --git a/src/components/accordion-container/readme.md b/src/components/accordion-container/readme.md index 2ed09b1ef4d67ca1137baf0a8327e083e9c2168b..66dd13b69dd30df4e386a3ad5cd848c599f5ff36 100644 --- a/src/components/accordion-container/readme.md +++ b/src/components/accordion-container/readme.md @@ -10,6 +10,10 @@ ## Dependencies +### Used by + +- [hy-footer-info](../footer/hy-footer-info) + ### Depends on - [hy-box](../hy-box) @@ -19,6 +23,7 @@ ```mermaid graph TD; hy-accordion-container --> hy-box + hy-footer-info --> hy-accordion-container style hy-accordion-container fill:#f9f,stroke:#333,stroke-width:4px ``` diff --git a/src/components/accordion-item/readme.md b/src/components/accordion-item/readme.md index aaf6ca6a466479ea21453c679ba0583d7542b1e0..b54677a5131a7334b22b80209227401f6aa65180 100644 --- a/src/components/accordion-item/readme.md +++ b/src/components/accordion-item/readme.md @@ -45,6 +45,10 @@ Accordion component ## Dependencies +### Used by + +- [hy-footer-info](../footer/hy-footer-info) + ### Depends on - [hy-icon](../icon) @@ -56,6 +60,7 @@ Accordion component graph TD; hy-accordion-item --> hy-icon hy-accordion-item --> hy-box + hy-footer-info --> hy-accordion-item style hy-accordion-item fill:#f9f,stroke:#333,stroke-width:4px ``` diff --git a/src/components/button/readme.md b/src/components/button/readme.md index 7928b9cec4b2d92c2aef0fd67c6b1897b65d46f4..b8df5006ea713d7e44726237e33cfb78f453b40b 100644 --- a/src/components/button/readme.md +++ b/src/components/button/readme.md @@ -139,6 +139,10 @@ Well, it's a button. ## Dependencies +### Used by + +- [hy-footer-info](../footer/hy-footer-info) + ### Depends on - [hy-icon](../icon) @@ -148,6 +152,7 @@ Well, it's a button. ```mermaid graph TD; hy-button --> hy-icon + hy-footer-info --> hy-button style hy-button fill:#f9f,stroke:#333,stroke-width:4px ``` diff --git a/src/components/footer/hy-footer-action/hy-footer-action.scss b/src/components/footer/hy-footer-action/hy-footer-action.scss new file mode 100644 index 0000000000000000000000000000000000000000..a119d283caf0eebef187ce710a853301ac0a956b --- /dev/null +++ b/src/components/footer/hy-footer-action/hy-footer-action.scss @@ -0,0 +1,61 @@ +.hy-footer-action { + align-items: center; + border-top: 1px solid var(--grayscale-medium-dark); + display: flex; + flex-direction: row; + padding: 0 32px; + padding: 8px 16px 16px 16px; + place-content: center space-between; + width: 100%; + + @include breakpoint($medium) { + margin: 0 auto; + max-width: $fullhd; + padding: 16px 24px 16px 24px; + } + + @include breakpoint($wide) { + padding: 16px 32px 24px 32px; + } + + &__updated-text { + @include font-size(14px, 24px); + + color: var(--grayscale-dark); + font-family: var(--main-font-family); + letter-spacing: 0; + + @include breakpoint($medium) { + @include font-size(16px, 24px); + } + } + + &__scroll-up { + align-items: center; + display: flex; + + .hy-footer-action__up-button { + background-color: var(--brand-main-light); + border: 0; + box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.05); + padding: 8px; + + &:hover { + cursor: pointer; + } + } + + label { + @include font-size(16px, 24px); + + color: var(--grayscale-dark); + font-family: var(--main-font-family); + letter-spacing: 0; + margin-right: 8px; + } + + svg { + fill: var(--grayscale-white); + } + } +} diff --git a/src/components/footer/hy-footer-action/hy-footer-action.tsx b/src/components/footer/hy-footer-action/hy-footer-action.tsx new file mode 100644 index 0000000000000000000000000000000000000000..9d0a50e143cf89be3e98539c5ff72ff297ab5c0a --- /dev/null +++ b/src/components/footer/hy-footer-action/hy-footer-action.tsx @@ -0,0 +1,39 @@ +import {Component, Host, Prop, Listen, h} from '@stencil/core'; + +@Component({ + tag: 'hy-footer-action', + styleUrl: 'hy-footer-action.scss', + shadow: false, +}) +export class HyFooterAction { + /** + * String of text for updated text to be displayed. + */ + @Prop() updatedText: string; + /** + * Up button label. + */ + @Prop() upButtonLabel: string; + + @Listen('scrollTop', {capture: true}) scrollTop() { + window.scrollTo({top: 0, behavior: 'smooth'}); + } + + render() { + const classAttributes = ['hy-footer-action'].join(' '); + + return ( + <Host class={classAttributes}> + <span class={'hy-footer-action__updated-text'}>{this.updatedText}</span> + {this.upButtonLabel && ( + <span class="hy-footer-action__scroll-up"> + <label htmlFor="scroll-up">{this.upButtonLabel}</label> + <button name="scroll-up" onClick={() => this.scrollTop()} class="hy-footer-action__up-button" type="button"> + <hy-icon class={'hy-footer-action__up-icon'} icon={'hy-icon-arrow-up'} size={26} /> + </button> + </span> + )} + </Host> + ); + } +} diff --git a/src/components/footer/hy-footer-action/readme.md b/src/components/footer/hy-footer-action/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..5478e63efdbeeaff01bab189d7156d4177290dc9 --- /dev/null +++ b/src/components/footer/hy-footer-action/readme.md @@ -0,0 +1,28 @@ +# hy-footer-action + +<!-- Auto Generated Below --> + +## Properties + +| Property | Attribute | Description | Type | Default | +| --------------- | ----------------- | ------------------------------------------------ | -------- | ----------- | +| `upButtonLabel` | `up-button-label` | Up button label. | `string` | `undefined` | +| `updatedText` | `updated-text` | String of text for updated text to be displayed. | `string` | `undefined` | + +## Dependencies + +### Depends on + +- [hy-icon](../../icon) + +### Graph + +```mermaid +graph TD; + hy-footer-action --> hy-icon + style hy-footer-action fill:#f9f,stroke:#333,stroke-width:4px +``` + +--- + +Helsinki University Design System diff --git a/src/components/footer/hy-footer-base/hy-footer-base.scss b/src/components/footer/hy-footer-base/hy-footer-base.scss new file mode 100644 index 0000000000000000000000000000000000000000..98333e15c785978109dd4baf16dd93587c727882 --- /dev/null +++ b/src/components/footer/hy-footer-base/hy-footer-base.scss @@ -0,0 +1,187 @@ +.hy-footer-base--content-container { + background-color: var(--grayscale-black); + display: block; + max-width: 100%; +} + +.hy-footer-base { + background-color: var(--grayscale-black); + display: flex; + flex-direction: column-reverse; + max-height: 100%; + padding: 32px 24px 32px 24px; + place-content: center space-between; + position: relative; + width: 100%; + + @include breakpoint($medium) { + flex-direction: column-reverse; + margin: 0 auto; + max-width: $fullhd; + padding: 32px 24px 32px 24px; + } + + @include breakpoint($wide) { + flex-direction: row; + padding: 36px 32px 36px 32px; + } + + @include breakpoint($extrawide) { + padding: 40px 32px 40px 32px; + } + + &__left { + align-items: center; + display: flex; + flex-direction: column; + justify-content: space-between; + margin-top: 24px; + + @include breakpoint($medium) { + align-items: center; + width: 100%; + } + + @include breakpoint($wide) { + align-items: flex-start; + width: 31.11%; + } + } + + &__logo { + @include font-size(18px, 16px); + + font-family: var(--main-font-family); + font-weight: bold; + letter-spacing: -0.9px; + } + + &__content { + @include font-size(16px, 24px); + + color: var(--grayscale-white); + font-family: var(--main-font-family); + font-weight: 600; + letter-spacing: -0.1px; + margin: 32px 0; + white-space: pre-line; + + @include breakpoint($medium) { + margin: 32px 0; + } + + @include breakpoint($wide) { + margin: 42px 0; + } + + @include breakpoint($extrawide) { + margin: 54px 0; + } + } + + &__some { + align-items: center; + display: flex; + flex-direction: column; + justify-content: center; + margin-bottom: 64px; + z-index: 2; + + @include breakpoint($wide) { + align-items: flex-start; + flex-direction: column; + margin-bottom: 0; + } + + @include breakpoint($extrawide) { + align-items: center; + flex-direction: row; + } + + &__label { + @include font-size(16px, 24px); + + color: var(--grayscale-white); + font-family: var(--main-font-family); + font-weight: 600; + letter-spacing: -0.1px; + margin-bottom: 8px; + margin-right: 24px; + + @include breakpoint($wide) { + margin-bottom: 8px; + } + } + + &__items { + align-items: center; + display: flex; + flex-direction: row; + } + + &__item { + margin-right: 24px; + + :last-child() { + margin-right: 0; + } + } + + svg { + fill: var(--grayscale-white); + } + } + + &__right { + display: flex; + flex-direction: column; + flex-wrap: wrap; + justify-content: flex-start; + max-height: 100%; + width: 100%; + + @include breakpoint($medium) { + margin-bottom: 32px; + max-height: 300px; + width: calc(100% + 24px); + } + + @include breakpoint($wide) { + max-height: 350px; + width: 65.56%; + } + } + + &__copy { + @include font-size(16px, 24px); + + bottom: 40px; + color: var(--grayscale-white); + display: inline-block; + font-family: var(--main-font-family); + font-weight: 600; + letter-spacing: -0.1px; + position: absolute; + right: 50%; + text-align: center; + transform: translateX(50%); + width: 100%; + + @include breakpoint($medium) { + bottom: 32px; + right: 50%; + transform: translateX(50%); + } + + @include breakpoint($wide) { + bottom: 36px; + right: 32px; + text-align: right; + transform: none; + } + + @include breakpoint($extrawide) { + bottom: 40px; + } + } +} diff --git a/src/components/footer/hy-footer-base/hy-footer-base.tsx b/src/components/footer/hy-footer-base/hy-footer-base.tsx new file mode 100644 index 0000000000000000000000000000000000000000..32e87f6914248c868daa73458c1c52994bed4617 --- /dev/null +++ b/src/components/footer/hy-footer-base/hy-footer-base.tsx @@ -0,0 +1,119 @@ +export interface FooterBaseLinks { + label: string; + url: string; + isActive?: boolean; + mainlink?: boolean; + items: Array<FooterBaseLinks>; +} + +export interface FooterBaseSome { + label: string; + url: string; + type: string; +} + +import {Component, ComponentInterface, Watch, Host, Prop, h} from '@stencil/core'; +import {FooterLinkItemColor, SiteLogoSize, ColorVariant} from '../../../utils/utils'; + +@Component({ + tag: 'hy-footer-base', + styleUrl: 'hy-footer-base.scss', + shadow: false, +}) +export class HyFooterBase implements ComponentInterface { + /** + * Link item color + */ + @Prop() color: FooterLinkItemColor = FooterLinkItemColor.white; + /** + * Logo url + */ + @Prop() logoUrl?: string; + /** + * Logo label + */ + @Prop() logoLabel?: string; + /** + * Logo size + */ + @Prop() size: SiteLogoSize = SiteLogoSize.big; + /** + * Label for some links + */ + @Prop() someLabel?: string; + /** + * Copyright text + */ + @Prop() copyrightText: string; + + private _dataFooterBaseLinks: FooterBaseLinks[]; + private _dataFooterBaseSome: FooterBaseSome[]; + /** + * Footer links to be displayed + */ + @Prop() dataFooterBaseLinks: FooterBaseLinks[] | string; + /** + * Footer some links + */ + @Prop() dataFooterBaseSome: FooterBaseSome[] | string; + + @Watch('dataFooterBaseLinks') dataFooterBaseLinksWatcher(data: FooterBaseLinks[] | string) { + this._dataFooterBaseLinks = typeof data === 'string' ? JSON.parse(data) : data; + } + + @Watch('dataFooterBaseSome') dataFooterBaseSomeWatcher(data: FooterBaseSome[] | string) { + this._dataFooterBaseSome = typeof data === 'string' ? JSON.parse(data) : data; + } + componentWillLoad() { + this.dataFooterBaseLinksWatcher(this.dataFooterBaseLinks); + this.dataFooterBaseSomeWatcher(this.dataFooterBaseSome); + } + + render() { + const logoColor = ColorVariant.white; + const classAttributes = ['hy-footer-base--content-container'].join(' '); + const links = this._dataFooterBaseLinks as Array<FooterBaseLinks>; + const some = this._dataFooterBaseSome as Array<FooterBaseSome>; + + return ( + <Host class={classAttributes}> + <div class="hy-footer-base"> + <div class="hy-footer-base__left"> + <div class="hy-footer-base__logo"> + <hy-site-logo size={56} color={logoColor} url={this.logoUrl} label={this.logoLabel} /> + </div> + <div class="hy-footer-base__content"> + <slot name="content"></slot> + </div> + <div class="hy-footer-base__some"> + <span class="hy-footer-base__some__label">{this.someLabel}</span> + <div class="hy-footer-base__some__items"> + {some && + some.map((s) => { + return ( + <a href={s.url} class={`hy-footer-base__some__item`} title={s.label} aria-label={s.label}> + <hy-icon icon={`hy-icon-some-${s.type}`} size={36} /> + </a> + ); + })} + </div> + </div> + </div> + <div class="hy-footer-base__right"> + {links && + links.map((link) => { + return ( + <hy-footer-link-item + label={link.label} + url={link.url} + color={FooterLinkItemColor.white} + ></hy-footer-link-item> + ); + })} + {this.copyrightText && <span class="hy-footer-base__copy">{this.copyrightText}</span>} + </div> + </div> + </Host> + ); + } +} diff --git a/src/components/footer/hy-footer-base/readme.md b/src/components/footer/hy-footer-base/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..61d750b7c7c19c82ad3476affe0ae0e7b63addf3 --- /dev/null +++ b/src/components/footer/hy-footer-base/readme.md @@ -0,0 +1,41 @@ +# hy-footer-base + +<!-- Auto Generated Below --> + +## Properties + +| Property | Attribute | Description | Type | Default | +| --------------------- | ------------------------ | ---------------------------- | -------------------------------------------------------------- | --------------------------- | +| `color` | `color` | Link item color | `FooterLinkItemColor.black \| FooterLinkItemColor.white` | `FooterLinkItemColor.white` | +| `copyrightText` | `copyright-text` | Copyright text | `string` | `undefined` | +| `dataFooterBaseLinks` | `data-footer-base-links` | Footer links to be displayed | `FooterBaseLinks[] \| string` | `undefined` | +| `dataFooterBaseSome` | `data-footer-base-some` | Footer some links | `FooterBaseSome[] \| string` | `undefined` | +| `logoLabel` | `logo-label` | Logo label | `string` | `undefined` | +| `logoUrl` | `logo-url` | Logo url | `string` | `undefined` | +| `size` | `size` | Logo size | `SiteLogoSize.big \| SiteLogoSize.large \| SiteLogoSize.small` | `SiteLogoSize.big` | +| `someLabel` | `some-label` | Label for some links | `string` | `undefined` | + +## Dependencies + +### Depends on + +- [hy-site-logo](../../site-header/site-logo) +- [hy-icon](../../icon) +- [hy-footer-link-item](../hy-footer-link-item) + +### Graph + +```mermaid +graph TD; + hy-footer-base --> hy-site-logo + hy-footer-base --> hy-icon + hy-footer-base --> hy-footer-link-item + hy-site-logo --> hy-icon + hy-footer-link-item --> hy-icon + hy-footer-link-item --> hy-heading + style hy-footer-base fill:#f9f,stroke:#333,stroke-width:4px +``` + +--- + +Helsinki University Design System diff --git a/src/components/footer/hy-footer-info/hy-footer-info.scss b/src/components/footer/hy-footer-info/hy-footer-info.scss new file mode 100644 index 0000000000000000000000000000000000000000..efd37e28125ea612149a51dbdf6c666ed9bb3cb6 --- /dev/null +++ b/src/components/footer/hy-footer-info/hy-footer-info.scss @@ -0,0 +1,82 @@ +:host { + display: block; +} + +.hy-footer-info { + display: flex; + flex-direction: column; + max-height: auto; + padding: 0 24px 40px 24px; + place-content: center space-between; + + @include breakpoint($medium) { + flex-direction: column; + margin: 0 auto; + max-width: $fullhd; + padding: 0 24px 32px 24px; + } + + @include breakpoint($wide) { + flex-direction: row; + padding: 0 32px 36px 32px; + } + + @include breakpoint($extrawide) { + padding: 0 32px 40px 32px; + } + + &__content { + margin-bottom: 24px; + width: 100%; + + @include breakpoint($medium) { + margin-bottom: 32px; + width: 100%; + } + + @include breakpoint($wide) { + width: 31.11%; + } + + .hy-heading { + padding-top: 0 !important; + } + } + + &__ingress { + @include font-size(20px, 32px); + + color: var(--grayscale-black); + font-family: var(--main-font-family); + font-weight: 600; + letter-spacing: -0.1px; + padding-bottom: 24px; + + @include breakpoint($wide) { + padding-bottom: 16px; + } + + @include breakpoint($extrawide) { + padding-bottom: 24px; + } + } + + &__links { + display: flex; + flex-direction: column; + flex-wrap: wrap; + max-height: auto; + overflow: hidden; + width: 100%; + + @include breakpoint($medium) { + max-height: 430px; + width: 100%; + } + + @include breakpoint($wide) { + max-height: 430px; + width: 65.56%; + } + } +} diff --git a/src/components/footer/hy-footer-info/hy-footer-info.tsx b/src/components/footer/hy-footer-info/hy-footer-info.tsx new file mode 100644 index 0000000000000000000000000000000000000000..d11b9484fa2be6453e91a51b412640374b8203b5 --- /dev/null +++ b/src/components/footer/hy-footer-info/hy-footer-info.tsx @@ -0,0 +1,124 @@ +export interface FooterInfoLinks { + label: string; + url: string; + isActive?: boolean; + mainlink?: boolean; + items: Array<FooterInfoLinks>; +} + +import {Component, ComponentInterface, Element, Watch, Host, State, Prop, h} from '@stencil/core'; +import ResizeObserver from 'resize-observer-polyfill'; +import {HeadingVarians, FooterLinkItemColor} from '../../../utils/utils'; + +@Component({ + tag: 'hy-footer-info', + styleUrl: 'hy-footer-info.scss', + shadow: false, +}) +export class HyFooterInfo implements ComponentInterface { + @Element() el: HTMLElement; + /** + * Content area title. + */ + @Prop() textTitle: string; + /** + * Content area text. + */ + @Prop() textDescription: string; + /** + * Content area link button text. + */ + @Prop() linkText: string; + /** + * Content area link button url. + */ + @Prop() linkUrl: string; + @State() isMobile: boolean; + + private ro: ResizeObserver; + private _dataFooterInfoLinks: FooterInfoLinks[]; + /** + * Data for links to be displayed. + */ + @Prop() dataFooterInfoLinks: FooterInfoLinks[] | string; + + @Watch('dataFooterInfoLinks') dataFooterInfoLinksWatcher(data: FooterInfoLinks[] | string) { + this._dataFooterInfoLinks = typeof data === 'string' ? JSON.parse(data) : data; + } + componentWillLoad() { + this.dataFooterInfoLinksWatcher(this.dataFooterInfoLinks); + } + + componentDidLoad() { + this.ro = new ResizeObserver((entries) => { + for (const entry of entries) { + this.checkForMobile(entry.contentRect.width); + } + }); + this.ro.observe(document.body); + } + + componentDidUnload() { + this.ro.disconnect(); + } + + checkForMobile(size: number) { + this.isMobile = size <= 479 ? true : false; + } + + render() { + const classAttributes = ['hy-footer-info'].join(' '); + const links = this._dataFooterInfoLinks as Array<FooterInfoLinks>; + + return ( + <Host class={classAttributes}> + <div class="hy-footer-info__content"> + <hy-heading heading={HeadingVarians.h2}>{this.textTitle}</hy-heading> + <div class="hy-footer-info__ingress">{this.textDescription}</div> + {this.linkUrl && ( + <hy-button variant="secondary" icon-right="hy-icon-arrow-right" url={this.linkUrl} size={'large'}> + {this.linkText} + </hy-button> + )} + </div> + {this.isMobile ? ( + <div class="hy-footer-info__links"> + <hy-accordion-container accordionid={'test'}> + {links && + links.map((link) => { + return ( + <hy-accordion-item accordiontitle={link.label}> + <hy-footer-link-item + color={FooterLinkItemColor.black} + label={link.label} + url={link.url} + main-link={link.mainlink} + items={link.items} + isMobile={this.isMobile} + ></hy-footer-link-item> + </hy-accordion-item> + ); + })} + </hy-accordion-container> + </div> + ) : ( + <div class="hy-footer-info__links"> + {links && + links.map((link) => { + return ( + <hy-footer-link-item + color={FooterLinkItemColor.black} + label={link.label} + url={link.url} + main-link={link.mainlink} + items={link.items} + isMobile={this.isMobile} + ></hy-footer-link-item> + ); + })} + </div> + )} + </Host> + ); + } +} diff --git a/src/components/footer/hy-footer-info/readme.md b/src/components/footer/hy-footer-info/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..ac2d06a47eb336d9cf3a44e0420421ab2300841e --- /dev/null +++ b/src/components/footer/hy-footer-info/readme.md @@ -0,0 +1,45 @@ +# hy-footer-info + +<!-- Auto Generated Below --> + +## Properties + +| Property | Attribute | Description | Type | Default | +| --------------------- | ------------------------ | ------------------------------- | ----------------------------- | ----------- | +| `dataFooterInfoLinks` | `data-footer-info-links` | Data for links to be displayed. | `FooterInfoLinks[] \| string` | `undefined` | +| `linkText` | `link-text` | Content area link button text. | `string` | `undefined` | +| `linkUrl` | `link-url` | Content area link button url. | `string` | `undefined` | +| `textDescription` | `text-description` | Content area text. | `string` | `undefined` | +| `textTitle` | `text-title` | Content area title. | `string` | `undefined` | + +## Dependencies + +### Depends on + +- [hy-heading](../../heading) +- [hy-button](../../button) +- [hy-accordion-container](../../accordion-container) +- [hy-accordion-item](../../accordion-item) +- [hy-footer-link-item](../hy-footer-link-item) + +### Graph + +```mermaid +graph TD; + hy-footer-info --> hy-heading + hy-footer-info --> hy-button + hy-footer-info --> hy-accordion-container + hy-footer-info --> hy-accordion-item + hy-footer-info --> hy-footer-link-item + hy-button --> hy-icon + hy-accordion-container --> hy-box + hy-accordion-item --> hy-icon + hy-accordion-item --> hy-box + hy-footer-link-item --> hy-icon + hy-footer-link-item --> hy-heading + style hy-footer-info fill:#f9f,stroke:#333,stroke-width:4px +``` + +--- + +Helsinki University Design System diff --git a/src/components/footer/hy-footer-link-item/hy-footer-link-item.scss b/src/components/footer/hy-footer-link-item/hy-footer-link-item.scss new file mode 100644 index 0000000000000000000000000000000000000000..cb33bb5e78d4d5bb0a8da791333bbba9ef36ec3c --- /dev/null +++ b/src/components/footer/hy-footer-link-item/hy-footer-link-item.scss @@ -0,0 +1,87 @@ +:host { + display: block; +} + +hy-footer-link-item { + width: 100%; + + @include breakpoint($medium) { + width: 50%; + } +} + +.hy-footer-link-item--container { + display: flex; + flex-direction: column; + + .hy-footer-link-item:last-child { + margin-bottom: 14px; + } +} + +.hy-footer-link-item { + @include font-size(14px, 16px); + + display: flex; + font-family: var(--main-font-family); + font-weight: 600; + letter-spacing: -0.44px; + margin-left: 0; + margin-right: 0; + padding: 15px 20px 15px 0; + position: relative; + text-decoration: none; + + @include breakpoint($medium) { + margin-left: 0px; + margin-right: 24px; + padding: 15px 20px 15px 0; + } + + @include breakpoint($wide) { + margin-left: 32px; + margin-right: 0; + padding: 15px 20px 15px 0; + } + + &__color-white { + border-bottom: 1px solid var(--grayscale-white); + color: var(--grayscale-white); + + .hy-footer-link-item__icon svg { + fill: var(--grayscale-white); + } + } + + &__color-black { + border-bottom: 1px solid var(--grayscale-medium); + color: var(--grayscale-nearly-black); + + .hy-footer-link-item__icon svg { + fill: var(--grayscale-black); + } + } + + &__main { + border: 0; + padding: 0; + margin-right: -32px; + + .hy-heading__container > h3.hy-heading { + padding: 0 0 1px 0 !important; + + .hy-footer-link-item__link { + color: var(--grayscale-nearly-black); + font-family: var(--main-font-family); + text-decoration: none; + } + } + } + + &__icon { + position: absolute; + right: 0; + top: 50%; + transform: translateY(-50%); + } +} diff --git a/src/components/footer/hy-footer-link-item/hy-footer-link-item.tsx b/src/components/footer/hy-footer-link-item/hy-footer-link-item.tsx new file mode 100644 index 0000000000000000000000000000000000000000..8108c7ad82ecf77a3b2409daa5aba4b2be9faf16 --- /dev/null +++ b/src/components/footer/hy-footer-link-item/hy-footer-link-item.tsx @@ -0,0 +1,78 @@ +import {Component, Prop, h} from '@stencil/core'; +import {HeadingVarians, FooterLinkItemColor} from '../../../utils/utils'; + +@Component({ + tag: 'hy-footer-link-item', + styleUrl: 'hy-footer-link-item.scss', + shadow: false, +}) +export class HyFooterLinkItem { + @Prop() label: string; + @Prop() url: string; + @Prop() mainLink: boolean = false; + @Prop() items: Array<any>; + @Prop() color: FooterLinkItemColor = FooterLinkItemColor.black; + @Prop() isMobile: boolean; + + render() { + const containerClassAttributes = [ + 'hy-footer-link-item--container', + this.items && 'hy-footer-link-item__has-children', + ].join(' '); + const classAttributes = [ + 'hy-footer-link-item', + this.mainLink && 'hy-footer-link-item__main', + `hy-footer-link-item__color-${this.color}`, + ].join(' '); + + if (this.items) { + if (this.isMobile) { + return ( + <div class={containerClassAttributes}> + {this.items.map((item) => { + return ( + <a + class={`hy-footer-link-item hy-footer-link-item__color-${this.color}`} + href={item.url} + style={{color: this.color}} + > + {item.label} + <hy-icon class={'hy-footer-link-item__icon'} icon={'hy-icon-arrow-right'} size={16} /> + </a> + ); + })} + </div> + ); + } else { + return ( + <div class={containerClassAttributes}> + <hy-heading class={classAttributes} heading={HeadingVarians.h3}> + <a class={'hy-footer-link-item__link'} href={this.url} style={{color: this.color}}> + {this.label} + </a> + </hy-heading> + {this.items.map((item) => { + return ( + <a + class={`hy-footer-link-item hy-footer-link-item__color-${this.color}`} + href={item.url} + style={{color: this.color}} + > + {item.label} + <hy-icon class={'hy-footer-link-item__icon'} icon={'hy-icon-arrow-right'} size={16} /> + </a> + ); + })} + </div> + ); + } + } else { + return ( + <a class={classAttributes} href={this.url} style={{color: this.color}}> + {this.label} + <hy-icon class={'hy-footer-link-item__icon'} icon={'hy-icon-arrow-right'} size={16} /> + </a> + ); + } + } +} diff --git a/src/components/footer/hy-footer-link-item/readme.md b/src/components/footer/hy-footer-link-item/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..4b1177f9c8d2aab48e762b594b31445c53610226 --- /dev/null +++ b/src/components/footer/hy-footer-link-item/readme.md @@ -0,0 +1,41 @@ +# hy-footer-link-item + +<!-- Auto Generated Below --> + +## Properties + +| Property | Attribute | Description | Type | Default | +| ---------- | ----------- | ----------- | -------------------------------------------------------- | --------------------------- | +| `color` | `color` | | `FooterLinkItemColor.black \| FooterLinkItemColor.white` | `FooterLinkItemColor.black` | +| `isMobile` | `is-mobile` | | `boolean` | `undefined` | +| `items` | -- | | `any[]` | `undefined` | +| `label` | `label` | | `string` | `undefined` | +| `mainLink` | `main-link` | | `boolean` | `false` | +| `url` | `url` | | `string` | `undefined` | + +## Dependencies + +### Used by + +- [hy-footer-base](../hy-footer-base) +- [hy-footer-info](../hy-footer-info) + +### Depends on + +- [hy-icon](../../icon) +- [hy-heading](../../heading) + +### Graph + +```mermaid +graph TD; + hy-footer-link-item --> hy-icon + hy-footer-link-item --> hy-heading + hy-footer-base --> hy-footer-link-item + hy-footer-info --> hy-footer-link-item + style hy-footer-link-item fill:#f9f,stroke:#333,stroke-width:4px +``` + +--- + +Helsinki University Design System diff --git a/src/components/footer/hy-footer/hy-footer.scss b/src/components/footer/hy-footer/hy-footer.scss new file mode 100644 index 0000000000000000000000000000000000000000..0c5bac0e8692263cd1505b086d5a727fbe0ffb3c --- /dev/null +++ b/src/components/footer/hy-footer/hy-footer.scss @@ -0,0 +1,3 @@ +.hy-footer { + display: block; +} diff --git a/src/components/footer/hy-footer/hy-footer.tsx b/src/components/footer/hy-footer/hy-footer.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0cc95a05000edff708ccaa096a2b0f9970f2dafe --- /dev/null +++ b/src/components/footer/hy-footer/hy-footer.tsx @@ -0,0 +1,18 @@ +import {Component, h} from '@stencil/core'; + +@Component({ + tag: 'hy-footer', + styleUrl: 'hy-footer.scss', + shadow: false, +}) +export class HyFooter { + render() { + const classAttributes = ['hy-footer']; + + return ( + <footer class={classAttributes.join(' ')}> + <slot></slot> + </footer> + ); + } +} diff --git a/src/components/footer/hy-footer/readme.md b/src/components/footer/hy-footer/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..92ac392b1fa9a4b0cf3bd2cdc4f00986877c2f8a --- /dev/null +++ b/src/components/footer/hy-footer/readme.md @@ -0,0 +1,7 @@ +# hy-footer + +<!-- Auto Generated Below --> + +--- + +Helsinki University Design System diff --git a/src/components/heading/readme.md b/src/components/heading/readme.md index 5fcc3fc6515a35814250d99cb908b26090e2d56c..e02907796fa7ceb404ea60a4123de3a376c3315f 100644 --- a/src/components/heading/readme.md +++ b/src/components/heading/readme.md @@ -98,6 +98,8 @@ Provide heading attribute for the component to choose what type of heading to us ### Used by +- [hy-footer-info](../footer/hy-footer-info) +- [hy-footer-link-item](../footer/hy-footer-link-item) - [hy-hero](../hy-hero) - [hy-introduction](../hy-introduction) - [hy-large-process-flow](../hy-large-process-flow) @@ -107,6 +109,8 @@ Provide heading attribute for the component to choose what type of heading to us ```mermaid graph TD; + hy-footer-info --> hy-heading + hy-footer-link-item --> hy-heading hy-hero --> hy-heading hy-introduction --> hy-heading hy-large-process-flow --> hy-heading diff --git a/src/components/hy-breadcrumbs/hy-breadcrumbs.scss b/src/components/hy-breadcrumbs/hy-breadcrumbs.scss new file mode 100644 index 0000000000000000000000000000000000000000..6c539421b4c65645055fb6b41e374c600d7adada --- /dev/null +++ b/src/components/hy-breadcrumbs/hy-breadcrumbs.scss @@ -0,0 +1,304 @@ +:host { + display: block; +} + +// Default variant +.hy-breadcrumbs { + display: inline-block; + width: auto; + + &.is-condensed { + width: 100%; + } + + ol { + margin: 0; + padding: 0; + } + + .breadcrumb-container { + color: var(--grayscale-dark); + display: flex; + flex-wrap: nowrap; + font-family: var(--main-font-family); + list-style-type: none; + margin: 0; + min-height: 72px; + overflow: hidden; + padding: 0; + + @include breakpoint($narrow) { + min-height: 76px; + } + @include breakpoint($wide) { + min-height: 86px; + } + @include breakpoint($extrawide) { + min-height: 94px; + } + } + + .breadcrumb-item { + display: flex; + flex-direction: row; + align-items: center; + flex: 0 0 auto; + + a { + color: var(--brand-main-light); + display: flex; + flex-direction: row; + align-items: center; + margin-right: 20px; + position: relative; + text-decoration: none; + + @include breakpoint($medium) { + margin-right: 28px; + } + + @include breakpoint($wide) { + margin-right: 30px; + } + + .breadcrumb-item-caret { + position: absolute; + right: -15px; + top: 50%; + transform: translateY(-50%); + + @include breakpoint($medium) { + right: -18px; + } + + @include breakpoint($wide) { + right: -19px; + } + + &:hover { + cursor: default; + } + } + } + + a.default { + @include font-size(14px, 20px); + + @include breakpoint($narrow) { + @include font-size(16px, 24px); + } + } + + &:focus { + outline: auto; + } + + &.hidden { + display: none; + } + } + + .breadcrumb-item.home { + hy-icon.default { + svg { + fill: var(--brand-main-light); + stroke: var(--brand-main-light); + } + } + } + + .breadcrumb-item.main { + min-width: 0; + } + + .breadcrumb-item__more { + display: none; + flex-direction: row; + align-items: center; + position: relative; + margin-right: 20px; + + @include breakpoint($medium) { + margin-right: 25px; + } + + @include breakpoint($wide) { + margin-right: 30px; + } + + &.visible { + display: flex; + } + + .breadcrumb-item-caret { + position: absolute; + right: -15px; + top: 50%; + transform: translateY(-50%); + + @include breakpoint($medium) { + right: -18px; + } + + &:hover { + cursor: default; + } + + &__drop { + position: absolute; + right: 5.5px; + top: 50%; + transform: translateY(-50%); + } + } + } + + .breadcrumb-item-dropdown-button { + display: flex; + flex-direction: row; + color: var(--brand-main-light); + cursor: pointer; + border: 1.5px solid var(--brand-main-light); + font-size: 1.5rem; + line-height: 10px; + border-radius: 3px; + background-color: var(--grayscale-white); + box-shadow: 0 0 10px 0 rgba(14, 104, 139, 0.1); + padding: 0 25px 9px 10px; + position: relative; + + hy-icon { + svg { + fill: var(--brand-main-light); + margin: 0 0 -3px 10px; + transform: rotate(90deg); + } + } + } + + .breadcrumb-item-dropdown-button.is-open { + background-color: var(--brand-main-light); + color: var(--grayscale-white); + + svg { + fill: var(--grayscale-white); + margin: 0 0 -3px 10px; + transform: rotate(270deg); + } + } + + .breadcrumb-hidden-items { + display: none; + visibility: hidden; + + &__is-open { + background: var(--grayscale-white); + box-shadow: 0 0 10px 0 rgba(14, 104, 139, 0.1); + display: block; + margin-top: -9px; + padding: 32px 16px 6px 16px; + position: absolute; + visibility: visible; + z-index: 5; + + @include breakpoint($narrow) { + padding: 32px 64px 6px 32px; + } + + a { + margin: 0; + padding-bottom: 26px; + } + } + } + + .breadcrumb-item__current { + flex: 0 2 auto; + min-width: 0; + } + + .breadcrumb-item__current a { + color: var(--grayscale-dark); + font-family: var(--main-font-family); + text-decoration: none; + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + min-height: auto; + + &:hover { + cursor: default; + } + } + + .intermediate { + display: flex; + text-overflow: initial; + } + + .intermediate.hidden { + display: none; + visibility: hidden; + } + + #more, + .more { + display: none; + visibility: hidden; + } + #more.visible, + .more.visible { + display: flex; + visibility: visible; + } +} + +// Large variant. Do not show Breadcrumbs if there is a hero and a sidebar on Large/Medium screens +.hy-breadcrumbs.large.with-sidebar { + display: block; + visibility: visible; + + a.large { + @include font-size(26px, 26px); + color: var(--grayscale-black); + font-weight: 700; + + //@todo change home icon to be 20px x 20px and be as in the specs + + .breadcrumb-item-caret { + // @todo set styles for caret near the home icon + // should be bold + // padding: 0 6px 0 8px; (mobile) && padding: 0 8px 0 10px (tablet + desktop); + } + } + + .breadcrumb-container { + color: var(--grayscale-black); + display: flex; + flex-wrap: nowrap; + font-family: var(--main-font-family); + list-style-type: none; + margin: 0; + min-height: 64px; + overflow: hidden; + padding: 0; + + @include breakpoint($narrow) { + min-height: 84px; + } + + .breadcrumb-item.home { + svg { + fill: var(--grayscale-black); + stroke: var(--grayscale-black); + stroke-width: 30; + } + } + } + + @include breakpoint($extrawide) { + display: none; + visibility: hidden; + } +} diff --git a/src/components/hy-breadcrumbs/hy-breadcrumbs.tsx b/src/components/hy-breadcrumbs/hy-breadcrumbs.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a3321f64218989f98e975fe376fa8db6bd668f2a --- /dev/null +++ b/src/components/hy-breadcrumbs/hy-breadcrumbs.tsx @@ -0,0 +1,305 @@ +export interface Breadcrumb { + url: string; + text: string; +} +let breadcrumbsWidth = null; +import {Component, Element, h, Listen, Prop, State, Watch} from '@stencil/core'; +import {BreadcrumbVariants} from '../../utils/utils'; + +@Component({ + tag: 'hy-breadcrumbs', + styleUrl: 'hy-breadcrumbs.scss', + shadow: false, +}) +export class HyBreadcrumbs { + private _dataItems: Breadcrumb[]; + @Prop() dataItems: Breadcrumb[] | string; + @Prop() variant: BreadcrumbVariants = BreadcrumbVariants.default as any; + @Prop() headerstyle: string = 'with-sidebar'; + + @State() menuOpen: boolean = false; + @Element() el: HTMLElement; + + @Watch('dataItems') + arrayDataWatcher(newValue: Breadcrumb[] | string) { + if (typeof newValue === 'string') { + this._dataItems = JSON.parse(newValue); + } else { + this._dataItems = newValue; + } + } + componentWillLoad() { + this.arrayDataWatcher(this.dataItems); + } + + componentDidLoad() { + let hyMainDiv = this.el.closest('.hy-main'); + if (hyMainDiv) { + if (!hyMainDiv.classList.contains('with-sidebar')) { + this.headerstyle = 'without-sidebar'; + } + } + + // Set breadcumbs width + paddings. + breadcrumbsWidth = this.el.offsetWidth + 64; + if (breadcrumbsWidth >= document.body.scrollWidth) { + this.adjustBreadcrumbsMenuVisibility(); + } + } + + adjustBreadcrumbsMenuVisibility(showMenu = true) { + // Show ... and Hide intermediate links + if (!showMenu) { + this.closeMoreMenu(); + } + + const crumbContainer = document.querySelectorAll('.hy-breadcrumbs')[0]; + const moreDotsItem = document.querySelectorAll('#more')[0]; + const moreDotsItemWrapper = document.querySelectorAll('.breadcrumb-item__more')[0]; + if (moreDotsItem) { + if (showMenu) { + crumbContainer.classList.add('is-condensed'); + moreDotsItem.classList.add('visible'); + moreDotsItemWrapper.classList.add('visible'); + } else { + crumbContainer.classList.remove('is-condensed'); + moreDotsItem.classList.remove('visible'); + moreDotsItemWrapper.classList.remove('visible'); + } + } + + const intermediateItems = document.querySelectorAll('.intermediate'); + if (intermediateItems) { + for (let i = 0; i < intermediateItems.length; i++) { + if (showMenu) { + intermediateItems[i].classList.add('hidden'); + } else { + intermediateItems[i].classList.remove('hidden'); + } + } + } + } + + HomeItem(url) { + const homeItemClass = ['hy-icon-wrapper', this.variant].join(' '); + return ( + <li class="breadcrumb-item home"> + <a href={url} class={homeItemClass}> + <hy-icon icon={'hy-icon-home'} class={`${this.variant}`} size={20} /> + <hy-icon icon={'hy-icon-caret-right'} class={'breadcrumb-item-caret'} size={10} /> + </a> + </li> + ); + } + + BreadcrumbItem(label, url, className = '', withCaret = true) { + const breadcrumbClass = ['breadcrumb-item', className].join(' '); + const caretClass = ['breadcrumb-item-caret', this.variant].join(' '); + if (url) { + if (withCaret) { + return ( + <li class={breadcrumbClass}> + <a href={url} class={`${this.variant}`}> + {label} + <hy-icon icon={'hy-icon-caret-right'} class={caretClass} size={10} /> + </a> + </li> + ); + } else { + return ( + <li class={breadcrumbClass}> + <a href={url} class={`${this.variant}`}> + {label} + </a> + </li> + ); + } + } else { + return ( + <li class={`${breadcrumbClass} breadcrumb-item__current`}> + <a aria-current="page" href={url} class={`${this.variant}`}> + {label} + </a> + </li> + ); + } + } + + BreadcrumbTextItem(label, className = '') { + const breadcrumbClass = ['breadcrumb-item', className].join(' '); + return <li class={breadcrumbClass}>{label}</li>; + } + + DropdownMenuItem() { + return ( + <li class="breadcrumb-item__more"> + <button + type="button" + aria-hidden="true" + aria-expanded="false" + id="more" + key="more" + class="breadcrumb-item-dropdown-button" + > + ... + <hy-icon + icon={'hy-icon-caret-right'} + class={'breadcrumb-item-caret__drop breadcrumb-item__more__icon'} + size={10} + /> + </button> + <hy-icon icon={'hy-icon-caret-right'} class={'breadcrumb-item-caret'} size={10} /> + </li> + ); + } + + adjustHiddenMenuWidth() { + // set width to the menu area equal to the widest link + paddings + const moreMenu = document.querySelectorAll('.breadcrumb-hidden-items')[0]; + if (moreMenu) { + if (document.body.scrollWidth < 480) { + (moreMenu as HTMLElement).style.width = '100%'; + } else { + //maxIntermediateLinkWidth + var maxIntermediateLinkWidth = 0; + const moreMenuLinks = document.querySelectorAll('.breadcrumb-hidden-items .breadcrumb-item a'); + if (moreMenuLinks) { + for (let i = 0; i < moreMenuLinks.length; i++) { + if (maxIntermediateLinkWidth < (moreMenuLinks[i] as HTMLElement).offsetWidth) { + maxIntermediateLinkWidth = (moreMenuLinks[i] as HTMLElement).offsetWidth; + } + } + maxIntermediateLinkWidth = maxIntermediateLinkWidth + 32 + 64; + } + (moreMenu as HTMLElement).style.width = maxIntermediateLinkWidth.toString().concat('px'); + } + } + } + + closeMoreMenu() { + const moreMenu = document.querySelectorAll('.breadcrumb-hidden-items')[0]; + if (moreMenu) { + moreMenu.classList.remove('breadcrumb-hidden-items__is-open'); + this.menuOpen = false; + } + const moreBreadcrumb = document.querySelectorAll('#more')[0]; + if (moreBreadcrumb) { + moreBreadcrumb.classList.remove('is-open'); + } + } + + // When a ... is clicked, show/hide the Menu with hidden breadcrumbs + @Listen('click') + clickEventListener(event) { + if (!event) return; + + const target = event.target; + const moreMenu = document.querySelectorAll('.breadcrumb-hidden-items')[0]; + const moreButton = document.querySelectorAll('.breadcrumb-item-dropdown-button')[0]; + + // Trigger if target is button or svg icon + // TODO: Make this if prettier + if ( + target && + (target.id === 'more' || + ((target.tagName == 'svg' || 'path') && + target.closest('hy-icon').classList.contains('breadcrumb-item__more__icon'))) + ) { + //@todo Show the menu on the right place of the screen + if (moreMenu) { + if (this.menuOpen) { + moreMenu.classList.remove('breadcrumb-hidden-items__is-open'); + moreButton.classList.remove('is-open'); + moreButton.setAttribute('aria-expanded', 'false'); + } else { + moreMenu.classList.add('breadcrumb-hidden-items__is-open'); + moreButton.classList.add('is-open'); + moreButton.setAttribute('aria-expanded', 'true'); + + if (document.body.scrollWidth < 480) { + (moreMenu as HTMLElement).style.left = '16px'; + } else { + var rect = (moreButton as HTMLElement).getBoundingClientRect(); + (moreMenu as HTMLElement).style.left = (rect.left - 64).toString().concat('px'); + this.adjustHiddenMenuWidth(); + } + } + this.menuOpen = !this.menuOpen; + } + } else { + this.closeMoreMenu(); + } + + event.stopPropagation(); + event.stopImmediatePropagation(); + } + + @Listen('resize', {target: 'window'}) + resizeEventListener(event) { + if (!event) return; + + const breadcrumbsElement = document.querySelectorAll('.hy-breadcrumbs')[0]; + if (breadcrumbsElement) { + if (breadcrumbsWidth + 64 >= document.body.scrollWidth) { + this.adjustBreadcrumbsMenuVisibility(true); + } else { + this.adjustBreadcrumbsMenuVisibility(false); + } + } + } + + render() { + //@todo Accesibility + const TOTAL_ITEMS = this._dataItems.length; + const MAX_ITEMS_TO_SHOW = 3; + + let isMenuNeeded = TOTAL_ITEMS > MAX_ITEMS_TO_SHOW; + + let itemsBreadcrumbs = []; + let itemsToShowInMenu = []; + + if (this.variant == BreadcrumbVariants.landingLarge) { + // Landing pages, Large variant + this._dataItems.map((x, index) => { + if (index < 2) { + if (index == 0) { + itemsBreadcrumbs.push(this.HomeItem(x.url)); + } else { + //itemsBreadcrumbs.push(this.BreadcrumbTextItem(x.text, 'main')); + itemsBreadcrumbs.push(this.BreadcrumbItem(x.text, '', 'main')); + } + } + }); + } else { + // Landing and Content pages, Standard variant + this._dataItems.map((x, index) => { + let breadcrumbEl = this.BreadcrumbItem(x.text, x.url, '', false); + + if (isMenuNeeded && index > 1 && index < TOTAL_ITEMS - 1) { + itemsToShowInMenu.push(<div>{breadcrumbEl}</div>); + + if (index === 2) { + itemsBreadcrumbs.push(this.DropdownMenuItem()); + } + itemsBreadcrumbs.push(this.BreadcrumbItem(x.text, x.url, 'intermediate')); + return; + } else { + if (index == 0) { + itemsBreadcrumbs.push(this.HomeItem(x.url)); + } else { + itemsBreadcrumbs.push(this.BreadcrumbItem(x.text, x.url, 'main')); + } + } + }); + } + + const breadcrumbsClass = ['hy-breadcrumbs', this.variant, this.headerstyle].join(' '); + + return ( + <nav aria-label="Breadcrumb" role="navigation" aria-labelledby="system-breadcrumb" class={breadcrumbsClass}> + <ol class="breadcrumb-container">{itemsBreadcrumbs}</ol> + {itemsToShowInMenu && <ol class="breadcrumb-hidden-items">{itemsToShowInMenu}</ol>} + </nav> + ); + } +} diff --git a/src/components/hy-breadcrumbs/readme.md b/src/components/hy-breadcrumbs/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..4cb1efaac77235b2b63d0cb80109189249e393a0 --- /dev/null +++ b/src/components/hy-breadcrumbs/readme.md @@ -0,0 +1,29 @@ +# hy-breadcrumbs + +<!-- Auto Generated Below --> + +## Properties + +| Property | Attribute | Description | Type | Default | +| ------------- | ------------- | ----------- | --------------------------------------------------------------- | ----------------------------------- | +| `dataItems` | `data-items` | | `Breadcrumb[] \| string` | `undefined` | +| `headerstyle` | `headerstyle` | | `string` | `'with-sidebar'` | +| `variant` | `variant` | | `BreadcrumbVariants.default \| BreadcrumbVariants.landingLarge` | `BreadcrumbVariants.default as any` | + +## Dependencies + +### Depends on + +- [hy-icon](../icon) + +### Graph + +```mermaid +graph TD; + hy-breadcrumbs --> hy-icon + style hy-breadcrumbs fill:#f9f,stroke:#333,stroke-width:4px +``` + +--- + +Helsinki University Design System diff --git a/src/components/icon/Home.tsx b/src/components/icon/Home.tsx index a2e39101f9bb3770ea226d06ef945ce0c6dd25da..2473ea70b58f219f66c1a2085fdb9604caf5ba3b 100644 --- a/src/components/icon/Home.tsx +++ b/src/components/icon/Home.tsx @@ -2,11 +2,11 @@ import {h} from '@stencil/core'; function SvgHome(props) { return ( - <svg viewBox="0 0 1000 1000" {...props}> + <svg viewBox="0 0 1000 1000" {...props} stroke="black" stroke-width="1"> <path d="M345.3,998.7c-30.3,0-55.4-25.2-55.4-55.6c0-30.4,25.1-55.6,55.4-55.6h479.9l0-509.9L500,114.2L174.8,377.6 v565.5c0,30.4-25.1,55.6-55.4,55.6c-30.3,0-55.4-25.2-55.4-55.6l0-567.6c0-31.5,14.6-61.9,38.7-81.9L434.1,25 - c37.7-30.4,93-30.4,130.7,0l332.5,268.6c25.1,19.9,38.7,49.3,38.7,81.9v568.7c0,29.4-25.1,54.6-55.4,54.6L345.3,998.7z" + c37.7-30.4,93-30.4,130.7,0l332.5,268.6c25.1,19.9,38.7,49.3,38.7,81.9v568.7c0,29.4-25.1,54.6-55.4,54.6L345.3,998.7z" /> </svg> ); diff --git a/src/components/icon/SomeFacebook.tsx b/src/components/icon/SomeFacebook.tsx new file mode 100644 index 0000000000000000000000000000000000000000..c3879b4686c9ae5c0cff61154caff115e2b5268c --- /dev/null +++ b/src/components/icon/SomeFacebook.tsx @@ -0,0 +1,14 @@ +import {h} from '@stencil/core'; + +function SomeFacebook(props) { + return ( + <svg {...props} id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 56"> + <path + class="cls-1" + d="M56,28A28,28,0,1,0,23.62,55.66V36.09h-7.1V28h7.1V21.83c0-7,4.19-10.89,10.58-10.89a43.71,43.71,0,0,1,6.27.54v6.9H36.94c-3.48,0-4.56,2.15-4.56,4.37V28h7.76L38.9,36.09H32.38V55.66A28,28,0,0,0,56,28Z" + /> + </svg> + ); +} + +export default SomeFacebook; diff --git a/src/components/icon/SomeInstagram.tsx b/src/components/icon/SomeInstagram.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f82b0b30dfaa97cf01d88b774d191dd8b48b9fdf --- /dev/null +++ b/src/components/icon/SomeInstagram.tsx @@ -0,0 +1,19 @@ +import {h} from '@stencil/core'; + +function SomeInstagram(props) { + return ( + <svg {...props} id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 56"> + <path + class="cls-1" + d="M28,0c-7.6,0-8.56,0-11.54.17a20.68,20.68,0,0,0-6.8,1.3,13.74,13.74,0,0,0-5,3.23,13.72,13.72,0,0,0-3.22,5,20.2,20.2,0,0,0-1.31,6.8C0,19.44,0,20.4,0,28s0,8.56.17,11.54a20.68,20.68,0,0,0,1.3,6.8,13.74,13.74,0,0,0,3.23,5,13.74,13.74,0,0,0,5,3.23,20.48,20.48,0,0,0,6.8,1.3C19.44,56,20.4,56,28,56s8.56,0,11.54-.17a20.42,20.42,0,0,0,6.8-1.3,14.3,14.3,0,0,0,8.19-8.19,20.48,20.48,0,0,0,1.3-6.8C56,36.56,56,35.6,56,28s0-8.56-.17-11.54a20.68,20.68,0,0,0-1.3-6.8,13.74,13.74,0,0,0-3.23-5,13.72,13.72,0,0,0-5-3.22A20.2,20.2,0,0,0,39.54.17C36.56,0,35.6,0,28,0Zm0,5c7.48,0,8.36,0,11.31.17a15.46,15.46,0,0,1,5.2,1,8.77,8.77,0,0,1,3.23,2.1,8.62,8.62,0,0,1,2.09,3.22,15.45,15.45,0,0,1,1,5.2c.13,2.95.16,3.84.16,11.31s0,8.36-.16,11.32a15.45,15.45,0,0,1-1,5.2,9.26,9.26,0,0,1-5.31,5.31,15.71,15.71,0,0,1-5.2,1c-3,.13-3.84.16-11.32.16s-8.36,0-11.31-.16a15.71,15.71,0,0,1-5.2-1,8.62,8.62,0,0,1-3.22-2.09,8.77,8.77,0,0,1-2.1-3.23,15.46,15.46,0,0,1-1-5.2C5.07,36.36,5,35.48,5,28s0-8.36.17-11.32a15.38,15.38,0,0,1,1-5.19,8.77,8.77,0,0,1,2.1-3.23,8.62,8.62,0,0,1,3.22-2.09,15.45,15.45,0,0,1,5.2-1C19.64,5.07,20.53,5,28,5" + /> + <path + class="cls-1" + d="M28,37.33A9.34,9.34,0,1,1,37.34,28h0A9.34,9.34,0,0,1,28,37.33Zm0-23.71A14.38,14.38,0,1,0,42.38,28h0A14.38,14.38,0,0,0,28,13.62Z" + /> + <path class="cls-1" d="M46.31,13.05A3.36,3.36,0,1,1,43,9.69,3.36,3.36,0,0,1,46.31,13.05Z" /> + </svg> + ); +} + +export default SomeInstagram; diff --git a/src/components/icon/SomeLinkedin.tsx b/src/components/icon/SomeLinkedin.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f779be46cf3647d5b2270f11d504229b3e094ab4 --- /dev/null +++ b/src/components/icon/SomeLinkedin.tsx @@ -0,0 +1,14 @@ +import {h} from '@stencil/core'; + +function SomeLinkedin(props) { + return ( + <svg {...props} id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 56"> + <path + class="cls-1" + d="M50.46,0H5.54A5.54,5.54,0,0,0,0,5.54V50.47A5.54,5.54,0,0,0,5.54,56H50.46A5.54,5.54,0,0,0,56,50.47V5.54A5.54,5.54,0,0,0,50.46,0ZM17.24,48.06H8.77V21h8.47Zm-.73-32.13A4.68,4.68,0,0,1,13,17.25h0a4.47,4.47,0,0,1-4.7-4.65A4.48,4.48,0,0,1,9.59,9.27a4.7,4.7,0,0,1,3.46-1.33,4.49,4.49,0,0,1,4.7,4.66A4.42,4.42,0,0,1,16.51,15.93ZM47.74,48.06H39.31V33.56a8.15,8.15,0,0,0-1.06-4.51A3.66,3.66,0,0,0,35,27.44a3.88,3.88,0,0,0-2.67.93,6.3,6.3,0,0,0-1.66,2.35,7,7,0,0,0-.28,2.2V48.06H21.9q0-10.92,0-17.73v-8l0-1.32h8.47v3.85a11.89,11.89,0,0,1,1-1.5,10.54,10.54,0,0,1,1.42-1.42,6.59,6.59,0,0,1,2.26-1.17,8.43,8.43,0,0,1,3-.39,8.85,8.85,0,0,1,7,3.08q2.67,3.09,2.67,9.11Z" + /> + </svg> + ); +} + +export default SomeLinkedin; diff --git a/src/components/icon/SomeTwitter.tsx b/src/components/icon/SomeTwitter.tsx new file mode 100644 index 0000000000000000000000000000000000000000..db74fec5d2142049d2d2974e741999be43e4e8e6 --- /dev/null +++ b/src/components/icon/SomeTwitter.tsx @@ -0,0 +1,14 @@ +import {h} from '@stencil/core'; + +function SomeTwitter(props) { + return ( + <svg {...props} id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 56"> + <path + class="cls-1" + d="M56,28A28,28,0,1,1,28,0,28,28,0,0,1,56,28ZM22.88,42.77c12.41,0,19.2-10.29,19.2-19.21,0-.3,0-.59,0-.87a13.68,13.68,0,0,0,3.37-3.5,13.43,13.43,0,0,1-3.87,1.06,6.71,6.71,0,0,0,3-3.73,13.42,13.42,0,0,1-4.28,1.63,6.76,6.76,0,0,0-11.68,4.62,6,6,0,0,0,.19,1.54,19.13,19.13,0,0,1-13.92-7,6.79,6.79,0,0,0-.91,3.39,6.72,6.72,0,0,0,3,5.61,6.68,6.68,0,0,1-3.05-.84v.08a6.76,6.76,0,0,0,5.42,6.63,7,7,0,0,1-1.78.23,6.77,6.77,0,0,1-1.28-.12,6.75,6.75,0,0,0,6.3,4.69,13.6,13.6,0,0,1-8.38,2.88,12.21,12.21,0,0,1-1.61-.1,18.74,18.74,0,0,0,10.32,3.06" + /> + </svg> + ); +} + +export default SomeTwitter; diff --git a/src/components/icon/SomeYoutube.tsx b/src/components/icon/SomeYoutube.tsx new file mode 100644 index 0000000000000000000000000000000000000000..420c15b70180ee13d39c91f5a2b3c614dccdd6dc --- /dev/null +++ b/src/components/icon/SomeYoutube.tsx @@ -0,0 +1,14 @@ +import {h} from '@stencil/core'; + +function SomeYoutube(props) { + return ( + <svg {...props} id="Layer_1" data-name="Layer 1" viewBox="0 0 56 56"> + <path + class="cls-3" + d="M52.59,15.56A6.44,6.44,0,0,0,48.05,11C44,9.92,28,9.92,28,9.92S12,9.92,7.94,11a6.44,6.44,0,0,0-4.53,4.56C2.33,19.6,2.33,28,2.33,28s0,8.41,1.08,12.44A6.47,6.47,0,0,0,7.94,45C12,46.08,28,46.08,28,46.08s16,0,20.06-1.07a6.47,6.47,0,0,0,4.53-4.57c1.08-4,1.08-12.44,1.08-12.44s0-8.4-1.08-12.44M22.75,35.63V20.37L36.17,28Z" + /> + </svg> + ); +} + +export default SomeYoutube; diff --git a/src/components/icon/icon.tsx b/src/components/icon/icon.tsx index 856929d6109691eb610f894d762a1386d25a19e3..ac28adb441f75a73a07c844c0014e997c6cb0368 100644 --- a/src/components/icon/icon.tsx +++ b/src/components/icon/icon.tsx @@ -8,6 +8,7 @@ const iconNames: IconName = { 'hy-icon-arrow-right': (p) => <icons.IconArrowRight {...p} />, 'hy-icon-arrow-to-right': (p) => <icons.IconArrowToRight {...p} />, 'hy-icon-arrow-down': (p) => <icons.ArrowDown {...p} />, + 'hy-icon-arrow-up': (p) => <icons.ArrowUp {...p} />, 'hy-icon-camera': (p) => <icons.Camera {...p} />, 'hy-icon-caret-down': (p) => <icons.CaretDown {...p} />, 'hy-icon-caret-left': (p) => <icons.CaretLeft {...p} />, @@ -22,6 +23,11 @@ const iconNames: IconName = { 'hy-icon-quote': (p) => <icons.IconQuote {...p} />, 'hy-icon-remove': (p) => <icons.Remove {...p} />, 'hy-icon-search': (p) => <icons.Search {...p} />, + 'hy-icon-some-facebook': (p) => <icons.SomeFacebook {...p} />, + 'hy-icon-some-instagram': (p) => <icons.SomeInstagram {...p} />, + 'hy-icon-some-youtube': (p) => <icons.SomeYoutube {...p} />, + 'hy-icon-some-twitter': (p) => <icons.SomeTwitter {...p} />, + 'hy-icon-some-linkedin': (p) => <icons.SomeLinkedin {...p} />, }; @Component({ diff --git a/src/components/icon/icons.tsx b/src/components/icon/icons.tsx index 046b44e4d473b1790001f4626d8509ff57d5b930..c3eff2d2eaaacb80493947b681c798fb7e1404ed 100644 --- a/src/components/icon/icons.tsx +++ b/src/components/icon/icons.tsx @@ -156,6 +156,11 @@ export {default as RotateRight} from './RotateRight'; export {default as Search} from './Search'; export {default as Share} from './Share'; export {default as SocialMedia} from './SocialMedia'; +export {default as SomeFacebook} from './SomeFacebook'; +export {default as SomeInstagram} from './SomeInstagram'; +export {default as SomeTwitter} from './SomeTwitter'; +export {default as SomeYoutube} from './SomeYoutube'; +export {default as SomeLinkedin} from './SomeLinkedin'; export {default as Spinner} from './Spinner'; export {default as SquareChecked} from './SquareChecked'; export {default as Square} from './Square'; diff --git a/src/components/icon/readme.md b/src/components/icon/readme.md index f60cfe02de93c63e5b28111f26ae3030efaf56e0..82e396ca8c7f096fe8db7b0202ec8d1ae892407c 100644 --- a/src/components/icon/readme.md +++ b/src/components/icon/readme.md @@ -15,9 +15,13 @@ ### Used by - [hy-accordion-item](../accordion-item) +- [hy-breadcrumbs](../hy-breadcrumbs) - [hy-button](../button) - [hy-cta-button](../cta-button) - [hy-cta-link](../cta-link) +- [hy-footer-action](../footer/hy-footer-action) +- [hy-footer-base](../footer/hy-footer-base) +- [hy-footer-link-item](../footer/hy-footer-link-item) - [hy-hero](../hy-hero) - [hy-introduction](../hy-introduction) - [hy-link-box](../link-box) @@ -36,9 +40,13 @@ ```mermaid graph TD; hy-accordion-item --> hy-icon + hy-breadcrumbs --> hy-icon hy-button --> hy-icon hy-cta-button --> hy-icon hy-cta-link --> hy-icon + hy-footer-action --> hy-icon + hy-footer-base --> hy-icon + hy-footer-link-item --> hy-icon hy-hero --> hy-icon hy-introduction --> hy-icon hy-link-box --> hy-icon diff --git a/src/components/site-header/site-logo/readme.md b/src/components/site-header/site-logo/readme.md index b90fc7b66e0e326a8e27f0bf015c88ce88260625..24fb530f21102a30a16100f4c6a5c50982a1f206 100644 --- a/src/components/site-header/site-logo/readme.md +++ b/src/components/site-header/site-logo/readme.md @@ -15,6 +15,7 @@ ### Used by +- [hy-footer-base](../../footer/hy-footer-base) - [hy-menu](../../navigation/menu) - [hy-site-header](..) - [hy-user-login-form](../../hy-user-login-form) @@ -28,6 +29,7 @@ ```mermaid graph TD; hy-site-logo --> hy-icon + hy-footer-base --> hy-site-logo hy-menu --> hy-site-logo hy-site-header --> hy-site-logo hy-user-login-form --> hy-site-logo diff --git a/src/index.html b/src/index.html index 0b9bbc0188a3bd45df1b718d472333cb1356ae24..5f6fc07d9a1b07782d406ae7db5a18ca7696b230 100644 --- a/src/index.html +++ b/src/index.html @@ -167,249 +167,7 @@ </hy-menu> </hy-site-header> <hy-main has-sidebar="true"> - <div class="layout-content"></div> - - <aside class="layout-sidebar-first" role="complementary"> - <hy-menu - slot="menu" - menu-type="sidenav" - open="true" - is-demo="true" - data-menu-language='[ - {"langCode":"fi","abbr":"fin","label":"Finnish","url":"/fi"}, - {"langCode":"en","abbr":"eng","label":"English","url":"/en","isActive":"true"}, - {"langCode":"sv","abbr":"swe","label":"Swedish","url":"/sv"} - ]' - data-menu-donate='[{"url":"#","label":"Support us"}]' - > - <hy-menu-level-container menu-type="sidenav" menu-level="1"> - <hy-menu-item is-demo menu-type="sidenav" menu-link-id="1" url="#" label="News"> - <hy-menu-level-container menu-type="sidenav" menu-level="2"> - <hy-menu-item is-demo menu-type="sidenav" menu-link-id="2" url="#" label="News"></hy-menu-item> - <hy-menu-item is-demo menu-type="sidenav" menu-link-id="3" url="#" label="Events"></hy-menu-item> - <hy-menu-item is-demo menu-type="sidenav" menu-link-id="4" url="#" label="Think Corner"></hy-menu-item> - <hy-menu-item is-demo menu-type="sidenav" menu-link-id="5" url="#" label="Unitube"></hy-menu-item> - </hy-menu-level-container> - </hy-menu-item> - <hy-menu-item is-demo menu-type="sidenav" menu-link-id="6" url="#" label="Research" in-active-trail="true"> - <hy-menu-level-container menu-type="sidenav" menu-level="2"> - <hy-menu-item is-demo menu-type="sidenav" menu-link-id="7" url="#" label="Top research"></hy-menu-item> - <hy-menu-item is-demo menu-type="sidenav" menu-link-id="15" url="#" label="Researchers"></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="16" - url="#" - label="Fields of science" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="17" - url="#" - label="Research groups" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="18" - url="#" - label="Doctoral education" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="24" - url="#" - label="Research institutes" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="25" - url="#" - label="Research stations" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="26" - url="#" - label="Services for researchers and research policy" - in-active-trail="true" - is-active="true" - > - <hy-menu-level-container menu-type="sidenav" menu-level="3"> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="27" - url="#" - label="Research infrastructures" - > - <hy-menu-level-container menu-type="sidenav" menu-level="4"> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="28" - url="#" - label="Research infrastructure development programme" - ></hy-menu-item> - </hy-menu-level-container> - </hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="29" - url="#" - label="Research funding" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="30" - url="#" - label="Data management" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="35" - url="#" - label="Open science" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="39" - url="#" - label="Commercialisation of research" - ></hy-menu-item> - </hy-menu-level-container> - </hy-menu-item> - </hy-menu-level-container> - </hy-menu-item> - <hy-menu-item is-demo menu-type="sidenav" menu-link-id="45" url="#" label="Admissions"></hy-menu-item> - <hy-menu-item is-demo menu-type="sidenav" menu-link-id="46" url="#" label="Cooperation"></hy-menu-item> - <hy-menu-item is-demo menu-type="sidenav" menu-link-id="47" url="#" label="About us"></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="48" - menu-item-alternative="true" - url="#" - label="Faculties and units" - > - <hy-menu-level-container menu-type="sidenav" menu-level="2"> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="49" - url="#" - label="Faculty of Agriculture and Forestry" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="50" - url="#" - label="Faculty of Arts" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="51" - url="#" - label="Faculty of Biological and Environmental Sciences" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="52" - url="#" - label="Faculty of Educational Sciences" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="53" - url="#" - label="Faculty of Law" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="54" - url="#" - label="Faculty of Medicine" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="55" - url="#" - label="Faculty of Pharmacy" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="56" - url="#" - label="Faculty of Science" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="57" - url="#" - label="Faculty of Social Sciences" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="58" - url="#" - label="Faculty of Theology" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="59" - url="#" - label="Faculty of Veterinary Medicine" - ></hy-menu-item> - <hy-menu-item - is-demo - menu-type="sidenav" - menu-link-id="50" - url="#" - label="Swedish School of Social Science" - ></hy-menu-item> - </hy-menu-level-container> - </hy-menu-item> - </hy-menu-level-container> - </hy-menu> - </aside> - </hy-main> - <hy-main role="main"> <div class="layout-content"> - <section> - <a href="#facebook_ads_example">Click here to see an example of how a company uses Facebook ads.</a> - </section> - - <section> - <a href="#this-is-an-accordion-item-3--title">Click here to go to Accordion Item 3</a> - </section> - <hy-heading heading="h2" section="subsection">This is a subsection heading</hy-heading> - <hy-shortcuts - list-heading="Shortcuts list heading number one" - data-items='[ - {"heading":"3500 h","url":"https://yle.fi"}, - {"heading":"Example link label one","url":"https://yle.fi"}, - {"heading":"Example link label two. Very Long label indeed to test if it fits.", "url":"https://yle.fi"}, - {"heading":"Example link label three", "url":"https://yle.fi"}]' - > - </hy-shortcuts> <hy-hero color-variant="blue" image="https://www.helsinki.fi/sites/default/files/styles/16_9_huge/public/ambassadors_toolo_4_1920x1080_original_hero_valoisampi.jpg" @@ -418,32 +176,17 @@ url="https://www.helsinki.fi/fi/uutiset" url-title="See latest publications" sc-label="Aria label" - /> - <hy-banner - text-title="Check upcoming conferences" - text-description="Take advantage of our curated list of high profile conferences near Helsinki and in the Nordics." - url="#this-is-an-accordion-item-2--title" - url-title="Show list of conferences" - sc-label="List of conferences" - > - </hy-banner> - + ></hy-hero> + THIS IS MAIN CONTENT <hy-banner text-title="Check upcoming conferences" text-description="Take advantage of our curated list of high profile conferences near Helsinki and in the Nordics." - url="#this-is-an-accordion-item-2--title" + url="https://helsinki.fi" url-title="Show list of conferences" sc-label="List of conferences" > </hy-banner> - - <hy-baseline> - <hy-heading heading="h2" section="subsection">H2 With divider</hy-heading> - <hy-button button-classes="button-additional-class another-class" button-type="button">Primary</hy-button> - <hy-button>Primary</hy-button> - </hy-baseline> - - <hy-accordion-container accordionId="example-accordion"> + <hy-accordion-container accordionid="example-accordion"> <hy-accordion-item accordiontitle="This is a accordion item 1"> <hy-paragraph-text>Accordion content</hy-paragraph-text> </hy-accordion-item> @@ -455,7 +198,80 @@ </hy-accordion-item> </hy-accordion-container> </div> + + <div class="layout-sidebar-first" role="complementary"> + THIS IS SIDEBAR + </div> </hy-main> - --> + <hy-footer> + <hy-footer-action updated-text="Updated on 14.10.2020" up-button-label="Up"></hy-footer-action> + <hy-footer-info + text-title="Campuses" + text-description="University operates on four campuses in Helsinki and nine other locations." + link-text="See all" + link-url="www.google.com" + data-footer-info-links='[ + {"label": "City Centre Campus", "url": "#", "mainlink": true, + "items": [ + {"label": "Faculti of Educational Sciences", "url": "#"}, + {"label": "Faculti of Educational Theology", "url": "#"}, + {"label": "Faculti of Educational Arts", "url": "#"}, + {"label": "Faculti of Educational Sociology", "url": "#"}, + {"label": "Faculti of Educational Medicine", "url": "#"}, + {"label": "Faculti of Educational Pharmacy", "url": "#"}, + {"label": "Faculti of Educational Law", "url": "#"} + ] + }, + {"label": "Kumpula Campus", "url": "#", "mainlink": true, + "items": [ + {"label": "Faculti of Educational Sciences", "url": "#"} + ] + }, + {"label": "Meilahti Campus", "url": "#", "mainlink": true, + "items": [ + {"label": "Faculti of Educational Sciences", "url": "#"} + ] + }, + {"label": "Viikki Campus", "url": "#", "mainlink": true, + "items": [ + {"label": "Faculti of Educational Sciences", "url": "#"}, + {"label": "Faculti of Educational Arts", "url": "#"}, + {"label": "Faculti of Educational Medicine", "url": "#"}, + {"label": "Faculti of Educational Social theory", "url": "#"} + ] + } + ]' + ></hy-footer-info> + <hy-footer-base + logo-label="University of Helsinki" + logo-url="/" + some-label="Follow us" + copyright-text="© University of Helsinki 2020" + data-footer-base-links='[ + {"label": "People finder", "url": "#"}, + {"label": "Press and media", "url": "#"}, + {"label": "Opening hours", "url": "#"}, + {"label": "Flamma", "url": "#"}, + {"label": "Library", "url": "#"}, + {"label": "Webshop", "url": "#"}, + {"label": "About website", "url": "#"}, + {"label": "Data protection", "url": "#"}, + {"label": "More Data protection", "url": "#"}, + {"label": "Accessibility", "url": "#"}, + {"label": "Give feedback", "url": "#"} + ]' + data-footer-base-some='[ + {"label": "Follow us on Facebook", "url": "#", "type": "facebook"}, + {"label": "Follow us on Twitter", "url": "#", "type": "twitter"}, + {"label": "Follow us on Youtube", "url": "#", "type": "youtube"}, + {"label": "Follow us on LinkedIn", "url": "#", "type": "linkedin"}, + {"label": "Follow us on Instagram", "url": "#", "type": "instagram"} + ]' + > + <div slot="content"> + P.O. Box 4 (Yliopistonkatu 3) 00014 University of Helsinki Switchboard: +358 (0) 2941 911 + </div> + </hy-footer-base> + </hy-footer> </body> </html> diff --git a/src/utils/utils.ts b/src/utils/utils.ts index c112c3da6cf3a2368813628e3f1b34bde3d93712..5b2c68b2b70afd7dc4d49826457ec50b81d5f8a8 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -12,6 +12,11 @@ export type IconName = { [key: string]: (props: any) => FunctionalComponent; }; +export enum BreadcrumbVariants { + default = 'default', + landingLarge = 'large', +} + export enum HeadingVarians { default = 'h1', h2 = 'h2', @@ -140,3 +145,8 @@ export enum HeroColorVariant { black = 'black', white = 'white', } + +export enum FooterLinkItemColor { + black = 'black', + white = 'white', +}