diff --git a/packages/design/components/breadcrumb/design-breadcrumb.mdx b/packages/design/components/breadcrumb/design-breadcrumb.mdx new file mode 100644 index 0000000000..f7ed3412bf --- /dev/null +++ b/packages/design/components/breadcrumb/design-breadcrumb.mdx @@ -0,0 +1,40 @@ +## Preview + + + +## Description + +A list of links showing the current page location in the navigational hierarchy. + +## Usage + +It has several usage : + +- Displaying sub-pages of a site structure +- Show a step progress of a process +- Simplify site structure navigation in a quicker way + +## Anatomy + +A Breadcrumb component has two main areas : + +- A list of Links joined with a separator ("|" character) referring to the parent pages +- A non-clickable text showing the user current page + +## Placement + +A Breadcrumb is used at the top of a web page, preferably start-aligned. + +Its width is automatic, relative to its content and is not adjustable. +Behavior + +When the Breadcrumb has more than 4 Links visible, an ellipsis is displayed as a replacement for the middle links. + +A click on the ellipsis will expanded all previously hidden links inline, the collapsed state can't be redone afterwards. + +The Breadcrumb links are kept inline, even on mobile viewports. +Variants + +## Accessibility + +All Links are accessible through tabulation. diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-attributes.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-attributes.ts new file mode 100644 index 0000000000..a280d2285a --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-attributes.ts @@ -0,0 +1,19 @@ +import { OdsComponentAttributes } from '../../ods-component-attributes'; +import { OdsIconName } from '../../icon/ods-icon-size'; + +export interface OdsBreadcrumbItemAttributes extends OdsComponentAttributes { + /** contrasted or not: see component principles */ + contrasted?: boolean, + /** Item link to redirect to */ + href: string; + /** Icon to display */ + icon?: OdsIconName; + /** @internal */ + isCollapsed: boolean; + /** @internal */ + isExpandableItem: boolean; + /** @internal */ + isLast: boolean; + /** Text to display */ + label?: string; +} diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-controller.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-controller.ts new file mode 100644 index 0000000000..46148155ab --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-controller.ts @@ -0,0 +1,12 @@ +import { OdsBreadcrumbItem } from './ods-breadcrumb-item'; +import { OdsComponentController } from '../../ods-component-controller'; + +/** + * common controller logic for component used by the different implementations. + * it contains all the glue between framework implementation and the third party service. + */ +export class OdsBreadcrumbItemController extends OdsComponentController { + constructor(component: OdsBreadcrumbItem) { + super(component); + } +} diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-default-attributes.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-default-attributes.ts new file mode 100644 index 0000000000..34614fa333 --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-default-attributes.ts @@ -0,0 +1,10 @@ +import { OdsBreadcrumbItemAttributes } from './ods-breadcrumb-item-attributes'; + +export const odsBreadcrumbItemDefaultAttributesDoc = { + contrasted: false, + isCollapsed: false, + isExpandableItem: false, + isLast: false, +} as const; + +export const odsBreadcrumbItemDefaultAttributes = odsBreadcrumbItemDefaultAttributesDoc as OdsBreadcrumbItemAttributes; diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-events.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-events.ts new file mode 100644 index 0000000000..91ae3f1bba --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-events.ts @@ -0,0 +1,8 @@ +import { OdsComponentEvents } from '../../ods-component-events'; + +export interface OdsBreadcrumbItemEvents extends OdsComponentEvents { + /** + * Event triggered on collapsed item click + */ + odsBreadcrumbItemCollapsedClick: void; +} diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-methods.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-methods.ts new file mode 100644 index 0000000000..62426f8d4a --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-methods.ts @@ -0,0 +1,5 @@ +import { OdsComponentMethods } from '../../ods-component-methods'; + +export interface OdsBreadcrumbItemMethods extends OdsComponentMethods { + // Methods +} diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item.ts new file mode 100644 index 0000000000..5d2092bd68 --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item.ts @@ -0,0 +1,16 @@ +import { OdsBreadcrumbItemAttributes } from './ods-breadcrumb-item-attributes'; +import { OdsBreadcrumbItemController } from './ods-breadcrumb-item-controller'; +import { OdsBreadcrumbItemEvents } from './ods-breadcrumb-item-events'; +import { OdsBreadcrumbItemMethods } from './ods-breadcrumb-item-methods'; +import { OdsComponent } from '../../ods-component'; +import { OdsComponentGenericEvents } from '../../ods-component-generic-events'; +import { OdsComponentGenericMethods } from '../../ods-component-generic-methods'; + +/** + * interface description of all implementation of `ods-breadcrumb-item`. + * each implementation must have defined events, methods, attributes + * and one controller for the common behavior logic + */ +export type OdsBreadcrumbItem = OdsComponentGenericMethods, + ComponentEvents extends OdsComponentGenericEvents = OdsComponentGenericEvents> = + OdsComponent; diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/public-api.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/public-api.ts new file mode 100644 index 0000000000..acc34dcc2b --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb-item/public-api.ts @@ -0,0 +1,6 @@ +export * from './ods-breadcrumb-item'; +export * from './ods-breadcrumb-item-attributes'; +export * from './ods-breadcrumb-item-controller'; +export * from './ods-breadcrumb-item-default-attributes'; +export * from './ods-breadcrumb-item-events'; +export * from './ods-breadcrumb-item-methods'; diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-attributes.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-attributes.ts new file mode 100644 index 0000000000..85306c9d13 --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-attributes.ts @@ -0,0 +1,20 @@ +import { OdsComponentAttributes } from '../../ods-component-attributes'; +import { OdsIconName } from '../../icon/ods-icon-size'; + +export interface OdsBreadcrumbAttributeItem { + /** Item link to redirect to */ + href: string, + /** Icon to display */ + icon?: OdsIconName, + /** Text to display */ + label?: string, +} + +export interface OdsBreadcrumbAttributes extends OdsComponentAttributes { + /** contrasted or not: see component principles */ + contrasted?: boolean, + /** + * List of breadcrumb items to display + */ + items: OdsBreadcrumbAttributeItem[] | string, +} diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-behavior.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-behavior.ts new file mode 100644 index 0000000000..c487b01c60 --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-behavior.ts @@ -0,0 +1,16 @@ +export interface OdsBreadcrumbBehavior { + /** + * Reference to the host element. + */ + el: HTMLElement; + + /** + * Items initialisation on first render + */ + componentWillLoad(): void; + + /** + * Receive and handle a collapsed item click event. + */ + onBreadcrumbItemCollapsedClick(): void; +} diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-controller.spec.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-controller.spec.ts new file mode 100644 index 0000000000..a7726ef721 --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-controller.spec.ts @@ -0,0 +1,165 @@ +import { OdsClearLoggerSpy, OdsInitializeLoggerSpy, OdsLoggerSpyReferences } from '@ovhcloud/ods-testing/src'; +import { OdsLogger } from '../../../logger/ods-logger'; +import { OdsBreadcrumb } from './ods-breadcrumb'; +import { OdsBreadcrumbController } from './ods-breadcrumb-controller'; +import { OdsBreadcrumbMock } from './ods-breadcrumb-mock'; + +describe('spec:ods-breadcrumb-controller', () => { + let controller: OdsBreadcrumbController; + let component: OdsBreadcrumb; + let loggerSpyReferences: OdsLoggerSpyReferences; + + function setup(attributes: Partial = {}) { + component = { ...component, ...attributes }; + controller = new OdsBreadcrumbController(component); + } + + beforeEach(() => { + component = new OdsBreadcrumbMock(); + + const loggerMocked = new OdsLogger('myLoggerMocked'); + loggerSpyReferences = OdsInitializeLoggerSpy({ + loggerMocked: loggerMocked as never, + spiedClass: OdsBreadcrumbController, + }); + }); + + afterEach(() => { + OdsClearLoggerSpy(loggerSpyReferences); + jest.clearAllMocks(); + }); + + describe('methods', () => { + describe('getBreadcrumbItems', () => { + beforeEach(() => { + setup(); + }); + + it('should return an empty array if there are no items', () => { + expect(controller.getBreadcrumbItems([], true)).toEqual([]); + }); + + it('should return all items non collapsed with last set', () => { + const dummyItems = [ + { href: 'dummy href 1'}, + { href: 'dummy href 2'}, + ]; + + expect(controller.getBreadcrumbItems(dummyItems, true)).toEqual([ + { + ...dummyItems[0], + isCollapsed: false, + isExpandableItem: false, + isLast: false, + }, + { + ...dummyItems[1], + isCollapsed: false, + isExpandableItem: false, + isLast: true, + }, + ]); + }); + + it('should return all middle items collapsed with last set', () => { + const dummyItems = [ + { href: 'dummy href 1'}, + { href: 'dummy href 2'}, + { href: 'dummy href 3'}, + { href: 'dummy href 4'}, + { href: 'dummy href 5'}, + { href: 'dummy href 6'}, + ]; + + expect(controller.getBreadcrumbItems(dummyItems, true)).toEqual([ + { + ...dummyItems[0], + isCollapsed: false, + isExpandableItem: false, + isLast: false, + }, + { + ...dummyItems[1], + isCollapsed: true, + isExpandableItem: true, + isLast: false, + }, + { + ...dummyItems[2], + isCollapsed: true, + isExpandableItem: false, + isLast: false, + }, + { + ...dummyItems[3], + isCollapsed: true, + isExpandableItem: false, + isLast: false, + }, + { + ...dummyItems[4], + isCollapsed: true, + isExpandableItem: false, + isLast: false, + }, + { + ...dummyItems[5], + isCollapsed: false, + isExpandableItem: false, + isLast: true, + }, + ]); + }); + + it('should return all items non collapsed if component is no more collapsed with last set', () => { + const dummyItems = [ + { href: 'dummy href 1'}, + { href: 'dummy href 2'}, + { href: 'dummy href 3'}, + { href: 'dummy href 4'}, + { href: 'dummy href 5'}, + { href: 'dummy href 6'}, + ]; + + expect(controller.getBreadcrumbItems(dummyItems, false)).toEqual([ + { + ...dummyItems[0], + isCollapsed: false, + isExpandableItem: false, + isLast: false, + }, + { + ...dummyItems[1], + isCollapsed: false, + isExpandableItem: false, + isLast: false, + }, + { + ...dummyItems[2], + isCollapsed: false, + isExpandableItem: false, + isLast: false, + }, + { + ...dummyItems[3], + isCollapsed: false, + isExpandableItem: false, + isLast: false, + }, + { + ...dummyItems[4], + isCollapsed: false, + isExpandableItem: false, + isLast: false, + }, + { + ...dummyItems[5], + isCollapsed: false, + isExpandableItem: false, + isLast: true, + }, + ]); + }); + }); + }); +}); diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-controller.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-controller.ts new file mode 100644 index 0000000000..7962771ae9 --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-controller.ts @@ -0,0 +1,38 @@ +import { OdsBreadcrumb } from './ods-breadcrumb'; +import { OdsComponentController } from '../../ods-component-controller'; +import { OdsBreadcrumbItemAttributes } from '../breadcrumb-item/ods-breadcrumb-item-attributes'; +import { OdsBreadcrumbAttributeItem } from './ods-breadcrumb-attributes'; + +const MAX_DISPLAYED_ITEMS = 4; + +/** + * common controller logic for component used by the different implementations. + * it contains all the glue between framework implementation and the third party service. + */ +export class OdsBreadcrumbController extends OdsComponentController { + constructor(component: OdsBreadcrumb) { + super(component); + } + + getBreadcrumbItems(items: OdsBreadcrumbAttributeItem[], isCollapsed: boolean): OdsBreadcrumbItemAttributes[] { + if (!items.length) { + return []; + } + + if (isCollapsed && items.length > MAX_DISPLAYED_ITEMS) { + return items.map((item, index) => ({ + ...item, + isCollapsed: index >= 1 && index < (items.length - 1), + isExpandableItem: index === 1, + isLast: index === (items.length - 1), + } as OdsBreadcrumbItemAttributes)); + } + + return items.map((item, index) => ({ + ...item, + isCollapsed: false, + isExpandableItem: false, + isLast: index === (items.length - 1), + } as OdsBreadcrumbItemAttributes)); + } +} diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-default-attributes.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-default-attributes.ts new file mode 100644 index 0000000000..85153fb4b2 --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-default-attributes.ts @@ -0,0 +1,7 @@ +import { OdsBreadcrumbAttributes } from './ods-breadcrumb-attributes'; + +export const odsBreadcrumbDefaultAttributesDoc = { + contrasted: false, +} as const; + +export const odsBreadcrumbDefaultAttributes = odsBreadcrumbDefaultAttributesDoc as OdsBreadcrumbAttributes; diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-events.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-events.ts new file mode 100644 index 0000000000..28c2abeb94 --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-events.ts @@ -0,0 +1,5 @@ +import { OdsComponentEvents } from '../../ods-component-events'; + +export interface OdsBreadcrumbEvents extends OdsComponentEvents { + // Events +} diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-methods.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-methods.ts new file mode 100644 index 0000000000..de1afbc49c --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-methods.ts @@ -0,0 +1,5 @@ +import { OdsComponentMethods } from '../../ods-component-methods'; + +export interface OdsBreadcrumbMethods extends OdsComponentMethods { + // Methods +} diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-mock.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-mock.ts new file mode 100644 index 0000000000..526edb58b3 --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-mock.ts @@ -0,0 +1,14 @@ +import { OdsBreadcrumb } from './ods-breadcrumb'; +import { OdsBreadcrumbController } from './ods-breadcrumb-controller'; +import { OdsBreadcrumbEvents } from './ods-breadcrumb-events'; +import { OdsBreadcrumbMethods } from './ods-breadcrumb-methods'; + +export class OdsBreadcrumbMock implements OdsBreadcrumb { + el!: HTMLElement; + contrasted?: boolean; + controller: OdsBreadcrumbController = jest.fn() as unknown as OdsBreadcrumbController; + items = []; + + componentWillLoad = jest.fn(); + onBreadcrumbItemCollapsedClick = jest.fn(); +} diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb.ts new file mode 100644 index 0000000000..b3fcbfaa66 --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb/ods-breadcrumb.ts @@ -0,0 +1,17 @@ +import { OdsBreadcrumbAttributes } from './ods-breadcrumb-attributes'; +import { OdsBreadcrumbBehavior } from './ods-breadcrumb-behavior'; +import { OdsBreadcrumbController } from './ods-breadcrumb-controller'; +import { OdsBreadcrumbEvents } from './ods-breadcrumb-events'; +import { OdsBreadcrumbMethods } from './ods-breadcrumb-methods'; +import { OdsComponent } from '../../ods-component'; +import { OdsComponentGenericEvents } from '../../ods-component-generic-events'; +import { OdsComponentGenericMethods } from '../../ods-component-generic-methods'; + +/** + * interface description of all implementation of `ods-breadcrumb`. + * each implementation must have defined events, methods, attributes + * and one controller for the common behavior logic + */ +export type OdsBreadcrumb = OdsComponentGenericMethods, + ComponentEvents extends OdsComponentGenericEvents = OdsComponentGenericEvents> = + OdsComponent; diff --git a/packages/libraries/core/src/components/breadcrumb/breadcrumb/public-api.ts b/packages/libraries/core/src/components/breadcrumb/breadcrumb/public-api.ts new file mode 100644 index 0000000000..751417491a --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/breadcrumb/public-api.ts @@ -0,0 +1,7 @@ +export * from './ods-breadcrumb'; +export * from './ods-breadcrumb-attributes'; +export * from './ods-breadcrumb-behavior'; +export * from './ods-breadcrumb-controller'; +export * from './ods-breadcrumb-default-attributes'; +export * from './ods-breadcrumb-events'; +export * from './ods-breadcrumb-methods'; diff --git a/packages/libraries/core/src/components/breadcrumb/public-api.ts b/packages/libraries/core/src/components/breadcrumb/public-api.ts new file mode 100644 index 0000000000..f3d025ba16 --- /dev/null +++ b/packages/libraries/core/src/components/breadcrumb/public-api.ts @@ -0,0 +1,2 @@ +export * from './breadcrumb/public-api'; +export * from './breadcrumb-item/public-api'; diff --git a/packages/libraries/core/src/components/component-types.json b/packages/libraries/core/src/components/component-types.json index 435e225070..2fe999686d 100644 --- a/packages/libraries/core/src/components/component-types.json +++ b/packages/libraries/core/src/components/component-types.json @@ -1,6 +1,7 @@ [ "OdsAccordion", "OdsAccordionGroup", + "OdsBreadcrumb", "OdsButton", "OdsCart", "OdsCartFooter", diff --git a/packages/libraries/core/src/components/ods-component-attributes-2-string-attributes.ts b/packages/libraries/core/src/components/ods-component-attributes-2-string-attributes.ts index 94bb143429..0f8eed3efa 100644 --- a/packages/libraries/core/src/components/ods-component-attributes-2-string-attributes.ts +++ b/packages/libraries/core/src/components/ods-component-attributes-2-string-attributes.ts @@ -31,6 +31,8 @@ export function OdsComponentAttributes2StringAttributes(attributes: OdsCompon parameters[name] = `${value}`; } else if (typeof value === "string") { parameters[name] = `${value}`; + } else if (typeof value === "object") { + parameters[name] = JSON.stringify(value); } else if(value) { console.warn(`your attribute ${name}=${value} cannot be set as DOM attribute. use setProperty instead`); } diff --git a/packages/libraries/core/src/components/public-api.ts b/packages/libraries/core/src/components/public-api.ts index 713503710e..2e5e9533d8 100644 --- a/packages/libraries/core/src/components/public-api.ts +++ b/packages/libraries/core/src/components/public-api.ts @@ -1,5 +1,6 @@ export * from './accordion/public-api'; export * from './accordion-group/public-api'; +export * from './breadcrumb/public-api'; export * from './button/public-api'; export * from './cart-footer-item/public-api'; export * from './cart-footer/public-api'; diff --git a/packages/libraries/testing/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-base-attributes.ts b/packages/libraries/testing/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-base-attributes.ts new file mode 100644 index 0000000000..a67059e7d8 --- /dev/null +++ b/packages/libraries/testing/src/components/breadcrumb/breadcrumb-item/ods-breadcrumb-item-base-attributes.ts @@ -0,0 +1,11 @@ +import { OdsBreadcrumbItemAttributes } from '@ovhcloud/ods-core'; + +/** + * Base attributes value + */ +export const odsBreadcrumbItemBaseAttributes: OdsBreadcrumbItemAttributes = { + href: '', + isCollapsed: false, + isExpandableItem: false, + isLast: false, +}; diff --git a/packages/libraries/testing/src/components/breadcrumb/breadcrumb-item/public-api.ts b/packages/libraries/testing/src/components/breadcrumb/breadcrumb-item/public-api.ts new file mode 100644 index 0000000000..c4a4dfa01d --- /dev/null +++ b/packages/libraries/testing/src/components/breadcrumb/breadcrumb-item/public-api.ts @@ -0,0 +1 @@ +export * from './ods-breadcrumb-item-base-attributes'; diff --git a/packages/libraries/testing/src/components/breadcrumb/breadcrumb/ods-breadcrumb-base-attributes.ts b/packages/libraries/testing/src/components/breadcrumb/breadcrumb/ods-breadcrumb-base-attributes.ts new file mode 100644 index 0000000000..12640d8074 --- /dev/null +++ b/packages/libraries/testing/src/components/breadcrumb/breadcrumb/ods-breadcrumb-base-attributes.ts @@ -0,0 +1,8 @@ +import { OdsBreadcrumbAttributes } from '@ovhcloud/ods-core'; + +/** + * Base attributes value + */ +export const odsBreadcrumbBaseAttributes: OdsBreadcrumbAttributes = { + items: [], +}; diff --git a/packages/libraries/testing/src/components/breadcrumb/breadcrumb/public-api.ts b/packages/libraries/testing/src/components/breadcrumb/breadcrumb/public-api.ts new file mode 100644 index 0000000000..3037926f65 --- /dev/null +++ b/packages/libraries/testing/src/components/breadcrumb/breadcrumb/public-api.ts @@ -0,0 +1 @@ +export * from './ods-breadcrumb-base-attributes'; diff --git a/packages/libraries/testing/src/components/breadcrumb/public-api.ts b/packages/libraries/testing/src/components/breadcrumb/public-api.ts new file mode 100644 index 0000000000..f3d025ba16 --- /dev/null +++ b/packages/libraries/testing/src/components/breadcrumb/public-api.ts @@ -0,0 +1,2 @@ +export * from './breadcrumb/public-api'; +export * from './breadcrumb-item/public-api'; diff --git a/packages/libraries/testing/src/components/public-api.ts b/packages/libraries/testing/src/components/public-api.ts index 5e2e9fa5de..05873a62f1 100644 --- a/packages/libraries/testing/src/components/public-api.ts +++ b/packages/libraries/testing/src/components/public-api.ts @@ -27,3 +27,4 @@ export * from './textarea/public-api'; export * from './tile/public-api'; export * from './toggle/public-api'; export * from './spinner/public-api'; +export * from './breadcrumb/public-api'; \ No newline at end of file diff --git a/packages/libraries/theming/size/ods-size-definitions.scss b/packages/libraries/theming/size/ods-size-definitions.scss index 9bb12d82e5..a0674b088f 100644 --- a/packages/libraries/theming/size/ods-size-definitions.scss +++ b/packages/libraries/theming/size/ods-size-definitions.scss @@ -1,4 +1,5 @@ @import './ods-theming-size.accordion'; +@import './ods-theming-size.breadcrumb'; @import './ods-theming-size.button'; @import './ods-theming-size.cart'; @import './ods-theming-size.checkbox-button'; @@ -24,6 +25,7 @@ /// @access public $ods-size-definitions: ( accordion: ods-get-accordion-component-size-definition(), + breadcrumb: ods-get-breadcrumb-component-size-definition(), button: ods-get-button-component-size-definition(), cart: ods-get-cart-component-size-definition(), checkbox-button: ods-get-checkbox-button-component-size-definition(), diff --git a/packages/libraries/theming/size/ods-theming-size.breadcrumb.scss b/packages/libraries/theming/size/ods-theming-size.breadcrumb.scss new file mode 100644 index 0000000000..4ed3580a49 --- /dev/null +++ b/packages/libraries/theming/size/ods-theming-size.breadcrumb.scss @@ -0,0 +1,13 @@ +/// @access private +@function ods-get-breadcrumb-size-properties($size-name) { + @return ( + padding: var(--ods-size-breadcrumb-#{$size-name}-padding) + ) +} + +/// @access private +@function ods-get-breadcrumb-component-size-definition() { + @return ( + md: ods-get-breadcrumb-size-properties(md) + ); +} diff --git a/packages/libraries/theming/size/ods-theming-size.scss b/packages/libraries/theming/size/ods-theming-size.scss index 26308279e6..946708d941 100644 --- a/packages/libraries/theming/size/ods-theming-size.scss +++ b/packages/libraries/theming/size/ods-theming-size.scss @@ -53,6 +53,7 @@ /// @access public @function ods-create-size-config( $accordion, + $breadcrumb, $button, $cart, $checkbox-button, @@ -74,6 +75,7 @@ ) { @return ( accordion: ods-create-component-size-config(accordion, $accordion), + breadcrumb: ods-create-component-size-config(breadcrumb, $breadcrumb), button: ods-create-component-size-config(button, $button), cart: ods-create-component-size-config(cart, $cart), checkbox-button: ods-create-component-size-config(checkbox-button, $checkbox-button), diff --git a/packages/specifications/components/breadcrumb/specifications-breadcrumb-contents.mdx b/packages/specifications/components/breadcrumb/specifications-breadcrumb-contents.mdx new file mode 100644 index 0000000000..8044ac46ab --- /dev/null +++ b/packages/specifications/components/breadcrumb/specifications-breadcrumb-contents.mdx @@ -0,0 +1,3 @@ +| Name | default | Description | +|---------|---------|-------------| +| - | '' | | diff --git a/packages/specifications/components/breadcrumb/specifications-breadcrumb-events.mdx b/packages/specifications/components/breadcrumb/specifications-breadcrumb-events.mdx new file mode 100644 index 0000000000..61b93206c8 --- /dev/null +++ b/packages/specifications/components/breadcrumb/specifications-breadcrumb-events.mdx @@ -0,0 +1 @@ +_none_ diff --git a/packages/specifications/components/breadcrumb/specifications-breadcrumb-methods.mdx b/packages/specifications/components/breadcrumb/specifications-breadcrumb-methods.mdx new file mode 100644 index 0000000000..61b93206c8 --- /dev/null +++ b/packages/specifications/components/breadcrumb/specifications-breadcrumb-methods.mdx @@ -0,0 +1 @@ +_none_ diff --git a/packages/specifications/components/breadcrumb/specifications-breadcrumb-properties.mdx b/packages/specifications/components/breadcrumb/specifications-breadcrumb-properties.mdx new file mode 100644 index 0000000000..ffbff6cf2e --- /dev/null +++ b/packages/specifications/components/breadcrumb/specifications-breadcrumb-properties.mdx @@ -0,0 +1,3 @@ +| Name | Type | default | Description | +|------|------|---------|-------------| +| | | | | diff --git a/packages/specifications/components/breadcrumb/specifications-breadcrumb-tests.mdx b/packages/specifications/components/breadcrumb/specifications-breadcrumb-tests.mdx new file mode 100644 index 0000000000..61b93206c8 --- /dev/null +++ b/packages/specifications/components/breadcrumb/specifications-breadcrumb-tests.mdx @@ -0,0 +1 @@ +_none_ diff --git a/packages/specifications/components/breadcrumb/specifications-breadcrumb.mdx b/packages/specifications/components/breadcrumb/specifications-breadcrumb.mdx new file mode 100644 index 0000000000..77ede94e8f --- /dev/null +++ b/packages/specifications/components/breadcrumb/specifications-breadcrumb.mdx @@ -0,0 +1,14 @@ +import {Description} from '@storybook/addon-docs'; + +[//]: # (import Specs from '@ovhcloud/ods-core/src/components/breadcrumb/docs/spec.md';) +import Specs from '@ovhcloud/ods-core/src/components/breadcrumb/docs/spec.md'; +import SpecsBreadcrumbContents from '@ovhcloud/ods-specifications/components/breadcrumb/specifications-breadcrumb-contents.mdx'; +import SpecsBreadcrumbTests from '@ovhcloud/ods-specifications/components/breadcrumb/specifications-breadcrumb-tests.mdx'; + +{Specs} + +## Contents + + +## Tests + diff --git a/packages/stencil/components/breadcrumb/.gitignore b/packages/stencil/components/breadcrumb/.gitignore new file mode 100644 index 0000000000..d9e1d2628b --- /dev/null +++ b/packages/stencil/components/breadcrumb/.gitignore @@ -0,0 +1,33 @@ +dist/ +custom-elements/ +custom-elements-bundle/ +www/ +loader/ +docs-api +src/components.d.ts + +*~ +*.sw[mnpcod] +*.log +*.lock +*.tmp +*.tmp.* +log.txt +*.sublime-project +*.sublime-workspace + +.stencil/ +screenshot/ +.idea/ +.vscode/ +.sass-cache/ +.versions/ +node_modules/ +$RECYCLE.BIN/ + +.DS_Store +Thumbs.db +UserInterfaceState.xcuserstate +.env + +src/**/readme.md diff --git a/packages/stencil/components/breadcrumb/.npmignore b/packages/stencil/components/breadcrumb/.npmignore new file mode 100644 index 0000000000..a93bc21a3f --- /dev/null +++ b/packages/stencil/components/breadcrumb/.npmignore @@ -0,0 +1,4 @@ +!dist/ +!loader/ +!docs-api/ +src/ diff --git a/packages/stencil/components/breadcrumb/CHANGELOG.md b/packages/stencil/components/breadcrumb/CHANGELOG.md new file mode 100644 index 0000000000..e4d87c4d45 --- /dev/null +++ b/packages/stencil/components/breadcrumb/CHANGELOG.md @@ -0,0 +1,4 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/stencil/components/breadcrumb/THIRD-PARTY-LICENCES b/packages/stencil/components/breadcrumb/THIRD-PARTY-LICENCES new file mode 100644 index 0000000000..fbfb0992b6 --- /dev/null +++ b/packages/stencil/components/breadcrumb/THIRD-PARTY-LICENCES @@ -0,0 +1,5 @@ +This file was generated with the generate-license-file npm package! +https://www.npmjs.com/package/generate-license-file + +This file was generated with the generate-license-file npm package! +https://www.npmjs.com/package/generate-license-file diff --git a/packages/stencil/components/breadcrumb/jest.config.ts b/packages/stencil/components/breadcrumb/jest.config.ts new file mode 100644 index 0000000000..03c8f901bd --- /dev/null +++ b/packages/stencil/components/breadcrumb/jest.config.ts @@ -0,0 +1,22 @@ +import type { Config } from '@jest/types'; +import { OdsGetJestConfig } from '@ovhcloud/ods-testing'; + +const args = process.argv.slice(2); + +/** + * synchronous config for jest. + * + * example with async config : + * ```typescript + * export default async (): Promise => { + * return { + * verbose: true, + * }; + * }; + * ``` + */ +const config: Config.InitialOptions = OdsGetJestConfig({ + basePath: '/../../../..', + args +}); +export default config; diff --git a/packages/stencil/components/breadcrumb/package.json b/packages/stencil/components/breadcrumb/package.json new file mode 100644 index 0000000000..1fc83a70a2 --- /dev/null +++ b/packages/stencil/components/breadcrumb/package.json @@ -0,0 +1,46 @@ +{ + "name": "@ovhcloud/ods-stencil-breadcrumb", + "version": "12.0.5", + "private": true, + "description": "Breadcrumb component", + "author": "OVH SAS", + "license": "Apache-2.0", + "main": "dist/index.cjs.js", + "module": "dist/index.js", + "es2015": "dist/esm/index.js", + "es2017": "dist/esm/index.js", + "types": "dist/types/components.d.ts", + "collection": "dist/collection/collection-manifest.json", + "collection:main": "dist/collection/index.js", + "scripts": { + "build:prod": "npm run build:stencil --if-present && npm run build:react --if-present && npm run build:vue --if-present", + "build": "echo \"use build:prod\"", + "build:stencil": "stencil build --docs --prod --config stencil.config.ts", + "build:react": "npm --prefix react run build", + "build:vue": "npm --prefix vue run build", + "watch": "stencil build --docs --watch --dev --config stencil.config.ts", + "start": "stencil build --docs --dev --watch --serve", + "ignore:rm": "git clean -Xdf", + "generate": "stencil generate", + "doc:api": "typedoc", + "generate:licence": "npx generate-license-file --input package.json --output THIRD-PARTY-LICENCES --overwrite", + "test": "yarn run test:spec && yarn run test:e2e", + "test:spec": "stencil test --spec --config stencil.config.ts --coverage", + "test:spec:ci": "stencil test --config stencil.config.ts --spec --ci --coverage", + "test:e2e": "stencil test --e2e --config stencil.config.ts", + "test:e2e:screenshot": "stencil test --e2e --screenshot --config stencil.config.ts --passWithNoTests", + "test:e2e:screenshot:update": "stencil test --e2e --screenshot --config stencil.config.ts --update-screenshot --passWithNoTests", + "test:e2e:ci": "stencil test --config stencil.config.ts --e2e --ci", + "test:e2e:ci:screenshot": "stencil test --config stencil.config.ts --e2e --ci --screenshot --passWithNoTests", + "test:e2e:ci:screenshot:update": "stencil test --config stencil.config.ts --e2e --ci --screenshot --update-screenshot --passWithNoTests" + }, + "dependencies": { + "@ovhcloud/ods-stencil-component": "^12.0.5" + }, + "devDependencies": { + "@ovhcloud/ods-stencil-component-dev": "^12.0.5" + }, + "publishConfig": { + "registry": "" + } +} diff --git a/packages/stencil/components/breadcrumb/react/.gitignore b/packages/stencil/components/breadcrumb/react/.gitignore new file mode 100644 index 0000000000..496f9a49cd --- /dev/null +++ b/packages/stencil/components/breadcrumb/react/.gitignore @@ -0,0 +1,2 @@ +dist/ +src/ diff --git a/packages/stencil/components/breadcrumb/react/.npmignore b/packages/stencil/components/breadcrumb/react/.npmignore new file mode 100644 index 0000000000..3753d5f6a1 --- /dev/null +++ b/packages/stencil/components/breadcrumb/react/.npmignore @@ -0,0 +1,2 @@ +!dist/ +src/ diff --git a/packages/stencil/components/breadcrumb/react/CHANGELOG.md b/packages/stencil/components/breadcrumb/react/CHANGELOG.md new file mode 100644 index 0000000000..e9fb6ecf59 --- /dev/null +++ b/packages/stencil/components/breadcrumb/react/CHANGELOG.md @@ -0,0 +1,4 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. \ No newline at end of file diff --git a/packages/stencil/components/breadcrumb/react/package.json b/packages/stencil/components/breadcrumb/react/package.json new file mode 100644 index 0000000000..5787f081f3 --- /dev/null +++ b/packages/stencil/components/breadcrumb/react/package.json @@ -0,0 +1,38 @@ +{ + "name": "@ovhcloud/ods-stencil-breadcrumb-react", + "version": "12.0.5", + "private": true, + "description": "React specific wrapper for ods", + "keywords": [], + "author": "OVH SAS", + "license": "Apache-2.0", + "scripts": { + "build": "npm run clean && npm run compile", + "clean": "rimraf dist", + "compile": "npm run compile:esm && npm run compile:cjs", + "compile:esm": "tsc -p tsconfig.json", + "compile:cjs": "tsc -p tsconfig.cjs.json" + }, + "main": "dist/cjs/index.js", + "module": "dist/esm/index.js", + "types": "dist/types/index.d.ts", + "files": [ + "dist/" + ], + "dependencies": { + "@ovhcloud/ods-stencil-breadcrumb": "^12.0.5", + "tslib": "*" + }, + "peerDependencies": { + "react": ">=16.8.6", + "react-dom": ">=16.8.6" + }, + "devDependencies": { + "@types/react": "17.0.37", + "@types/react-dom": "17.0.11", + "react": "16.14.0", + "react-dom": "16.14.0", + "rimraf": "^3.0.2", + "typescript": "4.7.4" + } +} diff --git a/packages/stencil/components/breadcrumb/react/tsconfig.cjs.json b/packages/stencil/components/breadcrumb/react/tsconfig.cjs.json new file mode 100644 index 0000000000..164b6b818e --- /dev/null +++ b/packages/stencil/components/breadcrumb/react/tsconfig.cjs.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "dist/cjs", + "module": "CommonJS", + "declaration": false, + "declarationDir": null + } +} diff --git a/packages/stencil/components/breadcrumb/react/tsconfig.json b/packages/stencil/components/breadcrumb/react/tsconfig.json new file mode 100644 index 0000000000..816d5b7e90 --- /dev/null +++ b/packages/stencil/components/breadcrumb/react/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.react.json", + "compilerOptions": { + "outDir": "dist/esm", + "declarationDir": "dist/types" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"] +} diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/osds-breadcrumb-item.e2e.screenshot.ts b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/osds-breadcrumb-item.e2e.screenshot.ts new file mode 100644 index 0000000000..d9a06bf14b --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/osds-breadcrumb-item.e2e.screenshot.ts @@ -0,0 +1,72 @@ +import { E2EPage, newE2EPage } from '@stencil/core/testing'; +import { + OdsBreadcrumbItemAttributes, + odsBreadcrumbItemDefaultAttributes, + OdsComponentAttributes2StringAttributes, + OdsIconName +} from '@ovhcloud/ods-core'; +import { odsBreadcrumbItemBaseAttributes, OdsCreateAttributes, OdsStringAttributes2Str } from '@ovhcloud/ods-testing'; + +describe('e2e:osds-breadcrumb-item', () => { + let page: E2EPage; + + async function setup({ attributes = {} }: { attributes?: Partial } = {}) { + const minimalAttributes: OdsBreadcrumbItemAttributes = OdsCreateAttributes(attributes, odsBreadcrumbItemBaseAttributes); + const stringAttributes = OdsComponentAttributes2StringAttributes(minimalAttributes, odsBreadcrumbItemDefaultAttributes); + + page = await newE2EPage(); + await page.setContent(``); + await page.evaluate(() => document.body.style.setProperty('margin', '0')); + } + + describe('screenshots', () => { + it('should render', async () => { + await setup({ attributes: { href: 'dummyHref', isCollapsed: false, label: 'dummyLabel' } }); + + const results = await page.compareScreenshot('breadcrumb-item', { fullPage: false, omitBackground: true }); + expect(results).toMatchScreenshot({ allowableMismatchedRatio: 0 }); + }); + + it('should render link with text only', async () => { + await setup({ attributes: { href: 'dummyHref', label: 'dummyLabel' }}); + + const results = await page.compareScreenshot('breadcrumb-item', { fullPage: false, omitBackground: true }); + expect(results).toMatchScreenshot({ allowableMismatchedRatio: 0 }); + }); + + it('should render link with icon only', async () => { + await setup({ attributes: { href: 'dummyHref', icon: OdsIconName.HOME }}); + + const results = await page.compareScreenshot('breadcrumb-item', { fullPage: false, omitBackground: true }); + expect(results).toMatchScreenshot({ allowableMismatchedRatio: 0 }); + }); + + it('should render link with text and icon', async () => { + await setup({ attributes: { href: 'dummyHref', icon: OdsIconName.HOME, label: 'dummyLabel' }}); + + const results = await page.compareScreenshot('breadcrumb-item', { fullPage: false, omitBackground: true }); + expect(results).toMatchScreenshot({ allowableMismatchedRatio: 0 }); + }); + + it('should render link disabled', async () => { + await setup({ attributes: { href: 'dummyHref', isLast: true, label: 'dummyLabel' }}); + + const results = await page.compareScreenshot('breadcrumb-item', { fullPage: false, omitBackground: true }); + expect(results).toMatchScreenshot({ allowableMismatchedRatio: 0 }); + }); + + it('should render as collapsed item', async () => { + await setup({ attributes: { href: 'dummyHref', isCollapsed: true, isExpandableItem: true, label: 'dummyLabel' }}); + + const results = await page.compareScreenshot('breadcrumb-item', { fullPage: false, omitBackground: true }); + expect(results).toMatchScreenshot({ allowableMismatchedRatio: 0 }); + }); + + it('should render contrasted', async () => { + await setup({ attributes: { contrasted: true, href: 'dummyHref', isCollapsed: false, label: 'dummyLabel' } }); + + const results = await page.compareScreenshot('breadcrumb-item', { fullPage: false, omitBackground: true }); + expect(results).toMatchScreenshot({ allowableMismatchedRatio: 0 }); + }); + }); +}); diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/osds-breadcrumb-item.e2e.ts b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/osds-breadcrumb-item.e2e.ts new file mode 100644 index 0000000000..06a09302c1 --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/osds-breadcrumb-item.e2e.ts @@ -0,0 +1,167 @@ +import { E2EElement, E2EPage, newE2EPage } from '@stencil/core/testing'; +import { + OdsBreadcrumbItemAttributes, + OdsComponentAttributes2StringAttributes, + odsBreadcrumbItemDefaultAttributes, + OdsIconName +} from '@ovhcloud/ods-core'; +import { OdsCreateAttributes, OdsStringAttributes2Str, odsBreadcrumbItemBaseAttributes } from '@ovhcloud/ods-testing'; + +describe('e2e:osds-breadcrumb-item', () => { + let page: E2EPage; + let el: E2EElement; + + async function setup({ attributes }: { attributes: Partial }) { + const minimalAttributes: OdsBreadcrumbItemAttributes = OdsCreateAttributes(attributes, odsBreadcrumbItemBaseAttributes); + const stringAttributes = OdsComponentAttributes2StringAttributes(minimalAttributes, odsBreadcrumbItemDefaultAttributes); + + page = await newE2EPage(); + await page.setContent(``); + await page.evaluate(() => document.body.style.setProperty('margin', '0px')); + + el = await page.find('osds-breadcrumb-item'); + } + + it('should render', async () => { + await setup({ attributes: {} }); + + expect(el).not.toBeNull(); + expect(el).toHaveClass('hydrated'); + }); + + it('should render not collapsed', async () => { + await setup({ attributes: { isCollapsed: false } }); + + expect(el).not.toHaveClass('collapsed'); + }); + + it('should render collapsed', async () => { + await setup({ attributes: { isCollapsed: true } }); + + expect(el).toHaveClass('collapsed'); + }); + + describe('item', () => { + const dummyHref = '#dummy-href'; + const dummyIcon = OdsIconName.HOME; + const dummyLabel = 'dummy label'; + let itemLinkElement: E2EElement; + let iconElement: E2EElement; + + async function setupItem(attributes: Partial) { + await setup({ attributes }); + + itemLinkElement = await page.find('osds-breadcrumb-item >>> .item > osds-link'); + iconElement = await itemLinkElement.find('osds-icon'); + } + + it('should render link with text only', async () => { + await setupItem({ href: dummyHref, label: dummyLabel }); + + expect(itemLinkElement.getAttribute('href')).toBe(dummyHref); + expect(itemLinkElement.getAttribute('disabled')).toBeNull(); + expect(itemLinkElement.innerText).toBe(dummyLabel); + expect(iconElement).toBeNull(); + }); + + it('should render link with icon only', async () => { + await setupItem({ href: dummyHref, icon: dummyIcon }); + + expect(itemLinkElement.getAttribute('href')).toBe(dummyHref); + expect(itemLinkElement.getAttribute('disabled')).toBeNull(); + expect(itemLinkElement.innerText).toBe(''); + expect(iconElement.getAttribute('name')).toBe(dummyIcon); + }); + + it('should render link with text and icon', async () => { + await setupItem({ href: dummyHref, icon: dummyIcon, label: dummyLabel }); + + expect(itemLinkElement.getAttribute('href')).toBe(dummyHref); + expect(itemLinkElement.getAttribute('disabled')).toBeNull(); + expect(itemLinkElement.innerText).toBe(dummyLabel); + expect(iconElement.getAttribute('name')).toBe(dummyIcon); + }); + + it('should render link disabled', async () => { + await setupItem({ href: dummyHref, isLast: true }); + + expect(itemLinkElement.getAttribute('href')).toBe(dummyHref); + expect(itemLinkElement.getAttribute('disabled')).not.toBeNull(); + }); + + it('should render contrasted', async () => { + await setupItem({ contrasted: true, href: dummyHref, icon: dummyIcon, label: dummyLabel }); + + expect(itemLinkElement.getAttribute('contrasted')).not.toBeNull(); + expect(iconElement.getAttribute('contrasted')).not.toBeNull(); + }); + }); + + describe('collapsed item', () => { + let collapsedItem: E2EElement; + + async function setupCollapsedItem(attributes: Partial) { + await setup({ attributes }); + + collapsedItem = await page.find('osds-breadcrumb-item >>> osds-link.expandable'); + } + + it('should not be rendered if not isExpandableItem', async () => { + await setupCollapsedItem({}); + + expect(collapsedItem).toBeNull(); + }); + + it('should be rendered if isExpandableItem', async () => { + await setupCollapsedItem({ isExpandableItem: true }); + + expect(collapsedItem).not.toBeNull(); + }); + + it('should render contrasted', async () => { + await setupCollapsedItem({ contrasted: true, isExpandableItem: true }); + + expect(collapsedItem.getAttribute('contrasted')).not.toBeNull(); + }); + }); + + describe('separator', () => { + let separatorItem: E2EElement; + + async function setupSeparator(attributes: Partial) { + await setup({ attributes }); + + separatorItem = await page.find('osds-breadcrumb-item >>> osds-text.separator'); + } + + it('should not be rendered if isLast', async () => { + await setupSeparator({ isLast: true }); + + expect(separatorItem).toBeNull(); + }); + + it('should not be rendered if isCollapsed but not isExpandableItem', async () => { + await setupSeparator({ isCollapsed: true, isExpandableItem: false }); + + expect(separatorItem).toBeNull(); + }); + + it('should be rendered if isCollapsed and isExpandableItem', async () => { + await setupSeparator({ isCollapsed: true, isExpandableItem: true }); + + expect(separatorItem).not.toBeNull(); + }); + + it('should be rendered if not isCollapsed', async () => { + await setupSeparator({ isCollapsed: false }); + + expect(separatorItem).not.toBeNull(); + }); + + it('should render contrasted', async () => { + await setupSeparator({ contrasted: true, isCollapsed: false }); + + expect(separatorItem.getAttribute('contrasted')).not.toBeNull(); + }); + }); +}); diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/osds-breadcrumb-item.scss b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/osds-breadcrumb-item.scss new file mode 100644 index 0000000000..54976f3a62 --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/osds-breadcrumb-item.scss @@ -0,0 +1,21 @@ +@import 'styles/osds-breadcrumb-item.mixins'; +@import 'styles/osds-breadcrumb-item.color'; +@import 'styles/osds-breadcrumb-item.size'; +@import 'styles/osds-breadcrumb-item.typography'; +@import '~@ovhcloud/ods-theming/color/ods-theming-color'; +@import '~@ovhcloud/ods-theming/ods-theme'; + +:host { + display: flex; + align-items: center; +} + +:host(.collapsed) .item { + display: none; +} + +@include ods-theme-component() { + @include osds-breadcrumb-item-theme-color(); + @include osds-breadcrumb-item-theme-size(); + @include osds-breadcrumb-item-theme-typography(); +} diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/osds-breadcrumb-item.spec.ts b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/osds-breadcrumb-item.spec.ts new file mode 100644 index 0000000000..14a182da7a --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/osds-breadcrumb-item.spec.ts @@ -0,0 +1,42 @@ +import { + OdsBreadcrumbItemAttributes, + odsBreadcrumbItemDefaultAttributes, + OdsComponentAttributes2StringAttributes +} from '@ovhcloud/ods-core'; +import { + OdsCreateAttributes, + OdsStringAttributes2Str, + odsBreadcrumbItemBaseAttributes, +} from '@ovhcloud/ods-testing'; +import { SpecPage, newSpecPage } from '@stencil/core/testing'; +import { OsdsBreadcrumbItem } from './osds-breadcrumb-item'; + +describe('spec:osds-breadcrumb-item', () => { + let page: SpecPage; + let root: HTMLElement | undefined; + let instance: OsdsBreadcrumbItem; + + afterEach(() => { + jest.clearAllMocks(); + }); + + async function setup({ attributes = {} }: { attributes?: Partial } = {}) { + const minimalAttributes: OdsBreadcrumbItemAttributes = OdsCreateAttributes(attributes, odsBreadcrumbItemBaseAttributes); + const stringAttributes = OdsComponentAttributes2StringAttributes(minimalAttributes, odsBreadcrumbItemDefaultAttributes); + + page = await newSpecPage({ + components: [OsdsBreadcrumbItem], + html: ``, + }); + + root = page.root; + instance = page.rootInstance; + } + + it('should render', async () => { + await setup({}); + + expect(root?.shadowRoot).toBeTruthy(); + expect(instance).toBeTruthy(); + }); +}); diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/osds-breadcrumb-item.tsx b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/osds-breadcrumb-item.tsx new file mode 100644 index 0000000000..c090cb10a9 --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/osds-breadcrumb-item.tsx @@ -0,0 +1,105 @@ +import { Component, Element, Event, EventEmitter, Host, h, Prop } from '@stencil/core'; +import { + OdsBreadcrumbItem, + OdsBreadcrumbItemController, + odsBreadcrumbItemDefaultAttributes, + OdsBreadcrumbItemEvents, + OdsBreadcrumbItemMethods, + OdsIconName, + OdsIconSize, +} from '@ovhcloud/ods-core'; +import { OdsStencilEvents, OdsStencilMethods } from '@ovhcloud/ods-stencil/libraries/stencil-core'; +import { OdsThemeColorIntent } from '@ovhcloud/ods-theming'; + +/** + * @slot (unnamed) - Breadcrumb Item content + */ +@Component({ + tag: 'osds-breadcrumb-item', + styleUrl: 'osds-breadcrumb-item.scss', + shadow: true +}) +export class OsdsBreadcrumbItem implements OdsBreadcrumbItem, OdsStencilEvents> { + private defaultColorIntent = OdsThemeColorIntent.primary; + controller: OdsBreadcrumbItemController = new OdsBreadcrumbItemController(this); + @Element() el!: HTMLElement; + + /** @see OdsBreadcrumbItemAttributes.contrasted */ + @Prop({ reflect: true }) public contrasted?: boolean = odsBreadcrumbItemDefaultAttributes.contrasted; + + /** @internal */ + @Prop() isCollapsed = odsBreadcrumbItemDefaultAttributes.isCollapsed; + + /** @internal */ + @Prop() isExpandableItem = odsBreadcrumbItemDefaultAttributes.isExpandableItem; + + /** @internal */ + @Prop() isLast = odsBreadcrumbItemDefaultAttributes.isLast; + + /** @see OdsBreadcrumbItemAttributes.href */ + @Prop({ reflect: true }) href = ''; + + /** @see OdsBreadcrumbItemAttributes.icon */ + @Prop({ reflect: true }) icon?: OdsIconName; + + /** @see OdsBreadcrumbItemAttributes.label */ + @Prop({ reflect: true }) label?: string; + + /** @see OdsBreadcrumbItemEvents.odsBreadcrumbItemCollapsedClick */ + @Event() odsBreadcrumbItemCollapsedClick!: EventEmitter; + + private onCollapsedElementClick() { + this.odsBreadcrumbItemCollapsedClick.emit(); + } + + render() { + const showSeparator = this.isLast ? false : this.isCollapsed ? this.isExpandableItem : true; + + return ( + +
+ + { + !!this.icon && + + + + + } + {this.label} + +
+ + { + this.isExpandableItem && + + } + + { + showSeparator && + + } +
+ ); + } +} diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/public-api.ts b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/public-api.ts new file mode 100644 index 0000000000..c4c75f224a --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/public-api.ts @@ -0,0 +1 @@ +export { OsdsBreadcrumbItem } from './osds-breadcrumb-item' diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/styles/osds-breadcrumb-item.color.scss b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/styles/osds-breadcrumb-item.color.scss new file mode 100644 index 0000000000..a702558217 --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/styles/osds-breadcrumb-item.color.scss @@ -0,0 +1,27 @@ +@import '~@ovhcloud/ods-theming/color/ods-component-color'; +@import './osds-breadcrumb-item.mixins'; + +@mixin osds-breadcrumb-item-theme-color-variant-default() { + @include ods-and-all-hue-foreach-theme-color(( + color: '800', + background-color: '100' + )) using($colors) { + @include osds-breadcrumb-item-on-selected-host() { + //color: map_get($colors, color); + //background-color: map_get($colors, background-color); + } + } +} + +// Main CSS color theme mixin +@mixin osds-breadcrumb-item-theme-color() { + /** base colors */ + :host { + border-color: transparent; + } + + /** no variant specified: default variant colors */ + :not([variant]) { + @include osds-breadcrumb-item-theme-color-variant-default(); + } +} diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/styles/osds-breadcrumb-item.mixins.scss b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/styles/osds-breadcrumb-item.mixins.scss new file mode 100644 index 0000000000..786e168852 --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/styles/osds-breadcrumb-item.mixins.scss @@ -0,0 +1,13 @@ +// general mixins and functions for the component + +@mixin osds-breadcrumb-item-on-selected-host() { + :host(&) { + @content; + } +} + +@mixin osds-breadcrumb-item-on-main-element() { + .breadcrumb-item__wrapper { + @content; + } +} diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/styles/osds-breadcrumb-item.size.scss b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/styles/osds-breadcrumb-item.size.scss new file mode 100644 index 0000000000..8b626e9913 --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/styles/osds-breadcrumb-item.size.scss @@ -0,0 +1,16 @@ +@import './osds-breadcrumb-item.mixins'; +@import '~@ovhcloud/ods-theming/size/ods-component-size'; + +// Main CSS mixin for sizes +@mixin osds-breadcrumb-item-theme-size() { + $size-definitions: ods-get-size-definitions(); + $component-size-definition: ods-get-component-size-definition($size-definitions, breadcrumb); + $size-properties: ods-get-size-properties($component-size-definition, md); + + :host { + .expandable, + .item { + padding: ods-get-size-property($size-properties, padding); + } + } +} diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/styles/osds-breadcrumb-item.typography.scss b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/styles/osds-breadcrumb-item.typography.scss new file mode 100644 index 0000000000..8aa4486cf6 --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb-item/styles/osds-breadcrumb-item.typography.scss @@ -0,0 +1,16 @@ +@import '~@ovhcloud/ods-theming/typography/ods-theming-typography'; +@import '~@ovhcloud/ods-theming/typography/ods-component-typography'; +@import './osds-breadcrumb-item.mixins'; + +// Main CSS mixin for typography +@mixin osds-breadcrumb-item-theme-typography() { + :host([size='md']) .breadcrumb-item__wrapper { + //$typography-properties: ods-get-typography-properties(body, '400'); + //font-family: ods-get-typography-property($typography-properties, font-family); + //font-size: ods-get-typography-property($typography-properties, font-size); + //font-style: ods-get-typography-property($typography-properties, font-style); + //font-weight: ods-get-typography-property($typography-properties, font-weight); + //letter-spacing: ods-get-typography-property($typography-properties, letter-spacing); + //line-height: ods-get-typography-property($typography-properties, line-height); + } +} diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/osds-breadcrumb.e2e.screenshot.ts b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/osds-breadcrumb.e2e.screenshot.ts new file mode 100644 index 0000000000..0018962197 --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/osds-breadcrumb.e2e.screenshot.ts @@ -0,0 +1,76 @@ +import { E2EPage, newE2EPage } from '@stencil/core/testing'; +import { + OdsBreadcrumbAttributes, + odsBreadcrumbDefaultAttributes, + OdsComponentAttributes2StringAttributes, + OdsIconName +} from '@ovhcloud/ods-core'; +import { OdsStringAttributes2Str } from '@ovhcloud/ods-testing'; + +describe('e2e:osds-breadcrumb', () => { + let page: E2EPage; + + async function setup({ attributes }: { attributes: OdsBreadcrumbAttributes }) { + const stringAttributes = OdsComponentAttributes2StringAttributes>({ contrasted: attributes.contrasted }, odsBreadcrumbDefaultAttributes); + + page = await newE2EPage(); + await page.setContent(``); + await page.evaluate(() => document.body.style.setProperty('margin', '0')); + } + + describe('screenshots', () => { + it('should render with 4 visible items', async () => { + const dummyItems = [ + {href: 'href1', label: 'label1'}, + {href: 'href2', label: 'label2'}, + {href: 'href3', label: 'label3'}, + {href: 'href4', label: 'label4'}, + ]; + await setup({ attributes: { items: dummyItems }}); + + const results = await page.compareScreenshot('breadcrumb', { fullPage: false, omitBackground: true }); + expect(results).toMatchScreenshot({ allowableMismatchedRatio: 0 }); + }); + + it('should render with icons and text', async () => { + const dummyItems = [ + {href: 'href1', icon: OdsIconName.HOME }, + {href: 'href2', icon: OdsIconName.BOOK, label: 'label2'}, + {href: 'href3', label: 'label3'}, + {href: 'href4', label: 'label4'}, + ]; + await setup({ attributes: { items: dummyItems }}); + + const results = await page.compareScreenshot('breadcrumb', { fullPage: false, omitBackground: true }); + expect(results).toMatchScreenshot({ allowableMismatchedRatio: 0 }); + }); + + it('should render first and last items and a collapsed one in the middle', async () => { + const dummyItems = [ + {href: 'href1', label: 'label1'}, + {href: 'href2', label: 'label2'}, + {href: 'href3', label: 'label3'}, + {href: 'href4', label: 'label4'}, + {href: 'href5', label: 'label5'}, + {href: 'href6', label: 'label6'}, + ]; + await setup({ attributes: { items: dummyItems }}); + + const results = await page.compareScreenshot('breadcrumb', { fullPage: false, omitBackground: true }); + expect(results).toMatchScreenshot({ allowableMismatchedRatio: 0 }); + }); + + it('should render contrasted', async () => { + const dummyItems = [ + {href: 'href1', label: 'label1'}, + {href: 'href2', label: 'label2'}, + {href: 'href3', label: 'label3'}, + {href: 'href4', label: 'label4'}, + ]; + await setup({ attributes: { contrasted: true, items: dummyItems }}); + + const results = await page.compareScreenshot('breadcrumb', { fullPage: false, omitBackground: true }); + expect(results).toMatchScreenshot({ allowableMismatchedRatio: 0 }); + }); + }); +}); diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/osds-breadcrumb.e2e.ts b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/osds-breadcrumb.e2e.ts new file mode 100644 index 0000000000..228b48555f --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/osds-breadcrumb.e2e.ts @@ -0,0 +1,128 @@ +import { E2EElement, E2EPage, newE2EPage } from '@stencil/core/testing'; +import { OdsBreadcrumbAttributeItem } from '@ovhcloud/ods-core'; + +describe('e2e:osds-breadcrumb', () => { + const dummyItems = [ + {href: 'href1', label: 'label1'}, + {href: 'href2', label: 'label2'}, + {href: 'href3', label: 'label3'}, + {href: 'href4', label: 'label4'}, + ]; + let page: E2EPage; + let el: E2EElement; + let breadcrumbItemElements: E2EElement[]; + + function isItemVisible(breadcrumbItemElement: E2EElement): boolean { + return !breadcrumbItemElement.classList.contains('collapsed'); + } + + function isExpandableItem(breadcrumbItemElement: E2EElement): boolean { + return !!breadcrumbItemElement.shadowRoot.querySelector('osds-link.expandable'); + } + + async function setup(items: OdsBreadcrumbAttributeItem[] = []) { + page = await newE2EPage(); + + await page.setContent(``); + await page.evaluate(() => document.body.style.setProperty('margin', '0px')); + + el = await page.find('osds-breadcrumb'); + breadcrumbItemElements = await page.findAll('osds-breadcrumb >>> osds-breadcrumb-item'); + } + + it('should render', async () => { + await setup(); + + expect(el).not.toBeNull(); + expect(el).toHaveClass('hydrated'); + }); + + it('should render with 4 visible items', async () => { + await setup(dummyItems); + + expect(breadcrumbItemElements.length).toBe(dummyItems.length); + + expect(isItemVisible(breadcrumbItemElements[0])).toBe(true); + expect(isExpandableItem(breadcrumbItemElements[0])).toBe(false); + + expect(isItemVisible(breadcrumbItemElements[1])).toBe(true); + expect(isExpandableItem(breadcrumbItemElements[1])).toBe(false); + + expect(isItemVisible(breadcrumbItemElements[2])).toBe(true); + expect(isExpandableItem(breadcrumbItemElements[2])).toBe(false); + + expect(isItemVisible(breadcrumbItemElements[3])).toBe(true); + expect(isExpandableItem(breadcrumbItemElements[3])).toBe(false); + }); + + it('should render first and last items and a collapsed one in the middle', async () => { + const moreDummyItems = [...dummyItems, + {href: 'href5', label: 'label5'}, + {href: 'href6', label: 'label6'}, + ]; + await setup(moreDummyItems); + + expect(breadcrumbItemElements.length).toBe(moreDummyItems.length); + + expect(isItemVisible(breadcrumbItemElements[0])).toBe(true); + expect(isExpandableItem(breadcrumbItemElements[0])).toBe(false); + + expect(isItemVisible(breadcrumbItemElements[1])).toBe(false); + expect(isExpandableItem(breadcrumbItemElements[1])).toBe(true); + + expect(isItemVisible(breadcrumbItemElements[2])).toBe(false); + expect(isExpandableItem(breadcrumbItemElements[2])).toBe(false); + + expect(isItemVisible(breadcrumbItemElements[3])).toBe(false); + expect(isExpandableItem(breadcrumbItemElements[3])).toBe(false); + + expect(isItemVisible(breadcrumbItemElements[4])).toBe(false); + expect(isExpandableItem(breadcrumbItemElements[4])).toBe(false); + + expect(isItemVisible(breadcrumbItemElements[5])).toBe(true); + expect(isExpandableItem(breadcrumbItemElements[5])).toBe(false); + }); + + it('should render all on collapsed item click', async () => { + const moreDummyItems = [...dummyItems, + { href: 'href5', label: 'label5' }, + { href: 'href6', label: 'label6' }, + ]; + await setup(moreDummyItems); + + expect(breadcrumbItemElements.length).toBe(moreDummyItems.length); + + expect(isItemVisible(breadcrumbItemElements[1])).toBe(false); + expect(isExpandableItem(breadcrumbItemElements[1])).toBe(true); + + await page.evaluate((index) => { + const breadcrumbItemElements = document.querySelector('osds-breadcrumb')?.shadowRoot?.querySelectorAll('osds-breadcrumb-item'); + if (breadcrumbItemElements && breadcrumbItemElements.length > index) { + const collapsedItem = breadcrumbItemElements[index].shadowRoot?.querySelector('osds-link.expandable') as HTMLButtonElement; + + if (collapsedItem) { + collapsedItem.click(); + } + } + }, 1); + await page.waitForChanges(); + + expect(isItemVisible(breadcrumbItemElements[0])).toBe(true); + expect(isExpandableItem(breadcrumbItemElements[0])).toBe(false); + + expect(isItemVisible(breadcrumbItemElements[1])).toBe(true); + expect(isExpandableItem(breadcrumbItemElements[1])).toBe(false); + + expect(isItemVisible(breadcrumbItemElements[2])).toBe(true); + expect(isExpandableItem(breadcrumbItemElements[2])).toBe(false); + + expect(isItemVisible(breadcrumbItemElements[3])).toBe(true); + expect(isExpandableItem(breadcrumbItemElements[3])).toBe(false); + + expect(isItemVisible(breadcrumbItemElements[4])).toBe(true); + expect(isExpandableItem(breadcrumbItemElements[4])).toBe(false); + + expect(isItemVisible(breadcrumbItemElements[5])).toBe(true); + expect(isExpandableItem(breadcrumbItemElements[5])).toBe(false); + }); +}); diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/osds-breadcrumb.scss b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/osds-breadcrumb.scss new file mode 100644 index 0000000000..2a9f6f76d4 --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/osds-breadcrumb.scss @@ -0,0 +1,18 @@ +@import 'styles/osds-breadcrumb.mixins'; +@import 'styles/osds-breadcrumb.color'; +@import 'styles/osds-breadcrumb.size'; +@import 'styles/osds-breadcrumb.typography'; +@import '~@ovhcloud/ods-theming/color/ods-theming-color'; +@import '~@ovhcloud/ods-theming/ods-theme'; + +:host { + display: flex; + flex-wrap: wrap; + align-items: center; +} + +@include ods-theme-component() { + @include osds-breadcrumb-theme-color(); + @include osds-breadcrumb-theme-size(); + @include osds-breadcrumb-theme-typography(); +} diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/osds-breadcrumb.spec.ts b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/osds-breadcrumb.spec.ts new file mode 100644 index 0000000000..e28020453d --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/osds-breadcrumb.spec.ts @@ -0,0 +1,63 @@ +jest.mock('@ovhcloud/ods-core/src/components/breadcrumb/breadcrumb/ods-breadcrumb-controller'); // keep jest.mock before any + +import { + OdsBreadcrumbAttributes, + OdsBreadcrumbController, + odsBreadcrumbDefaultAttributes, + OdsComponentAttributes2StringAttributes +} from '@ovhcloud/ods-core'; +import { + OdsCreateAttributes, + OdsStringAttributes2Str, + odsBreadcrumbBaseAttributes, +} from '@ovhcloud/ods-testing'; +import { SpecPage, newSpecPage } from '@stencil/core/testing'; +import { OsdsBreadcrumb } from './osds-breadcrumb'; + +describe('spec:osds-breadcrumb', () => { + let page: SpecPage; + let root: HTMLElement | undefined; + let instance: OsdsBreadcrumb; + let controller: OdsBreadcrumbController; + + afterEach(() => { + jest.clearAllMocks(); + }); + + async function setup({ attributes = {} }: { attributes?: Partial } = {}) { + const minimalAttributes: OdsBreadcrumbAttributes = OdsCreateAttributes(attributes, odsBreadcrumbBaseAttributes); + const stringAttributes = OdsComponentAttributes2StringAttributes(minimalAttributes, odsBreadcrumbDefaultAttributes); + + page = await newSpecPage({ + components: [OsdsBreadcrumb], + html: ``, + }); + + root = page.root; + instance = page.rootInstance; + controller = (OdsBreadcrumbController as unknown as jest.SpyInstance).mock.instances[0]; + } + + it('should render', async () => { + await setup({}); + expect(root?.shadowRoot).toBeTruthy(); + expect(instance).toBeTruthy(); + expect(instance.isCollapsed).toBe(true); + }); + + describe('methods', () => { + describe('onBreadcrumbItemCollapsedClick', () => { + it('should set the isCollapsed on refresh displayed items', async () => { + await setup({}); + + expect(instance.isCollapsed).toBe(true); + expect(controller.getBreadcrumbItems).toHaveBeenCalledWith([], true); + + instance.onBreadcrumbItemCollapsedClick() + + expect(instance.isCollapsed).toBe(false); + expect(controller.getBreadcrumbItems).toHaveBeenCalledWith([], false); + }); + }); + }); +}); diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/osds-breadcrumb.tsx b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/osds-breadcrumb.tsx new file mode 100644 index 0000000000..32c8bf1a01 --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/osds-breadcrumb.tsx @@ -0,0 +1,88 @@ +import { Component, Element, Host, h, Listen, Prop, State, Watch } from '@stencil/core'; +import { + OdsBreadcrumb, + OdsBreadcrumbAttributeItem, + OdsBreadcrumbController, + odsBreadcrumbDefaultAttributes, + OdsBreadcrumbEvents, + OdsBreadcrumbItemAttributes, + OdsBreadcrumbMethods, + OdsLogger, +} from '@ovhcloud/ods-core'; +import { OdsStencilEvents, OdsStencilMethods } from '@ovhcloud/ods-stencil/libraries/stencil-core'; + +/** + * @slot (unnamed) - Breadcrumb content + */ +@Component({ + tag: 'osds-breadcrumb', + styleUrl: 'osds-breadcrumb.scss', + shadow: true +}) +export class OsdsBreadcrumb implements OdsBreadcrumb, OdsStencilEvents> { + private logger = new OdsLogger('OsdsBreadcrumb'); + private breadcrumbItems: OdsBreadcrumbItemAttributes[] = []; + private parsedItems: OdsBreadcrumbAttributeItem[] = []; + controller: OdsBreadcrumbController = new OdsBreadcrumbController(this); + @Element() el!: HTMLElement; + + @State() isCollapsed = true; + + /** @see OdsBreadcrumbAttributes.contrasted */ + @Prop({ reflect: true }) public contrasted?: boolean = odsBreadcrumbDefaultAttributes.contrasted; + + /** @see OdsBreadcrumbAttributes.items */ + @Prop({ reflect: true }) public items: OdsBreadcrumbAttributeItem[] | string = []; + + componentWillLoad() { + this.parseItems(); + this.updateBreadcrumb(); + } + + @Watch('items') + onItemsChange() { + this.parseItems(); + this.updateBreadcrumb(); + } + + /** + * @see OdsBreadcrumbBehavior.onBreadcrumbItemCollapsedClick + */ + @Listen('odsBreadcrumbItemCollapsedClick') + onBreadcrumbItemCollapsedClick() { + this.isCollapsed = false; + this.updateBreadcrumb(); + } + + private parseItems() { + if (typeof this.items === 'string') { + try { + this.parsedItems = JSON.parse(this.items); + } catch { + this.logger.warn('[OsdsBreadcrumb] items string could not be parsed.'); + this.parsedItems = []; + } + } else { + this.parsedItems = [...this.items]; + } + } + + private updateBreadcrumb() { + this.breadcrumbItems = this.controller.getBreadcrumbItems(this.parsedItems, this.isCollapsed); + } + + render() { + return ( + + { + (this.breadcrumbItems || []).map((breadcrumbItem, index) => ( + + + )) + } + + ); + } +} diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/public-api.ts b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/public-api.ts new file mode 100644 index 0000000000..0fd9564523 --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/public-api.ts @@ -0,0 +1 @@ +export { OsdsBreadcrumb } from './osds-breadcrumb' diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/styles/osds-breadcrumb.color.scss b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/styles/osds-breadcrumb.color.scss new file mode 100644 index 0000000000..fa5a8b2c6d --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/styles/osds-breadcrumb.color.scss @@ -0,0 +1,27 @@ +@import '~@ovhcloud/ods-theming/color/ods-component-color'; +@import './osds-breadcrumb.mixins'; + +@mixin osds-breadcrumb-theme-color-variant-default() { + @include ods-and-all-hue-foreach-theme-color(( + color: '800', + background-color: '100' + )) using($colors) { + @include osds-breadcrumb-on-selected-host() { + //color: map_get($colors, color); + //background-color: map_get($colors, background-color); + } + } +} + +// Main CSS color theme mixin +@mixin osds-breadcrumb-theme-color() { + /** base colors */ + :host { + border-color: transparent; + } + + /** no variant specified: default variant colors */ + :not([variant]) { + @include osds-breadcrumb-theme-color-variant-default(); + } +} diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/styles/osds-breadcrumb.mixins.scss b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/styles/osds-breadcrumb.mixins.scss new file mode 100644 index 0000000000..aa81d0527f --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/styles/osds-breadcrumb.mixins.scss @@ -0,0 +1,13 @@ +// general mixins and functions for the component + +@mixin osds-breadcrumb-on-selected-host() { + :host(&) { + @content; + } +} + +@mixin osds-breadcrumb-on-main-element() { + .breadcrumb__wrapper { + @content; + } +} diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/styles/osds-breadcrumb.size.scss b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/styles/osds-breadcrumb.size.scss new file mode 100644 index 0000000000..f5475bef47 --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/styles/osds-breadcrumb.size.scss @@ -0,0 +1,7 @@ +@import './osds-breadcrumb.mixins'; +@import '~@ovhcloud/ods-theming/size/ods-component-size'; + +// Main CSS mixin for sizes +@mixin osds-breadcrumb-theme-size() { + +} diff --git a/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/styles/osds-breadcrumb.typography.scss b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/styles/osds-breadcrumb.typography.scss new file mode 100644 index 0000000000..f0ca960606 --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/components/osds-breadcrumb/styles/osds-breadcrumb.typography.scss @@ -0,0 +1,16 @@ +@import '~@ovhcloud/ods-theming/typography/ods-theming-typography'; +@import '~@ovhcloud/ods-theming/typography/ods-component-typography'; +@import './osds-breadcrumb.mixins'; + +// Main CSS mixin for typography +@mixin osds-breadcrumb-theme-typography() { + :host([size='md']) .breadcrumb__wrapper { + //$typography-properties: ods-get-typography-properties(body, '400'); + //font-family: ods-get-typography-property($typography-properties, font-family); + //font-size: ods-get-typography-property($typography-properties, font-size); + //font-style: ods-get-typography-property($typography-properties, font-style); + //font-weight: ods-get-typography-property($typography-properties, font-weight); + //letter-spacing: ods-get-typography-property($typography-properties, letter-spacing); + //line-height: ods-get-typography-property($typography-properties, line-height); + } +} diff --git a/packages/stencil/components/breadcrumb/src/docs/osds-breadcrumb/usage.mdx b/packages/stencil/components/breadcrumb/src/docs/osds-breadcrumb/usage.mdx new file mode 100644 index 0000000000..e6f8b5764d --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/docs/osds-breadcrumb/usage.mdx @@ -0,0 +1,12 @@ +import GenericStyle from '@ovhcloud/ods-core/docs/generic-style.mdx'; + + + +## Usage + +### Default +Breadcrumb + +```html +Breadcrumb +``` diff --git a/packages/stencil/components/breadcrumb/src/global.dev.ts b/packages/stencil/components/breadcrumb/src/global.dev.ts new file mode 100644 index 0000000000..ca8180371a --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/global.dev.ts @@ -0,0 +1,22 @@ +// ### +// global script file to include only in dev mode with the www dev server. +// it always has to include './components' and './global.ts' +// ### + +import './components'; +import './global'; +import { OdsLogger } from '@ovhcloud/ods-core'; +import '@ovhcloud/ods-stencil/components/icon'; +import '@ovhcloud/ods-stencil/components/link'; +import '@ovhcloud/ods-stencil/components/text'; + +const logger = new OdsLogger('global-dev'); +logger.log('init'); + +(window as any).globalMethod = async function () { + logger.log('globalMethod'); +}; + +(async () => { + await customElements.whenDefined('osds-breadcrumb'); +})(); diff --git a/packages/stencil/components/breadcrumb/src/global.prod.ts b/packages/stencil/components/breadcrumb/src/global.prod.ts new file mode 100644 index 0000000000..874fc2902b --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/global.prod.ts @@ -0,0 +1,5 @@ +// ### +// global script file to include only in prod mode for build prod. +// it always has to include './global.ts' +// ### +import './global'; diff --git a/packages/stencil/components/breadcrumb/src/global.test.ts b/packages/stencil/components/breadcrumb/src/global.test.ts new file mode 100644 index 0000000000..9197799cbc --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/global.test.ts @@ -0,0 +1,10 @@ +// ### +// global script file to include only in test mode. +// it always has to include './global.ts' +// ### + +import './global'; + +import '@ovhcloud/ods-stencil/components/icon'; +import '@ovhcloud/ods-stencil/components/link'; +import '@ovhcloud/ods-stencil/components/text'; diff --git a/packages/stencil/components/breadcrumb/src/global.ts b/packages/stencil/components/breadcrumb/src/global.ts new file mode 100644 index 0000000000..62b43891b0 --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/global.ts @@ -0,0 +1,9 @@ +// ### +// main global file to include in this package in any cases (dev and prod mode). +// it allows to initialize some stuff of the library, after the component itself +// ### + +import { OdsLogger } from '@ovhcloud/ods-core'; + +const logger = new OdsLogger('breadcrumb.global'); +logger.log('init'); diff --git a/packages/stencil/components/breadcrumb/src/index.html b/packages/stencil/components/breadcrumb/src/index.html new file mode 100644 index 0000000000..3bcc27191a --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/index.html @@ -0,0 +1,69 @@ + + + + + + Dev ods-breadcrumb + + + + + + + + + +

Default

+ + + +

Collapsed

+ + + +

With icon

+ + + +

Contrasted

+
+ + +
+ + + + + diff --git a/packages/stencil/components/breadcrumb/src/index.ts b/packages/stencil/components/breadcrumb/src/index.ts new file mode 100644 index 0000000000..b723b2fd53 --- /dev/null +++ b/packages/stencil/components/breadcrumb/src/index.ts @@ -0,0 +1 @@ +export * from './components/osds-breadcrumb/public-api'; diff --git a/packages/stencil/components/breadcrumb/stencil.config.ts b/packages/stencil/components/breadcrumb/stencil.config.ts new file mode 100644 index 0000000000..66dd5fc110 --- /dev/null +++ b/packages/stencil/components/breadcrumb/stencil.config.ts @@ -0,0 +1,29 @@ +import { Config } from '@stencil/core'; +import { getStencilConfig } from '@ovhcloud/ods-stencil/libraries/stencil-core'; +import * as jestConfig from './jest.config'; + +const args = process.argv.slice(2); + +export const config: Config = getStencilConfig({ + namespace: 'osds-breadcrumb', + args, + jestConfig: jestConfig.default, + reactOutput: { + componentCorePackage: '@ovhcloud/ods-stencil/components/breadcrumb', + // exclude peer dependencies that corresponds to www usage + excludeComponents: ['osds-icon', 'osds-link', 'osds-text'] + }, + vueOutput: { + componentCorePackage: '@ovhcloud/ods-stencil/components/breadcrumb', + excludeComponents: ['osds-icon', 'osds-link', 'osds-text'] + }, + dev: { + globalScript: 'src/global.dev.ts', + }, + prod: { + globalScript: 'src/global.prod.ts' + }, + test: { + globalScript: 'src/global.test.ts' + } +}); diff --git a/packages/stencil/components/breadcrumb/tsconfig.dev.json b/packages/stencil/components/breadcrumb/tsconfig.dev.json new file mode 100644 index 0000000000..73587a82c3 --- /dev/null +++ b/packages/stencil/components/breadcrumb/tsconfig.dev.json @@ -0,0 +1,6 @@ +{ + "extends": "../tsconfig.dev.json", + "include": [ + "src" + ] +} diff --git a/packages/stencil/components/breadcrumb/tsconfig.json b/packages/stencil/components/breadcrumb/tsconfig.json new file mode 100644 index 0000000000..902306b6c2 --- /dev/null +++ b/packages/stencil/components/breadcrumb/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../tsconfig.json", + "include": [ + "src" + ] +} diff --git a/packages/stencil/components/breadcrumb/tsconfig.prod.json b/packages/stencil/components/breadcrumb/tsconfig.prod.json new file mode 100644 index 0000000000..71267ee2a3 --- /dev/null +++ b/packages/stencil/components/breadcrumb/tsconfig.prod.json @@ -0,0 +1,6 @@ +{ + "extends": "../tsconfig.prod.json", + "include": [ + "src" + ] +} diff --git a/packages/stencil/components/breadcrumb/tsconfig.test.json b/packages/stencil/components/breadcrumb/tsconfig.test.json new file mode 100644 index 0000000000..2981dd3671 --- /dev/null +++ b/packages/stencil/components/breadcrumb/tsconfig.test.json @@ -0,0 +1,6 @@ +{ + "extends": "../tsconfig.test.json", + "include": [ + "src" + ] +} diff --git a/packages/stencil/components/breadcrumb/typedoc.json b/packages/stencil/components/breadcrumb/typedoc.json new file mode 100644 index 0000000000..0bb1c61220 --- /dev/null +++ b/packages/stencil/components/breadcrumb/typedoc.json @@ -0,0 +1,7 @@ +{ + "entryPoints": ["src"], + "out": "docs-api/stencil-components-breadcrumb", + "tsconfig":"tsconfig.prod.json", + "exclude": "**/*+(index|.spec|.e2e|.d).ts", + "plugin": "none" +} diff --git a/packages/stencil/components/breadcrumb/vue/.gitignore b/packages/stencil/components/breadcrumb/vue/.gitignore new file mode 100644 index 0000000000..496f9a49cd --- /dev/null +++ b/packages/stencil/components/breadcrumb/vue/.gitignore @@ -0,0 +1,2 @@ +dist/ +src/ diff --git a/packages/stencil/components/breadcrumb/vue/.npmignore b/packages/stencil/components/breadcrumb/vue/.npmignore new file mode 100644 index 0000000000..3753d5f6a1 --- /dev/null +++ b/packages/stencil/components/breadcrumb/vue/.npmignore @@ -0,0 +1,2 @@ +!dist/ +src/ diff --git a/packages/stencil/components/breadcrumb/vue/CHANGELOG.md b/packages/stencil/components/breadcrumb/vue/CHANGELOG.md new file mode 100644 index 0000000000..e9fb6ecf59 --- /dev/null +++ b/packages/stencil/components/breadcrumb/vue/CHANGELOG.md @@ -0,0 +1,4 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. \ No newline at end of file diff --git a/packages/stencil/components/breadcrumb/vue/package.json b/packages/stencil/components/breadcrumb/vue/package.json new file mode 100644 index 0000000000..801743c8c3 --- /dev/null +++ b/packages/stencil/components/breadcrumb/vue/package.json @@ -0,0 +1,33 @@ +{ + "name": "@ovhcloud/ods-stencil-breadcrumb-vue", + "version": "12.0.5", + "private": true, + "description": "Vue specific wrapper for ods", + "keywords": [], + "author": "OVH SAS", + "license": "Apache-2.0", + "scripts": { + "build": "npm run clean && npm run compile", + "clean": "rimraf dist", + "compile": "npm run compile:esm && npm run compile:cjs", + "compile:esm": "tsc -p tsconfig.json", + "compile:cjs": "tsc -p tsconfig.cjs.json" + }, + "main": "dist/cjs/index.js", + "module": "dist/esm/index.js", + "types": "dist/types/index.d.ts", + "files": [ + "dist/" + ], + "dependencies": { + "@ovhcloud/ods-stencil-breadcrumb": "^12.0.5" + }, + "peerDependencies": { + "vue": ">=3" + }, + "devDependencies": { + "rimraf": "^3.0.2", + "typescript": "4.7.4", + "vue": "^3.2.41" + } +} diff --git a/packages/stencil/components/breadcrumb/vue/tsconfig.cjs.json b/packages/stencil/components/breadcrumb/vue/tsconfig.cjs.json new file mode 100644 index 0000000000..164b6b818e --- /dev/null +++ b/packages/stencil/components/breadcrumb/vue/tsconfig.cjs.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "dist/cjs", + "module": "CommonJS", + "declaration": false, + "declarationDir": null + } +} diff --git a/packages/stencil/components/breadcrumb/vue/tsconfig.json b/packages/stencil/components/breadcrumb/vue/tsconfig.json new file mode 100644 index 0000000000..0fe7d2f68a --- /dev/null +++ b/packages/stencil/components/breadcrumb/vue/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.vue.json", + "compilerOptions": { + "outDir": "dist/esm", + "declarationDir": "dist/types" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"] +} diff --git a/packages/stencil/components/tsconfig.components.dev.json b/packages/stencil/components/tsconfig.components.dev.json index faea211f4f..4eb8b5203f 100644 --- a/packages/stencil/components/tsconfig.components.dev.json +++ b/packages/stencil/components/tsconfig.components.dev.json @@ -12,6 +12,7 @@ }, "include": [ "accordion/src", + "breadcrumb/src", "button/src", "cart/src", "checkbox-button/src", diff --git a/packages/stencil/components/tsconfig.components.prod.json b/packages/stencil/components/tsconfig.components.prod.json index bbe1081823..e1094e788f 100644 --- a/packages/stencil/components/tsconfig.components.prod.json +++ b/packages/stencil/components/tsconfig.components.prod.json @@ -13,6 +13,7 @@ }, "include": [ "accordion/src", + "breadcrumb/src", "button/src", "cart/src", "checkbox-button/src", diff --git a/packages/stencil/components/tsconfig.components.test.json b/packages/stencil/components/tsconfig.components.test.json index f3daec2ac8..410bb27491 100644 --- a/packages/stencil/components/tsconfig.components.test.json +++ b/packages/stencil/components/tsconfig.components.test.json @@ -11,8 +11,8 @@ } }, "include": [ - "src", "accordion/src", + "breadcrumb/src", "button/src", "cart/src", "checkbox-button/src", @@ -36,6 +36,7 @@ "select/src", "skeleton/src", "spinner/src", + "src", "tabs/src", "text/src", "textarea/src", diff --git a/packages/themes/blue-jeans/theme/theme.scss b/packages/themes/blue-jeans/theme/theme.scss index 6dceef7479..d764534fd1 100644 --- a/packages/themes/blue-jeans/theme/theme.scss +++ b/packages/themes/blue-jeans/theme/theme.scss @@ -69,6 +69,11 @@ border-width: var(--ods-size-inset-02) ) ), + $breadcrumb: ( + md:( + padding: 0 var(--ods-size-inset-04), + ) + ), $button: ( sm: (height: 2.25rem, border-radius: var(--ods-size-border-radius-02), border-width: var(--ods-size-inset-02), padding-y: 0, padding-x: var(--ods-size-inline-05)), md: (height: 3.25rem, border-radius: var(--ods-size-border-radius-02), border-width: var(--ods-size-inset-02), padding-y: 0, padding-x: var(--ods-size-inline-06)) diff --git a/packages/tools/storybook/stories/components/Introduction.stories.ts b/packages/tools/storybook/stories/components/Introduction.stories.ts index 0a9d1bab20..0b3317c15f 100644 --- a/packages/tools/storybook/stories/components/Introduction.stories.ts +++ b/packages/tools/storybook/stories/components/Introduction.stories.ts @@ -249,6 +249,19 @@ const uiComponents = { `, }, }, + { + name: '️Breadcrumb', + tag: 'osds-breadcrumb', + url: '/?path=/story/ui-components-breadcrumb-molecule-web-component--default', + attributes: { + items: [ + { href: "#home", label: "Home" }, + { href: "#services", label: "Services" }, + { href: "#products", label: "Products" }, + { href: "#web", label: "Web" }, + ], + }, + }, { name: "Radio Group", tag: 'osds-radio-group', @@ -267,7 +280,7 @@ const uiComponents = { Radio Button A - + html` text-align: center; "> Atomic Design paradigm - + . @@ -461,7 +474,7 @@ const TemplateIntroduction = () => html` uiComponents[section].map( ({ name, tag, url, attributes, slots }) => html` + +# Breadcrumb +--- + +<>{getToC(['Preview', 'Description', 'Usage', 'Anatomy', 'Placement', 'Accessibility'])} + + diff --git a/packages/tools/storybook/stories/components/breadcrumb/breadcrumb.specifications.stories.mdx b/packages/tools/storybook/stories/components/breadcrumb/breadcrumb.specifications.stories.mdx new file mode 100644 index 0000000000..d48feb160a --- /dev/null +++ b/packages/tools/storybook/stories/components/breadcrumb/breadcrumb.specifications.stories.mdx @@ -0,0 +1,13 @@ +import { Meta } from '@storybook/addon-docs'; +import SpecificationsBreadcrumb from '@ovhcloud/ods-specifications/components/breadcrumb/specifications-breadcrumb.mdx'; +import Notes from '../notes.mdx'; + + + +# Breadcrumb - Technical Specification +---- + + + +--- + diff --git a/packages/tools/storybook/stories/components/breadcrumb/breadcrumb.web-component.stories.page.mdx b/packages/tools/storybook/stories/components/breadcrumb/breadcrumb.web-component.stories.page.mdx new file mode 100644 index 0000000000..37f27fa42e --- /dev/null +++ b/packages/tools/storybook/stories/components/breadcrumb/breadcrumb.web-component.stories.page.mdx @@ -0,0 +1,18 @@ +import { Canvas, Description, Meta, DocsContainer } from '@storybook/addon-docs'; + +import Usage from '@ovhcloud/ods-stencil-breadcrumb/src/docs/osds-breadcrumb/usage.mdx'; +import APITable from '@ovhcloud/ods-stencil-breadcrumb/dist/docs/components/osds-breadcrumb/readme.md'; + + + +# `` + +## Table of Contents +> - **[Usage](#usage)** +> - **[Getting Started](#getting-started)** +> - **[API Table](#api-table)** + +
+ +
+
{APITable}
diff --git a/packages/tools/storybook/stories/components/breadcrumb/breadcrumb.web-components.stories.ts b/packages/tools/storybook/stories/components/breadcrumb/breadcrumb.web-components.stories.ts new file mode 100644 index 0000000000..f7a52e7e42 --- /dev/null +++ b/packages/tools/storybook/stories/components/breadcrumb/breadcrumb.web-components.stories.ts @@ -0,0 +1,54 @@ +import { html } from 'lit-html'; +import { iframe } from '../../../.storybook/iframe'; + +import { defineCustomElements } from '@ovhcloud/ods-stencil-breadcrumb/loader'; +import { + extractArgTypes, + extractStoryParams, + getTagAttributes, +} from '../../../core/componentHTMLUtils'; + +import changelog from '@ovhcloud/ods-stencil-breadcrumb/CHANGELOG.md'; +import page from './breadcrumb.web-component.stories.page.mdx'; + +defineCustomElements(); + +/* Default story parameters */ +const storyParams = { + items: { + category: 'General', + defaultValue: [ + { href: "#home", label: "Home" }, + { href: "#services", label: "Services" }, + { href: "#products", label: "Products" }, + { href: "#web", label: "Web" }, + ], + }, + contrasted: { + category: 'Misc', + defaultValue: false + }, +}; + +export default { + title: 'UI Components/Breadcrumb [molecule]/Web Component', + parameters: { + notes: { + API: iframe('/stencil-breadcrumb/modules/index.html'), + changelog, + }, + docs: { page } + }, + argTypes: extractArgTypes(storyParams) +}; + +/* Default */ +const TemplateDefault = (args:any) => { + return html` + + `; +} +export const Default = TemplateDefault.bind({}); +Default.args = { + ...extractStoryParams(storyParams), +}; diff --git a/packages/tools/storybook/stories/components/pagination/pagination.specifications.stories.mdx b/packages/tools/storybook/stories/components/pagination/pagination.specifications.stories.mdx index 8c330d56e9..96a32e3206 100644 --- a/packages/tools/storybook/stories/components/pagination/pagination.specifications.stories.mdx +++ b/packages/tools/storybook/stories/components/pagination/pagination.specifications.stories.mdx @@ -9,3 +9,7 @@ import Notes from '../notes.mdx'; --- + +--- + + diff --git a/yarn.lock b/yarn.lock index 2893962e0e..096113c75c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5619,6 +5619,46 @@ __metadata: languageName: unknown linkType: soft +"@ovhcloud/ods-stencil-breadcrumb-react@workspace:packages/stencil/components/breadcrumb/react": + version: 0.0.0-use.local + resolution: "@ovhcloud/ods-stencil-breadcrumb-react@workspace:packages/stencil/components/breadcrumb/react" + dependencies: + "@ovhcloud/ods-stencil-breadcrumb": ^12.0.5 + "@types/react": 17.0.37 + "@types/react-dom": 17.0.11 + react: 16.14.0 + react-dom: 16.14.0 + rimraf: ^3.0.2 + tslib: "*" + typescript: 4.7.4 + peerDependencies: + react: ">=16.8.6" + react-dom: ">=16.8.6" + languageName: unknown + linkType: soft + +"@ovhcloud/ods-stencil-breadcrumb-vue@workspace:packages/stencil/components/breadcrumb/vue": + version: 0.0.0-use.local + resolution: "@ovhcloud/ods-stencil-breadcrumb-vue@workspace:packages/stencil/components/breadcrumb/vue" + dependencies: + "@ovhcloud/ods-stencil-breadcrumb": ^12.0.5 + rimraf: ^3.0.2 + typescript: 4.7.4 + vue: ^3.2.41 + peerDependencies: + vue: ">=3" + languageName: unknown + linkType: soft + +"@ovhcloud/ods-stencil-breadcrumb@^12.0.5, @ovhcloud/ods-stencil-breadcrumb@workspace:packages/stencil/components/breadcrumb": + version: 0.0.0-use.local + resolution: "@ovhcloud/ods-stencil-breadcrumb@workspace:packages/stencil/components/breadcrumb" + dependencies: + "@ovhcloud/ods-stencil-component": ^12.0.5 + "@ovhcloud/ods-stencil-component-dev": ^12.0.5 + languageName: unknown + linkType: soft + "@ovhcloud/ods-stencil-button-react@workspace:packages/stencil/components/button/react": version: 0.0.0-use.local resolution: "@ovhcloud/ods-stencil-button-react@workspace:packages/stencil/components/button/react"