Skip to content

feat(asset): exploring 2nd gen usage#6021

Draft
aramos-adobe wants to merge 7 commits intomainfrom
aziz/swc1463-migrating-asset-comp
Draft

feat(asset): exploring 2nd gen usage#6021
aramos-adobe wants to merge 7 commits intomainfrom
aziz/swc1463-migrating-asset-comp

Conversation

@aramos-adobe
Copy link
Copy Markdown
Contributor

@aramos-adobe aramos-adobe commented Feb 12, 2026

Description

Asset (2nd gen)

  • Error state: Supports failed or unavailable asset content (e.g. broken images) with a clear error icon and optional visible label, improving feedback and accessibility.
  • Aspect ratio: Provides ability to fit the media element on desired ratio ie. 16:9, 4:3, or 1:1. Portrait ratios are also supported
  • Still maintains file and folder variants

New swc-image component/tool (2nd-gen)

image-only component: a container that renders an <img> from src and exposes the inner image for styling (e.g. width, height, border-radius) via the image part and .spectrum-Image-image class.

  • Research showed sp-asset is often used as a div wrapper around an image (or video), with a class like asset-image used to style size and border-radius. This adds a dedicated image-only component that:
    • Always renders from src (no slot).
    • Exposes the inner image via part="image" and .spectrum-Image-image so engineers can target it for width, height, border-radius, etc., similar to the existing asset-image pattern.

Motivation and context

This PR leads the discussion on what to do with the asset component now that the design dictionary in Spectrum 2 has diverged from its usage while the component is still being used in applications such as Photoshop Web.

Related issue(s)

  • fixes [SWC-1463]

Screenshots (if appropriate)


Author's checklist

  • I have read the CONTRIBUTING and PULL_REQUESTS documents.
  • I have reviewed at the Accessibility Practices for this feature, see: Aria Practices
  • I have added automated tests to cover my changes.
  • I have included a well-written changeset if my change needs to be published.
  • I have included updated documentation if my change required it.

Reviewer's checklist

  • Includes a Github Issue with appropriate flag or Jira ticket number without a link
  • Includes thoughtfully written changeset if changes suggested include patch, minor, or major features
  • Automated tests cover all use cases and follow best practices for writing
  • Validated on all supported browsers
  • All VRTs are approved before the author can update Golden Hash

Manual review test cases

  • Asset error state

    1. Open Storybook → Asset → States → Error.
    2. Confirm the error icon and label “Failed to load image” (or current story label) are shown.
    3. Toggle the error control and confirm the asset switches between error and normal (e.g. file/folder/src/slot) as expected.
  • swc-image

    1. Open Storybook → Image → Playground.
    2. Open “Styling the image” and confirm Default, Rounded, and Circle examples render and the ::part(image) styles apply (rounded corners and circle).
    3. Confirm ObjectFit examples (contain, cover, fill) behave as expected.

Device review

  • Did it pass in Desktop?
  • Did it pass in (emulated) Mobile?
  • Did it pass in (emulated) iPad?

@aramos-adobe aramos-adobe requested a review from a team as a code owner February 12, 2026 15:42
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Feb 12, 2026

⚠️ No Changeset found

Latest commit: f1ed776

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@aramos-adobe aramos-adobe self-assigned this Feb 12, 2026
@aramos-adobe aramos-adobe changed the title Aziz/swc1463-migrating-asset-comp feat(asset): exploring 2nd gen usage Feb 12, 2026
@aramos-adobe aramos-adobe marked this pull request as draft February 12, 2026 15:45
@github-actions
Copy link
Copy Markdown
Contributor

📚 Branch Preview Links

🔍 First Generation Visual Regression Test Results

When a visual regression test fails (or has previously failed while working on this branch), its results can be found in the following URLs:

Deployed to Azure Blob Storage: pr-6021

If the changes are expected, update the current_golden_images_cache hash in the circleci config to accept the new images. Instructions are included in that file.
If the changes are unexpected, you can investigate the cause of the differences and update the code accordingly.

@aramos-adobe aramos-adobe added the Status:Ready for review PR ready for review or re-review. label Feb 15, 2026
Copy link
Copy Markdown
Contributor

@Rajdeepc Rajdeepc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good effort. Noticed a few structural gaps in this PR.
The image-related types are duplicated in both Asset.types.ts and Image.types.ts, which is a drift — these should be consolidated into a shared source or imported from one place.

The new swc-image component is also introduced without any unit or accessibility tests (there’s no components/image/test/ coverage), which we shouldn’t ship for a new component.

The accessibility documentation in asset.stories.ts is quite thin. It’s missing keyboard behavior (even stating non-interactive), visual accessibility considerations, ARIA implementation details, and clarification of error-state semantics.

I’ve left more inline comments, but these should be addressed before moving forward.

Comment on lines +37 to +118
@property({ type: String })
public src?: string;

/**
* Alternative text for the image. Required for accessibility when using `src`.
*/
@property({ type: String })
public alt?: string;

/**
* Loading behavior for the image.
* - 'lazy': Defers loading until near the viewport
* - 'eager': Loads immediately
*/
@property({ type: String })
public loading?: LoadingType;

/**
* How the image fits within the container.
* - 'contain': Scale to fit, maintain aspect ratio
* - 'cover': Scale to fill, maintain aspect ratio
* - 'fill': Stretch to fill
* - 'none': Do not resize
* - 'scale-down': Smaller of none or contain
*/
@property({ type: String, attribute: 'object-fit' })
public objectFit?: ObjectFit;

/**
* Position of the image when using object-fit.
* Accepts CSS object-position values (e.g. 'center', 'top left').
*/
@property({ type: String, attribute: 'object-position' })
public objectPosition?: string;

/**
* Responsive image sources (e.g. "image-320w.jpg 320w, image-480w.jpg 480w").
*/
@property({ type: String })
public srcset?: string;

/**
* Sizes for responsive images (e.g. "(max-width: 600px) 480px, 800px").
*/
@property({ type: String })
public sizes?: string;

/**
* Image decoding hint: 'sync' | 'async' | 'auto'.
*/
@property({ type: String })
public decoding?: DecodingType;

/**
* CORS setting for cross-origin images.
*/
@property({ type: String })
public crossorigin?: CrossOrigin;

/**
* Referrer policy for image requests.
*/
@property({ type: String })
public referrerpolicy?: ReferrerPolicy;

/**
* Width in pixels. Used for layout and aspect ratio.
*/
@property({ type: Number })
public width?: number;

/**
* Height in pixels. Used for layout and aspect ratio.
*/
@property({ type: Number })
public height?: number;

/**
* When true, shows an error state (e.g. failed to load).
*/
@property({ type: Boolean, reflect: true })
public error = false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

swc-image has its own ImageBase with the exact same properties. This is a massive responsibility bloat on AssetBase. An swc-asset is conceptually a wrapperfor media. If you are making it also directly render elements means it's trying to be both a container and an image component simultaneously.

* When true, shows an error state (e.g. failed to load).
*/
@property({ type: Boolean, reflect: true })
public error = false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are you planning to create an automatic error detection when an image URL fails? This seems like a dead property. If consumer adds <swc-image error> nothing will happen. Kindly implement error state rendering in Image.ts.

}) => {
const asset = await gotoStory(
page,
'components-asset--media-wrapper',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check this. This might fail.

Comment thread 2nd-gen/packages/core/components/asset/Asset.base.ts Outdated
Comment on lines +58 to +72
<img
part="image"
class="spectrum-Image-image"
src=${this.src}
alt=${this.alt || ''}
loading=${ifDefined(this.loading)}
decoding=${ifDefined(this.decoding)}
srcset=${ifDefined(this.srcset)}
sizes=${ifDefined(this.sizes)}
crossorigin=${ifDefined(this.crossorigin)}
referrerpolicy=${ifDefined(this.referrerpolicy)}
width=${ifDefined(this.width)}
height=${ifDefined(this.height)}
style=${styleMap(imageStyles)}
/>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no way for consumers to know when the image finishes loading. At minimum you can add a error state here like @error=${() => this.error = true} and dispatch a custom event like swc-image-error`.

Comment thread 2nd-gen/packages/swc/components/asset/stories/asset.stories.ts Outdated
* Useful for grids and cards where thumbnails should share the same ratio.
*/
export const AspectRatio: Story = {
render: () => html`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always spread ...args into template calls. This and Rounder stories are using render: () => (no args) and you are hardcoding everything which means Storybook controls are completely non-functional for these stories.

Comment on lines +279 to +285
export const Error: Story = {
args: {
error: true,
label: 'Failed to load',
},
tags: ['states'],
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very standalone error demonstration. can you be a more robust on this story and show

  1. Error with a variant set
  2. Error without a label
  3. Error with rounded corners


protected override render(): TemplateResult {
if (!this.src) {
return html`<div class="spectrum-Image"></div>`;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An empty div takes up space in layout (the CSS gives it inline-size: 100% and block-size: 100%). Please consider rendering nothing so the empty state is intentional.

Comment on lines +194 to +199
.image-rounded::part(image) {
border-radius: 8px;
}
.image-circle::part(image) {
border-radius: 50%;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use global style tags in storybook. It will leak unto other stries when SB reuses the DOM canvas. You can use a scoped decorator.

@Rajdeepc Rajdeepc added blocked Ticket or PR is blocked for some reason, eg another PR needs to go in first and removed Status:Ready for review PR ready for review or re-review. labels Feb 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocked Ticket or PR is blocked for some reason, eg another PR needs to go in first

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants