ReactStrap input group bug (not 100% width) - css

Does anyone have this bug where an input group addon or dropdown is taking up half of the entire width instead of a 100%. (basically the InputGroupButton is taking up the other 50% so 100% width spread automatically between two elements but in the Reactstrp docs there's every indication that this is goes against expected behavior)
I want my input group to be 100% width like the rest.
https://reactstrap.github.io/components/input-group/
this is what I currently have :
and if I open Inspect Element :
you can see that the InputGroupButton isn't setting a padding or a margin like "auto" or something similar which you'd expect to be responsible for this.
here's the small snipet of react render concerning the password field :
render() {
return (
<Label className="password">
<InputGroup>
<Input
className="password__input"
placeholder="Mot de Passe"
type={this.state.type}
onChange={this.passwordStrength}
/>
<InputGroupButton><Button onClick={this.showHide}>
{this.state.type === 'password' ?
<i className="fa fa-eye" aria-hidden="true" />
:
<i className="fa fa-eye-slash" aria-hidden="true" />
}</Button></InputGroupButton>
</InputGroup>
<span
className="password__strength"
data-score={this.state.score}
/>
</Label>
);
}
and here's the render that calls it (it's called at "ShowPassword") :
render() {
return (
<div>
<Button color="info" onClick={this.toggle}>{this.props.buttonLabel}</Button>
<Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
<ModalHeader toggle={this.toggle}>Créer un compte</ModalHeader>
<ModalBody>
Veuillez renseigner les champs ci-dessous afin de créer votre compte
<InputGroup>
<Input placeholder="Nom d'utilisateur" />
</InputGroup>
<InputGroup>
<Input placeholder="E-mail" />
</InputGroup>
<InputGroup>
<ShowPassword />
</InputGroup>
<InputGroup>
<Input placeholder="Confirmer"/>
</InputGroup>
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.toggle}>Envoyer</Button>{' '}
<Button color="secondary" onClick={this.toggle}>Annuler</Button>
</ModalFooter>
</Modal>
</div>
);
}

This is not a bug. You are using reactstrap an unintended manner. reactstrap is based on Bootstrap CSS Library. Bootstrap expects you to structure your elements and CSS classes in a certain way it describes in the documentation. If we don't follow them, we can't get the expected result.
As an example, Bootstrap only expects certain elements like Input, InputGroupButton and InputGroupAddon inside the InputGroup. But in your case, if we replace ShowPassword with its actual JSX structure, you will have a Label inside InputGroup and another InputGroup inside the Label. What is why it is not rendered as expected.
First, to wrap your ShowPassword, you should use a div instead of a Label.
render() {
return (
<div className="password">
<InputGroup>
<Input
className="password__input"
placeholder="Mot de Passe"
type={this.state.type}
onChange={this.passwordStrength}
/>
<InputGroupButton>
<Button onClick={this.showHide}>
{this.state.type === "password"
? <i className="fa fa-eye" aria-hidden="true" />
: <i className="fa fa-eye-slash" aria-hidden="true" />}
</Button>
</InputGroupButton>
</InputGroup>
<span className="password__strength" data-score={this.state.score} />
</div>
);
}
and then you should remove additional InputGroup which wrap your ShowPassword component.
render() {
return (
<div>
<Button color="info" onClick={this.toggle}>
{this.props.buttonLabel}
</Button>
<Modal
isOpen={this.state.modal}
toggle={this.toggle}
className={this.props.className}
>
<ModalHeader toggle={this.toggle}>Créer un compte</ModalHeader>
<ModalBody>
Veuillez renseigner les champs ci-dessous afin de créer votre compte
<InputGroup>
<Input placeholder="Nom d'utilisateur" />
</InputGroup>
<InputGroup>
<Input placeholder="E-mail" />
</InputGroup>
<ShowPassword />
<InputGroup>
<Input placeholder="Confirmer" />
</InputGroup>
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.toggle}>
Envoyer
</Button>{" "}
<Button color="secondary" onClick={this.toggle}>
Annuler
</Button>
</ModalFooter>
</Modal>
</div>
);
}
Hopefully, now you will get the expected the result.

Related

Issues manipulating css with react

hope any of you could help me out in here...
On the code below I have 2 separete elements which I want to show one at the time.
first element is an iframe
second is a Div
the ideia is if the user click on the {title} then the frame disaper and the div appear.
I can manage to make the frame disapper and appear by clicking on the title, but the same does not happen with the div.
the code is basically the same, so I don't really get why is the div not having the same behavior then the frame.
Also I double checked and both css classes get changed as expected, just that the css class seems not to work on the Div.
Tks in advance.
import React, { useState } from 'react';
const Card = (props) => {
const { id, title, active, site, img } = props.data;
const [content, setContent] = useState(false);
return (
<div className={`card ${active && 'active'}`} >
<img id='img_cover' src={img} alt='image01' onClick={() => props.onCardClick(id)}></img>
<div className='txt'>
<h2 onClick={() => setContent(!content)}>{title}</h2>
</div>
<iframe className={`${content ? 'content_site' : 'content_frame'}`} src={site} frameborder="0" title={title}>
</iframe>
<div className={`${content ? 'content_frame' : 'content_site'}`}>
<form id="contact-form" action="#" className="table">
<input className='input_espace row' id='nome' placeholder="Name" name="name" type="text" required />
<input className='input_espace row' id='email' placeholder="Email" name="email" type="email" required />
<textarea id="text_area" className='row' cols="50" placeholder="Message" type="text" name="message" />
<button type="button" class="btn btn-outline-warning button_submit"> Enviar</button>
</form>
</div>
</div >
)
}
export default Card;
className={`${content ? 'content_site' : 'content_frame'}`}
and
className={`${content ? 'content_frame' : 'content_site'}`}
are contrandicting each other because both are expecting content to be true change one to be !content
change the second one as you can see in your method setContent(!content)}
like this:
import React, { useState } from 'react';
const Card = (props) => {
const { id, title, active, site, img } = props.data;
const [content, setContent] = useState(false);
return (
<div className={`card ${active && 'active'}`} >
<img id='img_cover' src={img} alt='image01' onClick={() => props.onCardClick(id)}></img>
<div className='txt'>
<h2 onClick={() => setContent(!content)}>{title}</h2>
</div>
<iframe className={`${content ? 'content_site' : 'content_frame'}`} src={site} frameborder="0" title={title}>
</iframe>
<div className={`${!content ? 'content_frame' : 'content_site'}`}>
<form id="contact-form" action="#" className="table">
<input className='input_espace row' id='nome' placeholder="Name" name="name" type="text" required />
<input className='input_espace row' id='email' placeholder="Email" name="email" type="email" required />
<textarea id="text_area" className='row' cols="50" placeholder="Message" type="text" name="message" />
<button type="button" class="btn btn-outline-warning button_submit"> Enviar</button>
</form>
</div>
</div >
)
}
export default Card;

Upload an image and change the background

I'm trying to make the background change whenever the user is uploading an image, the background is set on default however, I found that I have to use <input /> but then I got stuck
this my work so far !
const [backgroundShown, setBackgroundShown] = useState(false);
const changeBackground = () => {
setBackgroundShown(!backgroundShown);
};
{file && (
<img
className="writeImg"
src={URL.createObjectURL(file)}
/>
)
}
<form className="writeForm" onSubmit={handlerSubmit}>
<div className="writeFormGroup">
<label htmlFor="fileInput">
<img
type={backgroundShown ? "img" : "file"}
className="writeIcon"
src="/Images/Upload-Vector.png"
></img>
</label>
<div>
<input
onClick={changeBackground}
type={backgroundShown ? "file" : "img"}
accept="image/*"
id="fileInput"
style={{ display: "none" }}
onChange={e => setFile(e.target.files[0])}>
</input>
</div>
It sounds like you want to remove the button when the user "uploads".
If so, just conditionally render it when the user hasn't uploaded.
{file && (
<img
className="writeImg"
src={URL.createObjectURL(file)}
/>
)
}
{!file &&
<form className="writeForm" onSubmit={handlerSubmit}>
<div className="writeFormGroup">
<label htmlFor="fileInput">
<img
type={backgroundShown ? "img" : "file"}
className="writeIcon"
src="/Images/Upload-Vector.png"
></img>
</label>
<div>
<input
onClick={changeBackground}
type={backgroundShown ? "file" : "img"}
accept="image/*"
id="fileInput"
style={{ display: "none" }}
onChange={e => setFile(e.target.files[0])}>
</input>
</div>
}

Can't set height of textarea in reactstrap card

I'm using reactstrap in my project I have a simple card and I want to place a text area inside it using the following code:
<Card>
<CardBody>
<Form>
<FormGroup>
<Input
type="textarea"
defaultValue="Hello world"
/>
</FormGroup>
</Form>
</CardBody>
</Card>
If I then try to set the height it just doesn't work. I have tried using style:
<Card>
<CardBody>
<Form>
<FormGroup>
<Input
type="textarea"
defaultValue={tweet.full_text}
style={{ height: 220 }}
/>
</FormGroup>
</Form>
</CardBody>
</Card>
And also tried using a custom css class:
.text-area-custom {
height: 220px;
}
<Card>
<CardBody>
<Form>
<FormGroup>
<Input
className="text-area-custom"
type="textarea"
defaultValue={tweet.full_text}
/>
</FormGroup>
</Form>
</CardBody>
</Card>
Neither of these methods work. Any idea what I am doing wrong here?
Try and set the rows attribute
<Card>
<CardBody>
<Form>
<FormGroup>
<Input
type="textarea"
defaultValue={tweet.full_text}
rows="5"
/>
</FormGroup>
</Form>
</CardBody>
</Card>

VUE - QUASAR - TIPTAP - How to Set CSS Height on Editor's Inner Element

How can I get the inner editor portion (which is highlighted with a thin blue line) to go full height. This is the internal element that gets created by the tiptap editor:
<div contenteditable="true" tabindex="0" class="ProseMirror" spellcheck="false"> Editable content goes here./div>
UPDATE:
I manually added the classes ('col' and 'column') in the rendered output and now it works the way I want it to. Is there a way to do this without having to reach into the class property of the element?
<div contenteditable="true" tabindex="0" class="ProseMirror col column" spellcheck="false"> Content Here </div>
Here is the component code I am using in my quasar example app. I have tried umpteen different variations of classes in the divs around the editor. Nothing I do seems to affect the resulting "contenteditable" div container above.
<template>
<q-page class="column justify-start">
<div class="column col absolute-full bg-secondary">
<div class="col column editor">
<editor-menu-bar :editor="editor" v-slot="{ commands, isActive }">
<div class="menubar">
<button
class="menubar__button"
:class="{ 'is-active': isActive.bold() }"
#click="commands.bold"
>
<icon name="bold" />
</button>
<button
class="menubar__button"
:class="{ 'is-active': isActive.italic() }"
#click="commands.italic"
>
<icon name="italic" />
</button>
<button
class="menubar__button"
:class="{ 'is-active': isActive.strike() }"
#click="commands.strike"
>
<icon name="strike" />
</button>
<button
class="menubar__button"
:class="{ 'is-active': isActive.underline() }"
#click="commands.underline"
>
<icon name="underline" />
</button>
<button
class="menubar__button"
:class="{ 'is-active': isActive.code() }"
#click="commands.code"
>
<icon name="code" />
</button>
<button
class="menubar__button"
:class="{ 'is-active': isActive.paragraph() }"
#click="commands.paragraph"
>
<icon name="paragraph" />
</button>
<button
class="menubar__button"
:class="{ 'is-active': isActive.heading({ level: 1 }) }"
#click="commands.heading({ level: 1 })"
>
H1
</button>
<button
class="menubar__button"
:class="{ 'is-active': isActive.heading({ level: 2 }) }"
#click="commands.heading({ level: 2 })"
>
H2
</button>
<button
class="menubar__button"
:class="{ 'is-active': isActive.heading({ level: 3 }) }"
#click="commands.heading({ level: 3 })"
>
H3
</button>
<button
class="menubar__button"
:class="{ 'is-active': isActive.bullet_list() }"
#click="commands.bullet_list"
>
<icon name="ul" />
</button>
<button
class="menubar__button"
:class="{ 'is-active': isActive.ordered_list() }"
#click="commands.ordered_list"
>
<icon name="ol" />
</button>
<button
class="menubar__button"
:class="{ 'is-active': isActive.blockquote() }"
#click="commands.blockquote"
>
<icon name="quote" />
</button>
<button
class="menubar__button"
:class="{ 'is-active': isActive.code_block() }"
#click="commands.code_block"
>
<icon name="code" />
</button>
<button
class="menubar__button"
#click="commands.horizontal_rule"
>
<icon name="hr" />
</button>
<button
class="menubar__button"
#click="commands.undo"
>
<icon name="undo" />
</button>
<button
class="menubar__button"
#click="commands.redo"
>
<icon name="redo" />
</button>
</div>
</editor-menu-bar>
<editor-content class="col column editor__content" :editor="editor" />
</div>
</div>
</q-page>
</template>
<script>
import Icon from 'components/Icon'
import { Editor, EditorContent, EditorMenuBar } from 'tiptap'
import {
Blockquote,
CodeBlock,
HardBreak,
Heading,
HorizontalRule,
OrderedList,
BulletList,
ListItem,
TodoItem,
TodoList,
Bold,
Code,
Italic,
Link,
Strike,
Underline,
History
} from 'tiptap-extensions'
export default {
components: {
EditorContent,
EditorMenuBar,
Icon
},
data () {
return {
editor: new Editor({
extensions: [
new Blockquote(),
new BulletList(),
new CodeBlock(),
new HardBreak(),
new Heading({ levels: [1, 2, 3] }),
new HorizontalRule(),
new ListItem(),
new OrderedList(),
new TodoItem(),
new TodoList(),
new Link(),
new Bold(),
new Code(),
new Italic(),
new Strike(),
new Underline(),
new History()
],
content: `
<h2>
Hi there,
</h2>
<p>
this is a very <em>basic</em> example of tiptap.
</p>
<pre><code>body { display: none; }</code></pre>
<ul>
<li>
A regular list
</li>
<li>
With regular items
</li>
</ul>
<blockquote>
It's amazing 👏
<br />
– mom
</blockquote>
`
})
}
},
beforeDestroy () {
this.editor.destroy()
}
}
</script>
<style>
</style>
I have been learning about Vue.js & Quasar UI toolset. I want to use the TIPTAP WYSIWYG editor component (available here: https://github.com/scrumpy/tiptap). I am fine with their examples, I can get the component to load and work fine. But for the life of me, I cannot figure out how to get the inner editing part (which gets outlined in blue when you click on it) to go 'Full Height' from the outset.
I have tried everything I can think of and searched and searched for some sort of example. The editor expands (grows) fine when you add content, but for some reason, I can't get it to start at full height-- which I'll note the example doesn't illustrate either.
What am I not doing?
Try writing this on css
/* remove outline */
.ProseMirror:focus {
outline: none;
}
/* set */
.ProseMirror {
min-height: 100px;
max-height: 100px;
overflow: scroll;
}

React : Vertically centre Bootstrap Container component on screen

I have a login form using the Container component from Bootstrap. How do I vertically align the entire container in the center of the screen?
function Auth() {
return (
<Container >
<Row className="justify-content-center">
<Col sm={6}>
<Card >
<Card.Body>
<Form>
<Form.Group controlId="formBasicEmail">
<Form.Label>Username</Form.Label>
<Form.Control type="text" placeholder="Username" />
</Form.Group>
<Form.Group controlId="formBasicPassword">
<Form.Label>Password</Form.Label>
<Form.Control type="password" placeholder="Password" />
</Form.Group>
<Form.Group controlId="formBasicCheckbox">
<Form.Check type="checkbox" label="Check me out" />
</Form.Group>
<Button variant="primary" type="submit">
Login
</Button>
</Form>
</Card.Body>
</Card>
</Col>
</Row>
</Container>
);
}

Resources