Improve mobile responsiveness and styling

This commit is contained in:
Greg Shuflin 2025-03-07 01:45:33 -08:00
parent 650b7c28d6
commit 8c82698593
4 changed files with 279 additions and 29 deletions

View File

@ -1,7 +1,18 @@
// Color variables
$background-color: #f0f0b8;
$primary-color: #b2a336;
$primary-color-dark: #a69530;
$text-color: #333;
$accent-color: #a63333;
$accent-color-dark: #6a3131;
$white: #fff;
body {
background-color: #f0f0b8;
background-color: $background-color;
font-size: 18pt;
font-family: "Biwa";
margin: 0;
padding: 0;
}
input {
@ -10,11 +21,13 @@ input {
main {
text-align: center;
padding: 1rem;
}
div .container {
max-width: 62rem;
margin: auto;
padding: 0 1rem;
}
div .results {
@ -22,30 +35,74 @@ div .results {
}
div .textInput {
max-width: 70%;
max-width: 100%;
margin: auto;
font-size: 22px;
}
input {
width: 100%;
padding: 8px;
box-sizing: border-box;
border: 1px solid $primary-color;
border-radius: 4px;
}
.searchDropdown {
font-size: 22px;
font-family: "Biwa";
padding: 10px 15px;
border: 2px solid $primary-color;
border-radius: 8px;
background-color: $white;
color: $text-color;
cursor: pointer;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
$encoded-primary-color: str-slice("#{$primary-color}", 2);
background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23#{$encoded-primary-color}%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E");
background-repeat: no-repeat;
background-position: right 15px top 50%;
background-size: 12px auto;
padding-right: 35px;
transition: border-color 0.3s, box-shadow 0.3s;
width: 100%;
max-width: 300px;
margin: 10px 0;
}
.searchDropdown:hover, .searchDropdown:focus {
border-color: $primary-color-dark;
box-shadow: 0 0 0 3px rgba($primary-color, 0.25);
outline: none;
}
.searchButton {
padding: 5px;
margin: 10px;
padding: 10px 15px;
margin: 10px 5px;
font-size: 22px;
font-family: "Biwa";
background-color: $primary-color;
color: $white;
border: none;
border-radius: 8px;
cursor: pointer;
transition: background-color 0.3s, transform 0.1s;
min-width: 120px;
}
.searchButton:hover {
background-color: $primary-color-dark;
}
.searchButton:active {
transform: translateY(1px);
}
.searchResult {
border-bottom: 1px solid #b2a336;
padding: 5px;
border-bottom: 1px solid $primary-color;
padding: 10px 5px;
}
.searchResultHeader {
@ -53,18 +110,172 @@ input {
}
.additionalNotes {
color: #a63333;
color: $accent-color;
}
.semField {
font-variant: small-caps;
color: #6a3131;
color: $accent-color-dark;
}
.saimiarNounMorpho {
color: #a63333;
color: $accent-color;
i {
color: #6a3131;
color: $accent-color-dark;
}
}
.passwordDialog {
padding: 20px;
border-radius: 4px;
border: 1px solid $primary-color;
background-color: $background-color;
width: 90%;
max-width: 400px;
}
.passwordDialog h3 {
margin-top: 0;
}
.passwordDialog input {
margin-bottom: 10px;
width: 100%;
}
.dialogButtons {
display: flex;
justify-content: space-between;
}
.passwordDialog button {
margin: 5px;
padding: 8px 15px;
background-color: $primary-color;
color: $white;
border: none;
border-radius: 4px;
cursor: pointer;
min-width: 80px;
}
.passwordDialog button:hover {
background-color: $primary-color-dark;
}
.searchControls {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
margin-top: 1rem;
}
.buttonGroup {
display: flex;
flex-wrap: wrap;
justify-content: center;
margin-top: 0.5rem;
}
.dropdownContainer {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
margin-bottom: 10px;
}
.dropdownLabel {
font-weight: bold;
margin-bottom: 5px;
color: $accent-color-dark;
font-size: 18px;
}
/* Responsive styles for mobile devices */
@media (max-width: 768px) {
body {
font-size: 16pt;
}
h1 {
font-size: 1.8rem;
}
div .textInput {
max-width: 100%;
font-size: 18px;
}
.searchDropdown {
font-size: 18px;
padding: 12px 15px;
margin: 10px auto;
width: 100%;
max-width: none;
}
.search {
display: flex;
flex-direction: column;
align-items: center;
}
.search button {
width: 100%;
margin: 5px 0;
}
.searchControls {
width: 100%;
}
.buttonGroup {
flex-direction: column;
width: 100%;
}
.dropdownContainer {
margin-bottom: 5px;
}
.dropdownLabel {
font-size: 16px;
}
.searchButton {
font-size: 18px;
padding: 12px 15px;
margin: 5px 0;
width: 100%;
}
}
@media (max-width: 480px) {
body {
font-size: 14pt;
}
h1 {
font-size: 1.5rem;
}
main {
padding: 0.5rem;
}
div .container {
padding: 0 0.5rem;
}
.searchDropdown {
font-size: 16px;
padding: 10px 12px;
}
.searchButton {
font-size: 16px;
padding: 10px 12px;
}
}

View File

@ -25,9 +25,17 @@ const PasswordDialog = (_props) => {
return (
<dialog className="passwordDialog">
<input type="password" placeholder="enter password" value={password} onChange={ (evt) => setPasswordStr(evt.target.value) } />
<button onClick={save}>Save</button>
<button onClick={cancel}>Cancel</button>
<h3>Enter Password</h3>
<input
type="password"
placeholder="enter password"
value={password}
onChange={ (evt) => setPasswordStr(evt.target.value) }
/>
<div className="dialogButtons">
<button onClick={save}>Save</button>
<button onClick={cancel}>Cancel</button>
</div>
</dialog>);
};
@ -157,9 +165,22 @@ const App = (_props) => {
const conlangs = [Conlang.Saimiar, Conlang.Elesu, Conlang.Tukvaysi, Conlang.Juteyuji];
const langSelectDropdown = (
<select className="searchDropdown" value={conlang} onChange={ handleLangChange }>
{conlangs.map((conlang) => <option value={conlang} key={conlang}>{renderConlang(conlang)}</option>)}
</select>
<div className="dropdownContainer">
<label htmlFor="languageSelect" className="dropdownLabel">Select Language:</label>
<select
id="languageSelect"
className="searchDropdown"
value={conlang}
onChange={handleLangChange}
aria-label="Select language"
>
{conlangs.map((conlang) => (
<option value={conlang} key={conlang}>
{renderConlang(conlang)}
</option>
))}
</select>
</div>
);
const showPasswordBox = () => {
@ -177,19 +198,28 @@ const App = (_props) => {
<p><b>Kucinako</b> (<i>Saimiar</i> "word-book") is a dictionary of words in various languages of the world Arzhanø, and their English
equivalents.</p>
<div className="textInput">
<input className="textInput" type="text" value={ searchBoxInput } onChange={ (evt) => {
setSearchBoxInput(evt.target.value);
} } />
<input
className="textInput"
type="text"
value={ searchBoxInput }
onChange={ (evt) => {
setSearchBoxInput(evt.target.value);
}}
placeholder="Enter search term"
/>
</div>
<div className="searchControls">
{ langSelectDropdown }
<div className="buttonGroup">
<button onClick={ () => handleSearch(SearchDirection.ToEnglish) } className="searchButton">{renderConlang(conlang)}</button>
<button onClick={ () => handleSearch(SearchDirection.ToConlang) } className="searchButton">English</button>
<button onClick={ showPasswordBox } className="searchButton">Password</button>
</div>
</div>
<br/>
{ langSelectDropdown }
<button onClick={ () => handleSearch(SearchDirection.ToEnglish) } className="searchButton">{renderConlang(conlang)}</button>
<button onClick={ () => handleSearch(SearchDirection.ToConlang) } className="searchButton">English</button>
<button onClick={ showPasswordBox } className="searchButton">Password</button>
</div>
<Results
searchResults={ searchResults }
searchTerm= { searchTerm }
searchTerm={ searchTerm }
conlang={ conlang }
direction={ direction }
/>

View File

@ -20,6 +20,7 @@ const EntryBase = (props: BaseProps) => {
display: "flex",
justifyContent: "space-between",
flexDirection: "row",
flexWrap: "wrap",
};
const controlStyle = {
@ -27,14 +28,20 @@ const EntryBase = (props: BaseProps) => {
justifyContent: "space-between",
flexDirection: "row",
minWidth: "20%",
marginTop: "10px",
};
const save = () => {
updateEntry(props.conlang, props.id, english);
};
const engTranslation = editing ? <input type="text" value={ english } onChange={ (evt) => setEnglish(evt.target.value) }/>
: english;
const engTranslation = editing ?
<input
type="text"
value={ english }
onChange={ (evt) => setEnglish(evt.target.value) }
style={{ width: "100%", marginTop: "5px" }}
/> : english;
const EditControls = ({onSave}: { onSave: () => void }) => {
const cancel = () => setEditing(false);

View File

@ -1,6 +1,8 @@
{
"compilerOptions": {
"lib": ["ES2020", "dom"]
"lib": ["ES2020", "dom"],
"jsx": "react",
"esModuleInterop": true
},
"include": ["src/**/*"]
}