Skip to content

Commit

Permalink
feat #128: first step towards responsive layout
Browse files Browse the repository at this point in the history
  • Loading branch information
sadiqkhoja committed Jun 12, 2024
1 parent e7bef0c commit 9e93c81
Show file tree
Hide file tree
Showing 12 changed files with 289 additions and 27 deletions.
2 changes: 1 addition & 1 deletion packages/web-forms/e2e/vue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ test('All forms are rendered and there is no console error', async ({ page, brow
const langChanger = page.getByLabel('change language');

if ((await langChanger.count()) > 0) {
await langChanger.click();
await langChanger.first().click();
await page.locator('.language-dd-label').last().click();
}

Expand Down
38 changes: 35 additions & 3 deletions packages/web-forms/icomoon.json
Original file line number Diff line number Diff line change
Expand Up @@ -488,19 +488,51 @@
"setIdx": 0,
"setId": 4,
"iconIdx": 35
},
{
"icon": {
"paths": ["M128 256h768v86h-768v-86zM128 554v-84h768v84h-768zM128 768v-86h768v86h-768z"],
"attrs": [],
"isMulticolor": false,
"isMulticolor2": false,
"tags": ["menu"],
"grid": 24
},
"attrs": [],
"properties": {
"ligatures": "menu",
"id": 600,
"order": 299,
"prevSize": 48,
"code": 59670,
"name": "menu"
},
"setIdx": 0,
"setId": 4,
"iconIdx": 600
}
],
"height": 1024,
"metadata": { "name": "icomoon" },
"metadata": {
"name": "icomoon"
},
"preferences": {
"showGlyphs": true,
"showQuickUse": true,
"showQuickUse2": true,
"showSVGs": true,
"fontPref": {
"prefix": "icon-",
"metadata": { "fontFamily": "icomoon", "majorVersion": 1, "minorVersion": 0 },
"metrics": { "emSize": 1024, "baseline": 6.25, "whitespace": 50 },
"metadata": {
"fontFamily": "icomoon",
"majorVersion": 1,
"minorVersion": 0
},
"metrics": {
"emSize": 1024,
"baseline": 6.25,
"whitespace": 50
},
"embed": false,
"showSelector": true,
"showMetrics": true,
Expand Down
3 changes: 3 additions & 0 deletions packages/web-forms/src/assets/css/icomoon.css
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,6 @@
.icon-repeat:before {
content: '\e914';
}
.icon-menu:before {
content: '\e916';
}
2 changes: 1 addition & 1 deletion packages/web-forms/src/assets/css/style.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
body {
background: var(--gray-200);
margin: 0;
}
1 change: 1 addition & 0 deletions packages/web-forms/src/assets/fonts/icomoon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/web-forms/src/assets/fonts/icomoon.ttf
Binary file not shown.
Binary file modified packages/web-forms/src/assets/fonts/icomoon.woff
Binary file not shown.
107 changes: 102 additions & 5 deletions packages/web-forms/src/components/FormHeader.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,86 @@
<script setup lang="ts">
import Card from 'primevue/card';
defineProps<{title: string}>();
import { type RootNode } from '@getodk/xforms-engine';
import PrimeButton from 'primevue/button';
import PrimeCard from 'primevue/card';
import PrimeMenu from 'primevue/menu';
import { ref } from 'vue';
import FormLanguageDialog from './FormLanguageDialog.vue';
import FormLanguageMenu from './FormLanguageMenu.vue';
const props = defineProps<{form: RootNode}>();
const languageDialogState = ref(false);
const menu = ref<PrimeMenu>();
const languages = props.form.languages.filter(language => !language.isSyntheticDefault);
const print = () => window.print();
const items = ref([
{
label: 'Print',
icon: 'icon-local_printshop',
command: print
}
]);
if(languages.length > 0){
items.value.unshift({
label: 'Change language',
icon: 'icon-language',
command: () => languageDialogState.value = true
})
}
</script>

<template>
<Card class="form-title">
<!-- for desktop -->
<div class="hidden lg:flex justify-content-end flex-wrap gap-3">
<PrimeButton class="print-button" severity="secondary" rounded icon="icon-local_printshop" @click="print" />
<FormLanguageMenu :form="form" />
</div>
<PrimeCard class="form-title hidden lg:block">
<template #content>
<h1>{{ title }}</h1>
<!-- TODO/q: should the title be on the definition or definition.form be accessible instead of definition.bind.form -->
<h1>{{ form.definition.bind.form.title }}</h1>
<!-- last saved timestamp -->
</template>
</Card>
</PrimeCard>

<!-- for mobile and tablet -->
<div class="lg:hidden smaller-screens">
<div class="flex align-items-center">
<h1 class="flex-grow-1">
{{ form.definition.bind.form.title }}
</h1>

<!-- for tablet -->
<div class="odk-menu-bar hidden md:flex justify-content-end gap-3">
<PrimeButton class="print-button" severity="secondary" rounded icon="icon-local_printshop" @click="print" />
<FormLanguageMenu :form="form" />
</div>

<!-- for mobile -->
<PrimeButton icon="icon-menu" class="btn-menu md:hidden" text rounded aria-label="Menu" @click="menu?.toggle" />
<PrimeMenu id="overlay_menu" ref="menu" :model="items" :popup="true" />
<FormLanguageDialog v-model:state="languageDialogState" :form="form" />
</div>
</div>
</template>

<style scoped lang="scss">
.p-button.p-button-icon-only.p-button-rounded {
height: 2.5rem;
width: 2.5rem;
min-width: 2.5rem;
font-size: 1.5rem;
&:hover{
background: var(--primary-100);
}
&:active, &:focus {
background: var(--primary-50);
}
}
.form-title {
border-radius: 10px;
box-shadow: 0px 1px 3px 1px #00000026;
Expand All @@ -28,4 +97,32 @@ defineProps<{title: string}>();
}
}
}
.smaller-screens {
// this adds border to parent div so that bottom shadow of immediate child
// is visible.
border-bottom: 3px solid #fff;
// to show ellipsis in the heading
// https://css-tricks.com/using-flexbox-and-text-ellipsis-together/
min-width: 0;
> div {
box-shadow: 0px 1px 2px 0px #0000004D;
}
h1 {
padding-left: 10px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
font-size: 1.5rem;
}
.btn-menu{
color: #000;
font-size: 1.5rem;
}
}
</style>
102 changes: 102 additions & 0 deletions packages/web-forms/src/components/FormLanguageDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<script setup lang="ts">
import type { FormLanguage, RootNode } from '@getodk/xforms-engine';
import PrimeButton from 'primevue/button';
import PrimeDialog from 'primevue/dialog';
import PrimeRadioButton from 'primevue/radiobutton';
import { ref } from 'vue';
const props = defineProps<{ form: RootNode, state: boolean }>();
const emit = defineEmits(['update:state']);
const languages = props.form.languages.filter(language => !language.isSyntheticDefault);
const selectedLanguage = ref<FormLanguage>();
const initSelectedLanguage = () => {
if(!props.form.currentState.activeLanguage.isSyntheticDefault) {
selectedLanguage.value = props.form.currentState.activeLanguage;
}
}
initSelectedLanguage();
const handleSave = () => {
if(!selectedLanguage.value?.isSyntheticDefault){
props.form.setLanguage(selectedLanguage.value!);
}
emit('update:state',false);
};
const handleCancel = () => {
initSelectedLanguage();
emit('update:state',false);
}
</script>

<template>
<PrimeDialog :visible="state" modal header="Change language" class="language-dialog" :closable="false" @update:visible="handleCancel()">
<label
v-for="lang in languages"
:key="lang.language"
:for="lang.language"
class="lang-options"
>
<PrimeRadioButton
v-model="selectedLanguage"
:input-id="lang.language"
:name="lang.language"
:value="lang"
/>
{{ lang.language }}</label>

<div class="flex justify-content-end mt-5">
<PrimeButton label="Cancel" rounded text @click="handleCancel()" />
<PrimeButton label="Save" rounded raised @click="handleSave()" />
</div>
</PrimeDialog>
</template>

<style scoped lang="scss">
.lang-options {
width: 100%;
display: block;
border: 1px solid #E6E1E5;
padding: 10px 0 10px 8px;
border-radius: 10px;
margin-bottom: 10px;
cursor: pointer;
&:hover {
border-color: var(--primary-500);
}
> div {
margin-right: 10px;
}
}
button {
min-width: 100px;
}
</style>

<style lang="scss">
.p-dialog.language-dialog {
--radius: 20px;
min-width: 300px;
border-radius: var(--radius);
.p-dialog-header {
border-top-right-radius: var(--radius);
border-top-left-radius: var(--radius);
}
.p-dialog-content:last-of-type {
border-bottom-right-radius: var(--radius);
border-bottom-left-radius: var(--radius);
}
}
</style>
2 changes: 2 additions & 0 deletions packages/web-forms/src/components/FormLanguageMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const handleLanguageChange = (event: LanguageDropdownChangeEvent) => {
};
</script>

<template>
<Dropdown
v-if="languages.length > 0"
Expand Down Expand Up @@ -57,6 +58,7 @@ const handleLanguageChange = (event: LanguageDropdownChangeEvent) => {
.icon-language {
margin-right: 10px;
font-size: 1.5rem;
}
}
</style>
Loading

0 comments on commit 9e93c81

Please sign in to comment.