Repository: Telefonica/mistica-web
Pull request #1370: feat(mistica-css): TextField / SearchField
Author: login: atabel
Labels: name: released
Created: 2025-05-13T08:22:03Z | Merged: 2025-05-20T11:10:19Z

WEB-2194


Diff:
diff --git a/css/mistica-common.css b/css/mistica-common.css
index 68fd83a804..fb8d003cbd 100644
--- a/css/mistica-common.css
+++ b/css/mistica-common.css
@@ -1361,3 +1361,111 @@ button.mistica-display-card:has(.mistica-card__media):active:after {
 .mistica-checkbox-label:has(.mistica-checkbox:disabled) > .mistica-checkbox {
     opacity: initial; /* avoid applying 0.5 opacity twice */
 }
+
+/* TextField */
+.mistica-text-field {
+    --border-width: 1px;
+    --vertical-padding: calc(8px - var(--border-width));
+    --gap: 12px;
+    --right-padding: calc(16px - var(--border-width));
+    --shrinked-label-line-height: 1.25rem;
+    --label-scale: 1;
+    --icon-size: 1.5rem;
+    position: relative;
+    overflow: hidden;
+    border-radius: var(--mistica-border-radius-input);
+    border: var(--border-width) solid var(--mistica-color-inputBorder);
+    width: 328px;
+    background: var(--mistica-color-backgroundContainer);
+    color: var(--mistica-color-textPrimary);
+}
+
+@media (max-width: 1023px) {
+    .mistica-text-field {
+        --shrinked-label-line-height: 1rem;
+        width: 100%;
+    }
+}
+
+.mistica-text-field > * {
+    --start-icon-size: 0px;
+    --left-padding: calc(12px - var(--border-width) + var(--start-icon-size));
+}
+
+.mistica-text-field .mistica-text-field__start-icon ~ * {
+    --start-icon-size: calc(var(--icon-size) + var(--gap));
+}
+
+.mistica-text-field__start-icon {
+    width: var(--icon-size);
+    height: var(--icon-size);
+    position: absolute;
+    top: calc(50% - var(--icon-size) / 2);
+    left: 12px;
+    color: var(--mistica-color-neutralHigh);
+    margin-right: var(--gap);
+    pointer-events: none;
+}
+
+.mistica-text-field > label {
+    position: absolute;
+    left: var(--left-padding);
+    top: var(--vertical-padding);
+    pointer-events: none;
+    transform-origin: 0 0;
+    font-size: var(--mistica-font-size-3);
+    line-height: var(--mistica-line-height-3);
+    width: calc(100% - var(--left-padding) - var(--right-padding));
+    transform: translateY(calc(var(--shrinked-label-line-height) / 2));
+    transition:
+        transform 150ms,
+        width 150ms;
+    color: var(--mistica-color-textSecondary);
+    -webkit-line-clamp: 1;
+    overflow: hidden;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+}
+
+.mistica-text-field:focus-within > label,
+.mistica-text-field > input:not(:placeholder-shown) + label {
+    --label-scale: 0.75;
+    transform: translateY(0) scale(var(--label-scale));
+    line-height: calc(var(--shrinked-label-line-height) / var(--label-scale));
+    width: calc((100% - var(--left-padding) - var(--right-padding)) / var(--label-scale));
+    color: var(--mistica-color-textActivated);
+}
+
+.mistica-text-field > input {
+    width: 100%;
+    background: transparent;
+    border: none;
+    appearance: none;
+    font-size: var(--mistica-font-size-3);
+    line-height: var(--mistica-line-height-3);
+    font-weight: 400;
+    padding: calc(var(--vertical-padding) + var(--shrinked-label-line-height)) var(--right-padding)
+        var(--vertical-padding) var(--left-padding);
+    caret-color: var(--mistica-color-textActivated);
+    color: inherit;
+    border-radius: calc(var(--mistica-border-radius-input) - var(--border-width));
+    text-overflow: ellipsis;
+    outline: none;
+    box-shadow: none;
+}
+
+.mistica-text-field > input::placeholder {
+    opacity: 0;
+    transition: opacity 150ms cubic-bezier(0, 0, 0.2, 1) 0ms;
+}
+
+.mistica-text-field > input:focus::placeholder {
+    opacity: 0.5;
+}
+
+.mistica-text-field > input::-webkit-search-cancel-button {
+    appearance: none;
+}
+.mistica-text-field > input::-webkit-search-decoration {
+    appearance: none;
+}
diff --git a/examples/css/index.html b/examples/css/index.html
index 662a5f4cb8..a7f147a484 100644
--- a/examples/css/index.html
+++ b/examples/css/index.html
@@ -9,7 +9,7 @@
     </head>
     <body data-mistica-skin="movistar" data-mistica-color-scheme="light">
         <div id="app" class="mistica-responsive-layout">
-            <h1 class="mistica-text-title4">Hello mistica css</h1>
+            <h1 class="mistica-text-title4">Mística CSS</h1>
 
             <div class="controls">
                 <div>
@@ -46,7 +46,7 @@ <h1 class="mistica-text-title4">Hello mistica css</h1>
                 <h2 class="mistica-text-title3">Components</h2>
 
                 <h3 class="mistica-text-title2">Texts / Titles</h3>
-                <div class="cards-group">
+                <div class="horizontal-group">
                     <div>
                         <p class="mistica-text-1">Text 1</p>
                         <p class="mistica-text-2">Text 2</p>
@@ -89,8 +89,36 @@ <h3 class="mistica-text-title2">Tag</h3>
                     <div class="mistica-tag-error">Error</div>
                 </div>
 
+                <h3 class="mistica-text-title2">TextFields</h3>
+                <h4 class="mistica-text-title1">TextField</h4>
+                <div class="vertical-group">
+                    <div class="mistica-text-field">
+                        <input id="text-field-1" type="text" placeholder=" " />
+                        <label for="text-field-1"
+                            >Label too long to fit in one line too long to fit in one line too long to fit in
+                            one line too long to fit in one line</label
+                        >
+                    </div>
+                    <div class="mistica-text-field">
+                        <input id="text-field-1" type="text" placeholder="Some placeholder" />
+                        <label for="text-field-1">Label</label>
+                    </div>
+                </div>
+                <h4 class="mistica-text-title1">SearchField</h4>
+                <div class="mistica-text-field">
+                    <svg class="mistica-text-field__start-icon" viewBox="0 0 24 24" aria-hidden>
+                        <path
+                            fill="currentColor"
+                            d="M10.021 17.83A7.846 7.846 0 0 1 4.472 4.435a7.848 7.848 0 0 1 11.473 10.677l5.704 5.704a.561.561 0 0 1-.793.793l-5.697-5.697a7.8 7.8 0 0 1-5.138 1.918m0-14.571A6.726 6.726 0 0 0 5.265 14.74a6.73 6.73 0 0 0 9.513-.036 6.724 6.724 0 0 0 0-9.473 6.67 6.67 0 0 0-4.757-1.972"
+                        />
+                    </svg>
+                    <input id="search-field-1" type="search" placeholder=" " />
+                    <label for="search-field-1">Search</label>
+                </div>
+
                 <h3 class="mistica-text-title2">Switch</h3>
                 <input type="checkbox" class="mistica-switch" />
+
                 <h3 class="mistica-text-title2">Checkbox</h3>
                 <h4 class="mistica-text-title1">Without label</h4>
                 <input type="checkbox" class="mistica-checkbox" />
@@ -217,36 +245,32 @@ <h3 class="mistica-text-title2">Chip</h3>
                 </div>
 
                 <h3 class="mistica-text-title2">Breadcrumbs</h3>
-                <div class="cards-group">
-                    <nav class="mistica-breadcrumb">
-                        <ol>
-                            <li>
-                                <a href="/">Home</a>
-                            </li>
-                            <li>
-                                <a href="/">Section</a>
-                            </li>
-                            <li>
-                                <a aria-current="page" href="">Subsection</a>
-                            </li>
-                        </ol>
-                    </nav>
-                </div>
-                <div class="cards-group">
-                    <nav class="mistica-breadcrumb">
-                        <ol>
-                            <li>
-                                <a href="/">This is a long link in the breadcrumbs</a>
-                            </li>
-                            <li>
-                                <a href="/">This is a long link in the breadcrumbs</a>
-                            </li>
-                            <li>
-                                <a aria-current="page" href="">Subsection</a>
-                            </li>
-                        </ol>
-                    </nav>
-                </div>
+                <nav class="mistica-breadcrumb">
+                    <ol>
+                        <li>
+                            <a href="/">Home</a>
+                        </li>
+                        <li>
+                            <a href="/">Section</a>
+                        </li>
+                        <li>
+                            <a aria-current="page" href="">Subsection</a>
+                        </li>
+                    </ol>
+                </nav>
+                <nav class="mistica-breadcrumb">
+                    <ol>
+                        <li>
+                            <a href="/">This is a long link in the breadcrumbs</a>
+                        </li>
+                        <li>
+                            <a href="/">This is a long link in the breadcrumbs</a>
+                        </li>
+                        <li>
+                            <a aria-current="page" href="">Subsection</a>
+                        </li>
+                    </ol>
+                </nav>
 
                 <h3 class="mistica-text-title2">Buttons</h3>
                 <div>
@@ -456,7 +480,7 @@ <h4 class="mistica-text-title1">Multiple Open</h4>
 
                 <h3 class="mistica-text-title2">Cards</h3>
                 <h4 class="mistica-text-title1">MediaCard / DataCard / SnapCard</h4>
-                <div class="cards-group">
+                <div class="horizontal-group">
                     <section class="mistica-card">
                         <div
                             class="mistica-card__asset-floating"
@@ -541,7 +565,7 @@ <h2 class="mistica-card__title">Title</h2>
                         <p class="mistica-card__description">Description</p>
                     </section>
                 </div>
-                <div class="cards-group">
+                <div class="horizontal-group">
                     <a href="#" class="mistica-card">
                         <img class="mistica-card__media" src="https://picsum.photos/1200/1200" />
                         <div class="mistica-tag-promo">Headline</div>
@@ -564,7 +588,7 @@ <h2 class="mistica-card__title">Title</h2>
                     </a>
                 </div>
                 <h4 class="mistica-text-title1">NakedCard / SmallNakedCard</h4>
-                <div class="cards-group">
+                <div class="horizontal-group">
                     <section class="mistica-naked-card">
                         <img class="mistica-card__media" src="https://picsum.photos/1200/1200" />
                         <div class="mistica-tag-promo">Headline</div>
@@ -596,7 +620,7 @@ <h2 class="mistica-card__title">Title</h2>
                         <p class="mistica-card__description">Description</p>
                     </section>
                 </div>
-                <div class="cards-group">
+                <div class="horizontal-group">
                     <a href="#" class="mistica-naked-card">
                         <img class="mistica-card__media" src="https://picsum.photos/1200/1200" />
                         <div class="mistica-tag-promo">Headline</div>
@@ -614,7 +638,7 @@ <h2 class="mistica-card__title">Title</h2>
                 </div>
 
                 <h4 class="mistica-text-title1">DisplayMediaCard / DisplayDataCard</h4>
-                <div class="cards-group">
+                <div class="horizontal-group">
                     <div class="mistica-aspect-ratio" style="--aspect-ratio: 16 / 9">
                         <section class="mistica-display-card">
                             <img class="mistica-card__media" src="https://picsum.photos/1200/1200" />
@@ -665,7 +689,7 @@ <h2 class="mistica-card__title">Title</h2>
                         </section>
                     </div>
                 </div>
-                <div class="cards-group">
+                <div class="horizontal-group">
                     <div class="mistica-aspect-ratio" style="--aspect-ratio: 16 / 9">
                         <a href="#" class="mistica-display-card">
                             <img class="mistica-card__media" src="https://picsum.photos/1200/1200" />
diff --git a/examples/css/style.css b/examples/css/style.css
index 3695c57f52..803f0459a2 100644
--- a/examples/css/style.css
+++ b/examples/css/style.css
@@ -70,11 +70,17 @@ select {
     margin-top: 16px;
 }
 
-.cards-group {
+.horizontal-group {
     display: flex;
     gap: 16px;
 }
 
-.cards-group + .cards-group {
+.horizontal-group + .horizontal-group {
     margin-top: 16px;
 }
+
+.vertical-group {
+    display: flex;
+    flex-direction: column;
+    gap: 16px;
+}


Reviews:
user: login: atabel
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T08:26:23Z
user: login: yceballost
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T22:39:47Z
user: login: atabel
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T11:53:04Z
user: login: yceballost
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T17:11:01Z
user: login: atabel
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T10:18:25Z
user: login: DavidNietoGonzalez
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T10:32:03Z
user: login: atabel
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T11:05:41Z
user: login: yceballost
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T10:27:56Z

Review comments:
diff_hunk: @@ -83,6 +83,30 @@ <h3 class="mistica-text-title2">Tag</h3>
                     <div class="mistica-tag-error">Error</div>
                 </div>
 
+                <h3 class="mistica-text-title2">TextFields</h3>
+                <h4 class="mistica-text-title1">TextField</h4>
+                <div class="vertical-group">
+                    <div class="mistica-text-field">
+                        <input id="text-field-1" type="text" placeholder=" " />
path: examples/css/index.html
user: login: atabel
body: note that `placeholder` is always needed. Without a placeholder we can't implement the shrinking label effect when the input is filled (without js). With placeholder we can use the `:placeholder-visible` pseudoclass to do the trick. When we don't want the input to have a visible placeholder, we can set it to `" "` as I'm doing in this example
created_at: 2025-05-13T08:26:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -83,6 +83,30 @@ <h3 class="mistica-text-title2">Tag</h3>
                     <div class="mistica-tag-error">Error</div>
                 </div>
 
+                <h3 class="mistica-text-title2">TextFields</h3>
+                <h4 class="mistica-text-title1">TextField</h4>
+                <div class="vertical-group">
+                    <div class="mistica-text-field">
+                        <input id="text-field-1" type="text" placeholder=" " />
+                        <label for="text-field-1">Label</label>
+                    </div>
+                    <div class="mistica-text-field">
+                        <input id="text-field-1" type="text" placeholder="Some placeholder" />
+                        <label for="text-field-1">Label</label>
path: examples/css/index.html
user: login: yceballost
body: Long labels are bugged. Can we limit to 1 line? (I know this limitation is not good for accessibility but another solution is increase input field height to fit all the label. This is something that we need to improve in react too, a pending task.

![image](https://github.com/user-attachments/assets/4af37836-8f87-43f4-9e73-b6ab67ec4018)

created_at: 2025-05-13T22:33:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -9,7 +9,7 @@
     </head>
     <body data-mistica-skin="movistar" data-mistica-color-scheme="light">
         <div id="app" class="mistica-responsive-layout">
-            <h1 class="mistica-text-title4">Hello mistica css</h1>
+            <h1 class="mistica-text-title4">Mistica css</h1>
path: examples/css/index.html
user: login: yceballost
body: ```suggestion
            <h1 class="mistica-text-title4">Mística CSS</h1>
```

Just a stupid thing xD but always use "tick" to "Mística" name

and CSS i think should be in uppercase because is an acronym

created_at: 2025-05-13T22:35:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -83,6 +83,30 @@ <h3 class="mistica-text-title2">Tag</h3>
                     <div class="mistica-tag-error">Error</div>
                 </div>
 
+                <h3 class="mistica-text-title2">TextFields</h3>
+                <h4 class="mistica-text-title1">TextField</h4>
+                <div class="vertical-group">
+                    <div class="mistica-text-field">
+                        <input id="text-field-1" type="text" placeholder=" " />
+                        <label for="text-field-1">Label</label>
+                    </div>
+                    <div class="mistica-text-field">
+                        <input id="text-field-1" type="text" placeholder="Some placeholder" />
+                        <label for="text-field-1">Label</label>
path: examples/css/index.html
user: login: atabel
body: should be fixed
created_at: 2025-05-14T11:53:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -83,6 +83,30 @@ <h3 class="mistica-text-title2">Tag</h3>
                     <div class="mistica-tag-error">Error</div>
                 </div>
 
+                <h3 class="mistica-text-title2">TextFields</h3>
+                <h4 class="mistica-text-title1">TextField</h4>
+                <div class="vertical-group">
+                    <div class="mistica-text-field">
+                        <input id="text-field-1" type="text" placeholder=" " />
+                        <label for="text-field-1">Label</label>
+                    </div>
+                    <div class="mistica-text-field">
+                        <input id="text-field-1" type="text" placeholder="Some placeholder" />
+                        <label for="text-field-1">Label</label>
path: examples/css/index.html
user: login: yceballost
body: I don't think so 😬
![image](https://github.com/user-attachments/assets/52ba0b50-f84c-4e93-9d25-e39cedccf67a)
https://mistica-m2fh9sls4-flows-projects-65bb050e.vercel.app/mistica-css
created_at: 2025-05-14T17:11:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -83,6 +83,30 @@ <h3 class="mistica-text-title2">Tag</h3>
                     <div class="mistica-tag-error">Error</div>
                 </div>
 
+                <h3 class="mistica-text-title2">TextFields</h3>
+                <h4 class="mistica-text-title1">TextField</h4>
+                <div class="vertical-group">
+                    <div class="mistica-text-field">
+                        <input id="text-field-1" type="text" placeholder=" " />
+                        <label for="text-field-1">Label</label>
+                    </div>
+                    <div class="mistica-text-field">
+                        <input id="text-field-1" type="text" placeholder="Some placeholder" />
+                        <label for="text-field-1">Label</label>
path: examples/css/index.html
user: login: atabel
body: hmmm... this is how I see it 
![image](https://github.com/user-attachments/assets/6a6ece32-a37f-41cb-b087-ed140ef1d6ab)
which browser are you using?
created_at: 2025-05-16T10:18:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -83,6 +83,30 @@ <h3 class="mistica-text-title2">Tag</h3>
                     <div class="mistica-tag-error">Error</div>
                 </div>
 
+                <h3 class="mistica-text-title2">TextFields</h3>
+                <h4 class="mistica-text-title1">TextField</h4>
+                <div class="vertical-group">
+                    <div class="mistica-text-field">
+                        <input id="text-field-1" type="text" placeholder=" " />
+                        <label for="text-field-1">Label</label>
+                    </div>
+                    <div class="mistica-text-field">
+                        <input id="text-field-1" type="text" placeholder="Some placeholder" />
+                        <label for="text-field-1">Label</label>
path: examples/css/index.html
user: login: atabel
body: I've reproduced it in Firefox. I've made some changes to fix it. Please check again
created_at: 2025-05-16T11:05:41Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-13T08:24:08Z
body: **Size stats**

<table>
        <th>
            <td><b>master</b>
            <td><b>this branch</b>
            <td><b>diff</b>
        <tr>
            <td><b>Total JS</b>
            <td>12.4 MB
            <td>12.4 MB
            <td> 0 B
        <tr>
            <td><b>JS without icons</b>
            <td>2.12 MB
            <td>2.12 MB
            <td> 0 B
        <tr>
            <td><b>Lib overhead</b>
            <td>77.6 kB
            <td>77.6 kB
            <td> 0 B
        <tr>
            <td><b>Lib overhead (gzip)</b>
            <td>17.6 kB
            <td>17.6 kB
            <td> 0 B
    </table>
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-05-13T08:25:11Z
body: **Accessibility report**
✔️ No issues found

ℹ️ You can run this locally by executing `yarn audit-accessibility`.
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-05-13T08:27:35Z
body: Deploy preview for _mistica-web_ ready!

✅ Preview
https://mistica-hywlmevyc-flows-projects-65bb050e.vercel.app

Built with commit 882ae5446241653bfb3e2bdc0f3ab0027047198e.
This pull request is being automatically deployed with [vercel-action](https://github.com/marketplace/actions/vercel-action)
author_association: NONE
user: login: tuentisre
created_at: 2025-05-28T08:45:31Z
body: :tada: This PR is included in version 16.26.0 :tada:

The release is available on:
- [npm package (@latest dist-tag)](https://www.npmjs.com/package/@telefonica/mistica/v/16.26.0)
- [GitHub release](https://github.com/Telefonica/mistica-web/releases/tag/v16.26.0)

Your **[semantic-release](https://github.com/semantic-release/semantic-release)** bot :package::rocket:
author_association: COLLABORATOR