Skip to content

Commit

Permalink
Merge pull request #116 from qld-gov-au/QOLOE-117-modal-component
Browse files Browse the repository at this point in the history
QOLOE-117 Add modal component, bugfix for buttons, header
  • Loading branch information
stvp-qld authored May 14, 2024
2 parents 553ca7e + decf7e8 commit 823eeca
Show file tree
Hide file tree
Showing 12 changed files with 387 additions and 131 deletions.
11 changes: 5 additions & 6 deletions src/components/bs5/button/button.hbs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
<!-- // QGDS Component: Button -->
<!-- // https://getbootstrap.com/docs/5.3/components/buttons -->

{{#unless islink}}
<button class="btn {{variantClass}}" onclick="{{{onclick}}}" {{#if isdisabled}}disabled{{/if}}>
{{#if iconClass}}<span class="btn-icon {{iconClass}}"></span>{{/if}}{{label}}
<button class="btn {{variantClass}}" onclick="{{{onclick}}}" {{#if isdisabled}}disabled{{/if}} {{#if arialabel}}aria-label="{{arialabel}}"{{/if}} {{{dataatts}}}>
{{#if iconClass}}<span class="btn-icon {{iconClass}}"></span>{{/if}}{{label}}
</button>

{{else}}
<a class="btn {{variantClass}} {{#if isdisabled}}disabled" aria-disabled="true{{/if}}" href="{{href}}" target="{{target}}">

<a class="btn {{variantClass}} {{#if isdisabled}} disabled {{/if}}" {{#if isdisabled}} aria-disabled="true" {{/if}} href="{{href}}" target="{{target}}" {{#if arialabel}}aria-label="{{arialabel}}"{{/if}} {{{dataatts}}}>
{{#if iconClass}}<span class="btn-icon {{iconClass}}"></span>{{/if}}{{label}}
</a>
{{/unless }}
13 changes: 13 additions & 0 deletions src/components/bs5/modal/Modal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Component from '../../../js/QGDSComponent.js'
import template from "./modal.hbs?raw";

export class Modal {

// Use the global Component class to create a new instance of the Modal component.
// A data object, containing the Handlebars placeholder replacement strings, should be provided as an argument.

constructor( data = {} ) {
return new Component(template, data);
}

}
19 changes: 19 additions & 0 deletions src/components/bs5/modal/Modal.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Canvas, Meta, Story, Source } from "@storybook/blocks"
import * as ModalStories from "./modal.stories"

import { Modal } from './Modal.js';
import defaultdata from './modal.data.json';

# Modal
<Meta of={ModalStories} />

## Demo
Please use the **Default story** to see the modal in action.

## Example code
<Source code={new Modal(defaultdata).html} language='jsx' dark={false}/>

## Design resources
- [Draft state (Figma)](https://www.figma.com/file/nMmoukrjPJ8qvUiwmuj1bs/forgov.qld.gov.au?type=design&node-id=1062-38211&mode=design&t=Mo0dPyJzGQ7YPs0s-0)
- [Bootstrap] https://getbootstrap.com/docs/5.3/components/modal/

Empty file.
12 changes: 12 additions & 0 deletions src/components/bs5/modal/modal.data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"modalSize": "modal-lg",
"modalID": "terms-and-conditions",
"header": {
"title": "Terms and conditions",
"closeButton": true
},
"content": "<p>By signing in to this account, I agree to:</p><ul><li>Terms and conditions</li><li>Privacy policy</li><li>Cookie policy</li></ul>",
"footer": {
"buttons": []
}
}
9 changes: 9 additions & 0 deletions src/components/bs5/modal/modal.functions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Extends Bootstraop 5.3 default modal behaviour
*/

export function modal() {

//Write custom modal functions here

}
38 changes: 38 additions & 0 deletions src/components/bs5/modal/modal.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!-- Example button to trigger the modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#{{modalID}}">
{{launchButtonLabel}}
</button>

<!-- You can also use a standard link. It must contain data-bs-toggle and data-bs-target attributes -->
<p>You can also <a class="d-inline-block my-3" href="#" data-bs-toggle="modal" data-bs-target="#{{modalID}}">open a model</a> with a standard link.


<!-- QGDS Modal -->
<div class="modal fade" id="{{modalID}}" tabindex="-1" aria-labelledby="{{modalLabel}}" aria-hidden="true">
<div class="modal-dialog {{modalSize}}">
<div class="modal-content">

{{#if header}}
<div class="modal-header">
<h1 class="modal-title" id="{{modalLabel}}">{{{ header.title }}}</h1>
{{#if header.closeButton}}
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
{{/if}}
</div>
{{/if}}

<div class="modal-body">
{{{ content }}}
</div>

{{#if footer}}
<div class="modal-footer">
{{#each footer.buttons}}
{{{ . }}}
{{/each}}
</div>
{{/if}}

</div>
</div>
</div>
99 changes: 99 additions & 0 deletions src/components/bs5/modal/modal.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Modal extends https://getbootstrap.com/docs/5.3/components/modal/
// Default CSS variables https://getbootstrap.com/docs/5.3/components/modal/#variables

// Default
.modal {
--#{$prefix}modal-zindex: #{$zindex-modal};
--#{$prefix}modal-width: #{$modal-md};

--#{$prefix}modal-margin: #{$modal-dialog-margin};
--#{$prefix}modal-color: #{$modal-content-color};
--#{$prefix}modal-bg: #{$modal-content-bg};

--#{$prefix}modal-border-color: var(--qld-light-grey);
--#{$prefix}modal-border-width: 1px;
--#{$prefix}modal-border-radius: 0.75rem;

--#{$prefix}modal-box-shadow: #{$modal-content-box-shadow-xs};
--#{$prefix}modal-inner-border-radius: #{$modal-content-inner-border-radius};
--#{$prefix}modal-header-padding: 2rem 1.5rem;

--#{$prefix}modal-header-border-color: var(--qld-light-grey);
--#{$prefix}modal-header-border-width: 1px;

--#{$prefix}modal-title-line-height: 2rem;

--#{$prefix}modal-footer-gap: 0;
--#{$prefix}modal-footer-bg: none;
--#{$prefix}modal-footer-border-color: none;
--#{$prefix}modal-footer-border-width: none;

//QGDS specific
.btn-close {
--qld-btn-close-icon: "data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M18.0547 18.5938C17.8203 18.8281 17.3906 18.8281 17.1562 18.5938L12 13.3984L6.80469 18.5938C6.57031 18.8281 6.14062 18.8281 5.90625 18.5938C5.67188 18.3594 5.67188 17.9297 5.90625 17.6953L11.1016 12.5L5.90625 7.34375C5.67188 7.10938 5.67188 6.67969 5.90625 6.44531C6.14062 6.21094 6.57031 6.21094 6.80469 6.44531L12 11.6406L17.1562 6.44531C17.3906 6.21094 17.8203 6.21094 18.0547 6.44531C18.2891 6.67969 18.2891 7.10938 18.0547 7.34375L12.8594 12.5L18.0547 17.6953C18.2891 17.9297 18.2891 18.3594 18.0547 18.5938Z' /%3E%3C/svg%3E%0A";
--qld-btn-close-color: var(--qld-light-action-secondary);
--qld-btn-close-opacity: 1;
--qld-btn-close-hover-opacity: 1;
--qld-btn-close-focus-shadow: 0 0 0 .25rem rgba(13, 110, 253, .25);

background: var(--qld-btn-close-color);
mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M18.0547 18.5938C17.8203 18.8281 17.3906 18.8281 17.1562 18.5938L12 13.3984L6.80469 18.5938C6.57031 18.8281 6.14062 18.8281 5.90625 18.5938C5.67188 18.3594 5.67188 17.9297 5.90625 17.6953L11.1016 12.5L5.90625 7.34375C5.67188 7.10938 5.67188 6.67969 5.90625 6.44531C6.14062 6.21094 6.57031 6.21094 6.80469 6.44531L12 11.6406L17.1562 6.44531C17.3906 6.21094 17.8203 6.21094 18.0547 6.44531C18.2891 6.67969 18.2891 7.10938 18.0547 7.34375L12.8594 12.5L18.0547 17.6953C18.2891 17.9297 18.2891 18.3594 18.0547 18.5938Z' /%3E%3C/svg%3E%0A");
mask-repeat: no-repeat;
}

.modal-header {
padding: 2rem 1.5rem 1.5rem 1.5rem;

.modal-title {
line-height: var(--#{$prefix}modal-title-line-height);
font-size: 1.5rem;
}
}

.modal-body {
padding: 1.5rem 1.5rem 2rem 1.5rem;
}

.modal-footer {
padding: 0 1.5rem 2rem 1.5rem;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-end;

.btn {
margin: 0 0 0 1.5rem;
}
}

//Rescope for smaller modals
.modal-dialog {
&.modal-sm {
.modal-footer {
flex-direction: column-reverse;
.btn {
width: 100%;
margin: 0 0 1.5rem 0;
&:first-child {
margin: 0;
}
}
}
}
}

//Rescope for smaller viewports
@include media-breakpoint-between(xs, sm) {
.modal-footer {
flex-direction: column-reverse;
.btn {
width: 100%;
margin: 0 0 1.5rem 0;
&:first-child {
margin: 0;
}
}
}
}

}
116 changes: 116 additions & 0 deletions src/components/bs5/modal/modal.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// modal.stories.js
import { Modal } from './Modal.js';
import defaultdata from './modal.data.json';

//Load some buttons for modal footer
import { Button } from '../button/Button.js';

let buttonItems = [{
"variantClass": "btn-tertiary",
"islink": true,
"isdisabled": false,
"iconClass": "",
"href": "https:///www.google.com",
"label": "External link",
"target": "_blank",
"dataatts": false,
"arialabel": false,
},{
"variantClass": "btn-secondary",
"islink": false,
"isdisabled": false,
"iconClass": "",
"href": "#",
"label": "Cancel",
"target": "",
"dataatts": "data-bs-dismiss='modal'",
"arialabel": "Close",
},
{
"variantClass": "btn-primary",
"islink": false,
"isdisabled": false,
"iconClass": "",
"href": "#",
"label": "Confirm",
"target": "",
"dataatts": "data-bs-dismiss='modal'",
"arialabel": "Close",
}];

defaultdata.footer.buttons = buttonItems.map((item) => {
return new Button(item).html;
});


export default {
tags: [''],
title: 'Components/Modal',
render: (args) => new Modal(args).html,

argTypes: {
buttons: {
control: { disable: true },
},
modalSize: {
name: "Size",
description: `Set the size of the modal`,
control: {
type: "select",
labels: {
"modal-sm": "Small",
"modal-default": "Default",
"modal-lg": "Large",
"modal-xl": "Extra Large",
},
},
options: [
"modal-sm",
"modal-default",
"modal-lg",
"modal-xl",
],
},
},
};

/**
* Default Modal (Extra Large, 1140px)
*/
export const Default = {
args: {
...defaultdata,
modalID: 'modal-example-default',
modalLabel: 'Default modal example',
modalSize: 'modal-xl',
launchButtonLabel: 'Open default modal',
},
};

/**
* Small Modal (575px)
*/

export const SmallModal= {
args: {
...defaultdata,
modalID: 'modal-example-small',
modalLabel: 'Small modal example',
modalSize: 'modal-sm',
launchButtonLabel: 'Open small modal',
},
};


/**
* Large Modal (800px)
*/
export const LargeModal = {
args: {
...defaultdata,
modalID: 'modal-example-large',
modalLabel: 'Large modal example',
modalSize: 'modal-lg',
launchButtonLabel: 'Open large modal',
},
};
Loading

0 comments on commit 823eeca

Please sign in to comment.