|
137 | 137 |
|
138 | 138 | const affix = $derived(clearable || loading !== undefined); |
139 | 139 | const close = $derived(clearable && (focused || hovered) && value?.length && !rest?.disabled && !rest?.readonly); |
| 140 | + const isFloating = $derived(floating && !focused && !value?.length); |
| 141 | +
|
| 142 | + let labelRef = $state<HTMLLabelElement>(); |
| 143 | + let labelHeight = $state(); |
| 144 | +
|
| 145 | + $effect(() => { |
| 146 | + if (!labelRef || !floating) return; |
| 147 | + labelHeight = `${labelRef?.clientHeight ?? 0}px`; |
| 148 | + }); |
140 | 149 |
|
141 | 150 | const context: NeoInputContext = $derived({ |
142 | 151 | // Ref |
|
230 | 239 | class:start |
231 | 240 | class:skeleton |
232 | 241 | class:disabled={rest?.disabled} |
233 | | - class:raised={elevation > 3 || hover > 3} |
234 | | - class:inset={elevation < -3 || hover < -3} |
| 242 | + class:raised={elevation > 3 || elevation + hover > 3} |
| 243 | + class:inset={elevation < -3 || elevation + hover < -3} |
235 | 244 | class:flat={!elevation} |
236 | 245 | class:hover-flat={hoverFlat} |
237 | 246 | class:flat-hover={flatHover} |
|
249 | 258 | > |
250 | 259 | {@render before()} |
251 | 260 | {#if label} |
252 | | - <div class="neo-input-label-container" class:placeholder={floating && !focused && !value?.length}> |
253 | | - <label for={id} class="neo-input-label" class:prefix class:rounded> |
| 261 | + <div class="neo-input-label-container" class:prefix class:placeholder={isFloating}> |
| 262 | + <label bind:this={labelRef} for={id} class="neo-input-label" class:prefix class:rounded style:--neo-input-label-height={labelHeight}> |
254 | 263 | {#if typeof label === 'string'} |
255 | 264 | {label} |
256 | 265 | {:else} |
|
268 | 277 | <style lang="scss"> |
269 | 278 | @use 'src/lib/styles/mixin' as mixin; |
270 | 279 |
|
271 | | - .neo-input-label-container { |
272 | | - position: relative; |
273 | | - flex: 1 1 auto; |
274 | | - padding-top: calc(0.5rem + var(--neo-font-size-xs)); |
275 | | -
|
276 | | - .neo-input-label { |
277 | | - position: absolute; |
278 | | - top: 0.3rem; |
279 | | - left: 0; |
280 | | - width: 100%; |
281 | | - padding: 0.1rem 0.75rem; |
282 | | - overflow: hidden; |
283 | | - font-size: var(--neo-font-size-xs); |
284 | | - white-space: nowrap; |
285 | | - text-overflow: ellipsis; |
286 | | - transition: |
287 | | - color 0.3s ease, |
288 | | - font-size 0.3s ease, |
289 | | - top 0.3s ease, |
290 | | - left 0.3s ease; |
291 | | - pointer-events: unset; |
292 | | -
|
293 | | - &.prefix { |
294 | | - padding-left: 0; |
295 | | - } |
296 | | - } |
297 | | -
|
298 | | - &.placeholder { |
299 | | - .neo-input-label { |
300 | | - top: calc(50% - 0.1rem - var(--neo-font-size-xs)); |
301 | | - color: var(--neo-input-placeholder-color, var(--neo-text-color-disabled)); |
302 | | - font-size: var(--neo-font-size); |
303 | | - pointer-events: none; |
304 | | - } |
305 | | -
|
306 | | - ::placeholder { |
307 | | - opacity: 0; |
308 | | - } |
309 | | - } |
310 | | - } |
311 | | -
|
312 | 280 | .neo-input-group, |
313 | 281 | .neo-input, |
314 | 282 | .neo-input-clear, |
|
450 | 418 | } |
451 | 419 | } |
452 | 420 |
|
| 421 | + .neo-input-label-container { |
| 422 | + flex: 1 1 auto; |
| 423 | +
|
| 424 | + .neo-input-label { |
| 425 | + display: flex; |
| 426 | + min-height: var(--neo-input-label-height); |
| 427 | + padding: 0.5rem 1rem 0; |
| 428 | + overflow: hidden; |
| 429 | + font-size: var(--neo-font-size-xs); |
| 430 | + text-wrap: stable; |
| 431 | + text-overflow: ellipsis; |
| 432 | + transition: |
| 433 | + width 0.3s ease, |
| 434 | + color 0.3s ease, |
| 435 | + font-size 0.3s ease, |
| 436 | + translate 0.3s ease; |
| 437 | + will-change: width, color, font-size, translate; |
| 438 | +
|
| 439 | + &.prefix { |
| 440 | + padding-left: 0.25rem; |
| 441 | + } |
| 442 | + } |
| 443 | +
|
| 444 | + .neo-input { |
| 445 | + padding: 0.25rem 1rem 0.75rem; |
| 446 | + } |
| 447 | +
|
| 448 | + &.placeholder { |
| 449 | + .neo-input-label { |
| 450 | + color: var(--neo-input-placeholder-color, var(--neo-text-color-disabled)); |
| 451 | + font-size: var(--neo-font-size); |
| 452 | + translate: 0 calc(50% + 0.75rem - var(--neo-input-label-height) / 2); |
| 453 | + } |
| 454 | +
|
| 455 | + ::placeholder { |
| 456 | + opacity: 0; |
| 457 | + } |
| 458 | + } |
| 459 | + } |
| 460 | +
|
453 | 461 | .neo-input-group { |
454 | 462 | margin: var(--neo-shadow-margin, 0.6rem); |
455 | 463 | color: var(--neo-input-text-color, inherit); |
|
463 | 471 | } |
464 | 472 |
|
465 | 473 | &.inset { |
466 | | - padding: var(--neo-shadow-padding, 0.6rem); |
| 474 | + padding: 0.25rem; |
467 | 475 | } |
468 | 476 |
|
469 | 477 | &.hover.flat-hover:hover, |
|
480 | 488 | &.rounded { |
481 | 489 | border-radius: var(--neo-border-radius-lg, 2rem); |
482 | 490 |
|
483 | | - .neo-input-label-container { |
484 | | - padding-left: 0.5rem; |
485 | | -
|
486 | | - .neo-input-label { |
487 | | - left: 0.5rem; |
488 | | -
|
489 | | - &:not(.prefix) { |
490 | | - left: 0.75rem; |
491 | | - } |
492 | | - } |
493 | | - } |
494 | | -
|
495 | 491 | .neo-input { |
496 | 492 | padding: 0.75rem 1rem; |
497 | 493 | border-radius: var(--neo-border-radius-lg, 2rem); |
|
517 | 513 | padding-right: 0.75rem; |
518 | 514 | } |
519 | 515 | } |
| 516 | +
|
| 517 | + .neo-input-label-container { |
| 518 | + &:not(.prefix) { |
| 519 | + padding-left: 0.75rem; |
| 520 | + } |
| 521 | +
|
| 522 | + .neo-input-label { |
| 523 | + padding: 0.5rem 1rem 0; |
| 524 | +
|
| 525 | + &.prefix { |
| 526 | + padding-left: 0.125rem; |
| 527 | + } |
| 528 | + } |
| 529 | +
|
| 530 | + .neo-input { |
| 531 | + padding: 0.25rem 1rem 0.75rem; |
| 532 | + } |
| 533 | + } |
520 | 534 | } |
521 | 535 |
|
522 | 536 | &.glass { |
|
0 commit comments