diff --git a/pages/avatar/custom-style.page.tsx b/pages/avatar/custom-style.page.tsx new file mode 100644 index 0000000..0b882f4 --- /dev/null +++ b/pages/avatar/custom-style.page.tsx @@ -0,0 +1,132 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import SpaceBetween from "@cloudscape-design/components/space-between"; + +import { Avatar } from "../../lib/components"; +import { customIconSvg } from "./permutations.page"; +import smiley from "./smiley.png"; + +export default function CustomStyles() { + return ( + <> +

Custom Avatars

+ + + + + + + + + + + + + + + + ); +} diff --git a/pages/avatar/permutations.page.tsx b/pages/avatar/permutations.page.tsx index 6b8c5fb..e1c4268 100644 --- a/pages/avatar/permutations.page.tsx +++ b/pages/avatar/permutations.page.tsx @@ -8,7 +8,7 @@ import { TestBed } from "../app/test-bed"; import { ScreenshotArea } from "../screenshot-area"; import smiley from "./smiley.png"; -const customIconSvg = ( +export const customIconSvg = ( ; + return ; } if (initials) { @@ -59,6 +61,7 @@ export default function InternalAvatar({ iconSvg, iconUrl, imgUrl, + style, width = 28, __internalRootRef = null, ...rest @@ -99,7 +102,7 @@ export default function InternalAvatar({ role="img" aria-label={ariaLabel} {...tooltipAttributes} - style={{ [customCssProps.avatarSize]: `${computedSize}px` }} + style={{ [customCssProps.avatarSize]: `${computedSize}px`, ...getRootStyles(style) }} > {showTooltip && tooltipText && ( + diff --git a/src/avatar/loading-dots/index.tsx b/src/avatar/loading-dots/index.tsx index 9095945..04716ed 100644 --- a/src/avatar/loading-dots/index.tsx +++ b/src/avatar/loading-dots/index.tsx @@ -2,19 +2,23 @@ // SPDX-License-Identifier: Apache-2.0 import clsx from "clsx"; +import { AvatarProps } from "../interfaces.js"; +import { getLoadingDotsStyle } from "../style"; + import styles from "./styles.css.js"; interface LoadingDotsProps { color?: string; + style?: AvatarProps.Style; width?: number; } -export default function LoadingDots({ color, width }: LoadingDotsProps) { +export default function LoadingDots({ color, width, style }: LoadingDotsProps) { const dotSize = `calc(.14px * ${width})`; return ( // "gen-ai" class is added so that the gradient background animates. -
+
diff --git a/src/avatar/style.tsx b/src/avatar/style.tsx new file mode 100644 index 0000000..54056e5 --- /dev/null +++ b/src/avatar/style.tsx @@ -0,0 +1,64 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { SYSTEM } from "../internal/environment"; +import customCssProps from "../internal/generated/custom-css-properties"; +import { AvatarProps } from "./interfaces"; + +export function getRootStyles(style: AvatarProps.Style | undefined) { + let properties = {}; + + if (SYSTEM === "core" && style?.root) { + properties = { + background: style.root?.background, + borderRadius: style.root?.borderRadius, + boxShadow: style.root?.boxShadow, + color: style.root?.color, + [customCssProps.avatarRootBorderWidth]: style.root?.borderWidth, + [customCssProps.avatarFocusRingBorderColor]: style.root?.focusRing?.borderColor, + [customCssProps.avatarFocusRingBorderRadius]: style.root?.focusRing?.borderRadius, + [customCssProps.avatarFocusRingBorderWidth]: style.root?.focusRing?.borderWidth, + }; + } + + return properties; +} + +export function getContentStyles(style: AvatarProps.Style | undefined) { + let properties = {}; + + if (SYSTEM === "core" && style?.root) { + properties = { + borderColor: style.root?.borderColor, + borderRadius: style.root?.borderRadius, + borderStyle: style.root?.borderWidth && "solid", + borderWidth: style.root?.borderWidth, + }; + } + + return properties; +} + +export function getImageStyles(style: AvatarProps.Style | undefined) { + let properties = {}; + + if (SYSTEM === "core" && style?.root) { + properties = { + borderRadius: style.root?.borderRadius, + }; + } + + return properties; +} + +export function getLoadingDotsStyle(style: AvatarProps.Style | undefined) { + let properties = {}; + + if (SYSTEM === "core" && style?.root) { + properties = { + borderRadius: style.root?.borderRadius, + }; + } + + return properties; +} diff --git a/src/avatar/styles.scss b/src/avatar/styles.scss index c1c909f..9f0a623 100644 --- a/src/avatar/styles.scss +++ b/src/avatar/styles.scss @@ -9,9 +9,12 @@ .root { @include shared.styles-reset; + align-items: center; + display: flex; color: cs.$color-text-avatar; block-size: var(#{custom-props.$avatarSize}); inline-size: var(#{custom-props.$avatarSize}); + justify-content: center; position: relative; @include mixins.border-radius-avatar; @@ -35,7 +38,14 @@ } &:focus-visible { - @include shared.focus-highlight(4px, 50%); + @include shared.focus-highlight( + $gutter: calc( + 4px + var(#{custom-props.$avatarRootBorderWidth}, 0px) + var(#{custom-props.$avatarFocusRingBorderWidth}, 0px) + ), + $border-radius: var(#{custom-props.$avatarFocusRingBorderRadius}, 50%), + $border-color: var(#{custom-props.$avatarFocusRingBorderColor}, cs.$color-border-item-focused), + $border-width: var(#{custom-props.$avatarFocusRingBorderWidth}, 2px) + ); } &:has(.image) { diff --git a/src/internal/environment.d.ts b/src/internal/environment.d.ts index 0994079..56c6d8b 100644 --- a/src/internal/environment.d.ts +++ b/src/internal/environment.d.ts @@ -5,5 +5,6 @@ export declare const THEME: string; export declare const PACKAGE_SOURCE: string; export declare const PACKAGE_VERSION: string; +export declare const SYSTEM: string; /** Indicates that the current theme is always in visual refresh mode. */ export declare const ALWAYS_VISUAL_REFRESH: boolean; diff --git a/src/internal/shared.scss b/src/internal/shared.scss index de63971..4d762dc 100644 --- a/src/internal/shared.scss +++ b/src/internal/shared.scss @@ -4,7 +4,12 @@ */ @use "../../node_modules/@cloudscape-design/design-tokens/index.scss" as cs; -@mixin focus-highlight($gutter: 4px, $border-radius: cs.$border-radius-control-default-focus-ring) { +@mixin focus-highlight( + $gutter: 4px, + $border-radius: cs.$border-radius-control-default-focus-ring, + $border-color: cs.$color-border-item-focused, + $border-width: 2px +) { position: relative; box-sizing: border-box; outline: 2px dotted transparent; @@ -20,7 +25,7 @@ inline-size: calc(100% + 2 * #{$gutter}); block-size: calc(100% + 2 * #{$gutter}); border-radius: $border-radius; - border: 2px solid cs.$color-border-item-focused; + border: $border-width solid $border-color; } }