barbican-reset 3.32.0 → 3.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/BrConfirmDone.vue +19 -13
- package/components/BrConfirmEmail.vue +19 -18
- package/components/BrDetails.vue +6 -2
- package/components/BrFormCheckbox.vue +37 -3
- package/components/BrFormLabel.vue +2 -1
- package/components/BrFormRadio.vue +20 -2
- package/components/BrOverlay.vue +13 -6
- package/components/BrTableCell.vue +50 -0
- package/components/BrTableHeader.vue +1 -5
- package/components/BrTableRow.vue +5 -0
- package/components/BrWrap.vue +6 -0
- package/index.js +4 -0
- package/package.json +1 -1
- package/scripts/animations/confirm.js +79 -0
- package/scripts/helpers/constrainTabbing.js +40 -0
- package/scripts/helpers/logObject.js +3 -10
- package/scripts/helpers.js +2 -1
- package/scss/_atomic.scss +5 -0
- package/scss/_br-form-fieldset.scss +2 -2
- package/scss/_br-form-label.scss +3 -0
- package/scss/_br-form-radio.scss +17 -1
- package/scss/_br-table-cell.scss +75 -0
- package/scss/_br-table-header.scss +3 -49
- package/scss/_br-table-row.scss +24 -0
- package/scss/_variables.scss +3 -2
- package/scss/atomic/_font-sizes.scss +6 -0
- package/scss/atomic/_margins.scss +12 -0
- package/scss/atomic/_widths.scss +43 -0
- package/scss/index.scss +3 -0
- package/scss/mixins/_br-card.scss +3 -6
- package/scss/mixins/_br-form-radio.scss +3 -3
- package/scss/mixins/_br-wrap.scss +21 -18
- package/scss/mixins/_font-size.scss +9 -0
- package/scss/mixins/buttons/custom/_renew-membership.scss +2 -0
- package/scss/mixins/index.scss +1 -0
- package/scss/mixins/input/_checkbox.scss +20 -3
- package/animations/confirm.js +0 -61
- package/animations/index.js +0 -8
|
@@ -1,26 +1,32 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<br-card confirm
|
|
2
|
+
<br-card class="confirm-done">
|
|
3
3
|
<done-icon />
|
|
4
|
-
<br-card-title>Done</br-card-title>
|
|
5
|
-
<br-card-text v-if="$slots.default">
|
|
4
|
+
<br-card-title class="title">Done</br-card-title>
|
|
5
|
+
<br-card-text v-if="$slots.default" class="margin-top-1">
|
|
6
6
|
<slot />
|
|
7
7
|
</br-card-text>
|
|
8
8
|
</br-card>
|
|
9
9
|
</template>
|
|
10
10
|
|
|
11
|
-
<script>
|
|
11
|
+
<script setup>
|
|
12
|
+
import { onMounted } from 'vue'
|
|
13
|
+
import { animateDone } from '#scripts/animations/confirm'
|
|
14
|
+
|
|
12
15
|
import BrCard from '#components/BrCard.vue'
|
|
13
16
|
import BrCardTitle from '#components/BrCardTitle.vue'
|
|
14
17
|
import BrCardText from '#components/BrCardText.vue'
|
|
15
|
-
|
|
16
|
-
import Animations from '#animations/index'
|
|
17
18
|
import DoneIcon from '#icons/confirm/done.vue'
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
mixins: [Animations],
|
|
21
|
-
components: { BrCard, BrCardTitle, BrCardText, DoneIcon },
|
|
22
|
-
mounted() {
|
|
23
|
-
this.animateDone()
|
|
24
|
-
},
|
|
25
|
-
}
|
|
20
|
+
onMounted(() => animateDone())
|
|
26
21
|
</script>
|
|
22
|
+
|
|
23
|
+
<style scoped>
|
|
24
|
+
.confirm-done {
|
|
25
|
+
max-width: var(--width-title);
|
|
26
|
+
text-align: center;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.title {
|
|
30
|
+
text-align: center;
|
|
31
|
+
}
|
|
32
|
+
</style>
|
|
@@ -1,33 +1,34 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<br-card confirm
|
|
2
|
+
<br-card class="confirm-email">
|
|
3
3
|
<email-icon />
|
|
4
|
-
<br-card-title v-if="$slots.title">
|
|
4
|
+
<br-card-title v-if="$slots.title" class="title">
|
|
5
5
|
<slot name="title" />
|
|
6
6
|
</br-card-title>
|
|
7
|
-
<br-card-text v-if="$slots.default">
|
|
7
|
+
<br-card-text v-if="$slots.default" class="margin-top-1">
|
|
8
8
|
<slot />
|
|
9
9
|
</br-card-text>
|
|
10
10
|
</br-card>
|
|
11
11
|
</template>
|
|
12
12
|
|
|
13
|
-
<script>
|
|
13
|
+
<script setup>
|
|
14
|
+
import { onMounted } from 'vue'
|
|
15
|
+
import { animateEmail } from '#scripts/animations/confirm'
|
|
16
|
+
|
|
14
17
|
import BrCard from '#components/BrCard.vue'
|
|
15
18
|
import BrCardTitle from '#components/BrCardTitle.vue'
|
|
16
19
|
import BrCardText from '#components/BrCardText.vue'
|
|
17
|
-
|
|
18
|
-
import Animations from '#animations/index'
|
|
19
20
|
import EmailIcon from '#icons/confirm/email.vue'
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
mixins: [Animations],
|
|
23
|
-
components: {
|
|
24
|
-
BrCard,
|
|
25
|
-
BrCardTitle,
|
|
26
|
-
BrCardText,
|
|
27
|
-
EmailIcon,
|
|
28
|
-
},
|
|
29
|
-
mounted() {
|
|
30
|
-
this.animateEmail()
|
|
31
|
-
},
|
|
32
|
-
}
|
|
22
|
+
onMounted(() => animateEmail())
|
|
33
23
|
</script>
|
|
24
|
+
|
|
25
|
+
<style scoped>
|
|
26
|
+
.confirm-email {
|
|
27
|
+
max-width: var(--width-title);
|
|
28
|
+
text-align: center;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.title {
|
|
32
|
+
text-align: center;
|
|
33
|
+
}
|
|
34
|
+
</style>
|
package/components/BrDetails.vue
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="br-details">
|
|
3
|
-
<br-button variant="summary" @click="update">
|
|
3
|
+
<br-button variant="summary" @click="update" :data-test="'toggle-' + label">
|
|
4
4
|
<div class="wrap-title">
|
|
5
5
|
<slot name="title">Title goes here</slot>
|
|
6
6
|
</div>
|
|
@@ -20,6 +20,10 @@ const props = defineProps({
|
|
|
20
20
|
type: Boolean,
|
|
21
21
|
default: false,
|
|
22
22
|
},
|
|
23
|
+
label: {
|
|
24
|
+
type: String,
|
|
25
|
+
default: 'details',
|
|
26
|
+
},
|
|
23
27
|
})
|
|
24
28
|
|
|
25
29
|
const update = () => emit('update', { open: !props.open })
|
|
@@ -50,6 +54,6 @@ const update = () => emit('update', { open: !props.open })
|
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
.wrap-content.open {
|
|
53
|
-
margin-top: var(--margin-
|
|
57
|
+
margin-top: var(--margin-xxl);
|
|
54
58
|
}
|
|
55
59
|
</style>
|
|
@@ -1,14 +1,22 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component BrFormCheckbox
|
|
3
|
+
@description A checkbox form field that wraps BrFormInput (type="checkbox") inside a BrFormLabel.
|
|
4
|
+
Supports success/error states, disabled state, block-level layout, and an optional label slot.
|
|
5
|
+
Non-prop attributes (e.g. name, value) are forwarded directly to the underlying input element.
|
|
6
|
+
Any classes passed to this component are merged onto the root wrapper div.
|
|
7
|
+
-->
|
|
1
8
|
<template>
|
|
2
|
-
<div :class="['br-form-checkbox', { block }]">
|
|
9
|
+
<div :class="['br-form-checkbox', { block }, $attrs.class]">
|
|
3
10
|
<br-form-label
|
|
4
11
|
:class="[{ success }, { error }]"
|
|
5
12
|
:disabled="disabled"
|
|
13
|
+
:returns="returns"
|
|
6
14
|
:id="generateID">
|
|
7
15
|
<br-form-input
|
|
8
16
|
:class="[{ success }, { error }]"
|
|
9
17
|
:disabled="disabled"
|
|
18
|
+
v-bind="inputAttrs"
|
|
10
19
|
:id="generateID"
|
|
11
|
-
v-bind="$attrs"
|
|
12
20
|
type="checkbox"
|
|
13
21
|
:error="error" />
|
|
14
22
|
<span v-if="$slots.default" class="label-text">
|
|
@@ -19,21 +27,47 @@
|
|
|
19
27
|
</template>
|
|
20
28
|
|
|
21
29
|
<script setup>
|
|
22
|
-
import { computed } from 'vue'
|
|
30
|
+
import { computed, useAttrs } from 'vue'
|
|
23
31
|
import formatKebabCase from '#helpers/formatKebabCase'
|
|
24
32
|
import BrFormLabel from '#components/BrFormLabel.vue'
|
|
25
33
|
import BrFormInput from '#components/BrFormInput.vue'
|
|
26
34
|
|
|
35
|
+
/** All fallthrough attributes from the parent. */
|
|
36
|
+
const attrs = useAttrs()
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Attrs forwarded to the inner input, with `class` removed so it doesn't
|
|
40
|
+
* double-apply (class is already merged onto the root div via $attrs.class).
|
|
41
|
+
*
|
|
42
|
+
* @type {import('vue').ComputedRef<Record<string, unknown>>}
|
|
43
|
+
*/
|
|
44
|
+
const inputAttrs = computed(() => {
|
|
45
|
+
const { class: _, ...rest } = attrs
|
|
46
|
+
return rest
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Disable automatic attribute inheritance so $attrs can be manually
|
|
51
|
+
* forwarded to the inner input element rather than the root div.
|
|
52
|
+
*/
|
|
27
53
|
defineOptions({
|
|
28
54
|
inheritAttrs: false,
|
|
29
55
|
})
|
|
30
56
|
|
|
57
|
+
/**
|
|
58
|
+
* @prop {string} [id] - Explicit id for the input/label pair. Falls back to a random id.
|
|
59
|
+
* @prop {boolean} [disabled] - Disables the checkbox input and label.
|
|
60
|
+
* @prop {boolean} [success] - Applies success styling to the label and input.
|
|
61
|
+
* @prop {boolean} [error] - Applies error styling to the label and input.
|
|
62
|
+
* @prop {boolean} [block] - Makes the checkbox wrapper display as a block-level element.
|
|
63
|
+
*/
|
|
31
64
|
const props = defineProps({
|
|
32
65
|
id: String,
|
|
33
66
|
disabled: Boolean,
|
|
34
67
|
success: Boolean,
|
|
35
68
|
error: Boolean,
|
|
36
69
|
block: Boolean,
|
|
70
|
+
returns: Boolean,
|
|
37
71
|
})
|
|
38
72
|
|
|
39
73
|
// @description Returns a string for the "id" attribute
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<component
|
|
3
|
-
:class="['br-form-label', { disabled }]"
|
|
3
|
+
:class="['br-form-label', { disabled }, { returns }]"
|
|
4
4
|
:is="!disabled ? 'label' : 'div'"
|
|
5
5
|
:for="!disabled ? id : null">
|
|
6
6
|
<slot />
|
|
@@ -14,6 +14,7 @@ const props = defineProps({
|
|
|
14
14
|
disabled: Boolean,
|
|
15
15
|
required: Boolean,
|
|
16
16
|
optional: Boolean,
|
|
17
|
+
returns: Boolean,
|
|
17
18
|
id: String,
|
|
18
19
|
})
|
|
19
20
|
</script>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="
|
|
2
|
+
<div :class="generateClassnames">
|
|
3
3
|
<br-form-label
|
|
4
4
|
:class="[{ success }, { error }]"
|
|
5
5
|
:disabled="disabled"
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
v-bind="$attrs"
|
|
12
12
|
:error="error"
|
|
13
13
|
type="radio" />
|
|
14
|
-
<span class="label-text">
|
|
14
|
+
<span v-if="$slots.default" class="label-text">
|
|
15
15
|
<slot />
|
|
16
16
|
</span>
|
|
17
17
|
</br-form-label>
|
|
@@ -25,6 +25,20 @@ import formatKebabCase from '#helpers/formatKebabCase'
|
|
|
25
25
|
import BrFormLabel from '#components/BrFormLabel.vue'
|
|
26
26
|
import BrFormInput from '#components/BrFormInput.vue'
|
|
27
27
|
|
|
28
|
+
const generateClassnames = computed(() => {
|
|
29
|
+
let classnames = ['br-form-radio']
|
|
30
|
+
|
|
31
|
+
if (props.table) {
|
|
32
|
+
classnames.push('table')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!props.table) {
|
|
36
|
+
classnames.push('default')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return classnames
|
|
40
|
+
})
|
|
41
|
+
|
|
28
42
|
defineOptions({
|
|
29
43
|
inheritAttrs: false,
|
|
30
44
|
})
|
|
@@ -45,6 +59,10 @@ const props = defineProps({
|
|
|
45
59
|
default: false,
|
|
46
60
|
type: Boolean,
|
|
47
61
|
},
|
|
62
|
+
table: {
|
|
63
|
+
default: false,
|
|
64
|
+
type: Boolean,
|
|
65
|
+
},
|
|
48
66
|
})
|
|
49
67
|
|
|
50
68
|
// @description Returns a string for the "id" attribute
|
package/components/BrOverlay.vue
CHANGED
|
@@ -10,24 +10,31 @@
|
|
|
10
10
|
</template>
|
|
11
11
|
|
|
12
12
|
<script setup>
|
|
13
|
-
import { onMounted, onUnmounted } from 'vue'
|
|
14
|
-
import
|
|
15
|
-
import
|
|
13
|
+
import { onMounted, onUnmounted } from 'vue'
|
|
14
|
+
import { constrainTabbing } from '#scripts/helpers'
|
|
15
|
+
import BrButton from '#components/BrButton.vue'
|
|
16
|
+
import CloseIcon from '#icons/close.vue'
|
|
16
17
|
|
|
17
|
-
const emit = defineEmits([
|
|
18
|
+
const emit = defineEmits(['closeOverlay'])
|
|
19
|
+
|
|
20
|
+
function constrainOverlayPadding() {
|
|
21
|
+
let $overlay = document.querySelector('.br-overlay-wrap')
|
|
22
|
+
constrainTabbing($overlay)
|
|
23
|
+
}
|
|
18
24
|
|
|
19
25
|
function listenForKeys({ key }) {
|
|
20
26
|
if (key == 'Escape') {
|
|
21
|
-
emit('closeOverlay')
|
|
27
|
+
emit('closeOverlay')
|
|
22
28
|
}
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
onMounted(() => {
|
|
26
32
|
document.addEventListener('keydown', listenForKeys)
|
|
33
|
+
document.addEventListener('keydown', constrainOverlayPadding)
|
|
27
34
|
})
|
|
28
35
|
|
|
29
36
|
onUnmounted(() => {
|
|
30
37
|
document.removeEventListener('keydown', listenForKeys)
|
|
38
|
+
document.removeEventListener('keydown', constrainOverlayPadding)
|
|
31
39
|
})
|
|
32
40
|
</script>
|
|
33
|
-
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="generateClassnames">
|
|
3
|
+
<slot />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup>
|
|
8
|
+
import { computed } from 'vue'
|
|
9
|
+
|
|
10
|
+
const generateClassnames = computed(() => {
|
|
11
|
+
let classnames = ['br-table-cell']
|
|
12
|
+
|
|
13
|
+
if (props.width) {
|
|
14
|
+
classnames.push('width-' + props.width)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (props.right) {
|
|
18
|
+
classnames.push('align-right')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (props.center) {
|
|
22
|
+
classnames.push('align-center')
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (props.radio) {
|
|
26
|
+
classnames.push('radio')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (props.returns) {
|
|
30
|
+
classnames.push('returns')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!props.radio && !props.returns) {
|
|
34
|
+
classnames.push('default')
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return classnames
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const props = defineProps({
|
|
41
|
+
width: {
|
|
42
|
+
type: String,
|
|
43
|
+
default: 'stretch',
|
|
44
|
+
},
|
|
45
|
+
returns: Boolean,
|
|
46
|
+
right: Boolean,
|
|
47
|
+
center: Boolean,
|
|
48
|
+
radio: Boolean,
|
|
49
|
+
})
|
|
50
|
+
</script>
|
package/components/BrWrap.vue
CHANGED
|
@@ -17,11 +17,13 @@ const generateComponentClasses = computed(() => {
|
|
|
17
17
|
if (props.cluster) {
|
|
18
18
|
classnames.push('cluster')
|
|
19
19
|
classnames.push('align-' + props.align)
|
|
20
|
+
classnames.push('size-' + props.size)
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
if (props.orders) {
|
|
23
24
|
classnames.push('orders')
|
|
24
25
|
classnames.push('align-' + props.align)
|
|
26
|
+
classnames.push('size-' + props.size)
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
if (props.preferences) {
|
|
@@ -44,5 +46,9 @@ const props = defineProps({
|
|
|
44
46
|
type: String,
|
|
45
47
|
default: 'middle',
|
|
46
48
|
},
|
|
49
|
+
size: {
|
|
50
|
+
type: String,
|
|
51
|
+
default: 'xs',
|
|
52
|
+
},
|
|
47
53
|
})
|
|
48
54
|
</script>
|
package/index.js
CHANGED
|
@@ -45,7 +45,9 @@ import BrOverlay from '#components/BrOverlay.vue'
|
|
|
45
45
|
import BrLoader from '#components/BrLoader.vue'
|
|
46
46
|
import BrSkiplink from '#components/BrSkiplink.vue'
|
|
47
47
|
import BrStatusBars from '#components/BrStatusBars.vue'
|
|
48
|
+
import BrTableCell from '#components/BrTableCell.vue'
|
|
48
49
|
import BrTableHeader from '#components/BrTableHeader.vue'
|
|
50
|
+
import BrTableRow from '#components/BrTableRow.vue'
|
|
49
51
|
import BrWrap from '#components/BrWrap.vue'
|
|
50
52
|
|
|
51
53
|
export {
|
|
@@ -89,6 +91,8 @@ export {
|
|
|
89
91
|
BrOverlay,
|
|
90
92
|
BrSkiplink,
|
|
91
93
|
BrStatusBars,
|
|
94
|
+
BrTableCell,
|
|
92
95
|
BrTableHeader,
|
|
96
|
+
BrTableRow,
|
|
93
97
|
BrWrap,
|
|
94
98
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "barbican-reset",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.34.0",
|
|
4
4
|
"description": "Shared design system for Barbican projects, providing SCSS utilities, animations, icons, Vue components, and JS helpers for consistent styling and behaviour.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"exports": {
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import gsap from 'gsap'
|
|
2
|
+
|
|
3
|
+
let defaults = {
|
|
4
|
+
duration: 0.6,
|
|
5
|
+
ease: 'power1.in',
|
|
6
|
+
transformOrigin: 'center',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let fadeIn = {
|
|
10
|
+
duration: 0.3,
|
|
11
|
+
opacity: 0,
|
|
12
|
+
delay: 0.3,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let explode = {
|
|
16
|
+
ease: 'power1.out',
|
|
17
|
+
opacity: 0,
|
|
18
|
+
scale: 1.5,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function animateDone() {
|
|
22
|
+
let $card = document.querySelector('.br-card.confirm-done')
|
|
23
|
+
let $title = $card.querySelector('.br-card-title')
|
|
24
|
+
let $outline = $card.querySelector('.outline')
|
|
25
|
+
let $arrow = $card.querySelector('.arrow')
|
|
26
|
+
let $tick = $card.querySelector('.tick')
|
|
27
|
+
|
|
28
|
+
let tl = gsap.timeline({ defaults })
|
|
29
|
+
|
|
30
|
+
let $clone = $title.cloneNode(true)
|
|
31
|
+
|
|
32
|
+
$clone.classList.add('clone')
|
|
33
|
+
|
|
34
|
+
$title.after($clone)
|
|
35
|
+
|
|
36
|
+
let cloneHeight = $card.querySelector('.clone').offsetHeight
|
|
37
|
+
|
|
38
|
+
$clone.style.marginTop = `-${cloneHeight}px`
|
|
39
|
+
|
|
40
|
+
// prettier-ignore
|
|
41
|
+
tl.set($arrow, { opacity: 0 })
|
|
42
|
+
.from($title, fadeIn)
|
|
43
|
+
.set($clone, { opacity: 0.4 })
|
|
44
|
+
.from($outline, { drawSVG: '0%' }, 'start')
|
|
45
|
+
.from($tick, { drawSVG: '0%', duration: 0.3 }, 'start')
|
|
46
|
+
.to($clone, explode, 'start')
|
|
47
|
+
.set($arrow, { opacity: 1 })
|
|
48
|
+
.from($arrow, { x: -6, ease: 'power1.out' })
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function animateEmail() {
|
|
52
|
+
let $card = document.querySelector('.br-card.confirm-email')
|
|
53
|
+
let $title = $card.querySelector('.br-card-title')
|
|
54
|
+
let $outline = $card.querySelector('.outline')
|
|
55
|
+
let $arrow = $card.querySelector('.arrow')
|
|
56
|
+
let $fold = $card.querySelector('.fold')
|
|
57
|
+
|
|
58
|
+
let tl = gsap.timeline({ defaults })
|
|
59
|
+
|
|
60
|
+
let $clone = $title.cloneNode(true)
|
|
61
|
+
|
|
62
|
+
$clone.classList.add('clone')
|
|
63
|
+
|
|
64
|
+
$title.after($clone)
|
|
65
|
+
|
|
66
|
+
let cloneHeight = $card.querySelector('.clone').offsetHeight
|
|
67
|
+
|
|
68
|
+
$clone.style.marginTop = `-${cloneHeight}px`
|
|
69
|
+
|
|
70
|
+
// prettier-ignore
|
|
71
|
+
tl.set($arrow, { opacity: 0 })
|
|
72
|
+
.from($title, fadeIn)
|
|
73
|
+
.set($clone, { opacity: 0.4 })
|
|
74
|
+
.from($outline, { drawSVG: '0%' }, 'start')
|
|
75
|
+
.from($fold, { drawSVG: '0%', duration: 0.3 }, 'start')
|
|
76
|
+
.to($clone, explode, 'start')
|
|
77
|
+
.set($arrow, { opacity: 1 })
|
|
78
|
+
.from($arrow, { x: -6, ease: 'power1.out' })
|
|
79
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constrains keyboard tab focus to within a given DOM element, creating a focus trap.
|
|
3
|
+
* When the user tabs past the last focusable element, focus wraps to the first,
|
|
4
|
+
* and vice versa when shift-tabbing past the first.
|
|
5
|
+
*
|
|
6
|
+
* Useful for modal dialogs and overlays where focus should not escape to the
|
|
7
|
+
* rest of the page while the element is active.
|
|
8
|
+
*
|
|
9
|
+
* @param {HTMLElement} element - The container element to trap focus within.
|
|
10
|
+
* @returns {void}
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* constrainTabbing(document.getElementById('modal'))
|
|
14
|
+
*/
|
|
15
|
+
export default function (element) {
|
|
16
|
+
let focusableEls = element.querySelectorAll('a[href]:not([disabled], [rel=noopener]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])')
|
|
17
|
+
let firstFocusableEl = focusableEls[0]
|
|
18
|
+
let lastFocusableEl = focusableEls[focusableEls.length - 1]
|
|
19
|
+
let KEYCODE_TAB = 9
|
|
20
|
+
|
|
21
|
+
element.addEventListener('keydown', function (event) {
|
|
22
|
+
let { key, keyCode, shiftKey } = event
|
|
23
|
+
|
|
24
|
+
var isTabPressed = key === 'Tab' || keyCode === KEYCODE_TAB
|
|
25
|
+
|
|
26
|
+
if (!isTabPressed) return
|
|
27
|
+
|
|
28
|
+
if (shiftKey) {
|
|
29
|
+
if (document.activeElement === firstFocusableEl) {
|
|
30
|
+
lastFocusableEl.focus()
|
|
31
|
+
event.preventDefault()
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
if (document.activeElement === lastFocusableEl) {
|
|
35
|
+
firstFocusableEl.focus()
|
|
36
|
+
event.preventDefault()
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
}
|
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Logs
|
|
3
|
-
* Uses `util.inspect` to avoid truncation of complex or deeply nested structures.
|
|
2
|
+
* Logs a value to the console as pretty-printed JSON.
|
|
4
3
|
*
|
|
5
|
-
* @param {*} target - The value to
|
|
4
|
+
* @param {*} target - The value to log.
|
|
6
5
|
* @returns {void}
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* logObject({ complicated: 'object', with: { child: 'values' } })
|
|
10
6
|
*/
|
|
11
7
|
|
|
12
|
-
import util from 'util'
|
|
13
|
-
|
|
14
8
|
export default function (target) {
|
|
15
|
-
|
|
16
|
-
console.log(util.inspect(target, options))
|
|
9
|
+
return console.log(JSON.stringify(target, null, 2))
|
|
17
10
|
}
|
package/scripts/helpers.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import compareArrays from '#helpers/compareArrays'
|
|
2
|
+
import constrainTabbing from '#helpers/constrainTabbing'
|
|
2
3
|
import formatKebabCase from '#helpers/formatKebabCase'
|
|
3
4
|
import logObject from '#helpers/logObject'
|
|
4
5
|
|
|
5
|
-
export { compareArrays, formatKebabCase, logObject }
|
|
6
|
+
export { compareArrays, constrainTabbing, formatKebabCase, logObject }
|
package/scss/_atomic.scss
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
@use "atomic/min-widths";
|
|
10
10
|
@use "atomic/paddings";
|
|
11
11
|
@use "atomic/text-aligns";
|
|
12
|
+
@use "atomic/widths";
|
|
12
13
|
|
|
13
14
|
.border-radius-lg {
|
|
14
15
|
border-radius: var(--border-radius-lg);
|
|
@@ -48,4 +49,8 @@
|
|
|
48
49
|
|
|
49
50
|
.display-inline-block {
|
|
50
51
|
display: inline-block;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.word-wrap-break-word {
|
|
55
|
+
word-wrap: break-word;
|
|
51
56
|
}
|
|
@@ -23,14 +23,14 @@ fieldset,
|
|
|
23
23
|
|
|
24
24
|
@include small-up {
|
|
25
25
|
.fieldset.table {
|
|
26
|
-
grid-template-columns: auto calc(var(--width-column) * 2);
|
|
27
26
|
margin-top: var(--margin-sm);
|
|
28
27
|
border-radius: 0;
|
|
29
|
-
display:
|
|
28
|
+
display: flex;
|
|
30
29
|
padding: 0;
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
.fieldset .wrap-legend {
|
|
33
|
+
width: stretch;
|
|
34
34
|
margin-top: 0;
|
|
35
35
|
}
|
|
36
36
|
|
package/scss/_br-form-radio.scss
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
@use "mixins/input" as *;
|
|
2
|
+
@use "mixins/breakpoints" as *;
|
|
2
3
|
|
|
3
|
-
.br-form-radio {
|
|
4
|
+
.br-form-radio.default {
|
|
4
5
|
@include br-form-radio;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.br-form-radio.table {
|
|
9
|
+
@include br-form-radio;
|
|
10
|
+
|
|
11
|
+
@include medium-up {
|
|
12
|
+
.br-form-label {
|
|
13
|
+
padding: var(--padding-sm);
|
|
14
|
+
border-radius: 50%;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.label-text {
|
|
18
|
+
display: none;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
5
21
|
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
@use "mixins/breakpoints" as *;
|
|
2
|
+
@use "mixins/br-wrap" as *;
|
|
3
|
+
|
|
4
|
+
@mixin br-table-cell--default {
|
|
5
|
+
@include medium-up {
|
|
6
|
+
padding: var(--padding-md);
|
|
7
|
+
|
|
8
|
+
&:not(:first-child) {
|
|
9
|
+
border-left-color: var(--color-black-25-lighten);
|
|
10
|
+
border-left-width: var(--border-width-sm);
|
|
11
|
+
border-left-style: solid;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
&.align-right {
|
|
15
|
+
text-align: right;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
&.align-center {
|
|
19
|
+
text-align: center;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
&:not(.width-stretch) {
|
|
23
|
+
flex-shrink: 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
>label {
|
|
27
|
+
display: none;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@include medium-down {
|
|
32
|
+
margin: var(--margin-sm);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@mixin br-table-cell--radio {
|
|
37
|
+
@include br-table-cell--default;
|
|
38
|
+
|
|
39
|
+
@include medium-down {
|
|
40
|
+
&:not(.width-stretch) {
|
|
41
|
+
display: inline-block;
|
|
42
|
+
width: initial;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@mixin br-table-cell--returns {
|
|
48
|
+
@include br-table-cell--default;
|
|
49
|
+
|
|
50
|
+
@include medium-up {
|
|
51
|
+
padding: 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@include medium-down {
|
|
55
|
+
border-bottom-color: var(--color-black-25-lighten);
|
|
56
|
+
border-bottom-width: var(--border-width-sm);
|
|
57
|
+
border-bottom-style: dashed;
|
|
58
|
+
margin-right: -0.5rem;
|
|
59
|
+
margin-left: -0.5rem;
|
|
60
|
+
margin-bottom: 1rem;
|
|
61
|
+
margin-top: -0.5rem;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.br-table-cell.default {
|
|
66
|
+
@include br-table-cell--default;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.br-table-cell.radio {
|
|
70
|
+
@include br-table-cell--radio;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.br-table-cell.returns {
|
|
74
|
+
@include br-table-cell--returns;
|
|
75
|
+
}
|
|
@@ -3,58 +3,12 @@
|
|
|
3
3
|
.br-table-header {
|
|
4
4
|
border-color: var(--color-black-25-lighten);
|
|
5
5
|
border-width: var(--border-width-sm);
|
|
6
|
-
margin-bottom: var(--margin-
|
|
6
|
+
margin-bottom: var(--margin-md);
|
|
7
7
|
border-style: solid;
|
|
8
8
|
display: none;
|
|
9
9
|
|
|
10
|
-
@include
|
|
10
|
+
@include medium-up {
|
|
11
11
|
background-color: var(--color-black-5-lighten);
|
|
12
|
-
|
|
13
|
-
display: grid;
|
|
12
|
+
display: flex;
|
|
14
13
|
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
.br-table-header-title {
|
|
18
|
-
padding: var(--padding-md);
|
|
19
|
-
font-weight: bold;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.br-table-header-title+.br-table-header-title {
|
|
23
|
-
border-left-color: var(--color-black-25-lighten);
|
|
24
|
-
border-left-width: var(--border-width-sm);
|
|
25
|
-
border-left-style: solid;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
.br-table-header-title.yes,
|
|
29
|
-
.br-table-header-title.no {
|
|
30
|
-
text-align: center;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
.br-table-rows {
|
|
34
|
-
list-style: none;
|
|
35
|
-
padding: 0;
|
|
36
|
-
margin: 0;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.br-table-row {
|
|
40
|
-
border-color: var(--color-black-25-lighten);
|
|
41
|
-
border-width: var(--border-width-sm);
|
|
42
|
-
border-style: solid;
|
|
43
|
-
|
|
44
|
-
@include small-up {
|
|
45
|
-
grid-template-columns: auto repeat(2, 5rem);
|
|
46
|
-
display: grid;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
.br-table-row div {
|
|
51
|
-
border-color: var(--color-black-25-lighten);
|
|
52
|
-
border-width: var(--border-width-sm);
|
|
53
|
-
padding: var(--padding-md);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
.br-table-row div+div {
|
|
57
|
-
border-left-color: var(--color-black-25-lighten);
|
|
58
|
-
border-left-width: var(--border-width-sm);
|
|
59
|
-
border-left-style: solid;
|
|
60
14
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
@use "mixins/breakpoints" as *;
|
|
2
|
+
|
|
3
|
+
@mixin br-table-row--default {
|
|
4
|
+
border-color: var(--color-black-25-lighten);
|
|
5
|
+
border-width: var(--border-width-sm);
|
|
6
|
+
border-style: solid;
|
|
7
|
+
|
|
8
|
+
&:not(:last-child) {
|
|
9
|
+
margin-bottom: var(--margin-md);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@include medium-up {
|
|
13
|
+
display: flex;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@include medium-down {
|
|
17
|
+
border-radius: var(--border-radius-lg);
|
|
18
|
+
padding: var(--padding-sm);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.br-table-row {
|
|
23
|
+
@include br-table-row--default;
|
|
24
|
+
}
|
package/scss/_variables.scss
CHANGED
|
@@ -344,6 +344,7 @@
|
|
|
344
344
|
--line-height-xs: 1;
|
|
345
345
|
--line-height-sm: 1.15;
|
|
346
346
|
--line-height-md: 1.35;
|
|
347
|
+
--line-height-lg: 1.5;
|
|
347
348
|
|
|
348
349
|
// Fixed line height for button/menu items (`38px`).
|
|
349
350
|
--line-height-button-menu: 2.375rem;
|
|
@@ -432,8 +433,8 @@
|
|
|
432
433
|
--width-icon: 10rem;
|
|
433
434
|
// Title column width (`320px`).
|
|
434
435
|
--width-title: 20rem;
|
|
435
|
-
// Extra-small layout max-width (`
|
|
436
|
-
--width-layout-xs:
|
|
436
|
+
// Extra-small layout max-width (`400px`).
|
|
437
|
+
--width-layout-xs: 25rem;
|
|
437
438
|
// Small layout max-width (`800px`).
|
|
438
439
|
--width-layout-sm: 50rem;
|
|
439
440
|
// Medium layout max-width (`960px`).
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@use "../mixins/font-size" as *;
|
|
2
|
+
|
|
1
3
|
$iterations: (
|
|
2
4
|
"lg": var(--font-size-lg),
|
|
3
5
|
"h1": var(--font-size-h1),
|
|
@@ -12,4 +14,8 @@ $iterations: (
|
|
|
12
14
|
.font-size-#{$name} {
|
|
13
15
|
font-size: #{$value};
|
|
14
16
|
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.font-size-subtitle {
|
|
20
|
+
@include font-size-subtitle;
|
|
15
21
|
}
|
|
@@ -20,4 +20,16 @@ $iterations: (
|
|
|
20
20
|
#{$margin}: #{$value}rem;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@each $name, $value in $iterations {
|
|
26
|
+
.margin-top-bottom-#{$name} {
|
|
27
|
+
margin-bottom: #{$value}rem;
|
|
28
|
+
margin-top: #{$value}rem;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.margin-left-right-#{$name} {
|
|
32
|
+
margin-right: #{$value}rem;
|
|
33
|
+
margin-left: #{$value}rem;
|
|
34
|
+
}
|
|
23
35
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
$iterations: (
|
|
2
|
+
"0": 0,
|
|
3
|
+
"0-5": 0.5,
|
|
4
|
+
"1": 1,
|
|
5
|
+
"1-5": 1.5,
|
|
6
|
+
"2": 2,
|
|
7
|
+
"2-5": 2.5,
|
|
8
|
+
"3": 3,
|
|
9
|
+
"3-5": 3.5,
|
|
10
|
+
"4": 4,
|
|
11
|
+
"4-5": 4.5,
|
|
12
|
+
"5": 5,
|
|
13
|
+
"5-5": 5.5,
|
|
14
|
+
"6": 6,
|
|
15
|
+
"6-5": 6.5,
|
|
16
|
+
"7": 7,
|
|
17
|
+
"7-5": 7.5,
|
|
18
|
+
"8": 8,
|
|
19
|
+
"8-5": 8.5,
|
|
20
|
+
"9": 9,
|
|
21
|
+
"9-5": 9.5,
|
|
22
|
+
"10": 10,
|
|
23
|
+
"10-5": 10.5,
|
|
24
|
+
"11": 11,
|
|
25
|
+
"11-5": 11.5,
|
|
26
|
+
"12": 12,
|
|
27
|
+
"12-5": 12.5,
|
|
28
|
+
"13": 13,
|
|
29
|
+
"13-5": 13.5,
|
|
30
|
+
"14": 14,
|
|
31
|
+
"14-5": 14.5,
|
|
32
|
+
"15": 15,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
@each $name, $value in $iterations {
|
|
36
|
+
.width-#{$name} {
|
|
37
|
+
width: #{$value}rem;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.width-stretch {
|
|
42
|
+
width: stretch;
|
|
43
|
+
}
|
package/scss/index.scss
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
@use "br-form-checkbox";
|
|
9
9
|
@use "br-form-edit";
|
|
10
10
|
@use "br-form-fieldset";
|
|
11
|
+
@use "br-form-label";
|
|
11
12
|
@use "br-form-radio";
|
|
12
13
|
@use "br-form-row";
|
|
13
14
|
@use "br-form-textarea";
|
|
@@ -21,7 +22,9 @@
|
|
|
21
22
|
@use "br-promo";
|
|
22
23
|
@use "br-select";
|
|
23
24
|
@use "br-skiplink";
|
|
25
|
+
@use "br-table-cell";
|
|
24
26
|
@use "br-table-header";
|
|
27
|
+
@use "br-table-row";
|
|
25
28
|
@use "br-wrap";
|
|
26
29
|
|
|
27
30
|
@use "city-of-london";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
@use "../mixins/breakpoints" as *;
|
|
2
|
+
@use "../mixins/font-size" as *;
|
|
2
3
|
@use "card/default" as *;
|
|
3
4
|
@use "card/inline" as *;
|
|
4
5
|
@use "card/membership" as *;
|
|
@@ -62,11 +63,7 @@
|
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
@mixin br-card-subtitle {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
@include medium-up {
|
|
68
|
-
font-size: var(--font-size-h4);
|
|
69
|
-
}
|
|
66
|
+
@include font-size-subtitle;
|
|
70
67
|
}
|
|
71
68
|
|
|
72
69
|
@mixin br-card--body {
|
|
@@ -114,6 +111,6 @@
|
|
|
114
111
|
|
|
115
112
|
@mixin br-card-text {
|
|
116
113
|
+.br-card-text {
|
|
117
|
-
margin-top: var(--margin-
|
|
114
|
+
margin-top: var(--margin-sm);
|
|
118
115
|
}
|
|
119
116
|
}
|
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
@mixin br-form-radio--input {
|
|
16
16
|
cursor: pointer;
|
|
17
17
|
|
|
18
|
-
&:focus {
|
|
18
|
+
&:focus-visible {
|
|
19
19
|
outline-color: var(--color-black-25-lighten);
|
|
20
20
|
outline-offset: var(--outline-offset-lg);
|
|
21
21
|
outline-width: var(--border-width-sm);
|
|
22
22
|
outline-style: dashed;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
&:checked:focus {
|
|
25
|
+
&:checked:focus-visible {
|
|
26
26
|
@include br-form-radio--input-colors;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
cursor: pointer;
|
|
85
85
|
|
|
86
86
|
&:hover,
|
|
87
|
-
&:has(input:focus) {
|
|
87
|
+
&:has(input:focus-visible) {
|
|
88
88
|
@include br-form-radio-label--disabled;
|
|
89
89
|
@include br-form-radio-label--hover;
|
|
90
90
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
@use "../mixins/breakpoints" as *;
|
|
2
2
|
|
|
3
|
+
$sizes: xs, sm, md, lg;
|
|
4
|
+
|
|
3
5
|
@mixin br-wrap--default {
|
|
4
6
|
max-width: var(--width-layout-sm);
|
|
5
7
|
margin-right: auto;
|
|
@@ -17,10 +19,14 @@
|
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
@mixin br-wrap--cluster {
|
|
20
|
-
|
|
22
|
+
@each $size in $sizes {
|
|
23
|
+
&.size-#{$size} {
|
|
24
|
+
margin: var(--margin-wrap-#{$size});
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
|
|
26
|
+
>* {
|
|
27
|
+
margin: var(--margin-#{$size});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
24
30
|
}
|
|
25
31
|
|
|
26
32
|
&.align-middle>* {
|
|
@@ -34,8 +40,7 @@
|
|
|
34
40
|
|
|
35
41
|
@mixin br-wrap--preferences {
|
|
36
42
|
@include small-up {
|
|
37
|
-
|
|
38
|
-
display: grid;
|
|
43
|
+
display: flex;
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
@include small-down {
|
|
@@ -46,21 +51,19 @@
|
|
|
46
51
|
@mixin br-wrap--orders {
|
|
47
52
|
@include br-wrap--cluster;
|
|
48
53
|
|
|
49
|
-
$
|
|
54
|
+
@each $size in $sizes {
|
|
55
|
+
$margin: calc(var(--margin-#{$size}) * 2);
|
|
50
56
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
@include medium-up {
|
|
58
|
-
>* {
|
|
59
|
-
width: calc(50% - $margin);
|
|
60
|
-
}
|
|
57
|
+
&.size-#{$size} {
|
|
58
|
+
>* {
|
|
59
|
+
@include medium-down {
|
|
60
|
+
width: calc(100% - $margin);
|
|
61
|
+
}
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
@include medium-up {
|
|
64
|
+
width: calc(50% - $margin);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
64
67
|
}
|
|
65
68
|
}
|
|
66
69
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
@use "../../../mixins/buttons/outline" as *;
|
|
2
|
+
@use "../../../mixins/buttons/slim" as *;
|
|
2
3
|
|
|
3
4
|
$iterations: (
|
|
4
5
|
"member": var(--color-brand-membership),
|
|
@@ -12,6 +13,7 @@ $iterations: (
|
|
|
12
13
|
|
|
13
14
|
@mixin btn-renew-membership {
|
|
14
15
|
@include outline-button($color: white, $background: transparent);
|
|
16
|
+
@include btn-slim;
|
|
15
17
|
|
|
16
18
|
&:focus,
|
|
17
19
|
&:hover {
|
package/scss/mixins/index.scss
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@use "../../mixins/breakpoints" as *;
|
|
2
|
+
|
|
1
3
|
@mixin br-form-checkbox--input-colors {
|
|
2
4
|
&:not(.error):not(.success) {
|
|
3
5
|
outline-color: var(--color-status-neutral);
|
|
@@ -13,14 +15,14 @@
|
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
@mixin br-form-checkbox--input {
|
|
16
|
-
&:focus {
|
|
18
|
+
&:focus-visible {
|
|
17
19
|
outline-color: var(--color-black-50-lighten);
|
|
18
20
|
outline-offset: var(--outline-offset-lg);
|
|
19
21
|
outline-width: var(--border-width-sm);
|
|
20
22
|
outline-style: dashed;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
&:checked:focus {
|
|
25
|
+
&:checked:focus-visible {
|
|
24
26
|
@include br-form-checkbox--input-colors;
|
|
25
27
|
}
|
|
26
28
|
}
|
|
@@ -79,11 +81,26 @@
|
|
|
79
81
|
}
|
|
80
82
|
}
|
|
81
83
|
|
|
84
|
+
&.returns {
|
|
85
|
+
border-bottom-right-radius: 0;
|
|
86
|
+
border-bottom-left-radius: 0;
|
|
87
|
+
border-width: 0;
|
|
88
|
+
|
|
89
|
+
@include medium-up {
|
|
90
|
+
border-top-right-radius: 0;
|
|
91
|
+
border-top-left-radius: 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@include medium-down {
|
|
95
|
+
padding: var(--padding-lg);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
82
99
|
&:not(.disabled) {
|
|
83
100
|
cursor: pointer;
|
|
84
101
|
|
|
85
102
|
&:hover,
|
|
86
|
-
&:has(input:focus) {
|
|
103
|
+
&:has(input:focus-visible) {
|
|
87
104
|
@include br-form-checkbox-label--disabled;
|
|
88
105
|
@include br-form-checkbox-label--hover;
|
|
89
106
|
}
|
package/animations/confirm.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import gsap from 'gsap'
|
|
2
|
-
|
|
3
|
-
/** @type {gsap.TweenVars} Fade-in vars: animates element from transparent with a short delay */
|
|
4
|
-
const fadeIn = {
|
|
5
|
-
duration: 0.3,
|
|
6
|
-
opacity: 0,
|
|
7
|
-
delay: 0.3,
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/** @type {gsap.TweenVars} Explode vars: scales element up and fades it out */
|
|
11
|
-
const explode = {
|
|
12
|
-
ease: 'power1.out',
|
|
13
|
-
opacity: 0,
|
|
14
|
-
scale: 1.5,
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/** @type {gsap.TimelineVars} Default timeline settings shared across all confirm animations */
|
|
18
|
-
const defaults = {
|
|
19
|
-
duration: 0.6,
|
|
20
|
-
ease: 'power1.in',
|
|
21
|
-
transformOrigin: 'center',
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Animates the email confirmation card.
|
|
26
|
-
* Fades in the title, draws the envelope outline and fold SVG paths,
|
|
27
|
-
* explodes a cloned title, then slides in the arrow.
|
|
28
|
-
*/
|
|
29
|
-
export const animateEmail = () => {
|
|
30
|
-
const query = (target) => document.querySelector(`.card[email] ${target}`)
|
|
31
|
-
const title = query('.card-title')
|
|
32
|
-
const outline = query('.outline')
|
|
33
|
-
const arrow = query('.arrow')
|
|
34
|
-
const fold = query('.fold')
|
|
35
|
-
const tl = gsap.timeline({ defaults })
|
|
36
|
-
|
|
37
|
-
const clone = title.cloneNode(true)
|
|
38
|
-
clone.classList.add('clone')
|
|
39
|
-
title.after(clone)
|
|
40
|
-
|
|
41
|
-
tl.set(arrow, { opacity: 0 }).from(title, fadeIn).set(clone, { opacity: 0.4 }).from(outline, { drawSVG: '0%' }, 'start').from(fold, { drawSVG: '0%', duration: 0.3 }, 'start').to(clone, explode, 'start').set(arrow, { opacity: 1 }).from(arrow, { x: -6, ease: 'power1.out' })
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Animates the done confirmation card.
|
|
46
|
-
* Fades in the title, draws the circle outline and tick SVG paths,
|
|
47
|
-
* and explodes a cloned title.
|
|
48
|
-
*/
|
|
49
|
-
export const animateDone = () => {
|
|
50
|
-
const query = (target) => document.querySelector(`.card[done] ${target}`)
|
|
51
|
-
const title = query('.card-title')
|
|
52
|
-
const outline = query('.outline')
|
|
53
|
-
const tick = query('.tick')
|
|
54
|
-
const tl = gsap.timeline({ defaults })
|
|
55
|
-
|
|
56
|
-
const clone = title.cloneNode(true)
|
|
57
|
-
clone.classList.add('clone')
|
|
58
|
-
title.after(clone)
|
|
59
|
-
|
|
60
|
-
tl.from(title, fadeIn).set(clone, { opacity: 0.4 }).from(outline, { drawSVG: '0%' }, 'start').from(tick, { drawSVG: '0%', duration: 0.3 }, 'start+=0.3').to(clone, explode, 'start')
|
|
61
|
-
}
|