Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(components): add new component card-control #2260

Merged
Merged
Show file tree
Hide file tree
Changes from 87 commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
ac55cec
feat(components): add post-card-control (unfinished)
oliverschuerch Oct 6, 2023
f047766
feat(documentation): add card-control stories (unfinished)
oliverschuerch Oct 6, 2023
e456da6
Merge branch 'main' into feat/1929-Create_checkbox-_and_radio-Cards_w…
oliverschuerch Nov 9, 2023
1e04974
feat(components): add new component card-control (unfinished)
oliverschuerch Nov 10, 2023
1d819eb
feat(styles): add new custom color variable $focus
oliverschuerch Nov 10, 2023
e5a9343
chore: add todo
oliverschuerch Nov 10, 2023
e6f51a6
Merge branch 'main' into feat/1929-Create_checkbox-_and_radio-Cards_w…
oliverschuerch Dec 15, 2023
c53e701
fix(components): fix post-card-control group behaviour of
oliverschuerch Dec 19, 2023
4b29ccb
chore(components): update props and add controlChange event
oliverschuerch Dec 20, 2023
3918db9
feat(documentation): add card-control docs (unfinished)
oliverschuerch Dec 20, 2023
5c8ef53
chore: add more documentation details and fix smaller bugs in the car…
oliverschuerch Dec 22, 2023
a286ff6
feat(styles): add default background-color for form-check elements
oliverschuerch Dec 22, 2023
60bc278
chore(documentation): add forms sort order in storybook navigation
oliverschuerch Dec 22, 2023
3c826e5
Merge branch 'main' into feat/1929-Create_checkbox-_and_radio-Cards_w…
oliverschuerch Jan 18, 2024
05690d2
feat(components): extend cypress getCompnent command to be able to in…
oliverschuerch Jan 19, 2024
127025b
feat(components): remove controlId as prop (autocreation)
oliverschuerch Jan 19, 2024
62c9a94
feat(components): add errors when required props not set
oliverschuerch Jan 19, 2024
cc7a7c7
refactor(components): remove default value 'on' for value prop
oliverschuerch Jan 19, 2024
7110b16
refactor(components): state property to make it resettable
oliverschuerch Jan 19, 2024
f6fd5d9
fix(components): move card click handler to listen on the host
oliverschuerch Jan 19, 2024
84f217f
feat(components): improve clickable areas within content area
oliverschuerch Jan 19, 2024
2d2f981
chore(components): update story and component definitions accordingly
oliverschuerch Jan 19, 2024
f14797d
test(components): add basic testing
oliverschuerch Jan 19, 2024
d79f1a7
fix(components): card-control e2e tests
oliverschuerch Jan 24, 2024
f98dddb
Merge branch 'main' into feat/1929-Create_checkbox-_and_radio-Cards_w…
oliverschuerch Feb 2, 2024
b77ce94
chore(components): card-control add initialState state
oliverschuerch Feb 7, 2024
422621c
chore(components): card-control refactor required props checks
oliverschuerch Feb 7, 2024
ed5b52e
chore(components): card-control remove content area
oliverschuerch Feb 7, 2024
610565e
chore(components): card-control add slot docs
oliverschuerch Feb 7, 2024
ada227e
refactor(components): refactor card-control how the checked state is set
oliverschuerch Feb 7, 2024
c2cf3e8
chore(components): card-control remove custom controlChange event
oliverschuerch Feb 7, 2024
c6049ab
chore(components): card-control update props and add readonly prop
oliverschuerch Feb 7, 2024
4eb6c26
feat(components): card-control add form associated callbacks and corr…
oliverschuerch Feb 7, 2024
f60ebd5
feat(components): card-control add dark-bg styles
oliverschuerch Feb 7, 2024
eb91b56
feat(documentation): card-control add stories
oliverschuerch Feb 7, 2024
1bd3879
chore(components): card-control remove stories which will be included…
oliverschuerch Feb 7, 2024
99397b5
chore(components): card-component update property types
oliverschuerch Feb 7, 2024
4532d6b
chore(components): card-component implement native like custom events…
oliverschuerch Feb 8, 2024
9ab7100
chore(styles): remove wrongly added $focus variable (instead $outline…
oliverschuerch Feb 8, 2024
167e0c7
test(components): update card-control e2e tests
oliverschuerch Feb 8, 2024
e61fae1
feat(components): add reset and clearvalidity methods in card-control
oliverschuerch Feb 9, 2024
5e26582
test(components): add tests for methods and form-association
oliverschuerch Feb 9, 2024
5571ed0
chore(components): remove public method clearValidity out ouf card-co…
oliverschuerch Feb 9, 2024
ef74c50
chore(components): improve card-control background story
oliverschuerch Feb 9, 2024
8b40e3e
chore(components): adapt newest color definitions from design
oliverschuerch Feb 9, 2024
8e930ee
test(components): add radio-group tests
oliverschuerch Feb 9, 2024
1dababe
chore(components): add todos and fix some docs texts
oliverschuerch Feb 9, 2024
54ad560
chore(documentation): add card-control alert for the form-association…
oliverschuerch Feb 9, 2024
26193c2
feat(documentation): add uuid for card-control story
oliverschuerch Feb 16, 2024
994b14b
Merge branch 'main' into feat/1929-Create_checkbox-_and_radio-Cards_w…
oliverschuerch Feb 16, 2024
c9476c4
test(documentation): add card-control snapshot test
oliverschuerch Feb 16, 2024
29919ce
feat(documentation): add card-control fieldset example
oliverschuerch Feb 16, 2024
e71d908
chore(documentation): update card-control lined up story
oliverschuerch Feb 16, 2024
df7773c
feat(components): add the possibility to stretch all card-control ele…
oliverschuerch Feb 16, 2024
86194c6
chore(components): fix codesmells reported by sonar
oliverschuerch Feb 20, 2024
0da9eb6
Merge branch 'main' into feat/1929-Create_checkbox-_and_radio-Cards_w…
oliverschuerch Feb 20, 2024
79936b7
chore(components): add post-card-control to exported members
oliverschuerch Feb 20, 2024
f9d880c
chore(components): update eslint config
oliverschuerch Feb 20, 2024
44f0002
chore(components): remove todo comment reported by sonar
oliverschuerch Feb 20, 2024
f020ab6
chore: add changesets
oliverschuerch Feb 20, 2024
b5e8847
feat(components-angular): add `post-card-control` example to the cons…
oliverschuerch Feb 20, 2024
7f8ab0c
Update packages/components/src/components.d.ts
oliverschuerch Feb 22, 2024
5698dca
Update packages/documentation/src/stories/components/card-control/car…
oliverschuerch Feb 22, 2024
6615ff5
Update packages/documentation/src/stories/components/card-control/car…
oliverschuerch Feb 22, 2024
d18ea7b
Update packages/documentation/src/stories/components/card-control/car…
oliverschuerch Feb 22, 2024
95176a7
chore(documentation): remove `needs_revision` badge
oliverschuerch Feb 22, 2024
5380069
chore(components): add card-control comment for style order
oliverschuerch Feb 22, 2024
e4ac0ee
chore(components): update some generated files
oliverschuerch Feb 22, 2024
f4d202c
Merge branch 'main' into feat/1929-Create_checkbox-_and_radio-Cards_w…
oliverschuerch Feb 22, 2024
4ecf48a
feat(components): add a111y test for card-control
oliverschuerch Feb 22, 2024
8cbbc55
Merge branch 'main' into feat/1929-Create_checkbox-_and_radio-Cards_w…
oliverschuerch Mar 1, 2024
6570383
feat(components): add css modules for components package
oliverschuerch Mar 1, 2024
1b3ab73
feat(components): add sass-export util
oliverschuerch Mar 1, 2024
2fee563
chore(components): remove badges from card-control docs page
oliverschuerch Mar 1, 2024
1fb9e9a
fix(components): implement :host-context fallback for firefox and safari
oliverschuerch Mar 1, 2024
46dd288
refactor: post-card-control component
oliverschuerch Mar 12, 2024
0fd6370
feat(components-angular): add custom card-control-view
oliverschuerch Mar 12, 2024
3a85acb
test(components): update card-control tests
oliverschuerch Mar 13, 2024
9ff2620
test(components-angular): add post-card-control e2e test
oliverschuerch Mar 13, 2024
ad97d24
chore: update card-control form associated story
oliverschuerch Mar 13, 2024
3be777f
chore(components): remove unnecessary disconnectCallback in card-control
oliverschuerch Mar 13, 2024
632d765
Merge branch 'main' into feat/1929-Create_checkbox-_and_radio-Cards_w…
oliverschuerch Mar 13, 2024
6604d32
fix(components-angular): fix issue in angular build process, by addin…
oliverschuerch Mar 14, 2024
e1a20df
fix: lint errors
oliverschuerch Mar 14, 2024
d944368
fix(components): add @HostListener istead of host property in directi…
oliverschuerch Mar 14, 2024
87c309c
chore(components-angular): add post-rating to home view
oliverschuerch Mar 14, 2024
bfcfb9d
Merge branch 'main' into feat/1929-Create_checkbox-_and_radio-Cards_w…
oliverschuerch Mar 14, 2024
faff6bc
fix(components): prevent card-control from fiering errors, on startup
oliverschuerch Mar 14, 2024
62a9957
chore(components-angular): add a routerlink navigation
oliverschuerch Mar 14, 2024
e555dc7
chore(components-angular): add generated first-level-routes navigation
oliverschuerch Mar 14, 2024
6a18fc5
Merge branch 'main' into feat/1929-Create_checkbox-_and_radio-Cards_w…
oliverschuerch Mar 14, 2024
a480f5a
chore(documentation): use MetaComponent type instead of Meta in card-…
oliverschuerch Mar 19, 2024
1f5cdd8
Merge branch 'main' into feat/1929-Create_checkbox-_and_radio-Cards_w…
oliverschuerch Mar 19, 2024
316e288
Merge branch 'main' into feat/1929-Create_checkbox-_and_radio-Cards_w…
oliverschuerch Mar 20, 2024
df973e4
test(documentation): switch axe rule in card.cy.ts from prohibited to…
oliverschuerch Mar 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fair-singers-return.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@swisspost/design-system-styles': patch
---

Fixed the `.form-check-input` background-color, by setting it to white on none or light backgrounds.
7 changes: 7 additions & 0 deletions .changeset/shaggy-files-protect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@swisspost/design-system-components-angular-workspace': minor
'@swisspost/design-system-documentation': minor
'@swisspost/design-system-components': minor
---

Added a new web-component `post-card-control`, which works like a native `input[type="checkbox"]` or `input[type="radio"]` but with a custom visual design.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
"components:snapshots": "start-server-and-test docs:headless 9001 'pnpm --filter design-system-components snapshots'",
"components-angular:start": "pnpm --filter design-system-components-angular-workspace start",
"components-angular:build": "pnpm --filter design-system-components-angular-workspace build",
"components-angular:e2e": "pnpm --filter design-system-components-angular-workspace e2e",
"components-angular:e2e:watch": "pnpm --filter design-system-components-angular-workspace e2e:watch",
"header": "pnpm header:start",
"header:start": "pnpm --filter internet-header dev",
"header:build": "pnpm --filter internet-header build",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { DIRECTIVES } from './stencil-generated';
import { defineCustomElements } from '@swisspost/design-system-components/loader';

import { DIRECTIVES } from './stencil-generated';
import { BooleanValueAccessor } from './stencil-generated/boolean-value-accessor';
import { PostCardControlValueAccessorDirective } from './custom/value-accessors/post-card-control-radio-value-accessor';

const DECLARATIONS = [...DIRECTIVES, BooleanValueAccessor, PostCardControlValueAccessorDirective];

@NgModule({
declarations: [...DIRECTIVES],
declarations: DECLARATIONS,
exports: DECLARATIONS,
providers: [
{
provide: APP_INITIALIZER,
useFactory: () => defineCustomElements,
multi: true,
},
],
exports: [...DIRECTIVES],
})
export class PostComponentsModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Directive, ElementRef, HostListener } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';

@Directive({
/* eslint-disable-next-line @angular-eslint/directive-selector */
selector: 'post-card-control[type="radio"]',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: PostCardControlValueAccessorDirective,
multi: true,
},
],
})
export class PostCardControlValueAccessorDirective implements ControlValueAccessor {
private onChange: (value: any) => void = () => {
/**/
};
private onTouched: () => void = () => {
/**/
};
protected lastValue: any;

constructor(protected el: ElementRef) {}

writeValue(value: any) {
this.el.nativeElement.checked = this.lastValue =
this.el.nativeElement.value != value ? false : value;
}

@HostListener('change', ['$event.detail.value'])
handleChangeEvent(value: any) {
this.onChange(value);
}

@HostListener('focusout')
_handleBlurEvent() {
this.onTouched();
}

registerOnChange(fn: (value: any) => void) {
this.onChange = fn;
}
registerOnTouched(fn: () => void) {
this.onTouched = fn;
}

setDisabledState(isDisabled: boolean) {
this.el.nativeElement.disabled = isDisabled;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,11 @@
*/

export * from './lib/components.module';
export { DIRECTIVES } from './lib/stencil-generated';
export * from './lib/stencil-generated/components';
export { DIRECTIVES } from './lib/stencil-generated';

// Export all custom made components & directives!
// Skipping this step will lead to Angular Ivy errors when building for production.

export { BooleanValueAccessor } from './lib/stencil-generated/boolean-value-accessor';
export { PostCardControlValueAccessorDirective } from './lib/custom/value-accessors/post-card-control-radio-value-accessor';
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
"declaration": true,
"declarationMap": true,
"inlineSources": true,
"noImplicitOverride": false,
"types": []
},
"exclude": [
"**/*.spec.ts"
]
"exclude": ["**/*.spec.ts"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { defineConfig } from 'cypress';
export default defineConfig({
e2e: {
baseUrl: 'http://localhost:4200',
includeShadowDom: true,
},
component: {
devServer: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
describe('Card-Control', () => {
beforeEach(() => {
cy.visit('/card-control');

cy.get('post-card-control[type="checkbox"]').as('checkbox');
cy.get('@checkbox').find('input.card-control--input').as('checkbox-input');
cy.get('.form-check input.form-check-input[type="checkbox"]').as('native-checkbox');
cy.get('post-card-control[type="radio"]').as('radio');
cy.get('@radio').find('input.card-control--input').as('radio-input');
cy.get('.form-check input.form-check-input[type="radio"]').as('native-radio');

cy.get('button[type="reset"]').as('reset');

cy.get('#validity').as('state');
cy.get('#output').as('output');
});

it('should exist', () => {
cy.get('@checkbox').should('exist');
cy.get('@radio').should('exist');
});

it('should update the surrounding form value, when checked', () => {
cy.get('@output').then($output => {
cy.checkOutputProps($output, {
checkbox: null,
radio: null,
});

cy.get('@checkbox').click();
cy.checkOutputProps($output, { checkbox: true });
cy.get('@checkbox').click();
cy.checkOutputProps($output, { checkbox: false });
cy.get('@checkbox-input').type(' ');
cy.checkOutputProps($output, { checkbox: true });

cy.get('@radio').each(($control, i) => {
cy.wrap($control).click();
cy.checkOutputProps($output, { radio: `option_${i + 1}` });
});

cy.get('@radio-input').each(($input, i) => {
cy.wrap($input).type(' ');
cy.checkOutputProps($output, { radio: `option_${i + 1}` });
});
});
});

it('should not update the surrounding form value, when a disabled group member has been checked by keyboard', () => {
cy.get('@radio').eq(1).invoke('attr', 'disabled', true);
cy.get('@radio').eq(3).invoke('attr', 'disabled', true);

cy.wait(0)
.get('@output')
.then($output => {
cy.checkOutputProps($output, { radio: null });

let option: null | undefined | string = null;

cy.get('@radio-input')
.its('length')
.then(length => {
cy.get('@radio-input').each(($input, i) => {
cy.get('@radio-input')
.eq(i + 1 < length ? i + 1 : 0)
.then($next => {
const isDisabled = $next.attr('aria-disabled') !== undefined;

if (!isDisabled) option = $next.val()?.toString();

cy.wrap($input).focus().type('{downArrow}');
cy.checkOutputProps($output, { radio: option });
});
});
});
});
});

it('should update the surrounding form validity, when checked', () => {
cy.get('@state').should('contain.text', 'INVALID');

cy.get('@native-checkbox').check();
cy.get('@native-radio').eq(2).check();
cy.get('@radio').eq(2).click();
cy.get('@radio').eq(2).click();
cy.get('@state').should('contain.text', 'INVALID');

cy.get('@checkbox').click();
cy.get('@state').should('contain.text', 'VALID');
cy.get('@checkbox').click();
cy.get('@state').should('contain.text', 'INVALID');

cy.get('@reset').click();
cy.get('@native-checkbox').check();
cy.get('@native-radio').eq(2).check();
cy.get('@checkbox').click();
cy.get('@state').should('contain.text', 'INVALID');

cy.get('@radio').eq(2).click();
cy.get('@state').should('contain.text', 'VALID');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,11 @@
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })

Cypress.Commands.add('checkOutputProps', ($output, props) => {
const output = JSON.parse($output.text());

Object.entries(props).forEach(([key, value]) => {
expect(output[key]).to.be.eq(value);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
// ***********************************************************

// Import commands.js using ES2015 syntax:
import './commands'
import './commands';

// Alternatively you can use CommonJS syntax:
// require('./commands')

import { mount } from 'cypress/angular'
import { mount } from 'cypress/angular';

// Augment the Cypress namespace to include type definitions for
// your custom command.
Expand All @@ -28,12 +28,12 @@ import { mount } from 'cypress/angular'
declare global {
namespace Cypress {
interface Chainable {
mount: typeof mount
mount: typeof mount;
}
}
}

Cypress.Commands.add('mount', mount)
Cypress.Commands.add('mount', mount);

// Example use:
// cy.mount(MyComponent)
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
// ***********************************************************

// When a command from ./commands is ready to use, import with `import './commands'` syntax
// import './commands';
import './commands';
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare namespace Cypress {
interface Chainable {
checkOutputProps($output: JQuery<HTMLElement>, props: {}): Chainable<any>;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './routes/home/home.component';
import { CardControlComponent } from './routes/card-control/card-control.component';

const routes: Routes = [];
const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'card-control', component: CardControlComponent },
];

@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
exports: [RouterModule],
})
export class AppRoutingModule { }
export class AppRoutingModule {}
Original file line number Diff line number Diff line change
@@ -1,84 +1,5 @@
<h1>Hurray, it works!</h1>

<div class="my-4">
<h2>Post Accordion</h2>
<post-accordion>
<post-accordion-item>
<span slot="header">Titulum 1</span>
<p>Contentus momentus vero siteos et accusam iretea et justo.</p>
</post-accordion-item>

<post-accordion-item>
<span slot="header">Titulum 2</span>
<p>Contentus momentus vero siteos et accusam iretea et justo.</p>
</post-accordion-item>

<post-accordion-item>
<span slot="header">Titulum 3</span>
<p>Contentus momentus vero siteos et accusam iretea et justo.</p>
</post-accordion-item>
</post-accordion>
</div>

<div class="my-4">
<h2>Post Alert</h2>
<post-alert><p>Contentus momentus vero siteos et accusam iretea et justo.</p></post-alert>
</div>

<div class="my-4">
<h2>Post Collapsible</h2>
<post-collapsible>
<p>Contentus momentus vero siteos et accusam iretea et justo.</p>
</post-collapsible>
</div>

<div class="my-4">
<h2>Post Popover</h2>
<button class="btn btn-secondary btn-large" data-popover-target="popover-one">
Click here to see a popover
</button>
<post-popover id="popover-one" placement="top" arrow="">
<h2 class="h6">Optional title</h2>

<p class="mb-0">
A longer message that needs more time to read.
<a href="#">Links</a>
are also possible.
</p>
</post-popover>
</div>

<div class="my-4">
<h2>Post Popovercontainer</h2>
<post-popovercontainer></post-popovercontainer>
</div>

<div class="my-4">
<h2>Post Icon</h2>
<post-icon name="1001"></post-icon>
</div>

<div class="my-4">
<h2>Post Tabs</h2>
<post-tabs>
<post-tab-header slot="tabs" panel="unua">Unua langeto</post-tab-header>
<post-tab-header slot="tabs" panel="dua">Dua langeto</post-tab-header>
<post-tab-header slot="tabs" panel="tria">Tria langeto</post-tab-header>

<post-tab-panel name="unua">
Jen la enhavo de la unua langeto. Defaŭlte ĝi montriĝas komence.
</post-tab-panel>
<post-tab-panel name="dua">
Jen la enhavo de la dua langeto. Defaŭlte ĝi estas kaŝita komence.
</post-tab-panel>
<post-tab-panel name="tria">
Jen la enhavo de la tria langeto. Defaŭlte ĝi ankaŭ estas kaŝita komence.
</post-tab-panel>
</post-tabs>
</div>

<div class="my-4">
<h2>Post Tooltip</h2>
<button class="btn btn-secondary btn-large" data-tooltip-target="tooltip-one">Button</button>
<post-tooltip id="tooltip-one" placement="top">Hi there 👋</post-tooltip>
</div>
<main>
<router-outlet></router-outlet>
</main>
Loading
Loading