使用 React 和 Ant Design 的浮动标签

Posted

技术标签:

【中文标题】使用 React 和 Ant Design 的浮动标签【英文标题】:Floating labels using React and Ant Design 【发布时间】:2020-03-01 03:32:21 【问题描述】:

对于我的 React 应用程序,我正在尝试使用来自 Antd 的模板构建一个带有 浮动标签 的表单,该模板具有不同的输入类型,仅使用样式来使标签浮动。到目前为止,我已经能够将标签放在输入后面,但是当我将转换 + 转换应用于我的 css 代码时,它似乎根本不起作用。

这是我的表格的一部分:

switch (data.inputType) 
        case 'input':
          return (
            <Form.Item key=`frmItem-$data.id`>
              <label htmlFor=data.id className="floating-label">
                data.label
              </label>

              <Input
                key=`input-$data.id`
                id=data.id
                className="floating-label-field"
                project-field=data.id
                defaultValue=projectData[data.id]
                onChange=handleUpload
                // placeholder=data.placeholder
                allowClear
              />
            </Form.Item>
          )

这是我的 style.js:

export const StyledFormDiv = styled.div`
  .ant-form-item 
    position: relative;
  

  .ant-form-item-control 
    height: 50px;
  

  /* Floating label */
  .floating-label 
    /* top: 0; */
    /* left: 0; */
    position: absolute;
    /* z-index: 500; */
    /* transform: translate(0, 25px) scale(1); */
    /* transition: color 200ms cubic-bezier(0, 0, 0.2, 1) 0ms, */
    /* transform 200ms cubic-bezier(0, 0, 0.2, 1) 0ms; */
    /* transition: width 0.4s ease; */
  

  .floating-label-field 
    /* position: absolute; */
    /* touch-action: manipulation; */
    border-bottom: 1px solid #000 !important;
    border-radius: 0;
    box-shadow: none;
    width: 100%;
    /* transition: transform 0.25s, opacity 0.25s ease-in-out; */
    /* transform-origin: 0 0; */
    /* opacity: 0.5; */
    /* transition: padding-top 0.2s ease, margin-top 0.2s ease; */

    &::placeholder 
      color: transparent;
    
  

我认为 antd 可能有一些东西不允许我浮动标签,但我想要一种解决方法,不必安装另一个包或制作另一个组件。

【问题讨论】:

请制作一个沙盒,尝试描述“浮动标签”的含义。对您来说,它可能被称为“浮动”,请向我们展示您除了标签之外的期望行为。 另外,请注意,当 Form.Item 的行为类似于标签时,为 label 设置样式是没有意义的。 【参考方案1】:

你可以为浮动标签写一个简单的组件,它可以包装antd输入。

看看这个 FloatLabel 组件,

import React,  useState  from "react";

import "./index.css";

const FloatLabel = props => 
  const [focus, setFocus] = useState(false);
  const  children, label, value  = props;

  const labelClass = focus || value ? "label label-float" : "label";

  return (
    <div
      className="float-label"
      onBlur=() => setFocus(false)
      onFocus=() => setFocus(true)
    >
      children
      <label className=labelClass>label</label>
    </div>
  );
;

export default FloatLabel;

现在你可以像这样用 FloatLabel 组件包装你的 antd 输入,

<FloatLabel label="First Name" name="firstName" value=firstName>
  <Input value=firstName onChange=e => setFirstName(e.target.value) />
</FloatLabel>

您可以查看此code sandbox 示例。

【讨论】:

【参考方案2】:

我知道为时已晚,但它可能对某人有所帮助。

如果我从您的问题中理解正确,Ant 设计的浮动标签没有内置解决方案,所以我对表单字段和 CSS 进行了一些调整,我的代码如下。祝你好运!!!

<FormItem label="" className="group-floating-label">
    getFieldDecorator('name', 
        initialValue:'Jaison',
        rules: [ required: true, message: 'Field required', whitespace:true ]
    )(
        <Input
            className="input-control"
            placeholder="."
            suffix=<label className="floating-label" htmlFor="name">Full Name</label>
        />
    )
</FormItem>



/* * * * * * * * * * * * * * * * * *
Floating Label - .less
* * * * * * * * * * * * * * * * * */

//Custom version of floating label using the ant suffix method
.group-floating-label 
    position: relative;
    margin-bottom: 30px !important;

    .input-control 
        .ant-input 
            display: block;
            width: 100%;
            line-height: 1.25;
            color: #000;
            background-color: #fff;
            background-image: none;
            background-clip: padding-box;
            border: 1px solid rgba(0, 0, 0, .15);
            border-radius: .25rem;
            transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
            border: 0;
            box-shadow: none;
            border-bottom: 1px solid #e8e8e8;
            border-radius: 0;
            .font-size(1.6);
            padding: 0;

            &.ant-input-disabled 
                background-color: rgba(245, 245, 245, 0.36);
                color: rgba(0, 0, 0, 0.36);
            

            &:focus, &:hover 
                box-shadow: none;
                border-color: #4285f4;
            

            &::-webkit-input-placeholder 
                color: #fff;

            

            &::-moz-placeholder 
                color: #fff;
            

            &:-ms-input-placeholder 
                color: #fff;
            

            &:focus + .ant-input-suffix, &:not(:placeholder-shown) + .ant-input-suffix 
                .floating-label 
                    font-size: 85%;
                    transform: translate3d(0, -25px, 0);
                    color: rgba(0, 0, 0, .7);
                    padding-left: 0;
                
            
        

        @supports (-ms-ime-align:auto) 
            .ant-input-suffix 
                .floating-label 
                    font-size: 85%;
                    transform: translate3d(0, -25px, 0);
                    color: rgba(0, 0, 0, .7);
                    padding-left: 0;
                
            
        

        &.show-placeholder 
            .ant-input 
                &:focus 
                    &::-webkit-input-placeholder 
                        color: #ccc;
                        .font-size(1.3);
                    

                    &::-moz-placeholder 
                        color: #ccc;
                        .font-size(1.3);
                    

                    &:-ms-input-placeholder 
                        color: #ccc;
                        .font-size(1.3);
                    
                
            
        
    

    &.input-prefix 
        .prefix 
            display: inline-block;
            border: 1px solid #e8e8e8;
            border-radius: 20px;
            padding: 5px 10px;
            line-height: 10px;
            margin-right: 20px;
            position: absolute;
            left: 0;
            top: 4px;
            .font-size(1.6);
            text-align: center;
            z-index: 9;
            color: #000;
        

        .input-control 
            .ant-input 
                padding-left: 70px;
            
        

        .ant-input-suffix 
            .floating-label 
                padding-left: 70px;
            
        

        .ant-input-prefix 
            left: 0;
            top: 0;
        
    

    .ant-input-suffix 
        left: 0;
        right: 0;
        top: 0;

        .floating-label 
            position: absolute !important;
            top: 0;
            padding: 0px;
            transition: all 200ms;
            color: rgba(0, 0, 0, 0.5);
            line-height: 30px;
            transform: translate3d(0, 0, 0);
        
    

    .has-error 
        .ant-input 
            box-shadow: none !important;
        

        .input-control 
            .ant-input 
                border-bottom: 2px solid red;
            
        
    

    .ant-form-explain 
        margin-bottom: 0px;

        position: absolute;
        left: 0;
        right: 0;
        top: 35px;
    

    .suffix-right 
        position: absolute;
        right: 0;
        top: 3px;
        cursor: pointer;
    

    &.default-floated 
        .floating-label 
            transform: translate3d(0, -25px, 0) !important;
            padding-left: 0 !important;
        
    

【讨论】:

【参考方案3】:

我的例子可能会帮助某人https://codesandbox.io/s/antd-float-label-forked-k8p00?file=/Example.js

随时更新 css。

表单组件

import React from "react";
import  Form  from "antd";

import FloatInput from "./FloatInput";

import "antd/dist/antd.css";
import "./main.css";

const validator = 
  require: 
    required: true,
    message: "Required"
  
;

const Example = (props) => 
  return (
    <div className="example">
      <h3>Antd float labels Example</h3>

      <Form
        size="large"
        name="user_login"
        className="login-form"
        layout="vertical"
      >
        <Form.Item name="email" rules=[validator.require] hasFeedback>
          <FloatInput
            label="Email"
            placeholder="Email here please"
            name="email"
          />
        </Form.Item>
      </Form>
    </div>
  );
;

export default Example;

浮动输入组件

import React,  useState  from "react";
import  Input  from "antd";

import "./index.css";

const FloatInput = (props) => 
  const [focus, setFocus] = useState(false);
  let  label, value, placeholder, type, required  = props;

  if (!placeholder) placeholder = label;

  const isOccupied = focus || (value && value.length !== 0);

  const labelClass = isOccupied ? "label as-label" : "label as-placeholder";

  const requiredMark = required ? <span className="text-danger">*</span> : null;

  return (
    <div
      className="float-label"
      onBlur=() => setFocus(false)
      onFocus=() => setFocus(true)
    >
      <Input onChange=props.onChange type=type defaultValue=value />
      <label className=labelClass>
        isOccupied ? label : placeholder requiredMark
      </label>
    </div>
  );
;

export default FloatInput;

CSS

.float-label 
  position: relative;


.label 
  font-weight: normal;
  position: absolute;
  pointer-events: none;
  left: 12px;
  top: 11px;
  transition: 0.2s ease all;


.as-placeholder 
  color: gray;


.as-label 
  top: -8px;
  font-size: 12px !important;
  background: white;
  padding: 0 4px;
  margin-left: -4px;

【讨论】:

以上是关于使用 React 和 Ant Design 的浮动标签的主要内容,如果未能解决你的问题,请参考以下文章

React开发(169):ant design Popconfirm 使用

React开发(169):ant design Popconfirm 使用

Ant Design of React的安装和使用方法

无法让 @ant-design/pro-layout 的样式与“create-react-app”一起使用

React开发(265):ant design InputNumber

面面观 | 学习使用 Ant Design 框架