Skip to content

Commit

Permalink
chore(components): add anchor and button wrapper stories
Browse files Browse the repository at this point in the history
  • Loading branch information
oliverschuerch committed Oct 15, 2024
1 parent b21a32b commit 4ace470
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 53 deletions.
8 changes: 0 additions & 8 deletions packages/components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@ export namespace Components {
* Defines the users lastname.
*/
"lastname"?: string;
/**
* Defines the tag, the component represents.
*/
"tag": keyof typeof TAG_ROLES;
/**
* Defines the company internal userId.<div className="mb-1 alert alert-warning alert-sm">Can only be used on post.ch domains!</div>
*/
Expand Down Expand Up @@ -626,10 +622,6 @@ declare namespace LocalJSX {
* Defines the users lastname.
*/
"lastname"?: string;
/**
* Defines the tag, the component represents.
*/
"tag"?: keyof typeof TAG_ROLES;
/**
* Defines the company internal userId.<div className="mb-1 alert alert-warning alert-sm">Can only be used on post.ch domains!</div>
*/
Expand Down
43 changes: 29 additions & 14 deletions packages/components/src/components/post-avatar/post-avatar.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@use '@swisspost/design-system-styles/tokens/elements';
@use '@swisspost/design-system-styles/functions/tokens';
@use '@swisspost/design-system-styles/core' as post;

// tokens.$default-map: elements.$post-avatar;

Expand All @@ -11,6 +12,9 @@ tokens.$default-map: (
'post-avatar-border-color': #fff,
'post-avatar-border-radius': 50%,
'post-avatar-font-size': 16px,
'post-avatar-hover-bg': #666,
'post-avatar-hover-fg': white,
'post-avatar-hover-bg-img-overlay': #ffffff77,
'post-avatar-focus-outline-width': 2px,
'post-avatar-focus-outline-color': #000,
'post-avatar-focus-outline-offset': 2px
Expand All @@ -19,52 +23,63 @@ tokens.$default-map: (
:host {
--post-avatar-bg: #{tokens.get('avatar-bg')};
--post-avatar-fg: #{tokens.get('avatar-fg')};
--post-avatar-bg-img-overlay: transparent;

display: block;
display: inline-flex;
position: relative;
width: tokens.get('avatar-size');
height: tokens.get('avatar-size');
background-color: tokens.get('avatar-border-color');
border: tokens.get('avatar-border-width') solid tokens.get('avatar-border-color');
border-radius: tokens.get('avatar-border-radius');
font-size: tokens.get('avatar-font-size');
line-height: 1;
}

:host([role]) {
cursor: pointer;
&::after {
display: block;
content: '';
position: absolute;
inset: 0;
z-index: 1;
background-color: var(--post-avatar-bg-img-overlay);
border-radius: inherit;
}
}

:host([role]:hover) {
transform: scale(1.15);
*,
*::before,
*::after {
box-sizing: border-box;
}

:host([role]:focus-visible) {
outline: tokens.get('avatar-focus-outline-width') solid tokens.get('avatar-focus-outline-color');
outline-offset: tokens.get('avatar-focus-outline-offset');
.visually-hidden {
@include post.visually-hidden();
}

slot {
slot,
img,
::slotted(img) {
display: block;
width: 100%;
height: 100%;
}

img,
::slotted(img) {
display: block;
width: 100%;
height: 100%;
border-radius: tokens.get('avatar-border-radius');
}

::slotted(:not(img)) {
display: none;
display: none !important;
}

.initials {
display: flex;
justify-content: center;
align-items: center;
position: relative;
z-index: 2;
width: 100%;
height: 100%;
background-color: var(--post-avatar-bg);
border-radius: tokens.get('avatar-border-radius');
Expand Down
21 changes: 9 additions & 12 deletions packages/components/src/components/post-avatar/post-avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@ import { Component, Element, h, Host, Prop, State, Watch } from '@stencil/core';
import { version } from '@root/package.json';
import { checkNonEmpty } from '@/utils';

enum TAG_ROLES {
a = 'link',
button = 'button',
}

// https://docs.gravatar.com/api/avatars/images/
const GRAVATAR_DEFAULT = '404';
const GRAVATAR_RATING = 'g';
Expand Down Expand Up @@ -34,11 +29,6 @@ export class PostAvatar {

@Element() host: HTMLPostAvatarElement;

/**
* Defines the tag, the component represents.
*/
@Prop() readonly tag: keyof typeof TAG_ROLES = null;

/**
* Defines the users firstname.
*/
Expand Down Expand Up @@ -177,10 +167,17 @@ export class PostAvatar {

render() {
return (
<Host data-version={version} role={TAG_ROLES[this.tag]} tabindex={TAG_ROLES[this.tag] && 0}>
<Host data-version={version}>
<slot onSlotchange={this.onSlotDefaultChange.bind(this)}>
{this.avatarType === 'image' && <img src={this.imageUrl} alt={this.imageAlt} />}
{this.avatarType === 'initials' && <div class="initials">{this.initials}</div>}
{this.avatarType === 'initials' && (
<div class="initials">
<span aria-hidden="true">{this.initials}</span>
<span class="visually-hidden">
{this.firstname} {this.lastname}
</span>
</div>
)}
</slot>
</Host>
);
Expand Down
13 changes: 6 additions & 7 deletions packages/components/src/components/post-avatar/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@

## Properties

| Property | Attribute | Description | Type | Default |
| ------------------------ | ----------- | --------------------------------------------------------------------------------------------------------------------------------- | ----------------- | ----------- |
| `email` | `email` | Defines the users email address associated with a gravatar profile picture. | `string` | `undefined` |
| `firstname` _(required)_ | `firstname` | Defines the users firstname. | `string` | `undefined` |
| `lastname` | `lastname` | Defines the users lastname. | `string` | `undefined` |
| `tag` | `tag` | Defines the tag, the component represents. | `"a" \| "button"` | `null` |
| `userid` | `userid` | Defines the company internal userId.<div className="mb-1 alert alert-warning alert-sm">Can only be used on post.ch domains!</div> | `string` | `undefined` |
| Property | Attribute | Description | Type | Default |
| ------------------------ | ----------- | --------------------------------------------------------------------------------------------------------------------------------- | -------- | ----------- |
| `email` | `email` | Defines the users email address associated with a gravatar profile picture. | `string` | `undefined` |
| `firstname` _(required)_ | `firstname` | Defines the users firstname. | `string` | `undefined` |
| `lastname` | `lastname` | Defines the users lastname. | `string` | `undefined` |
| `userid` | `userid` | Defines the company internal userId.<div className="mb-1 alert alert-warning alert-sm">Can only be used on post.ch domains!</div> | `string` | `undefined` |


## Slots
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,33 @@ import * as AvatarPictureStories from './avatar.stories';
<Canvas of={AvatarPictureStories.Default} sourceState="shown" />
<Controls of={AvatarPictureStories.Default} />

## Interactive Wrapper Element

### Anchor

Nest the `<post-avatar>` component inside an anchor tag to make it clickable.
Use this approach to create a link to the user profile.

<Canvas of={AvatarPictureStories.AnchorWrapped} sourceState="shown" />

### Button

Nest the `<post-avatar>` component inside a button tag to make it clickable.
Use this approach to use the component as a menu toggler, ...

<Canvas of={AvatarPictureStories.ButtonWrapped} sourceState="shown" />

## Customize background and forground colors

The component provides two css-variables, which allow you to switch the background and the foreground color if needed (this gets visible when used with initials only).
The component provides some css-variables, which allow you to switch the background and the foreground color if needed.

<post-alert type="warning">Please ensure at all times, that the background and foreground colors have sufficient contrast!</post-alert>

```scss
post-avatar {
--post-avatar-bg: #f00;
--post-avatar-fg: #000;
--post-avatar-bg-img-overlay: transparent;
}
```

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Args, StoryContext, StoryFn, StoryObj } from '@storybook/web-components';
import { MetaComponent } from '@root/types';
import { html, nothing } from 'lit';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { components } from '@swisspost/design-system-components/dist/docs.json';
import { coloredBackground } from '@/shared/decorators/dark-background';

Expand All @@ -20,7 +21,6 @@ const meta: MetaComponent = {
},
},
args: {
tag: null,
firstname: 'Firstname',
lastname: '',
userid: '',
Expand All @@ -38,14 +38,6 @@ const meta: MetaComponent = {
EMAIL_ARGTYPE?.docs ?? ''
} <div className="alert alert-info alert-sm">Do you need an example email address? Try it out with <strong>[email protected]</strong>.</div>`,
},
'imageSrc': {
control: 'text',
description:
'Define an image `src` to insert a custom image.<div className="alert alert-info alert-sm">Do you need an example? Try our logo <strong>/assets/images/logo-swisspost.svg</strong>.</div>',
table: {
category: 'Content',
},
},
'slots-default': {
name: 'default',
table: {
Expand All @@ -54,6 +46,14 @@ const meta: MetaComponent = {
},
},
},
'imageSrc': {
control: 'text',
description:
'Define an image `src` to insert a custom image.<div className="alert alert-info alert-sm">Do you need an example? Try our logo <strong>/assets/images/logo-swisspost.svg</strong>.</div>',
table: {
category: 'Content',
},
},
},
};

Expand All @@ -66,8 +66,6 @@ export const Default: Story = {
(story: StoryFn, context: StoryContext) => coloredBackground(story, context, 'light'),
],
render: (args: Args) => html`<post-avatar
tag="${args.tag || nothing}"
href="${(args.tag === 'a' && '#') || nothing}"
firstname="${args.firstname || nothing}"
lastname="${args.lastname || nothing}"
userid="${args.userid || nothing}"
Expand All @@ -80,3 +78,15 @@ export const Default: Story = {
: nothing}</post-avatar
>`,
};

export const AnchorWrapped: Story = {
render: (args: Args, context: StoryContext) => {
return html`<a href="#">${Default.render?.(args, context)}</a>`;
},
};

export const ButtonWrapped: Story = {
render: (args: Args, context: StoryContext) => {
return html`<button>${Default.render?.(args, context)}</button>`;
},
};

0 comments on commit 4ace470

Please sign in to comment.