Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions packages/dialtone-css/lib/build/less/components/notice.less
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@
box-shadow: var(--notice-box-shadow);
}

.d-toast-alternate {
--notice-alternate-border: var(--dt-size-100) solid;
--notice-alternate-border-color: var(--dt-color-border-subtle);

border: var(--notice-alternate-border);
border-color: var(--notice-alternate-border-color);
}

// ============================================================================
// $ NOTICE AREAS
// ============================================================================
Expand Down Expand Up @@ -122,6 +130,10 @@
}
}

.d-toast--failure {
--notice-alternate-border-color: var(--dt-color-border-critical-subtle);
}

// $$ INFO
// ----------------------------------------------------------------------------
.d-notice--info,
Expand Down Expand Up @@ -154,6 +166,10 @@
}
}

.d-toast--positive {
--notice-alternate-border-color: var(--dt-color-border-success-subtle);
}

// $$ WARNING
// ----------------------------------------------------------------------------
.d-notice--warning,
Expand All @@ -170,6 +186,29 @@
}
}

.d-toast--neutral {
--notice-alternate-border-color: var(--dt-color-border-subtle);
}

// $$ ASSIST
// ----------------------------------------------------------------------------
.d-toast--assist {
--notice-alternate-border-color: var(--dt-color-border-accent);
}

// $$ PLAYBOOK
// ----------------------------------------------------------------------------
.d-toast--playbook {
--notice-alternate-border-color: var(--dt-color-border-accent);
}

// $$ CHAT
// ----------------------------------------------------------------------------
.d-toast--chat {
--notice-alternate-border-color: var(--dt-color-border-subtle);
}


// $$ TRUNCATE TEXT
// ----------------------------------------------------------------------------
.d-notice.d-notice--truncate {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const NOTICE_KINDS = ['base', 'error', 'info', 'success', 'warning'];
export const NOTICE_KINDS = ['base', 'error', 'info', 'success', 'warning', 'assist', 'playbook', 'chat', 'system'];
export const NOTICE_ROLES = ['alert', 'alertdialog', 'status'];

export default {
Expand Down
10 changes: 10 additions & 0 deletions packages/dialtone-vue2/components/notice/notice_icon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import {
DtIconAlertTriangle,
DtIconAlertCircle,
DtIconBell,
DtIconDialpadSparkle,
DtIconMessage,
DtIconNotes,
} from '@dialpad/dialtone-icons/vue2';
import { NOTICE_KINDS } from './notice_constants.js';

Expand All @@ -30,6 +33,10 @@ const kindToIcon = new Map([
['warning', DtIconAlertTriangle],
['error', DtIconAlertCircle],
['base', DtIconBell],
['assist', DtIconDialpadSparkle],
['chat', DtIconMessage],
['playbook', DtIconNotes],
['system', DtIconInfo],
]);

export default {
Expand All @@ -41,6 +48,9 @@ export default {
DtIconAlertTriangle,
DtIconAlertCircle,
DtIconBell,
DtIconDialpadSparkle,
DtIconMessage,
DtIconNotes,
},

props: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
<!-- eslint-disable vue/no-bare-strings-in-template -->
<!-- stub for the new alternate toast layout -->
<template>
<div
v-if="isShown"
:class="[
'd-toast',
'd-toast-alternate',
kindClass,
]"
data-qa="dt-toast"
:aria-hidden="(!isShown).toString()"
>
<div class="d-toast__dialog">
<dt-notice-icon
v-if="!hideIcon"
:kind="kind"
v-on="$listeners"
>
<!-- @slot Slot for custom icon -->
<slot name="icon" />
</dt-notice-icon>
<div>
<p> {{ kind }}</p>
</div>
<div>
{{ getCurrentTime() }}
</div>
</div>
</div>
</template>

<script>
import utils from '@/common/utils';
import SrOnlyCloseButtonMixin from '@/common/mixins/sr_only_close_button';
import { DtNoticeIcon } from '@/components/notice';
import { TOAST_ROLES } from '../toast_constants.js';
export default {
name: 'ToastLayoutAlternate',

components: {
DtNoticeIcon,
},

mixins: [SrOnlyCloseButtonMixin],

props: {
isShown: {
type: Boolean,
default: false,
},

/**
* Sets an ID on the title element of the component. Useful for aria-describedby
* or aria-labelledby or any other reason you may need an id to refer to the title.
*/
titleId: {
type: String,
default () { return utils.getUniqueString(); },
},

/**
* Sets an ID on the content element of the component. Useful for aria-describedby
* or aria-labelledby or any other reason you may need an id to refer to the content.
*/
contentId: {
type: String,
default () { return utils.getUniqueString(); },
},

/**
* Title header of the toast. This can be left blank to remove the title from the toast entirely.
*/
title: {
type: String,
default: '',
},

/**
* Message of the toast. Overridden by default slot.
*/
message: {
type: String,
default: '',
},

/**
* Provides a role for the toast. 'status' is used by default to communicate a message. 'alert' is used to
* communicate an important message like an error that does not contain any interactive elements.
* @values status, alert
*/
role: {
type: String,
default: 'status',
validator: (role) => {
return TOAST_ROLES.includes(role);
},
},

/**
* Severity level of the toast, sets the icon and background
* @values base, success, error, gradient
*/
kind: {
type: String,
default: 'base',
},

/**
* Used in scenarios where the message needs to visually dominate the screen.
* @values true, false
*/
important: {
type: Boolean,
default: false,
},

/**
* Props for the toast close button.
*/
closeButtonProps: {
type: Object,
default: () => ({}),
},

/**
* Hides the close button from the toast
* @values true, false
*/
hideClose: {
type: Boolean,
default: false,
},

/**
* Hides the icon from the notice
* @values true, false
*/
hideIcon: {
type: Boolean,
default: false,
},

/**
* Hides the action from the notice
* @values true, false
*/
hideAction: {
type: Boolean,
default: false,
},
},

computed: {
kindClass () {
const kindClasses = {
assist: 'd-toast--assist',
chat: 'd-toast--chat',
playbook: 'd-toast--playbook',
success: 'd-toast--positive',
error: 'd-toast--failure',
warning: 'd-toast--neutral',
};

return kindClasses[this.kind];
},
},

methods: {
getCurrentTime () {
const time = new Date();
let hours = time.getHours();
const minutes = time.getMinutes().toString().padStart(2, '0');
const amPm = hours >= 12 ? 'pm' : 'am';

// Convert to 12-hour format
hours = (hours % 12) || 12; // Convert 0 to 12 for midnight
hours = hours.toString().padStart(2, '0'); // Ensure two digits for hours

return `${hours}:${minutes}${amPm}`;
},
},
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { createLocalVue } from '@vue/test-utils';
import ToastLayoutDefault from './toast_layout_default.vue';

const testContext = {};

describe('Toast Default Layout Tests', () => {
beforeAll(() => {
testContext.localVue = createLocalVue();
});

describe('Validation Tests', () => {
describe('Role Validator', () => {
const MOCK_PROP = ToastLayoutDefault.props.role;

describe('When provided role is in TOAST_ROLES', () => {
it('passes custom prop validation', () => {
expect(MOCK_PROP.validator(MOCK_PROP.default)).toBe(true);
});
});

describe('When provided role is not in TOAST_ROLES', () => {
it('fails custom prop validation', () => {
expect(MOCK_PROP.validator(`INVALID_ROLE`)).toBe(false);
});
});
});

describe('Kind Validator', () => {
const MOCK_PROP = ToastLayoutDefault.props.kind;

describe('When provided kind is in NOTICE_KINDS', () => {
it('passes custom prop validation', () => {
expect(MOCK_PROP.validator(MOCK_PROP.default)).toBe(true);
});
});

describe('When provided kind is not in NOTICE_KINDS', () => {
it('fails custom prop validation', () => {
expect(MOCK_PROP.validator(`INVALID_KIND`)).toBe(false);
});
});
});
});
});
Loading
Loading