Files
landing-app/landing/src/app/ui/contact-form.scss
pigui e9082b90ee Restore the numeric field's left inset
The value in "Horas por semana" sat 12px to the left of every other
field -- and, more visibly, 12px left of its own label, which stayed
where the others were.

It is a defect in @pi/ui, measured rather than guessed:

  field           has-icon-prefix   prefix   value starts at
  text-field      false             --       16px
  email-field     false             --       16px
  number-field    true              4px      4px

`pi-number-field` declares `<ng-container matPrefix>` unconditionally,
so Material treats the field as having an icon prefix even with nothing
projected into it. The empty 4px prefix displaces the 16px inset the
other fields get. Only two of the library's twenty field templates
declare a prefix, both numeric, and only `incremental-number-field`
actually fills one -- so it is an oversight, not a pattern.

This is the stopgap, marked as such and scoped to that field. The real
fix is already written in the library (`pireon-ui`,
`number-field.component.html`, guarded by a `contentChild`) but is not
built or published yet; this rule comes out when that version lands.

Verified in both themes: all four fields now start their value and their
label at 16px.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-30 19:36:00 +02:00

156 lines
6.0 KiB
SCSS

// The gap has to beat the distance from a field to its own error message,
// which Material renders flush underneath it — 0px. At 1.25rem the message
// ended up 6px from the *next* field's label and 0px from its own field, so
// "Falta el nombre" read as the caption of "HORAS POR SEMANA" rather than of
// the field above it. The three lines have to group with the field they belong
// to, which means the space between rows must be visibly larger than the space
// inside one.
.landing-form {
display: flex;
flex-direction: column;
gap: 2rem;
}
.landing-form__kind {
border: 0;
margin: 0;
padding: 0;
legend {
padding: 0 0 0.5rem;
font-weight: 600;
}
}
.landing-form__row {
display: grid;
gap: 1.25rem;
@media (min-width: 640px) {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
.landing-form__error {
margin: 0;
color: var(--pi-color-warn, #d64545);
}
// The hours field sits inside an @if, and that is what breaks its label.
//
// Angular Material measures an outlined field's floating label once, on init,
// and writes the result to the element as an inline
// `transform: var(--mat-mdc-form-field-label-transform, translateY(-50%) …)`.
// A field created inside a conditional block is measured before it has any
// geometry, so the value it keeps is the unfloated one: the label ends up 5px
// above the wrapper instead of 18, straddling the 2px outline and struck
// through by it.
//
// `@pi/ui` already publishes the right geometry for every other field
// (`translateY(-3rem) scale(1)`, a 48px label box), and that rule matches this
// one too — it simply loses to the inline style. `!important` is what beats an
// inline declaration, and it is restating the library's own values, not
// inventing new ones.
:host ::ng-deep .pi-field.pi-form-field__number {
.mdc-notched-outline .mdc-floating-label {
height: var(--pi-spacing-xxxx-large) !important;
}
.mdc-text-field:not(.mat-form-field-no-animations) .mdc-floating-label {
transform: translateY(-3rem) scale(1) !important;
}
}
// Two things the library gets wrong once a field is in a real state.
//
// 1. The label changes shape when you focus it. `@pi/ui` applies the theme's
// label typography under `:not(.mdc-text-field--focused)`, so text-transform,
// letter-spacing and weight all fall away the moment the field takes focus:
// "MENSAJE *" becomes "Mensaje *" in a lighter face, and the label visibly
// reflows under the cursor. Restated here without that guard. Colour is
// deliberately left alone — Material tints the label on focus, and that part
// is wanted.
//
// 2. The focus ring is a stadium on the textarea. Both the notched outline and
// the gradient ring take their radius from `--pi-theme-field-radius`, which
// the `alternative` shell sets to 999px. That is right for a 48px-tall input
// and wrong for a 112px-tall textarea: the two shapes stop coinciding and
// the field is drawn twice, once in the error colour and once in the
// gradient, offset from each other. A fixed radius makes them agree again.
:host ::ng-deep {
.pi-field .mdc-text-field:not(.mdc-text-field--disabled) .mdc-floating-label {
text-transform: var(--pi-theme-field-label-transform, none);
letter-spacing: var(--pi-theme-field-label-letter-spacing, normal);
font-weight: var(--pi-theme-field-label-weight, inherit);
}
// A stadium is right for a 48px input and wrong for a 112px textarea, which
// is all this is now — with the focus ring gone there is no second shape to
// agree with.
.pi-field.pi-form-field__textarea {
--pi-theme-field-radius: 1.25rem;
}
}
// Error states, which move the form around and read wrong.
//
// 1. Submitting an incomplete form shoved everything below it downwards.
// Material's subscript strip is 10px tall while a field is valid and 24px
// once it carries a message, so every errored field grew the form by 14px at
// once — the fields under the cursor jumped out from under it. Reserving the
// taller height up front costs 14px of whitespace and buys a form that does
// not move.
//
// 2. `pi-checkbox` renders its message as an inline span straight after the
// label, so it ran on as part of the sentence: "Acepto que guardéis mis
// datos para responderme. Hace falta tu consentimiento". It belongs on its
// own line, like every other field's message.
:host ::ng-deep {
.pi-field .mat-mdc-form-field-subscript-wrapper {
min-height: 1.5rem;
}
// Its own line, in space reserved for it. Left in flow it would push the
// submit button 25px down at the exact moment you press it — the same jump
// the reserved subscript above removes for the fields.
.pi-checkbox {
position: relative;
padding-bottom: 1.25rem;
}
// Nothing in the library styles this class, so the message inherited the
// body colour and read as ordinary text next to four red ones.
.pi-checkbox__error {
display: block;
position: absolute;
left: 0;
bottom: 0;
color: var(--pi-color-warn);
// `mat-error` renders the other four at 12px; this one inherited 15px.
font-size: var(--pi-font-size-x-small, 0.75rem);
}
}
// TEMPORARY. Remove when @pi/ui ships the fix.
//
// `pi-number-field` declares `<ng-container matPrefix>` unconditionally, so
// Material marks the field as having an icon prefix even though nothing is
// projected into it. The empty prefix is 4px wide and takes the place of the
// 16px inset every other field gets: the value ended up 12px to the left of
// its own label, which is what makes it look wrong.
//
// Only two of the library's twenty fields declare a prefix, both numeric, and
// only `incremental-number-field` actually uses one — so this is an oversight
// rather than a pattern. The fix belongs there and is written:
// `pireon-ui`, `number-field.component.html`, guarded by a `contentChild`.
// This restores the inset here until that version is published.
:host ::ng-deep .pi-form-field__number {
.mat-mdc-form-field-icon-prefix {
display: none;
}
.mat-mdc-form-field-infix {
padding-left: 16px;
}
}