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(avatar): added image position option #2433

Merged
merged 4 commits into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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/clever-rivers-compete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ebay/ebayui-core": minor
---

feat(avatar): added image position option
28 changes: 20 additions & 8 deletions src/components/ebay-avatar/avatar.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import avatar from "./index.marko";
import Readme from "./README.md";
import imageTemplate from "./examples/image.marko";
import imageTemplateCode from "./examples/image.marko?raw";
import autoImageTemplate from "./examples/with-auto-placement.marko";
import autoImageTemplateCode from "./examples/with-auto-placement.marko?raw";

import { Story } from "@storybook/marko";
import type { Input } from "./index.marko";

Expand Down Expand Up @@ -37,12 +40,7 @@ export default {
"magenta",
"pink",
],
table: {
defaultValue: {
summary: "teal",
},
},
type: { category: "Options" },
type: "select",
description:
"The color to color the background. This can be only used in the non icon/image case. This is used simply as an override to the username hash",
},
Expand All @@ -53,8 +51,7 @@ export default {
summary: "48",
},
},
type: { category: "Options" },

type: "select",
description:
"The pixel size of the avatar. Can only be specific sizes",
},
Expand All @@ -67,13 +64,19 @@ export default {
description:
'The label to describe the users state as well as their user name. Usually in the format of "Signed in as Bob" or "Signed out"',
},
knownAspectRatio: {
control: { type: "number" },
description:
"Optional, as aspect ratio will be calculated when the image loads on the client. This can be passed to help prevent a flash of incorrectly styled content before the image loads",
},
},
};

export const Default = Template.bind({});
Default.args = {
a11yText: "Signed in - as Elizabeth",
username: "Elizabeth",
color: "teal",
};

Default.parameters = {
Expand All @@ -93,6 +96,15 @@ export const WithImage = buildExtensionTemplate(
},
);

export const WithAutoPlacement = buildExtensionTemplate(
autoImageTemplate,
autoImageTemplateCode,
{
a11yText: "Signed in - as Doggy",
username: "Doggy",
},
);

export const SignedOut = Template.bind({});
SignedOut.args = {
a11yText: "Signed out",
Expand Down
44 changes: 44 additions & 0 deletions src/components/ebay-avatar/component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { WithNormalizedProps } from "../../global";
import type { AttrString } from "marko/tags-html";

type Size = 32 | 40 | 48 | 56 | 64 | 96 | 128;

type ImagePlacement = "cover" | "fit";

interface State {
imagePlacement: ImagePlacement;
}

interface AvatarInput extends Omit<Marko.HTML.Div, `on${string}`> {
username?: string;
color?: string;
"a11y-text"?: AttrString;
size?: Size | `${Size}`;
img?: Marko.AttrTag<Omit<Marko.HTML.Img, `on${string}`>>;
"known-aspect-ratio"?: number;
}

export interface Input extends WithNormalizedProps<AvatarInput> {}

class Avatar extends Marko.Component<Input, State> {
onCreate(input: Input) {
this.state = {
imagePlacement:
input.knownAspectRatio &&
(input.knownAspectRatio < 3 / 4 ||
input.knownAspectRatio > 4 / 3)
? "fit"
: "cover",
};
}
handleImageLoad(_event: Event, el: HTMLImageElement) {
const aspectRatio = el.naturalWidth / el.naturalHeight;
if (aspectRatio < 3 / 4 || aspectRatio > 4 / 3) {
this.state.imagePlacement = "fit";
} else {
this.state.imagePlacement = "cover";
}
}
}

export default Avatar;
2 changes: 1 addition & 1 deletion src/components/ebay-avatar/examples/default.marko
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<ebay-avatar a11yText="Signed in as Elizabeth" username="Elizabeth"></ebay-avatar>
<ebay-avatar a11yText="Signed in as Elizabeth" color="teal" username="Elizabeth"></ebay-avatar>
24 changes: 24 additions & 0 deletions src/components/ebay-avatar/examples/with-auto-placement.marko
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<div>
<ebay-avatar a11yText="Signed in as Doggy" ...input>
<@img
src="https://ir.ebaystatic.com/cr/v/c01/skin/docs/dog_profile2.png"
alt="my photo"
/>
</ebay-avatar>
</div>
<div>
<ebay-avatar a11yText="Signed in as Doggy" ...input>
<@img
src="https://ir.ebaystatic.com/cr/v/c01/skin/docs/dog_profile3.png"
alt="my photo"
/>
</ebay-avatar>
</div>
<div>
<ebay-avatar a11yText="Signed in as Doggy" ...input>
<@img
src="https://ir.ebaystatic.com/cr/v/c01/skin/docs/dog_profile4.png"
alt="my photo"
/>
</ebay-avatar>
</div>
19 changes: 3 additions & 16 deletions src/components/ebay-avatar/index.marko
Original file line number Diff line number Diff line change
@@ -1,19 +1,5 @@
import { processHtmlAttributes } from "../../common/html-attributes";
import { getColorForText } from "./util";
import type { WithNormalizedProps } from "../../global";
import type { AttrString } from "marko/tags-html";

static type Size = 32 | 40 | 48 | 56 | 64 | 96 | 128;

static interface AvatarInput extends Omit<Marko.HTML.Div, `on${string}`> {
username?: string;
color?: string;
"a11y-text"?: AttrString;
size?: Size | `${Size}`;
img?: Marko.AttrTag<Omit<Marko.HTML.Img, `on${string}`>>;
}

export interface Input extends WithNormalizedProps<AvatarInput> {}

$ const {
a11yText,
Expand All @@ -32,13 +18,14 @@ $ const {
aria-label=a11yText
class=[
"avatar",
state.imagePlacement === "fit" && "avatar--fit",
inputClass,
size && `avatar--${size}`,
`avatar--${getColorForText(username, color)}`,
username && !img && `avatar--${getColorForText(username, color)}`,
]
>
<if(img)>
<img ...img>
<img onLoad("handleImageLoad") ...img>
</if>

<else-if(renderBody)>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,15 @@ exports[`avatar > renders signed out 1`] = `
"<DocumentFragment>
<div
aria-label="Signed out"
class="avatar avatar--teal"
class="avatar"
role="img"
>
<svg
aria-hidden="true"
class="icon icon--avatar-signed-out"
data-marko-key="@svg s0-3-0"
focusable="false"
>
<defs
data-marko-key="@defs s0-3-0"
>
<defs>
<symbol
id="icon-avatar-signed-out"
viewBox="0 0 40 40"
Expand Down Expand Up @@ -86,7 +83,7 @@ exports[`avatar > renders with doggy as username 1`] = `
"<DocumentFragment>
<div
aria-label="Signed in - as Elizabeth"
class="avatar avatar--magenta"
class="avatar avatar--teal"
role="img"
>
D
Expand All @@ -98,7 +95,7 @@ exports[`avatar > renders with image 1`] = `
"<DocumentFragment>
<div
aria-label="Signed in - as Doggy"
class="avatar avatar--magenta"
class="avatar"
role="img"
>
<img
Expand All @@ -113,7 +110,7 @@ exports[`avatar > renders with robert as username 1`] = `
"<DocumentFragment>
<div
aria-label="Signed in - as Elizabeth"
class="avatar avatar--magenta"
class="avatar avatar--teal"
role="img"
>
R
Expand All @@ -125,7 +122,7 @@ exports[`avatar > renders with test as usernames 1`] = `
"<DocumentFragment>
<div
aria-label="Signed in - as Elizabeth"
class="avatar avatar--green"
class="avatar avatar--teal"
role="img"
>
T
Expand Down