Skip to content

Commit

Permalink
Merge pull request #212 from kgpmask/form-uniformity
Browse files Browse the repository at this point in the history
Form Uniformity
  • Loading branch information
ItsAnkan authored Jul 14, 2023
2 parents ee36206 + fb4f0d9 commit f23a55e
Show file tree
Hide file tree
Showing 8 changed files with 679 additions and 623 deletions.
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,42 @@ The default newsletter template is:

Take a look at existing articles for the various classes and where they're used.

### Forms

Among templates, there are a separate group of templates which use the `_form.njk` template as a base. These templates have a slightly different pattern and some more features.

```jinja
{% extends '_base.njk' %}
{% import '_form.njk' as forms %}
{% set scripts = ['https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js'] %}
{% block pagecontent %}
{% call forms.form() %}
{# Form Content #}
{% endcall %}
{% endblock %}
{% block customcss %}
{{ forms.formCss() }}
<style>
{# Extra Styles #}
</style>
{% endblock %}
{% block customjs %}
{{ forms.formFunction() }}
<script>
axios.defaults.withCredentials = true;
axios.defaults.headers.common['X-CSRF-TOKEN'] = '{{ csrfToken }}';
{# Other Functions #}
</script>
{% endblock %}
```

For in-depth info about the same, check out the [forms](https://github.com/kgpmask/MASK/docs/Forms.md) markdown file.

---

## Routers
Expand Down
167 changes: 167 additions & 0 deletions assets/styles/form.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
.message {
position: absolute;
top: 0;
right: calc(50vw - 220px);
padding: 20px;
z-index: 100;
color: #fff;
font-weight: 600;
font-size: 18px;
width: 400px;
transform-origin: top;
transition: transform 0.3s ease;
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
}
.error {
background-color: rgba(255, 51, 51, 0.85);
}
.success {
background-color: rgba(75, 189, 67, 0.85);
}
.hidden {
transform: scaleY(0);
}
.form-container{
padding: 23px 25px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
transform: 0.3s;
}
form {
display: flex;
flex-direction: column;
border: 1px solid var(--off-white);
border-radius: 12px;
padding: 12px 10px;
width: 40%;
background-color: rgba(255,255,255,0.13);
backdrop-filter: blur(5px);
}
form * {
outline: none;
border: none;
}
button {
align-self: center;
margin: 20px;
width: 44%;
background-color: var(--red);
color: white;
padding: 12px 0;
font-size: 18px;
font-weight: 600;
border-radius: 12px;
cursor: pointer;
}
.item {
display: flex;
flex-direction: column;
text-align: left;
position: relative;
margin: 10px 4vw;
}
.heading {
margin-block-start: 0.83em;
margin-block-end: 0.83em;
}
label {
color: var(--off-white);
margin-inline-start: 0.3em;
margin-block-end: 0.4em;
font-weight: 600;
font-size: 16px;
pointer-events: none;
}
.datetime > label{
top: -7px;
font-size: 16px;
padding: 0 2px;
background-color: rgba(0, 0, 0, 0);
}
input,
select{
background-color: rgba(255,255,255,0.07);
font-weight: 300;
border-radius: 5px;
padding: 10px;
border: 2px solid var(--light-gray);
color: #fff;
outline: none;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
select {
font-weight: 600;
}
.datetime > input {
color-scheme: dark;
}
.option {
position: relative;
display: flex;
align-items: center;
border-radius: 10px;
cursor: pointer;
transition: 0.3s;
padding: 5px 10px;
margin: 7px;
}
.option:focus-within,
.option:hover {
background: hsla(0, 0%, 80%, .14);
}
.option-input {
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
z-index: 1;
}
.option-design {
width: 22px;
height: 22px;
border-radius: 100px;
background: linear-gradient(to right bottom, hsl(0deg 100% 75%), hsl(0deg 100% 50%));
position: relative;
}
.checkbox > .option > .option-design {
border-radius: 2px;
}
.option-design::before {
content: '';
display: inline-block;
width: inherit;
height: inherit;
border-radius: inherit;
background: hsl(0, 0%, 90%);
transform: scale(1.1);
transition: 0.3s;
}
.option-input:checked + .option-design::before {
transform: scale(0);
}
.option-text {
color: hsl(0, 0%, 60%);
margin-left: 14px;
font-weight: 900;
transition: 0.3s;
}
.option-input:checked ~ .option-text {
color: hsl(184deg 58% 60%);
}
.singlecheck {
align-self: center;
flex-direction: row-reverse;
}
.singlecheck > .option-text {
margin-right: 14px;
margin-left: unset;
}
select > option {
background-color: var(--darker-gray);
padding: 10px;;
}
177 changes: 177 additions & 0 deletions docs/Forms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# Information Regarding Creating Pages Which Has Forms

We are using many pages with forms, to make them uniform



## How to use `_form.njk`

Forms follow the default page template, with a little modification

```jinja
{% extends '_base.njk' %}
{% import '_form.njk' as forms %}
{% set scripts = ['https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js'] %}
{% block pagecontent %}
{% call forms.form() %}
{# Form Content #}
{% endcall %}
{% endblock %}
{% block customcss %}
{{ forms.formCss() }}
<style>
{# Extra Styles #}
</style>
{% endblock %}
{% block customjs %}
{{ forms.formFunction() }}
<script>
axios.defaults.withCredentials = true;
axios.defaults.headers.common['X-CSRF-TOKEN'] = '{{ csrfToken }}';
{# Other Functions #}
</script>
{% endblock %}
```

Additionally the following variables may be set:

- `pagetitle`: Title of the page (default MASK)
- `pagedesc`: Description of the page (default 'MASK website')
- `thispage`: URL of intended position of current page, used to select active page in NAVBAR (default none)

## Function/Macro Documentation

The following functions/macros are exported from `_form.njk`

- `form(*formheading)` - The main form body, this needs to be executed in a call block. `formheading` is optional.
- `heading(h, label)` - Used to put a heading/divider between items. The arguments are:
- `h` - Heading level (eg, h1, h2, h3).
- `label` - Heading text.
- `field(id, label, *value)` - Text input field. The arguments are:
- `id` - ID of the input tag.
- `label` - Text to display above input tag.
- `value` - Optional, used to give a predefined value to input field.
- `datetime(id, label, value)` - Datetime input field. The arguments are:
- `id` - ID of the input tag.
- `label` - Text to display above input tag.
- `value` - Used to give a predefined value to input field.
- `radio(id, label, options)` or `checkbox(id, label, options)` - Radio/Checkbox buttons. The arguments are:
- `id` - ID of the option container.
- `label` - Text to display above the buttons.
- `options` - Array of options. Its data type is `[ {'id': 'ID of each option', 'label': 'Option text', 'value': 'Option value'}, ... ]`
- `select(id, label, options, *onchange)` - Select tag. The arguments are:
- `id` - ID of the select container.
- `label` - Text to display for the select tag.
- `options` - Array of options. Its data type is `[ {'label': 'Option text', 'value': 'Option value'}, ... ]`
- `onchange` - Optional. Function to call when select option is changed. **The select element will be passed to the function, so it must accept it.**
- `singlecheck(id, label, *checked)` - A single check button, may be used for a True/False value. The arguments are:
- `id` - ID of the check input.
- `label` - Text for the button.
- `checked` - Optional. Determines if option should be checked by default.
- `button(id, label, *onclick)` - Includes buttons in the form. The arguments are:
- `id` - ID of the button.
- `label` - Text displayed on the button
- `onclick` - Optional. The function to be called when the button is pressed. **If not defined, then button will submit the form.**
- `formCss()` - Use this to include the default form styling (present in `assets/styles/form.css`).
- `formFunction()` - Use this to include usefull form functions. The included functions are:
- `getData()` - Extracts data from all the elements made from the above macros, and returns an object with keys as ID's and values as the corresponding values of the ID's.
- `message(response, *location)` - Displays success/error message, and redirects the page to location. Its arguments are:
- `response` - Its the response from the axios post request. It must contain a `message` (the message which is displayed in the pop-up) and a `success` (if its an error or success) attributes.
- `location` - Optional. Location to redirect to. If not defined, then it reloads the page.

## Example Form

Here's an example form with all the elements.

```jinja
{% extends '_base.njk' %}
{% import '_form.njk' as forms %}
{% set scripts = ['https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js'] %}
{% set thispage = 'Example Form' %}
{% set pagetitle = 'Example Form' %}
{% block pagecontent %}
{% call forms.form('Example Form') %}
{{ forms.field('name', 'Name') }}
{{ forms.heading('h2', 'Some questions ') }}
{{ forms.checkbox('team', 'Select Teams', [
{
'id':'web',
'label': 'Web Dev',
'value': 'web'
},
{
'id':'quiz',
'label': 'Quiz',
'value': 'quiz'
},
{
'id':'mn',
'label': 'Media And Newsletter',
'value': 'mn'
}]) }}
{{ forms.select('favperson', 'Favourite Person in WebDev', [
{
'label': 'Goos',
'value': 'goos'
},
{
'label': 'Nishkal',
'value': 'np'
},
{
'label': 'Parth',
'value': 'parth'
}], 'change') }}
{{ forms.radio('like', 'DO you like MASK ?', [
{
'id':'yes',
'label': 'YES',
'value': 'yes'
},
{
'id':'no',
'label': 'NO',
'value': 'no'
}]) }}
<div style="display: flex; flex-direction: row; justify-content: space-around; flex-wrap: wrap;">
{{ forms.singlecheck('onichan', 'Onii-Chan', 1) }}
{{ forms.singlecheck('uwu', 'UWU') }}
{{ forms.singlecheck('nyaa', 'nyaaa~~~', 1) }}
</div>
{{ forms.datetime('date', 'Random Date', '2023-07-11') }}
{{ forms.button('submit', 'Submit-nyaa~~', 'print') }}
{% endcall %}
{% endblock %}
{% block customcss %}
{{ forms.formCss() }}
<style>
form {
width: 80%;
}
</style>
{% endblock %}
{% block customjs %}
{{ forms.formFunction() }}
<script>
function change(select) {
console.log('changed');
}
function print() {
console.log(getData());
// const response = (await axios.post)
const response = { message: 'Succesfully Done', success: true }
message(response);
}
</script>
{% endblock %}
```
Loading

0 comments on commit f23a55e

Please sign in to comment.