Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 12
feat(core): add icon style control#219
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
base:main
Are you sure you want to change the base?
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -27,6 +27,7 @@ declare global { | ||
| * @cssprop --color | ||
| * @cssprop --width | ||
| * @cssprop --height | ||
| * @attr appearance - Selects the outline or solid form of a named icon. | ||
| * @slot - Custom SVG content to override the named icon | ||
| * @aria https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img | ||
| */ | ||
| @@ -46,6 +47,12 @@ export class Icon extends LitElement { | ||
| */ | ||
| @property({ type: String, reflect: true }) direction?: 'up' | 'down' | 'left' | 'right'; | ||
| /** | ||
| * Selects the outline or solid form of the named icon. Solid icons use an optional `-solid` asset and fall back to | ||
| * the outline form when that asset is unavailable. | ||
| */ | ||
| @property({ type: String }) appearance?: 'outline' | 'solid'; | ||
Comment on lines
+50
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift Implement the public API specified by the PR objective. The PR objective requires
📍 Affects 3 files
🤖 Prompt for AI Agents | ||
| /** | ||
| * The name of the icon SVG sprite to render. | ||
| */ | ||
| @@ -80,12 +87,26 @@ export class Icon extends LitElement { | ||
| /** @private */ | ||
| declare _internals: ElementInternals; | ||
| get #resolvedIconName() { | ||
| if (!this.name || this.name.endsWith('.svg') || this.appearance !== 'solid' || this.name.endsWith('-solid')) { | ||
| return this.name; | ||
| } | ||
| const solidName = `${this.name}-solid`; | ||
| return Icon._iconsRegistry[solidName] ? solidName : this.name; | ||
| } | ||
| get #iconString() { | ||
| return isServer && globalThis._NVE_SSR_ICON_REGISTRY ? globalThis._NVE_SSR_ICON_REGISTRY[this.name!] : this.svg; | ||
| const iconName = this.#resolvedIconName; | ||
| return isServer && globalThis._NVE_SSR_ICON_REGISTRY && iconName | ||
| ? globalThis._NVE_SSR_ICON_REGISTRY[iconName] | ||
| : this.svg; | ||
| } | ||
| #iconRegistryEventName?: string; | ||
| #renderRequest = 0; | ||
| #onIconRegistryUpdate = (event: Event) => this.#asyncRender(event as CustomEvent<IconSVG>); | ||
| render() { | ||
| @@ -133,16 +154,17 @@ export class Icon extends LitElement { | ||
| async updated(props: PropertyValues<this>) { | ||
| super.updated(props); | ||
| if (props.has('name')) { | ||
| if (props.has('name') || props.has('appearance')) { | ||
| this.#removeIconRegistryListener(); | ||
| this.#addIconRegistryListener(); | ||
| } | ||
| await this.#render(); | ||
| } | ||
| #addIconRegistryListener() { | ||
| if (!this.isConnected || !this.name || this.#iconRegistryEventName) return; | ||
| this.#iconRegistryEventName = `${Icon.metadata.tag}-${this.name}`; | ||
| const iconName = this.#resolvedIconName; | ||
| if (!this.isConnected || !iconName || this.#iconRegistryEventName) return; | ||
| this.#iconRegistryEventName = `${Icon.metadata.tag}-${iconName}`; | ||
| globalThis.document?.addEventListener(this.#iconRegistryEventName, this.#onIconRegistryUpdate); | ||
Comment on lines
164
to
168
| ||
| } | ||
| @@ -159,11 +181,14 @@ export class Icon extends LitElement { | ||
| } | ||
| async #render() { | ||
| if (!this.name) return; | ||
| const svg = await (this.name.endsWith('.svg') | ||
| ? fetch(this.name).then(res => res.text()) | ||
| : (Icon._iconsRegistry[this.name]?.svg() ?? Promise.resolve(''))); | ||
| Icon._iconsRegistry[this.name] = { svg: () => svg, ...Icon._iconsRegistry[this.name] }; | ||
| const renderRequest = ++this.#renderRequest; | ||
| const iconName = this.#resolvedIconName; | ||
| if (!iconName) return; | ||
| const svg = await (iconName.endsWith('.svg') | ||
| ? fetch(iconName).then(res => res.text()) | ||
| : (Icon._iconsRegistry[iconName]?.svg() ?? Promise.resolve(''))); | ||
| if (renderRequest !== this.#renderRequest) return; | ||
| Icon._iconsRegistry[iconName] = { svg: () => svg, ...Icon._iconsRegistry[iconName] }; | ||
| this.svg = svg; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Restore
window.fetchwhen the test fails.If an awaited operation or assertion fails, line 251 does not run. Later tests then use this mock unexpectedly. Put the test body in
try/finally.Proposed fix
🤖 Prompt for AI Agents