Repository navigation
fix: style - #7777
fix: style#7777
Conversation
| <img :src="previewImages.float_icon || './MaxKB.gif'" alt="" class="size-8 shrink-0 object-contain" /> | ||
| <img :src="previewImages.float_icon || defaultFloatIconUrl" alt="" class="size-8 shrink-0 object-contain" /> | ||
| </div> | ||
| </template> |
There was a problem hiding this comment.
Here's my review of the diff:
Issues / potential concerns:
-
Absolute path import (
/MaxKB.gif?url) — Starts with/, which resolves from the project root (or public dir depending on bundler). This is fragile and inconsistent with the previous relative./MaxKB.gif. It can break in sub-path deployments (e.g., apps served under/app/) and differs across Vite/Webpack. Prefer a relative import likeimport defaultFloatIconUrl from '@/assets/MaxKB.gif?url'or importing fromsrc/assets. -
Importing a
.gifinto the bundle — Using?urlpulls the asset into the JS bundle pipeline, so the image gets fingerprinted/hashed. That's fine, but ensure your bundler is configured to handle GIFs. If this file is meant to be swapped out at deploy time, keeping it inpublic/and referencing via a static path is usually better. -
No fallback for load failure — The
:srcstill has no@errorhandler. IfpreviewImages.float_iconis a bad URL, the<img>will be broken. Consider:<img :src="..." @error="($event.target as HTMLImageElement).src = defaultFloatIconUrl" ... />
or compute a validated src.
-
Missing explicit width/height or aspect ratio —
size-8sets both, but withobject-containthe actual rendered content may look tiny for wide GIFs. Not critical, just a UX note. -
alt=""— Empty alt makes the image decorative, which is correct here since it's a preview icon. Fine. -
Type safety for
previewImages.float_icon— Ensure it's typed asstring | undefined; otherwise the||fallback logically works but TS won't complain — worth double-checkingApplicationDisplaySettingtyping. -
Changelog / naming —
defaultFloatIconUrlis descriptive; good. But consider centralizing all default asset URLs in one module so future defaults don't get scattered across components.
Optimization suggestions:
- Move
MaxKB.gifundersrc/assets/and import relatively. - Add an
@errorfallback for robustness. - If the GIF never changes, cache-busting via hash is fine; if it's user-replaceable, use
public/. - For performance, if the GIF is large, consider lazy loading (
loading="lazy" decoding="async").
Overall the change is functionally sound, but the absolute import path is the main thing I'd fix before merging.
| <div v-if="show" class="mt-4 cursor-auto space-y-2 wrap-anywhere" @click.stop> | ||
| <slot v-if="showContent" /> | ||
| <div v-else class="mk-gray-card-sm"> | ||
| <h6 class="mb-2">错误日志</h6> |
There was a problem hiding this comment.
Here's a review of the diff:
Change summary
- Added
wrap-anywhereto the content<div>that wraps the slot (v-if="showContent") and the error log fallback.
Potential issues
-
wrap-anywhereis not a standard Tailwind utility (as of common versions). Tailwind providesbreak-words,break-all,break-normal,whitespace-*, and (newer)text-wrap/text-balance/text-pretty, but notwrap-anywhere. Unless this is a custom utility defined in your CSS (e.g., via a plugin or@layer utilities), it will be silently ignored — no error, but no effect. Worth verifying whether it exists in your setup. -
If intended to enable word-breaking in long strings, the standard equivalent is likely:
break-words→overflow-wrap: break-word[overflow-wrap:anywhere]→ arbitrary value if you specifically wantanywhere(which also affects min-content sizing, unlikebreak-word)
If you truly want the
anywheresemantics, use the arbitrary variant:[overflow-wrap:anywhere]. Note this differs subtly frombreak-wordformin-contentcalculations, which matters inside flex/grid layouts. -
Scope too broad. The class applies to the whole content container, including both the slotted content and the error-log card. This means every child element inherits
overflow-wrap: anywherebehavior at the container level (though children can override). Long identifier-like strings (hashes, URLs, base64 blobs) will wrap, which is the goal — but non-text elements in the slot are unaffected, so this is generally safe. Just confirm the intent is "all descendants may break," not only the error log. -
Interaction with
@click.stop. No functional interaction; the change is purely presentational. No concern there. -
Class ordering / lint. Some setups enforce Tailwind class ordering (e.g.,
prettier-plugin-tailwindcss). Placingwrap-anywhereafterspace-y-2may be reordered by the formatter. Minor.
Suggestions
- Confirm
wrap-anywhereis defined in your design system/CSS. If not, prefer the standardbreak-wordsor[overflow-wrap:anywhere]. - If the goal is specifically long unbroken strings in logs, consider scoping to the error block:
rather than the entire content wrapper, to avoid changing slotted-content rendering.
<div v-else class="mk-gray-card-sm break-words">
- Add a brief comment explaining why wrapping is needed (e.g.,
<!-- allow long identifiers/URLs to wrap -->) since the rationale isn't obvious from the class name alone.
No correctness bugs introduced by the change itself, assuming the utility exists. The main risk is a silent no-op if wrap-anywhere isn't registered.
| :popper-options="popperOptions" | ||
| :persistent="persistent && hasOpened" | ||
| v-bind="$attrs" | ||
| @visible-change="handleVisibleChange" |
There was a problem hiding this comment.
Here are my observations on this diff:
1. popper-options is a deprecated prop in Element Plus
Depending on your Element Plus version, :popper-options may have been replaced by :popper-class / :teleported / the newer popover config API. In Element Plus ≥ 2.0, the dropdown/select components use popperOptions as a plain object passed via $attrs, but the actual accepted shape is { modifiers, strategy, ... }. Verify against your installed version's docs — otherwise the option will be silently ignored.
Also make sure not to name it in snake_case with a hyphen mixed into a top-level attribute if your component isn't configured to inherit attrs (see next point).
2. Interaction with v-bind="$attrs"
Because $attrs is spread after :popper-options, any user-provided popperOptions will override popperOptions from the component unless inheritAttrs: false and explicit merging is done. Consider using v-bind="mergeAttrs({ popperOptions })" or apply $attrs first so your default can act as a fallback:
v-bind="$attrs"
:popper-options="{ ...defaults, ...($attrs.popperOptions ?? {}) }"
3. Where is popperOptions defined?
The diff only shows the template binding — ensure popperOptions is declared in <script setup> (likely as a defineProps field or local ref). If it's a ref, the binding should be :popper-options="popperOptions" (works for refs in templates) but if it's expected to be reactive on mutations you need to reassign the ref, not mutate .value deeply.
4. Type safety
If the codebase uses TypeScript, type the prop explicitly:
const props = defineProps<{
popperOptions?: PopperOptions // from '@popperjs/core' or Element Plus types
}>()Otherwise any propagated from the parent leaks in silently.
5. Potential perf nit
popperOptions objects passed inline (e.g. :popper-options="{ placement: 'bottom' }") create a new reference each render, causing the dropdown to re-initialize its Popper instance. Prefer a stable object from computed or readonly.
6. Naming convention consistency
Your file uses kebab-case (hide-when-empty, visible-change) for other props; :popper-options matches that, good. Just double-check the component's declared prop name is popperOptions (not popper-options) so binding resolution works correctly in both setups.
7. Missing guards
Add a guard so an undefined popperOptions doesn't get passed through to Element Plus (which expects an object):
:popper-options="popperOptions || undefined"Summary: the change itself is fine syntactically, but verify prop deprecation status, $attrs precedence, and reactivity of the options object to avoid subtle overrides or re-init churn.
No description provided.