From 94572f6ff255ebd66dc3714f5a4ff197259b8e5b Mon Sep 17 00:00:00 2001 From: "iamgabrielsoft@gmail.com" Date: Thu, 4 Jul 2024 17:19:29 +0100 Subject: [PATCH 01/45] alert toast --- codex-ui/dev/Playground.vue | 13 ++ codex-ui/dev/pages/components/Alert.vue | 7 + codex-ui/dev/routes.ts | 6 + codex-ui/src/vue/components/alert/Alert.vue | 149 ++++++++++++++++++++ codex-ui/src/vue/components/alert/index.ts | 3 + codex-ui/src/vue/index.ts | 1 + 6 files changed, 179 insertions(+) create mode 100644 codex-ui/dev/pages/components/Alert.vue create mode 100644 codex-ui/src/vue/components/alert/Alert.vue create mode 100644 codex-ui/src/vue/components/alert/index.ts diff --git a/codex-ui/dev/Playground.vue b/codex-ui/dev/Playground.vue index 13dd09cf..919df490 100644 --- a/codex-ui/dev/Playground.vue +++ b/codex-ui/dev/Playground.vue @@ -192,6 +192,12 @@ const pages = computed(() => [ onActivate: () => router.push('/components/editor'), isActive: route.path === '/components/editor', }, + + { + title: 'Alert', + onActivate: () => router.push('/components/alert'), + isActive: route.path === '/components/alert' + } ], }, ]); @@ -199,9 +205,15 @@ const pages = computed(() => [ \ No newline at end of file diff --git a/codex-ui/src/vue/components/alert/index.ts b/codex-ui/src/vue/components/alert/index.ts new file mode 100644 index 00000000..6cdbf850 --- /dev/null +++ b/codex-ui/src/vue/components/alert/index.ts @@ -0,0 +1,3 @@ +import Alert from "./Alert.vue"; + +export { Alert } \ No newline at end of file diff --git a/codex-ui/src/vue/index.ts b/codex-ui/src/vue/index.ts index c3f65749..cefdb153 100644 --- a/codex-ui/src/vue/index.ts +++ b/codex-ui/src/vue/index.ts @@ -1,3 +1,4 @@ +export * from './components/alert' export * from './components/button'; export * from './components/form'; export * from './components/heading'; From c6df9ddd5440b8f9103058129f4731914390354a Mon Sep 17 00:00:00 2001 From: "iamgabrielsoft@gmail.com" Date: Thu, 4 Jul 2024 19:22:01 +0100 Subject: [PATCH 02/45] remove alert position for now --- codex-ui/src/vue/components/alert/Alert.vue | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/codex-ui/src/vue/components/alert/Alert.vue b/codex-ui/src/vue/components/alert/Alert.vue index 9f785750..dc939235 100644 --- a/codex-ui/src/vue/components/alert/Alert.vue +++ b/codex-ui/src/vue/components/alert/Alert.vue @@ -2,8 +2,7 @@
- - + {{ message }}
@@ -22,21 +21,16 @@ const props = withDefaults( /** * message to display */ - message: string, + message?: string, /** * alert status */ type: 'success' | 'error' | 'warning' | 'default' | 'info' - /** - * where to position the alert on the screen - */ - position: 'bottom-centera' }>(), { message: '', type: 'default', - position: 'bottom-center' } ) @@ -44,7 +38,6 @@ const props = withDefaults( /** determine alert status */ const alertType = computed(() => { if(props.type === 'success'){ - console.log('succ') return 'success'; } From d439310a66040ef1dc59ff821fcfb9c2e9c55a4f Mon Sep 17 00:00:00 2001 From: "iamgabrielsoft@gmail.com" Date: Thu, 4 Jul 2024 20:01:35 +0100 Subject: [PATCH 03/45] lint file working on useToast hook --- codex-ui/dev/Playground.vue | 7 ++- codex-ui/dev/pages/components/Alert.vue | 7 ++- codex-ui/dev/pages/components/Card.vue | 4 +- codex-ui/dev/routes.ts | 2 +- codex-ui/src/vue/components/alert/Alert.vue | 60 ++++++++++----------- codex-ui/src/vue/components/row/Row.vue | 10 +++- codex-ui/src/vue/index.ts | 2 +- 7 files changed, 47 insertions(+), 45 deletions(-) diff --git a/codex-ui/dev/Playground.vue b/codex-ui/dev/Playground.vue index 919df490..f36e89e7 100644 --- a/codex-ui/dev/Playground.vue +++ b/codex-ui/dev/Playground.vue @@ -194,10 +194,10 @@ const pages = computed(() => [ }, { - title: 'Alert', + title: 'Alert', onActivate: () => router.push('/components/alert'), - isActive: route.path === '/components/alert' - } + isActive: route.path === '/components/alert', + }, ], }, ]); @@ -234,7 +234,6 @@ const pages = computed(() => [ color: var(--base--text); } - .body { padding: var(--spacing-l); display: grid; diff --git a/codex-ui/dev/pages/components/Alert.vue b/codex-ui/dev/pages/components/Alert.vue index 5160f5da..d2aa457b 100644 --- a/codex-ui/dev/pages/components/Alert.vue +++ b/codex-ui/dev/pages/components/Alert.vue @@ -1,7 +1,10 @@ \ No newline at end of file + diff --git a/codex-ui/dev/pages/components/Card.vue b/codex-ui/dev/pages/components/Card.vue index 97d1f438..8c103ec4 100644 --- a/codex-ui/dev/pages/components/Card.vue +++ b/codex-ui/dev/pages/components/Card.vue @@ -16,7 +16,7 @@ orientation="horizontal" src="https://via.placeholder.com/150" > - +

The following outlines options for alert to display

@@ -29,7 +25,56 @@
- Timeout - Visibility duration in milliseconds, set to 0 to keep toast visible + Timeout - Visibility duration in milliseconds, set timeout to keep toast visible +
+ + +
+ +
+ Success + +
+ + +
+ Error + +
+ +
+ Warning + +
+ +
+ Info + +
+ +
+ Default +
@@ -39,15 +84,15 @@ + + \ No newline at end of file From 8ebbcd56af0396a9c2684a0a5741908de9fd3af5 Mon Sep 17 00:00:00 2001 From: "iamgabrielsoft@gmail.com" Date: Thu, 1 Aug 2024 18:16:08 +0100 Subject: [PATCH 23/45] lint file --- codex-ui/dev/Playground.vue | 7 +-- codex-ui/dev/routes.ts | 2 +- codex-ui/src/vue/components/alert/Alert.vue | 67 +++++++++------------ 3 files changed, 31 insertions(+), 45 deletions(-) diff --git a/codex-ui/dev/Playground.vue b/codex-ui/dev/Playground.vue index 1ec62e0f..de44913b 100644 --- a/codex-ui/dev/Playground.vue +++ b/codex-ui/dev/Playground.vue @@ -199,10 +199,10 @@ const pages = computed(() => [ }, { - title: 'Alert', + title: 'Alert', onActivate: () => router.push('/components/alert'), - isActive: route.path === '/components/alert' - } + isActive: route.path === '/components/alert', + }, ], }, ]); @@ -239,7 +239,6 @@ const pages = computed(() => [ color: var(--base--text); } - .body { padding: var(--spacing-l); display: grid; diff --git a/codex-ui/dev/routes.ts b/codex-ui/dev/routes.ts index 36b8c92e..af8dfbf0 100644 --- a/codex-ui/dev/routes.ts +++ b/codex-ui/dev/routes.ts @@ -150,7 +150,7 @@ const routes: RouteRecordRaw[] = [ { path: '/components/alert', component: Alert as Component, - } + }, ]; export default routes; diff --git a/codex-ui/src/vue/components/alert/Alert.vue b/codex-ui/src/vue/components/alert/Alert.vue index 9f785750..f3580f2b 100644 --- a/codex-ui/src/vue/components/alert/Alert.vue +++ b/codex-ui/src/vue/components/alert/Alert.vue @@ -1,18 +1,17 @@ - - \ No newline at end of file + From 8a9b36946aad1e941c657340f43a802c1edef1e1 Mon Sep 17 00:00:00 2001 From: "iamgabrielsoft@gmail.com" Date: Thu, 4 Jul 2024 20:04:04 +0100 Subject: [PATCH 24/45] lint files --- codex-ui/src/vue/components/alert/constant.ts | 17 ++++ codex-ui/src/vue/components/alert/useToast.ts | 84 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 codex-ui/src/vue/components/alert/constant.ts create mode 100644 codex-ui/src/vue/components/alert/useToast.ts diff --git a/codex-ui/src/vue/components/alert/constant.ts b/codex-ui/src/vue/components/alert/constant.ts new file mode 100644 index 00000000..a398cf62 --- /dev/null +++ b/codex-ui/src/vue/components/alert/constant.ts @@ -0,0 +1,17 @@ +export enum ToastType { + SUCCESS = 'success', + ERROR = 'error', + WARNING = 'warning', + INFO = 'info', + DEFAULT = 'default' +}; + +export enum EVENTS { + ADD = 'add' +} + +export interface ToastInterface {}; + +export interface ToastOptions { + +} diff --git a/codex-ui/src/vue/components/alert/useToast.ts b/codex-ui/src/vue/components/alert/useToast.ts new file mode 100644 index 00000000..d889ad8c --- /dev/null +++ b/codex-ui/src/vue/components/alert/useToast.ts @@ -0,0 +1,84 @@ +import { inject } from 'vue'; +import type { ToastInterface, ToastOptions } from './constant'; +import { EVENTS, ToastType } from './constant'; + +const toastSymbolKey = Symbol('Alert'); + +type Events = { + [EVENTS.ADD]: { + id: string; + }; +}; + +type Handler = (event: Events[E]) => void; + +type HandlerList = Handler[]; +type HandlerMap = { + [E in EVENTS]?: HandlerList +}; + +/** + * + */ +class EventBus { + protected allHandlers: HandlerMap = {}; + + protected getHandlers(eventType: E) { + return (this.allHandlers[eventType]) || []; + } + + public on(eventType: E, handler: Handler) { + const handlers = this.getHandlers(eventType).push(handler); + + this.allHandlers[eventType] = handlers as unknown as EventBus['allHandlers'][E ]; + } + + public off(eventType: E, handler: Handler) { + const handlers = this.getHandlers(eventType); + + handlers.splice(handlers.indexOf(handler) >>> 0, 1); + } + + public emit(eventType: E, event: Events[E]) { + return this.getHandlers(eventType).forEach(handler => handler(event)); + } +}; + +const eventBus = new EventBus(); + +interface ToastInstance { + (option?: ToastOptions): ToastInterface; +} + +const toastId = (i: number = 0) => i++; + +/** + * + * @param eventBus + */ +const useToast = (eventBus?: EventBus) => { + if (!eventBus) { + return; + } + + const toastMethod = (type: T) => { + eventBus.emit(EVENTS.ADD, eventBus); + + return { + id: toastId(), + type, + }; + }; + + return { + success: toastMethod(ToastType.SUCCESS), + error: toastMethod(ToastType.ERROR), + info: toastMethod(ToastType.INFO), + warning: toastMethod(ToastType.WARNING), + default: toastMethod(ToastType.DEFAULT), + }; +}; + +export { + useToast +}; From 5a41e1c343a5eef5eff8a6327e539dc14be02a1f Mon Sep 17 00:00:00 2001 From: "iamgabrielsoft@gmail.com" Date: Wed, 17 Jul 2024 14:51:25 +0100 Subject: [PATCH 25/45] theme not added yet --- codex-ui/src/vue/components/alert/Alert.vue | 136 ------------------ codex-ui/src/vue/components/alert/constant.ts | 17 --- codex-ui/src/vue/components/alert/useToast.ts | 84 ----------- 3 files changed, 237 deletions(-) delete mode 100644 codex-ui/src/vue/components/alert/Alert.vue delete mode 100644 codex-ui/src/vue/components/alert/constant.ts delete mode 100644 codex-ui/src/vue/components/alert/useToast.ts diff --git a/codex-ui/src/vue/components/alert/Alert.vue b/codex-ui/src/vue/components/alert/Alert.vue deleted file mode 100644 index f3580f2b..00000000 --- a/codex-ui/src/vue/components/alert/Alert.vue +++ /dev/null @@ -1,136 +0,0 @@ - - - - - diff --git a/codex-ui/src/vue/components/alert/constant.ts b/codex-ui/src/vue/components/alert/constant.ts deleted file mode 100644 index a398cf62..00000000 --- a/codex-ui/src/vue/components/alert/constant.ts +++ /dev/null @@ -1,17 +0,0 @@ -export enum ToastType { - SUCCESS = 'success', - ERROR = 'error', - WARNING = 'warning', - INFO = 'info', - DEFAULT = 'default' -}; - -export enum EVENTS { - ADD = 'add' -} - -export interface ToastInterface {}; - -export interface ToastOptions { - -} diff --git a/codex-ui/src/vue/components/alert/useToast.ts b/codex-ui/src/vue/components/alert/useToast.ts deleted file mode 100644 index d889ad8c..00000000 --- a/codex-ui/src/vue/components/alert/useToast.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { inject } from 'vue'; -import type { ToastInterface, ToastOptions } from './constant'; -import { EVENTS, ToastType } from './constant'; - -const toastSymbolKey = Symbol('Alert'); - -type Events = { - [EVENTS.ADD]: { - id: string; - }; -}; - -type Handler = (event: Events[E]) => void; - -type HandlerList = Handler[]; -type HandlerMap = { - [E in EVENTS]?: HandlerList -}; - -/** - * - */ -class EventBus { - protected allHandlers: HandlerMap = {}; - - protected getHandlers(eventType: E) { - return (this.allHandlers[eventType]) || []; - } - - public on(eventType: E, handler: Handler) { - const handlers = this.getHandlers(eventType).push(handler); - - this.allHandlers[eventType] = handlers as unknown as EventBus['allHandlers'][E ]; - } - - public off(eventType: E, handler: Handler) { - const handlers = this.getHandlers(eventType); - - handlers.splice(handlers.indexOf(handler) >>> 0, 1); - } - - public emit(eventType: E, event: Events[E]) { - return this.getHandlers(eventType).forEach(handler => handler(event)); - } -}; - -const eventBus = new EventBus(); - -interface ToastInstance { - (option?: ToastOptions): ToastInterface; -} - -const toastId = (i: number = 0) => i++; - -/** - * - * @param eventBus - */ -const useToast = (eventBus?: EventBus) => { - if (!eventBus) { - return; - } - - const toastMethod = (type: T) => { - eventBus.emit(EVENTS.ADD, eventBus); - - return { - id: toastId(), - type, - }; - }; - - return { - success: toastMethod(ToastType.SUCCESS), - error: toastMethod(ToastType.ERROR), - info: toastMethod(ToastType.INFO), - warning: toastMethod(ToastType.WARNING), - default: toastMethod(ToastType.DEFAULT), - }; -}; - -export { - useToast -}; From 43e9d83b2fed4f41afd16707ed1b84e5656e84d3 Mon Sep 17 00:00:00 2001 From: "iamgabrielsoft@gmail.com" Date: Wed, 17 Jul 2024 15:49:49 +0100 Subject: [PATCH 26/45] check build error --- codex-ui/dev/Playground.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/codex-ui/dev/Playground.vue b/codex-ui/dev/Playground.vue index de44913b..b8074142 100644 --- a/codex-ui/dev/Playground.vue +++ b/codex-ui/dev/Playground.vue @@ -218,7 +218,6 @@ const pages = computed(() => [ width: 100%; height: 100%; overflow-x: hidden; - /* height: 100vh; */ } .header { display: grid; From 6ed401f6d58de7f104ff0c4d7c388e35fde6105b Mon Sep 17 00:00:00 2001 From: "iamgabrielsoft@gmail.com" Date: Thu, 8 Aug 2024 07:00:13 +0100 Subject: [PATCH 27/45] added theme attr to alert --- codex-ui/dev/pages/components/Alert.vue | 5 +- codex-ui/src/styles/themes/amber.pcss | 16 ---- codex-ui/src/styles/themes/crimson.pcss | 16 ---- codex-ui/src/styles/themes/graphite.pcss | 16 ---- codex-ui/src/styles/themes/grass.pcss | 16 ---- codex-ui/src/styles/themes/pure.pcss | 16 ---- codex-ui/src/styles/themes/red.pcss | 12 --- codex-ui/src/styles/themes/sky.pcss | 16 ---- codex-ui/src/styles/themes/violet.pcss | 16 ---- .../src/vue/components/alert/BaseAlert.vue | 65 +++++++++---- .../src/vue/components/alert/core/constant.ts | 3 + .../src/vue/components/alert/core/types.ts | 10 +- .../src/vue/components/alert/core/useAlert.ts | 95 ++++++++++--------- codex-ui/src/vue/components/icon/Icon.vue | 2 +- 14 files changed, 111 insertions(+), 193 deletions(-) diff --git a/codex-ui/dev/pages/components/Alert.vue b/codex-ui/dev/pages/components/Alert.vue index 3ff71ce5..de7f5e6d 100644 --- a/codex-ui/dev/pages/components/Alert.vue +++ b/codex-ui/dev/pages/components/Alert.vue @@ -23,7 +23,7 @@
- Timeout - Visibility duration in milliseconds, set timeout to keep toast visible + Timeout - visibility duration in milliseconds, set timeout to keep toast visible
@@ -86,8 +86,7 @@ const toast = useAlert; const showToast = (status: AlertType) => { toast(status, { message: 'codex', - icon: 'Check', - type: status, + icon: 'Trash', timeout: 5000, }); }; diff --git a/codex-ui/src/styles/themes/amber.pcss b/codex-ui/src/styles/themes/amber.pcss index 937e9db2..66fb3d4c 100644 --- a/codex-ui/src/styles/themes/amber.pcss +++ b/codex-ui/src/styles/themes/amber.pcss @@ -9,10 +9,6 @@ --amber--text-secondary: #90847C; --amber--text: #E4D4C8; --amber--text-solid-foreground: #FFFFFF; - --amber-alert-success: #00A64D; - --amber-alert-error: #BB393D; - --amber-alert-warning: #DE6205; - --amber-alert-info: #54617B; } [color-scheme='light'] { @@ -26,10 +22,6 @@ --amber--text-secondary: #4D463F; --amber--text: #2C2825; --amber--text-solid-foreground: #ffffff; - --amber-alert-success: #00A64D; - --amber-alert-error: #BB393D; - --amber-alert-warning: #DE6205; - --amber-alert-info: #54617B; } /** @@ -46,10 +38,6 @@ --base--text-secondary: var(--amber--text-secondary); --base--text: var(--amber--text); --base--text-solid-foreground: var(--amber--text-solid-foreground); - --base-alert-success: var(--amber-alert-success); - --base-alert-error: var(--amber-alert-error); - --base-alert-warning: var(--amber-alert-warning); - --base-alert-info: var(--amber-alert-info); } [theme-accent='amber'] { @@ -63,8 +51,4 @@ --accent--text-secondary: var(--amber--text-secondary); --accent--text: var(--amber--text); --accent--text-solid-foreground: var(--amber--text-solid-foreground); - --accent-alert-success: var(--amber-alert-success); - --accent-alert-error: var(--amber-alert-error); - --accent-alert-warning: var(--amber-alert-warning); - --accent-alert-info: var(--amber-alert-info); } diff --git a/codex-ui/src/styles/themes/crimson.pcss b/codex-ui/src/styles/themes/crimson.pcss index 61b1886e..4982f99b 100644 --- a/codex-ui/src/styles/themes/crimson.pcss +++ b/codex-ui/src/styles/themes/crimson.pcss @@ -12,10 +12,6 @@ --crimson--text-secondary: #887076; --crimson--text: #e3d1d6; --crimson--text-solid-foreground: #FFF6FA; - --crimson-alert-success: #00A64D; - --crimson-alert-error: #BB393D; - --crimson-alert-warning: #DE6205; - --crimson-alert-info: #54617B; } [color-scheme='light'] { @@ -32,10 +28,6 @@ --crimson--text-secondary: #844860; --crimson--text: #3D2230; --crimson--text-solid-foreground: #F9F9F9; - --crimson-alert-success: #00A64D; - --crimson-alert-error: #BB393D; - --crimson-alert-warning: #DE6205; - --crimson-alert-info: #54617B; } /** @@ -52,10 +44,6 @@ --base--text-secondary: var(--crimson--text-secondary); --base--text: var(--crimson--text); --base--text-solid-foreground: var(--crimson--text-solid-foreground); - --base-alert-success: var(--crimson-alert-success); - --base-alert-error: var(--crimson-alert-error); - --base-alert-warning: var(--crimson-alert-warning); - --base-alert-info: var(--crimson-alert-info); } [theme-accent='crimson'] { @@ -69,8 +57,4 @@ --accent--text-secondary: var(--crimson--text-secondary); --accent--text: var(--crimson--text); --accent--text-solid-foreground: var(--crimson--text-solid-foreground); - --accent-alert-success: var(--crimson-alert-success); - --accent-alert-error: var(--crimson-alert-error); - --accent-alert-warning: var(--crimson-alert-warning); - --accent-alert-info: var(--crimson-alert-info); } diff --git a/codex-ui/src/styles/themes/graphite.pcss b/codex-ui/src/styles/themes/graphite.pcss index 9c06a11c..54329170 100644 --- a/codex-ui/src/styles/themes/graphite.pcss +++ b/codex-ui/src/styles/themes/graphite.pcss @@ -9,10 +9,6 @@ --graphite--text-secondary: #747E88; --graphite--text: #d5d9e9; --graphite--text-solid-foreground: #F5F5F5; - --graphtite-alert-success: #00A64D; - --graphtite-alert-error: #BB393D; - --graphtite-alert-warning: #DE6205; - --graphtite-alert-info: #54617B; } [color-scheme='light'] { @@ -26,10 +22,6 @@ --graphite--text-secondary: #6C7381; --graphite--text: #202020; --graphite--text-solid-foreground: #FFFFFF; - --graphtite-alert-success: #00A64D; - --graphtite-alert-error: #BB393D; - --graphtite-alert-warning: #DE6205; - --graphtite-alert-info: #54617B; } [theme-base='graphite'] { @@ -43,10 +35,6 @@ --base--text-secondary: var(--graphite--text-secondary); --base--text: var(--graphite--text); --base--text-solid-foreground: var(--graphite--text-solid-foreground); - --base-alert-success: var(--graphtite-alert-success); - --base-alert-error: var(--graphtite-alert-error); - --base-alert-warning: var(--graphtite-alert-warning); - --base-alert-info: var(--graphtite-alert-info); } [theme-accent='graphite'] { @@ -60,8 +48,4 @@ --accent--text-secondary: var(--graphite--text-secondary); --accent--text: var(--graphite--text); --accent--text-solid-foreground: var(--graphite--text-solid-foreground); - --accent-alert-success: var(--graphtite-alert-success); - --accent-alert-error: var(--graphtite-alert-error); - --accent-alert-warning: var(--graphtite-alert-warning); - --accent-alert-info: var(--graphtite-alert-info); } diff --git a/codex-ui/src/styles/themes/grass.pcss b/codex-ui/src/styles/themes/grass.pcss index 97a49ee3..72162846 100644 --- a/codex-ui/src/styles/themes/grass.pcss +++ b/codex-ui/src/styles/themes/grass.pcss @@ -12,10 +12,6 @@ --grass--text-secondary: #729180; --grass--text: #f3fff9; --grass--text-solid-foreground: #EAFFF4; - --grass-alert-success: #00A64D; - --grass-alert-error: #BB393D; - --grass-alert-warning: #DE6205; - --grass-alert-info: #54617B; } [color-scheme='light'] { @@ -32,10 +28,6 @@ --grass--text-secondary: #7ca58f; --grass--text: #243A2E; --grass--text-solid-foreground: #E1FFE9; - --grass-alert-success: #00A64D; - --grass-alert-error: #BB393D; - --grass-alert-warning: #DE6205; - --grass-alert-info: #54617B; } /** @@ -52,10 +44,6 @@ --base--text-secondary: var(--grass--text-secondary); --base--text: var(--grass--text); --base--text-solid-foreground: var(--grass--text-solid-foreground); - --base-alert-success: var(--grass-alert-success); - --base-alert-error: var(--grass-alert-error); - --base-alert-warning: var(--grass-alert-warning); - --base-alert-info: var(--grass-alert-info); } [theme-accent='grass'] { @@ -69,8 +57,4 @@ --accent--text-secondary: var(--grass--text-secondary); --accent--text: var(--grass--text); --accent--text-solid-foreground: var(--grass--text-solid-foreground); - --accent-alert-success: var(--grass-alert-success); - --accent-alert-error: var(--grass-alert-error); - --accent-alert-warning: var(--grass-alert-warning); - --accent-alert-info: var(--grass-alert-info); } diff --git a/codex-ui/src/styles/themes/pure.pcss b/codex-ui/src/styles/themes/pure.pcss index ddd7dc1c..4546b09a 100644 --- a/codex-ui/src/styles/themes/pure.pcss +++ b/codex-ui/src/styles/themes/pure.pcss @@ -9,10 +9,6 @@ --pure--text-secondary: #828282; --pure--text: #ffffff; --pure--text-solid-foreground: #000000; - --pure-alert-success: #00A64D; - --pure-alert-error: #BB393D; - --pure-alert-warning: #DE6205; - --pure-alert-info: #54617B; } [color-scheme='light'] { @@ -26,10 +22,6 @@ --pure--text-secondary: #505050; --pure--text: #000000; --pure--text-solid-foreground: #ffffff; - --pure-alert-success: #00A64D; - --pure-alert-error: #BB393D; - --pure-alert-warning: #DE6205; - --pure-alert-info: #54617B; } /** @@ -46,10 +38,6 @@ --base--text-secondary: var(--pure--text-secondary); --base--text: var(--pure--text); --base--text-solid-foreground: var(--pure--text-solid-foreground); - --base-alert-success: var(--pure-alert-success); - --base-alert-error: var(--pure-alert-error); - --base-alert-warning: var(--pure-alert-warning); - --base-alert-info: var(--pure-alert-info); } [theme-accent='pure'] { @@ -63,8 +51,4 @@ --accent--text-secondary: var(--pure--text-secondary); --accent--text: var(--pure--text); --accent--text-solid-foreground: var(--pure--text-solid-foreground); - --accent-alert-success: var(--pure-alert-success); - --accent-alert-error: var(--pure-alert-error); - --accent-alert-warning: var(--pure-alert-warning); - --accent-alert-info: var(--pure-alert-info); } diff --git a/codex-ui/src/styles/themes/red.pcss b/codex-ui/src/styles/themes/red.pcss index 37cc1133..7858c4c8 100644 --- a/codex-ui/src/styles/themes/red.pcss +++ b/codex-ui/src/styles/themes/red.pcss @@ -12,10 +12,6 @@ --red--text-secondary: #B67E7C; --red--text: #F2DEDE; --red--text-solid-foreground: #FFE3E3; - --red-alert-success: #00A64D; - --red-alert-error: #BB393D; - --red-alert-warning: #DE6205; - --red-alert-info: #54617B; } [color-scheme='light'] { @@ -48,10 +44,6 @@ --base--text-secondary: var(--red--text-secondary); --base--text: var(--red--text); --base--text-solid-foreground: var(--red--text-solid-foreground); - --base-alert-success: var(--red-alert-success); - --base-alert-error: var(--red-alert-error); - --base-alert-warning: var(--red-alert-warning); - --base-alert-info: var(--red-alert-info); } [theme-accent='red'] { @@ -65,8 +57,4 @@ --accent--text-secondary: var(--red--text-secondary); --accent--text: var(--red--text); --accent--text-solid-foreground: var(--red--text-solid-foreground); - --accent-alert-success: var(--red-alert-success); - --accent-alert-error: var(--red-alert-error); - --accent-alert-warning: var(--red-alert-warning); - --accent-alert-info: var(--red-alert-info); } diff --git a/codex-ui/src/styles/themes/sky.pcss b/codex-ui/src/styles/themes/sky.pcss index 3074064f..57f6c42c 100644 --- a/codex-ui/src/styles/themes/sky.pcss +++ b/codex-ui/src/styles/themes/sky.pcss @@ -9,10 +9,6 @@ --sky--text-secondary: #769DCC; --sky--text: #dfe8f6; --sky--text-solid-foreground: #FFFFFF; - --sky-alert-success: #00A64D; - --sky-alert-error: #BB393D; - --sky-alert-warning: #DE6205; - --sky-alert-info: #54617B; } [color-scheme='light'] { @@ -26,10 +22,6 @@ --sky--text-secondary: #1A5192; --sky--text: #0C2A4D; --sky--text-solid-foreground: #FFFFFF; - --sky-alert-success: #00A64D; - --sky-alert-error: #BB393D; - --sky-alert-warning: #DE6205; - --sky-alert-info: #54617B; } [theme-base='sky'] { @@ -43,10 +35,6 @@ --base--text-secondary: var(--sky--text-secondary); --base--text: var(--sky--text); --base--text-solid-foreground: var(--sky--text-solid-foreground); - --base-alert-success: var(--sky-alert-success); - --base-alert-error: var(--sky-alert-error); - --base-alert-warning: var(--sky-alert-warning); - --base-alert-info: var(--sky-alert-info); } [theme-accent='sky'] { @@ -60,8 +48,4 @@ --accent--text-secondary: var(--sky--text-secondary); --accent--text: var(--sky--text); --accent--text-solid-foreground: var(--sky--text-solid-foreground); - --accent-alert-success: var(--sky-alert-success); - --accent-alert-error: var(--sky-alert-error); - --accent-alert-warning: var(--sky-alert-warning); - --accent-alert-info: var(--sky-alert-info); } diff --git a/codex-ui/src/styles/themes/violet.pcss b/codex-ui/src/styles/themes/violet.pcss index fed9c440..00c042ad 100644 --- a/codex-ui/src/styles/themes/violet.pcss +++ b/codex-ui/src/styles/themes/violet.pcss @@ -12,10 +12,6 @@ --violet--text-secondary: #a389bd; --violet--text: #d9cee5; --violet--text-solid-foreground: #f2f1f4; - --violet-alert-success: #00A64D; - --violet-alert-error: #BB393D; - --violet-alert-warning: #DE6205; - --violet-alert-info: #54617B; } [color-scheme='light'] { @@ -32,10 +28,6 @@ --violet--text-secondary: #6C3A9E; --violet--text: #341554; --violet--text-solid-foreground: #FAF8FF; - --violet-alert-success: #00A64D; - --violet-alert-error: #BB393D; - --violet-alert-warning: #DE6205; - --violet-alert-info: #54617B; } /** @@ -52,10 +44,6 @@ --base--text-secondary: var(--violet--text-secondary); --base--text: var(--violet--text); --base--text-solid-foreground: var(--violet--text-solid-foreground); - --base-alert-success: var(--violet-alert-success); - --base-alert-error: var(--violet-alert-error); - --base-alert-warning: var(--violet-alert-warning); - --base-alert-info: var(--violet-alert-info); } [theme-accent='violet'] { @@ -69,8 +57,4 @@ --accent--text-secondary: var(--violet--text-secondary); --accent--text: var(--violet--text); --accent--text-solid-foreground: var(--violet--text-solid-foreground); - --accent-alert-success: var(--violet-alert-success); - --accent-alert-error: var(--violet-alert-error); - --accent-alert-warning: var(--violet-alert-warning); - --accent-alert-info: var(--violet-alert-info); } diff --git a/codex-ui/src/vue/components/alert/BaseAlert.vue b/codex-ui/src/vue/components/alert/BaseAlert.vue index 19510c60..892a70cb 100644 --- a/codex-ui/src/vue/components/alert/BaseAlert.vue +++ b/codex-ui/src/vue/components/alert/BaseAlert.vue @@ -1,19 +1,17 @@ @@ -35,9 +33,9 @@ const props = withDefaults(defineProps(), { }); /** - * compute serveral style type + * computed style */ -const computedStyle = computed(() => { +const computedStyle = computed(() => { if (props.type === 'success') { return 'success'; } @@ -54,9 +52,36 @@ const computedStyle = computed(() => { return 'info'; } - return 'default'; + if (props.type === 'default') { + return 'default'; + } + + return null; }); +/** + * + * computed theme + */ +const computedTheme = computed(() => { + if (props.type === 'success') { + return 'grass'; + } + + if (props.type === 'error') { + return 'red'; + } + + if (props.type === 'warning') { + return 'amber'; + } + + if (props.type === 'info') { + return 'graphite'; + } + + return ''; +}); diff --git a/codex-ui/src/vue/components/alert/core/constant.ts b/codex-ui/src/vue/components/alert/core/constant.ts index c0c9e66d..8f3f3e1b 100644 --- a/codex-ui/src/vue/components/alert/core/constant.ts +++ b/codex-ui/src/vue/components/alert/core/constant.ts @@ -5,6 +5,9 @@ import { POSITION } from './types'; */ const getId = (i => () => i++)(0); +/** + * default styles + */ const ALERT_CONTAINER_STYLES: AlertOptions = { id: 0, position: POSITION.BOTTOM_CENTER, diff --git a/codex-ui/src/vue/components/alert/core/types.ts b/codex-ui/src/vue/components/alert/core/types.ts index cfdea165..71f95219 100644 --- a/codex-ui/src/vue/components/alert/core/types.ts +++ b/codex-ui/src/vue/components/alert/core/types.ts @@ -1,7 +1,13 @@ import type { Ref } from 'vue'; +/** + * Various alert type + */ export type AlertType = 'success' | 'error' | 'warning' | 'info' | 'default'; +/** + * position of alert, default position -> bottom-center + */ export enum POSITION { // eslint-disable-next-line @typescript-eslint/naming-convention @@ -51,10 +57,10 @@ export interface AlertInterface { /** * DOM reference to the alert container */ - alertRef: Ref; + alertRef: Ref; /** - * iterated store of alerts + * Iterated store of alerts */ alertStore: Ref; } diff --git a/codex-ui/src/vue/components/alert/core/useAlert.ts b/codex-ui/src/vue/components/alert/core/useAlert.ts index 404010a5..96f62f29 100644 --- a/codex-ui/src/vue/components/alert/core/useAlert.ts +++ b/codex-ui/src/vue/components/alert/core/useAlert.ts @@ -3,43 +3,45 @@ import { createSharedComposable } from '@vueuse/core'; import type { AlertInterface, AlertOptions, AlertType } from './types'; import { getId } from './constant'; -export const useStore = createSharedComposable(() => { - const alertRef = ref(null); +const useStore = createSharedComposable(() => { + const alertRef = ref(); const alertStore = ref([]); /** * trigger alert component + * @param type - type of alert (success, error, warning, info and default) * @param opt - alert options */ - function createAlertHandler(opt: Pick): void { + function createAlertHandler(type: AlertType, opt: Pick): void { opt.id = getId(); const alert = alertStore.value.findIndex((idx: AlertOptions) => idx.id === opt.id); - alertStore.value.push(opt); + alertStore.value.push({ type, + ...opt }); setTimeout(() => { alertStore.value.splice(alert, alertStore.value.length); }, opt.timeout); } - function success(opt: AlertOptions): void { - createAlertHandler(opt); + function success(type: AlertType, opt: Pick): void { + createAlertHandler(type, opt); } - function error(opt: AlertOptions): void { - createAlertHandler(opt); + function error(type: AlertType, opt: Pick): void { + createAlertHandler(type, opt); } - function warning(opt: AlertOptions): void { - createAlertHandler(opt); + function warning(type: AlertType, opt: Pick): void { + createAlertHandler(type, opt); } - function info(opt: AlertOptions): void { - createAlertHandler(opt); + function info(type: AlertType, opt: Pick): void { + createAlertHandler(type, opt); } - function defaultAlert(opt: AlertOptions): void { - createAlertHandler(opt); + function defaultAlert(type: AlertType, opt: Pick): void { + createAlertHandler(type, opt); } return { @@ -60,37 +62,44 @@ export const useStore = createSharedComposable(() => { * @param options - alert options */ -export function useAlert(type: AlertType | null, options: Pick): AlertInterface { - const store = useStore(); - - if (type === options.type) { - switch (type) { - case 'success': - store.success(options); - break; - - case 'error': - store.error(options); - break; - - case 'warning': - store.warning(options); - break; - - case 'info': - store.info(options); - break; - - case 'default': - store.defaultAlert(options); - break; - } - } else { - console.warn(`prop type and option type needs to be same <>`); +export function useAlert(type: AlertType | null, opt: Pick): AlertInterface { + const { + alertRef, + alertStore, + success, + error, + warning, + info, + defaultAlert, + } = useStore(); + + switch (type) { + case 'success': + alertRef.value = success(type, opt); + break; + + case 'error': + alertRef.value = error(type, opt); + break; + + case 'warning': + alertRef.value = warning(type, opt); + break; + + case 'info': + alertRef.value = info(type, opt); + break; + + case 'default': + alertRef.value = defaultAlert(type, opt); + break; + + default: + break; } return { - alertRef: store.alertRef, - alertStore: store.alertStore, + alertRef, + alertStore, }; }; diff --git a/codex-ui/src/vue/components/icon/Icon.vue b/codex-ui/src/vue/components/icon/Icon.vue index d37960cc..63b9c4eb 100644 --- a/codex-ui/src/vue/components/icon/Icon.vue +++ b/codex-ui/src/vue/components/icon/Icon.vue @@ -15,7 +15,7 @@ const props = defineProps<{ /** * Icon name */ - name: string | null; + name: string; }>(); const iconSource = computed(() => { From 1e1d2f0e0434081c8eb2017657b0ba4f7cb532b3 Mon Sep 17 00:00:00 2001 From: "iamgabrielsoft@gmail.com" Date: Thu, 8 Aug 2024 07:01:43 +0100 Subject: [PATCH 28/45] remove unecessary styles --- codex-ui/src/vue/components/alert/BaseAlert.vue | 5 ----- 1 file changed, 5 deletions(-) diff --git a/codex-ui/src/vue/components/alert/BaseAlert.vue b/codex-ui/src/vue/components/alert/BaseAlert.vue index 892a70cb..0142a38a 100644 --- a/codex-ui/src/vue/components/alert/BaseAlert.vue +++ b/codex-ui/src/vue/components/alert/BaseAlert.vue @@ -90,11 +90,6 @@ const computedTheme = computed(() => { --padding-right: var(--h-padding); --color: var(--accent--text-solid-foreground); --bg: var(--base-text); - --bg-success: var(--base-alert-success); - --bg-error: var(--base-alert-error); - --bg-warning: var(--base-alert-warning); - --bg-info: var(--base-alert-info); - --bg-default: var(--base--solid); position: relative; box-sizing: border-box; From f724101e15d0800187f4ee463db51b23d79e6588 Mon Sep 17 00:00:00 2001 From: Iamgabrielsoft Date: Wed, 14 Aug 2024 17:03:37 +0000 Subject: [PATCH 29/45] Update codex-ui/src/vue/components/alert/BaseAlert.vue Co-authored-by: Peter --- codex-ui/src/vue/components/alert/BaseAlert.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codex-ui/src/vue/components/alert/BaseAlert.vue b/codex-ui/src/vue/components/alert/BaseAlert.vue index 0142a38a..a4480e0f 100644 --- a/codex-ui/src/vue/components/alert/BaseAlert.vue +++ b/codex-ui/src/vue/components/alert/BaseAlert.vue @@ -80,7 +80,7 @@ const computedTheme = computed(() => { return 'graphite'; } - return ''; + return undefined; }); From 8b2611265073151bfd77bdbd15f926b4cb55cfb7 Mon Sep 17 00:00:00 2001 From: "iamgabrielsoft@gmail.com" Date: Thu, 15 Aug 2024 16:33:39 +0100 Subject: [PATCH 30/45] removed computed styles property --- .../src/vue/components/alert/BaseAlert.vue | 51 ++++--------------- 1 file changed, 10 insertions(+), 41 deletions(-) diff --git a/codex-ui/src/vue/components/alert/BaseAlert.vue b/codex-ui/src/vue/components/alert/BaseAlert.vue index a4480e0f..c4825711 100644 --- a/codex-ui/src/vue/components/alert/BaseAlert.vue +++ b/codex-ui/src/vue/components/alert/BaseAlert.vue @@ -3,7 +3,7 @@ ref="el" :class="[ $style.alert, - $style['alert--' + computedStyle] + $style['alert--' + props.type] ]" :theme-base="computedTheme" > @@ -18,7 +18,7 @@ diff --git a/codex-ui/src/vue/components/alert/BaseAlert.vue b/codex-ui/src/vue/components/alert/BaseAlert.vue index c4825711..cff36661 100644 --- a/codex-ui/src/vue/components/alert/BaseAlert.vue +++ b/codex-ui/src/vue/components/alert/BaseAlert.vue @@ -24,7 +24,6 @@ import { ALERT_CONTAINER_STYLES } from './core/constant'; const el = ref(); const props = withDefaults(defineProps(), { - id: ALERT_CONTAINER_STYLES.id, position: ALERT_CONTAINER_STYLES.position, message: ALERT_CONTAINER_STYLES.message, icon: ALERT_CONTAINER_STYLES.icon, @@ -59,7 +58,6 @@ const computedTheme = computed(() => { diff --git a/codex-ui/src/vue/components/alert/core/types.ts b/codex-ui/src/vue/components/alert/Alert.types.ts similarity index 91% rename from codex-ui/src/vue/components/alert/core/types.ts rename to codex-ui/src/vue/components/alert/Alert.types.ts index 2ea1a117..be53337d 100644 --- a/codex-ui/src/vue/components/alert/core/types.ts +++ b/codex-ui/src/vue/components/alert/Alert.types.ts @@ -28,19 +28,19 @@ export interface AlertOptions { */ message?: string; /** - * Type of the toast. + * Type of the alert. * * Can be any of `(success, error, default, info, warning)` */ type?: Alertype; /** - * Position of the toast on the screen. + * Position of the alert on the screen. * * (bottom-center). */ position?: POSITION.BOTTOM_CENTER; /** - * How many milliseconds for the toast to be auto dismissed, or false to disable. + * How many milliseconds for the alert to be auto dismissed */ timeout?: number; } diff --git a/codex-ui/src/vue/components/alert/AlertContainer.vue b/codex-ui/src/vue/components/alert/AlertContainer.vue index 2e7adfde..2f47d263 100644 --- a/codex-ui/src/vue/components/alert/AlertContainer.vue +++ b/codex-ui/src/vue/components/alert/AlertContainer.vue @@ -18,9 +18,9 @@ diff --git a/codex-ui/src/vue/components/alert/useAlert.ts b/codex-ui/src/vue/components/alert/useAlert.ts index 39cb45b8..08e4282a 100644 --- a/codex-ui/src/vue/components/alert/useAlert.ts +++ b/codex-ui/src/vue/components/alert/useAlert.ts @@ -1,109 +1,35 @@ import { ref } from 'vue'; -import type { AlertInterface, AlertOptions, Alertype } from './Alert.types'; import { createSharedComposable } from '@vueuse/core'; +import type { AlertInterface, AlertOptions, Alertype } from './Alert.types'; /** - * Store alerts state + * Alert service hook */ -const useStore = createSharedComposable(() => { - const alertStore = ref([]); +export const useAlert = createSharedComposable((): AlertInterface => { + const alerts = ref([]); /** * Trigger alert component - * @param type - type of alert (success, error, warning, info and default) - * @param opt - alert options(timeout, message and icon) + * @param type type of alert (success, error, warning, info and default) + * @param opt alert options(timeout, message and icon) */ - function triggerAlert(type: Alertype, opt?: Pick): void { - const alerts = alertStore.value.findIndex((idx: AlertOptions) => idx.timeout === opt?.timeout); + function triggerAlert(type?: Alertype, opt?: Pick): void { + const alertIndex = alerts.value.findIndex((idx: AlertOptions) => idx.timeout === opt?.timeout); - alertStore.value.push({ type, + alerts.value.push({ type, ...opt }); setTimeout(() => { - alertStore.value.splice(alerts, alertStore.value.shift() as number); + alerts.value.splice(alertIndex, alerts.value.shift() as number); }, opt?.timeout); } - function success(opt?: Pick): void { - triggerAlert('success', opt); - } - - function error(opt?: Pick): void { - triggerAlert('error', opt); - } - - function warning(opt?: Pick): void { - triggerAlert('warning', opt); - } - - function info(opt?: Pick): void { - triggerAlert('info', opt); - } - - function defaultAlert(opt?: Pick): void { - triggerAlert('default', opt); - } - return { - alertStore, - success, - error, - warning, - info, - defaultAlert, - triggerAlert, + alerts, + success: (opt?: Pick) => triggerAlert('success', opt), + error: (opt?: Pick) => triggerAlert('error', opt), + warning: (opt?: Pick) => triggerAlert('warning', opt), + info: (opt?: Pick) => triggerAlert('info', opt), + defaultAlert: (opt?: Pick) => triggerAlert('default', opt), }; }); - -/** - * Alert service hook - * @param type - alert type (success, error, warning, info and default) - * @param options - alert options(icon, message and timeout) - */ - -export function useAlert(type?: Alertype, opt?: Pick): AlertInterface { - const { - alertStore, - success, - error, - warning, - info, - defaultAlert, - triggerAlert, - } = useStore(); - - switch (type) { - case 'success': - - triggerAlert('success', opt); - break; - - case 'error': - triggerAlert('error', opt); - break; - - case 'warning': - triggerAlert('warning', opt); - break; - - case 'info': - triggerAlert('info', opt); - break; - - case 'default': - triggerAlert('default', opt); - break; - - default: - break; - } - - return { - alertStore, - success, - error, - info, - warning, - defaultAlert, - }; -}; From 88592476ce4236b8474c2abcb06a789316065c40 Mon Sep 17 00:00:00 2001 From: "iamgabrielsoft@gmail.com" Date: Tue, 24 Sep 2024 05:42:22 +0100 Subject: [PATCH 36/45] review fix --- codex-ui/dev/Playground.vue | 4 +- codex-ui/dev/pages/components/Alert.vue | 4 +- .../src/vue/components/alert/Alert.types.ts | 52 +---------------- .../alert/{BaseAlert.vue => Alert.vue} | 15 ++--- .../vue/components/alert/AlertContainer.vue | 17 +++--- .../vue/components/alert/AlertTransition.vue | 20 +------ codex-ui/src/vue/components/alert/constant.ts | 15 +---- codex-ui/src/vue/components/alert/useAlert.ts | 56 ++++++++++++++++--- 8 files changed, 75 insertions(+), 108 deletions(-) rename codex-ui/src/vue/components/alert/{BaseAlert.vue => Alert.vue} (84%) diff --git a/codex-ui/dev/Playground.vue b/codex-ui/dev/Playground.vue index b8074142..6ececc28 100644 --- a/codex-ui/dev/Playground.vue +++ b/codex-ui/dev/Playground.vue @@ -214,10 +214,8 @@ const pages = computed(() => [ flex-direction: column; background-color: var(--base--bg-primary); color: var(--base--text); - min-height: 100%; + min-height: 100vh; width: 100%; - height: 100%; - overflow-x: hidden; } .header { display: grid; diff --git a/codex-ui/dev/pages/components/Alert.vue b/codex-ui/dev/pages/components/Alert.vue index aa769274..d404ec41 100644 --- a/codex-ui/dev/pages/components/Alert.vue +++ b/codex-ui/dev/pages/components/Alert.vue @@ -81,7 +81,7 @@ import PageHeader from '../../components/PageHeader.vue'; import { Button, useAlert, AlertContainer } from '../../../src/vue'; -const { success, error, warning, info, defaultAlert } = useAlert(); +const { success, error, warning, info, alert } = useAlert(); const showSuccessAlert = () => { success({ @@ -112,7 +112,7 @@ const showInfoAlert = () => { }; const showDefaultAlert = () => { - defaultAlert({ + alert({ message: 'codex', timeout: 5000, }); diff --git a/codex-ui/src/vue/components/alert/Alert.types.ts b/codex-ui/src/vue/components/alert/Alert.types.ts index fbafd88b..a2926c6d 100644 --- a/codex-ui/src/vue/components/alert/Alert.types.ts +++ b/codex-ui/src/vue/components/alert/Alert.types.ts @@ -1,23 +1,14 @@ -import type { Ref } from 'vue'; - /** * Various alert type */ export type Alertype = 'success' | 'error' | 'warning' | 'info' | 'default'; -/** - * position of alert, default position -> bottom-center - */ -export enum POSITION { - - // eslint-disable-next-line @typescript-eslint/naming-convention - BOTTOM_CENTER = 'bottom-center' -} - /** * alert configuration */ export interface AlertOptions { + + id?: number; /** * Custom icon class to be used. * @@ -38,46 +29,9 @@ export interface AlertOptions { * * (bottom-center). */ - position?: POSITION.BOTTOM_CENTER; + position?: 'bottom-center'; /** * How many milliseconds for the alert to be auto dismissed */ timeout?: number; } - -export interface AlertInterface { - /** - * Iterated store of alerts - */ - alerts: Ref; - - /** - * trigger success alert - * @param opt - alert options - */ - success: (opt?: Pick) => void; - - /** - * trigger error alert - * @param opt - alert options - */ - error: (opt?: Pick) => void; - - /** - * trigger warning alert - * @param opt - alert options - */ - warning: (opt?: Pick) => void; - - /** - * trigger info alert - * @param opt - alert options - */ - info: (opt?: Pick) => void; - - /** - * trigger default alert - * @param opt - alert options - */ - defaultAlert: (opt?: Pick) => void; -} diff --git a/codex-ui/src/vue/components/alert/BaseAlert.vue b/codex-ui/src/vue/components/alert/Alert.vue similarity index 84% rename from codex-ui/src/vue/components/alert/BaseAlert.vue rename to codex-ui/src/vue/components/alert/Alert.vue index fd0eab68..24dfcd5b 100644 --- a/codex-ui/src/vue/components/alert/BaseAlert.vue +++ b/codex-ui/src/vue/components/alert/Alert.vue @@ -19,16 +19,17 @@ import { defineProps, computed, withDefaults, ref } from 'vue'; import Icon from '../icon/Icon.vue'; import type { AlertOptions } from './Alert.types'; -import { ALERT_CONTAINER_STYLES } from './constant'; +import { genId } from './constant'; const el = ref(); const props = withDefaults(defineProps(), { - position: ALERT_CONTAINER_STYLES.position, - message: ALERT_CONTAINER_STYLES.message, - icon: ALERT_CONTAINER_STYLES.icon, - type: ALERT_CONTAINER_STYLES.type, - timeout: ALERT_CONTAINER_STYLES.timeout, + id: genId(), + position: 'bottom-center', + message: '', + icon: '', + type: undefined, + timeout: 5000, }); /** @@ -94,7 +95,7 @@ const computedTheme = computed(() => { } &--default { - background-color: var(--base--solid-secondary); + background-color: var(--base--bg-secondary); } } diff --git a/codex-ui/src/vue/components/alert/AlertContainer.vue b/codex-ui/src/vue/components/alert/AlertContainer.vue index 7c3302b2..19cf744c 100644 --- a/codex-ui/src/vue/components/alert/AlertContainer.vue +++ b/codex-ui/src/vue/components/alert/AlertContainer.vue @@ -6,7 +6,7 @@ ]" > - - diff --git a/codex-ui/src/vue/components/alert/constant.ts b/codex-ui/src/vue/components/alert/constant.ts index 9a89b637..d8e63338 100644 --- a/codex-ui/src/vue/components/alert/constant.ts +++ b/codex-ui/src/vue/components/alert/constant.ts @@ -1,15 +1,4 @@ -import type { AlertOptions } from './Alert.types'; -import { POSITION } from './Alert.types'; - /** - * default styles + * Alert Id generator */ -const ALERT_CONTAINER_STYLES: AlertOptions = { - position: POSITION.BOTTOM_CENTER, - message: '', - icon: '', - type: undefined, - timeout: 50000, -}; - -export { ALERT_CONTAINER_STYLES }; +export const genId = (i => () => i++)(0); diff --git a/codex-ui/src/vue/components/alert/useAlert.ts b/codex-ui/src/vue/components/alert/useAlert.ts index 08e4282a..9a945baa 100644 --- a/codex-ui/src/vue/components/alert/useAlert.ts +++ b/codex-ui/src/vue/components/alert/useAlert.ts @@ -1,11 +1,49 @@ +import type { Ref } from 'vue'; import { ref } from 'vue'; import { createSharedComposable } from '@vueuse/core'; -import type { AlertInterface, AlertOptions, Alertype } from './Alert.types'; +import type { AlertOptions, Alertype } from './Alert.types'; + +export interface UseAlertComposableState { + /** + * Iterated store of alerts + */ + alerts: Ref; + + /** + * trigger success alert + * @param opt - alert options + */ + success: (opt?: Pick) => void; + + /** + * trigger error alert + * @param opt - alert options + */ + error: (opt?: Pick) => void; + + /** + * trigger warning alert + * @param opt - alert options + */ + warning: (opt?: Pick) => void; + + /** + * trigger info alert + * @param opt - alert options + */ + info: (opt?: Pick) => void; + + /** + * trigger default alert + * @param opt - alert options + */ + alert: (opt?: Pick) => void; +} /** * Alert service hook */ -export const useAlert = createSharedComposable((): AlertInterface => { +export const useAlert = createSharedComposable((): UseAlertComposableState => { const alerts = ref([]); /** @@ -13,8 +51,8 @@ export const useAlert = createSharedComposable((): AlertInterface => { * @param type type of alert (success, error, warning, info and default) * @param opt alert options(timeout, message and icon) */ - function triggerAlert(type?: Alertype, opt?: Pick): void { - const alertIndex = alerts.value.findIndex((idx: AlertOptions) => idx.timeout === opt?.timeout); + function triggerAlert(type?: Alertype, opt?: Pick): void { + const alertIndex = alerts.value.findIndex((idx: AlertOptions) => idx.id === opt?.id); alerts.value.push({ type, ...opt }); @@ -26,10 +64,10 @@ export const useAlert = createSharedComposable((): AlertInterface => { return { alerts, - success: (opt?: Pick) => triggerAlert('success', opt), - error: (opt?: Pick) => triggerAlert('error', opt), - warning: (opt?: Pick) => triggerAlert('warning', opt), - info: (opt?: Pick) => triggerAlert('info', opt), - defaultAlert: (opt?: Pick) => triggerAlert('default', opt), + success: (opt?: Omit) => triggerAlert('success', opt), + error: (opt?: Omit) => triggerAlert('error', opt), + warning: (opt?: Omit) => triggerAlert('warning', opt), + info: (opt?: Omit) => triggerAlert('info', opt), + alert: (opt?: Omit) => triggerAlert('default', opt), }; }); From 4509f673de878a6cfef856514143578f29a414be Mon Sep 17 00:00:00 2001 From: "iamgabrielsoft@gmail.com" Date: Thu, 26 Sep 2024 12:56:18 +0100 Subject: [PATCH 37/45] removed alert constant --- .../src/vue/components/alert/Alert.types.ts | 6 +++--- codex-ui/src/vue/components/alert/Alert.vue | 3 +-- .../vue/components/alert/AlertContainer.vue | 15 ++------------- codex-ui/src/vue/components/alert/constant.ts | 4 ---- codex-ui/src/vue/components/alert/useAlert.ts | 19 +++++++++++++++++-- 5 files changed, 23 insertions(+), 24 deletions(-) delete mode 100644 codex-ui/src/vue/components/alert/constant.ts diff --git a/codex-ui/src/vue/components/alert/Alert.types.ts b/codex-ui/src/vue/components/alert/Alert.types.ts index a2926c6d..93e4d650 100644 --- a/codex-ui/src/vue/components/alert/Alert.types.ts +++ b/codex-ui/src/vue/components/alert/Alert.types.ts @@ -1,14 +1,14 @@ /** * Various alert type */ -export type Alertype = 'success' | 'error' | 'warning' | 'info' | 'default'; +export type AlerType = 'success' | 'error' | 'warning' | 'info' | 'default'; /** * alert configuration */ export interface AlertOptions { - id?: number; + id?: string; /** * Custom icon class to be used. * @@ -23,7 +23,7 @@ export interface AlertOptions { * * Can be any of `(success, error, default, info, warning)` */ - type?: Alertype; + type?: AlerType; /** * Position of the alert on the screen. * diff --git a/codex-ui/src/vue/components/alert/Alert.vue b/codex-ui/src/vue/components/alert/Alert.vue index 24dfcd5b..e2b23b4d 100644 --- a/codex-ui/src/vue/components/alert/Alert.vue +++ b/codex-ui/src/vue/components/alert/Alert.vue @@ -19,12 +19,11 @@ import { defineProps, computed, withDefaults, ref } from 'vue'; import Icon from '../icon/Icon.vue'; import type { AlertOptions } from './Alert.types'; -import { genId } from './constant'; const el = ref(); const props = withDefaults(defineProps(), { - id: genId(), + id: `alert-' ${Math.random()}`, position: 'bottom-center', message: '', icon: '', diff --git a/codex-ui/src/vue/components/alert/AlertContainer.vue b/codex-ui/src/vue/components/alert/AlertContainer.vue index 19cf744c..63e7c5d0 100644 --- a/codex-ui/src/vue/components/alert/AlertContainer.vue +++ b/codex-ui/src/vue/components/alert/AlertContainer.vue @@ -2,7 +2,7 @@
@@ -19,19 +19,8 @@ import Alert from './Alert.vue'; import AlertTransition from './AlertTransition.vue'; import { useAlert } from './useAlert'; -import type { AlertOptions } from './Alert.types'; -import { genId } from './constant'; -const props = withDefaults(defineProps(), { - id: genId(), - position: 'bottom-center', - content: '', - icon: '', - type: undefined, - timeout: 5000, -}); - -const { alerts } = useAlert(); +const { alerts, defaultAlertOpt } = useAlert(); diff --git a/codex-ui/src/vue/components/alert/constant.ts b/codex-ui/src/vue/components/alert/constant.ts deleted file mode 100644 index d8e63338..00000000 --- a/codex-ui/src/vue/components/alert/constant.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Alert Id generator - */ -export const genId = (i => () => i++)(0); diff --git a/codex-ui/src/vue/components/alert/useAlert.ts b/codex-ui/src/vue/components/alert/useAlert.ts index 9a945baa..9e2c259f 100644 --- a/codex-ui/src/vue/components/alert/useAlert.ts +++ b/codex-ui/src/vue/components/alert/useAlert.ts @@ -1,9 +1,14 @@ import type { Ref } from 'vue'; import { ref } from 'vue'; import { createSharedComposable } from '@vueuse/core'; -import type { AlertOptions, Alertype } from './Alert.types'; +import type { AlertOptions, AlerType } from './Alert.types'; export interface UseAlertComposableState { + /** + * Default alert option + */ + defaultAlertOpt: Ref; + /** * Iterated store of alerts */ @@ -46,12 +51,21 @@ export interface UseAlertComposableState { export const useAlert = createSharedComposable((): UseAlertComposableState => { const alerts = ref([]); + const defaultAlertOpt = ref({ + id: `alert-'${Math.random()}`, + position: 'bottom-center', + message: '', + icon: undefined, + type: undefined, + timeout: 5000, + }); + /** * Trigger alert component * @param type type of alert (success, error, warning, info and default) * @param opt alert options(timeout, message and icon) */ - function triggerAlert(type?: Alertype, opt?: Pick): void { + function triggerAlert(type?: AlerType, opt?: Pick): void { const alertIndex = alerts.value.findIndex((idx: AlertOptions) => idx.id === opt?.id); alerts.value.push({ type, @@ -69,5 +83,6 @@ export const useAlert = createSharedComposable((): UseAlertComposableState => { warning: (opt?: Omit) => triggerAlert('warning', opt), info: (opt?: Omit) => triggerAlert('info', opt), alert: (opt?: Omit) => triggerAlert('default', opt), + defaultAlertOpt, }; }); From e200e7b2ab4be34ce9d12d1b8bdffa2f4cef9843 Mon Sep 17 00:00:00 2001 From: "iamgabrielsoft@gmail.com" Date: Sat, 28 Sep 2024 22:32:07 +0100 Subject: [PATCH 38/45] triggerAlert props are constant --- .../src/vue/components/alert/Alert.types.ts | 14 ++++++-- codex-ui/src/vue/components/alert/Alert.vue | 31 ++++++++--------- codex-ui/src/vue/components/alert/useAlert.ts | 34 +++++++++++-------- 3 files changed, 46 insertions(+), 33 deletions(-) diff --git a/codex-ui/src/vue/components/alert/Alert.types.ts b/codex-ui/src/vue/components/alert/Alert.types.ts index 93e4d650..8070cb94 100644 --- a/codex-ui/src/vue/components/alert/Alert.types.ts +++ b/codex-ui/src/vue/components/alert/Alert.types.ts @@ -3,33 +3,43 @@ */ export type AlerType = 'success' | 'error' | 'warning' | 'info' | 'default'; +/** + * Various alert theme type + */ +export type AlertTheme = 'grass' | 'red' | 'amber' | 'graphite' | ''; + /** * alert configuration */ export interface AlertOptions { - + /** unique alert id */ id?: string; + /** * Custom icon class to be used. * */ icon?: string; + /** * content to be rendered */ - message?: string; + message: string; + /** * Type of the alert. * * Can be any of `(success, error, default, info, warning)` */ type?: AlerType; + /** * Position of the alert on the screen. * * (bottom-center). */ position?: 'bottom-center'; + /** * How many milliseconds for the alert to be auto dismissed */ diff --git a/codex-ui/src/vue/components/alert/Alert.vue b/codex-ui/src/vue/components/alert/Alert.vue index e2b23b4d..afb84ab3 100644 --- a/codex-ui/src/vue/components/alert/Alert.vue +++ b/codex-ui/src/vue/components/alert/Alert.vue @@ -18,7 +18,7 @@ diff --git a/codex-ui/src/vue/components/alert/useAlert.ts b/codex-ui/src/vue/components/alert/useAlert.ts index 9e2c259f..09b4420e 100644 --- a/codex-ui/src/vue/components/alert/useAlert.ts +++ b/codex-ui/src/vue/components/alert/useAlert.ts @@ -3,6 +3,10 @@ import { ref } from 'vue'; import { createSharedComposable } from '@vueuse/core'; import type { AlertOptions, AlerType } from './Alert.types'; +/** + * + * Return values of useAlert composable + */ export interface UseAlertComposableState { /** * Default alert option @@ -18,35 +22,35 @@ export interface UseAlertComposableState { * trigger success alert * @param opt - alert options */ - success: (opt?: Pick) => void; + success: (opt: Pick) => void; /** * trigger error alert * @param opt - alert options */ - error: (opt?: Pick) => void; + error: (opt: Pick) => void; /** * trigger warning alert * @param opt - alert options */ - warning: (opt?: Pick) => void; + warning: (opt: Pick) => void; /** * trigger info alert * @param opt - alert options */ - info: (opt?: Pick) => void; + info: (opt: Pick) => void; /** * trigger default alert * @param opt - alert options */ - alert: (opt?: Pick) => void; + alert: (opt: Pick) => void; } /** - * Alert service hook + * Alert service composable hook */ export const useAlert = createSharedComposable((): UseAlertComposableState => { const alerts = ref([]); @@ -56,7 +60,7 @@ export const useAlert = createSharedComposable((): UseAlertComposableState => { position: 'bottom-center', message: '', icon: undefined, - type: undefined, + type: 'default', timeout: 5000, }); @@ -65,24 +69,24 @@ export const useAlert = createSharedComposable((): UseAlertComposableState => { * @param type type of alert (success, error, warning, info and default) * @param opt alert options(timeout, message and icon) */ - function triggerAlert(type?: AlerType, opt?: Pick): void { - const alertIndex = alerts.value.findIndex((idx: AlertOptions) => idx.id === opt?.id); + function triggerAlert(type: AlerType, opt: Omit): void { + const alertIndex = alerts.value.findIndex((idx: AlertOptions) => idx.id === opt.id); alerts.value.push({ type, ...opt }); setTimeout(() => { - alerts.value.splice(alertIndex, alerts.value.shift() as number); + alerts.value.splice(alertIndex, alerts.value.shift() as unknown as number); }, opt?.timeout); } return { alerts, - success: (opt?: Omit) => triggerAlert('success', opt), - error: (opt?: Omit) => triggerAlert('error', opt), - warning: (opt?: Omit) => triggerAlert('warning', opt), - info: (opt?: Omit) => triggerAlert('info', opt), - alert: (opt?: Omit) => triggerAlert('default', opt), + success: (opt: Omit) => triggerAlert('success', opt), + error: (opt: Omit) => triggerAlert('error', opt), + warning: (opt: Omit) => triggerAlert('warning', opt), + info: (opt: Omit) => triggerAlert('info', opt), + alert: (opt: Omit) => triggerAlert('default', opt), defaultAlertOpt, }; }); From cbe1b01317b481b612eeb1be9a3ab87b51664b48 Mon Sep 17 00:00:00 2001 From: "iamgabrielsoft@gmail.com" Date: Fri, 11 Oct 2024 17:44:09 +0100 Subject: [PATCH 39/45] fix transition --- codex-ui/dev/Playground.vue | 9 +++++---- .../src/vue/components/alert/Alert.types.ts | 12 ------------ codex-ui/src/vue/components/alert/Alert.vue | 18 +++++++++++++----- .../vue/components/alert/AlertContainer.vue | 9 +++++---- .../vue/components/alert/AlertTransition.vue | 11 ++++++++--- codex-ui/src/vue/components/alert/useAlert.ts | 8 +++----- 6 files changed, 34 insertions(+), 33 deletions(-) diff --git a/codex-ui/dev/Playground.vue b/codex-ui/dev/Playground.vue index 6ececc28..ff9e8ce6 100644 --- a/codex-ui/dev/Playground.vue +++ b/codex-ui/dev/Playground.vue @@ -30,6 +30,7 @@
+ @@ -38,8 +39,10 @@ import { computed } from 'vue'; import { VerticalMenu, Tabbar, - Popover + Popover, + AlertContainer } from '../src/vue'; + import { useTheme } from '../src/vue/composables/useTheme'; import { useRouter, useRoute } from 'vue-router'; @@ -210,12 +213,10 @@ const pages = computed(() => [ diff --git a/codex-ui/src/vue/components/alert/AlertContainer.vue b/codex-ui/src/vue/components/alert/AlertContainer.vue index 63e7c5d0..486c0706 100644 --- a/codex-ui/src/vue/components/alert/AlertContainer.vue +++ b/codex-ui/src/vue/components/alert/AlertContainer.vue @@ -2,9 +2,10 @@
+ @@ -35,8 +36,8 @@ const { alerts, defaultAlertOpt } = useAlert(); &--bottom-center { left: 50%; - bottom: 2rem + transform: translateX(-50%); + bottom: var(--spacing-l); } } - diff --git a/codex-ui/src/vue/components/alert/AlertTransition.vue b/codex-ui/src/vue/components/alert/AlertTransition.vue index 4eacb4c2..14fd7b40 100644 --- a/codex-ui/src/vue/components/alert/AlertTransition.vue +++ b/codex-ui/src/vue/components/alert/AlertTransition.vue @@ -9,13 +9,18 @@ diff --git a/codex-ui/src/vue/components/alert/useAlert.ts b/codex-ui/src/vue/components/alert/useAlert.ts index 09b4420e..93f95898 100644 --- a/codex-ui/src/vue/components/alert/useAlert.ts +++ b/codex-ui/src/vue/components/alert/useAlert.ts @@ -4,7 +4,6 @@ import { createSharedComposable } from '@vueuse/core'; import type { AlertOptions, AlerType } from './Alert.types'; /** - * * Return values of useAlert composable */ export interface UseAlertComposableState { @@ -57,7 +56,6 @@ export const useAlert = createSharedComposable((): UseAlertComposableState => { const defaultAlertOpt = ref({ id: `alert-'${Math.random()}`, - position: 'bottom-center', message: '', icon: undefined, type: 'default', @@ -66,11 +64,11 @@ export const useAlert = createSharedComposable((): UseAlertComposableState => { /** * Trigger alert component - * @param type type of alert (success, error, warning, info and default) + * @param type alert type (success, error, warning, info and default) * @param opt alert options(timeout, message and icon) */ - function triggerAlert(type: AlerType, opt: Omit): void { - const alertIndex = alerts.value.findIndex((idx: AlertOptions) => idx.id === opt.id); + function triggerAlert(type: AlerType, opt: AlertOptions): void { + let alertIndex = alerts.value.findIndex((idx: AlertOptions) => idx.id === opt.id); alerts.value.push({ type, ...opt }); From 6ad6208d54aebc1ebfd856ab253e71c7f85420fb Mon Sep 17 00:00:00 2001 From: "iamgabrielsoft@gmail.com" Date: Mon, 21 Oct 2024 10:34:37 +0100 Subject: [PATCH 40/45] rm reduntant props --- codex-ui/dev/Playground.vue | 1 - codex-ui/src/vue/components/alert/Alert.vue | 2 +- .../src/vue/components/alert/AlertTransition.vue | 3 +-- codex-ui/src/vue/components/alert/useAlert.ts | 13 ------------- 4 files changed, 2 insertions(+), 17 deletions(-) diff --git a/codex-ui/dev/Playground.vue b/codex-ui/dev/Playground.vue index ff9e8ce6..ef54a664 100644 --- a/codex-ui/dev/Playground.vue +++ b/codex-ui/dev/Playground.vue @@ -213,7 +213,6 @@ const pages = computed(() => [ diff --git a/codex-ui/src/vue/components/alert/useAlert.ts b/codex-ui/src/vue/components/alert/useAlert.ts index 75189382..bc5bc491 100644 --- a/codex-ui/src/vue/components/alert/useAlert.ts +++ b/codex-ui/src/vue/components/alert/useAlert.ts @@ -51,30 +51,29 @@ export const useAlert = createSharedComposable((): UseAlertComposableState => { const counter = ref(0); const alerts = ref([]); + function removeExpiredAlerts(): void { + const currentTime = new Date().getTime(); + + alerts.value = alerts.value.filter(alert => alert.timeout > currentTime); + } + /** * Trigger alert component * @param type alert type (success, error, warning, info and default) - * @param opt alert options(timeout, message and icon) + * @param opt alert optiontimeout, message and icon) */ function triggerAlert(type: AlertType, opt: AlertOptions): void { - const index = alerts.value.findIndex(m => m.id === opt.id); - - if (opt.id == null) { - opt.id = counter.value++; - opt.type = type; + if (opt.timeout === Infinity) { + return; } - alerts.value = [...alerts.value, opt]; - // alerts.value.push({ type, - // ...opt }); + const currentTime = new Date().getTime(); + const currentTimeout = currentTime + opt.timeout; - if (index !== 0) { - setTimeout(() => { - alerts.value.splice(alerts.value[opt?.id], 1); - }, opt?.timeout); - } + opt.id = counter.value++, opt.type = type, opt.timeout = currentTimeout; - console.log('counter id', opt.id); + alerts.value = [...alerts.value, opt]; + setInterval(removeExpiredAlerts, currentTimeout); } return { From 2612d1da60ccdd0e0bca42cfab429a7686c6d7bc Mon Sep 17 00:00:00 2001 From: Gabriel Eronini Odinaka Date: Thu, 3 Jul 2025 16:53:19 +0100 Subject: [PATCH 43/45] requestAnimation was used --- @codexteam/ui/dev/Playground.vue | 5 ++ @codexteam/ui/dev/routes.ts | 5 ++ .../src/vue/components/alert/Alert.types.ts | 0 .../ui}/src/vue/components/alert/Alert.vue | 0 .../vue/components/alert/AlertContainer.vue | 1 - .../vue/components/alert/AlertTransition.vue | 54 +++++++++++++++++ .../ui}/src/vue/components/alert/index.ts | 2 +- .../ui}/src/vue/components/alert/useAlert.ts | 60 +++++++++++++++++-- codex-ui/src/styles/z-axis.pcss | 4 -- .../vue/components/alert/AlertTransition.vue | 25 -------- 10 files changed, 121 insertions(+), 35 deletions(-) rename {codex-ui => @codexteam/ui}/src/vue/components/alert/Alert.types.ts (100%) rename {codex-ui => @codexteam/ui}/src/vue/components/alert/Alert.vue (100%) rename {codex-ui => @codexteam/ui}/src/vue/components/alert/AlertContainer.vue (99%) create mode 100644 @codexteam/ui/src/vue/components/alert/AlertTransition.vue rename {codex-ui => @codexteam/ui}/src/vue/components/alert/index.ts (74%) rename {codex-ui => @codexteam/ui}/src/vue/components/alert/useAlert.ts (58%) delete mode 100644 codex-ui/src/styles/z-axis.pcss delete mode 100644 codex-ui/src/vue/components/alert/AlertTransition.vue diff --git a/@codexteam/ui/dev/Playground.vue b/@codexteam/ui/dev/Playground.vue index e4c9db7f..b0036e0d 100644 --- a/@codexteam/ui/dev/Playground.vue +++ b/@codexteam/ui/dev/Playground.vue @@ -114,6 +114,11 @@ const pages = computed(() => [ { title: 'Components', items: [ + { + title: 'Alert', + onActivate: () => router.push('/alert'), + isActive: route.path === '/alert', + }, { title: 'Button', onActivate: () => router.push('/components/button'), diff --git a/@codexteam/ui/dev/routes.ts b/@codexteam/ui/dev/routes.ts index 2b9f8420..b48bc286 100644 --- a/@codexteam/ui/dev/routes.ts +++ b/@codexteam/ui/dev/routes.ts @@ -1,6 +1,7 @@ import type { RouteRecordRaw } from 'vue-router'; import type { Component } from 'vue'; import Index from './pages/Index.vue'; +import Alert from './pages/components/Alert.vue'; import TypeScale from './pages/base-concepts/TypeScale.vue'; import ControlsDimensions from './pages/base-concepts/ControlsDimensions.vue'; import Sizes from './pages/base-concepts/Sizes.vue'; @@ -41,6 +42,10 @@ const routes: RouteRecordRaw[] = [ path: '/', component: Index as Component, }, + { + path: '/alert', + component: Alert as Component, + }, { path: '/type-scale', component: TypeScale as Component, diff --git a/codex-ui/src/vue/components/alert/Alert.types.ts b/@codexteam/ui/src/vue/components/alert/Alert.types.ts similarity index 100% rename from codex-ui/src/vue/components/alert/Alert.types.ts rename to @codexteam/ui/src/vue/components/alert/Alert.types.ts diff --git a/codex-ui/src/vue/components/alert/Alert.vue b/@codexteam/ui/src/vue/components/alert/Alert.vue similarity index 100% rename from codex-ui/src/vue/components/alert/Alert.vue rename to @codexteam/ui/src/vue/components/alert/Alert.vue diff --git a/codex-ui/src/vue/components/alert/AlertContainer.vue b/@codexteam/ui/src/vue/components/alert/AlertContainer.vue similarity index 99% rename from codex-ui/src/vue/components/alert/AlertContainer.vue rename to @codexteam/ui/src/vue/components/alert/AlertContainer.vue index 6607aa59..fe4d0bf2 100644 --- a/codex-ui/src/vue/components/alert/AlertContainer.vue +++ b/@codexteam/ui/src/vue/components/alert/AlertContainer.vue @@ -20,7 +20,6 @@ import Alert from './Alert.vue'; import AlertTransition from './AlertTransition.vue'; import { useAlert } from './useAlert'; - const { alerts } = useAlert(); diff --git a/@codexteam/ui/src/vue/components/alert/AlertTransition.vue b/@codexteam/ui/src/vue/components/alert/AlertTransition.vue new file mode 100644 index 00000000..2c81bd38 --- /dev/null +++ b/@codexteam/ui/src/vue/components/alert/AlertTransition.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/codex-ui/src/vue/components/alert/index.ts b/@codexteam/ui/src/vue/components/alert/index.ts similarity index 74% rename from codex-ui/src/vue/components/alert/index.ts rename to @codexteam/ui/src/vue/components/alert/index.ts index fa424b41..afe72443 100644 --- a/codex-ui/src/vue/components/alert/index.ts +++ b/@codexteam/ui/src/vue/components/alert/index.ts @@ -1,4 +1,4 @@ -import { useAlert } from './useAlert'; +import { useAlert } from './useAlert.js'; import AlertContainer from './AlertContainer.vue'; export * from './Alert.types.js'; diff --git a/codex-ui/src/vue/components/alert/useAlert.ts b/@codexteam/ui/src/vue/components/alert/useAlert.ts similarity index 58% rename from codex-ui/src/vue/components/alert/useAlert.ts rename to @codexteam/ui/src/vue/components/alert/useAlert.ts index bc5bc491..bba33c1d 100644 --- a/codex-ui/src/vue/components/alert/useAlert.ts +++ b/@codexteam/ui/src/vue/components/alert/useAlert.ts @@ -1,5 +1,5 @@ import type { Ref } from 'vue'; -import { ref } from 'vue'; +import { onUnmounted, ref } from 'vue'; import { createSharedComposable } from '@vueuse/core'; import type { AlertOptions, AlertType } from './Alert.types'; @@ -49,7 +49,9 @@ export interface UseAlertComposableState { */ export const useAlert = createSharedComposable((): UseAlertComposableState => { const counter = ref(0); + const maxAlerts = 10; // Default maximum number of alerts const alerts = ref([]); + const animationFrameIds = new Map(); function removeExpiredAlerts(): void { const currentTime = new Date().getTime(); @@ -57,6 +59,27 @@ export const useAlert = createSharedComposable((): UseAlertComposableState => { alerts.value = alerts.value.filter(alert => alert.timeout > currentTime); } + function scheduleRemoval(alertId: number, timeout: number): void { + const startTime = performance.now(); + + const checkExpiry = (timestamp: number): void => { + const elpased = timestamp - startTime; + + if (elpased >= timeout) { + removeExpiredAlerts(); + animationFrameIds.delete(alertId); + } else { + const frameId = requestAnimationFrame(checkExpiry); + + animationFrameIds.set(alertId, frameId); + } + }; + + const frameId = requestAnimationFrame(checkExpiry); + + animationFrameIds.set(alertId, frameId); + } + /** * Trigger alert component * @param type alert type (success, error, warning, info and default) @@ -70,12 +93,41 @@ export const useAlert = createSharedComposable((): UseAlertComposableState => { const currentTime = new Date().getTime(); const currentTimeout = currentTime + opt.timeout; - opt.id = counter.value++, opt.type = type, opt.timeout = currentTimeout; + if (alerts.value.length >= maxAlerts) { + // Find and remove the oldest alert (smallest ID) + const oldestAlert = alerts.value.reduce((prev, current) => { + if (prev?.id === undefined || current.id === undefined) { + return prev; + } - alerts.value = [...alerts.value, opt]; - setInterval(removeExpiredAlerts, currentTimeout); + return (prev.id < current.id) ? prev : current; + }); + + alerts.value = alerts.value.filter(alert => alert.id !== oldestAlert?.id); + } + + const newAlert = { + ...opt, + id: counter.value++, + type, + timeout: currentTimeout, + }; + + alerts.value = [newAlert, ...alerts.value]; + + requestAnimationFrame(() => { + scheduleRemoval(Number(newAlert.id), opt.timeout); + }); } + onUnmounted(() => { + animationFrameIds.forEach((frameId) => { + cancelAnimationFrame(frameId); + }); + + animationFrameIds.clear(); + }); + return { alerts, success: (opt: Omit) => triggerAlert('success', opt), diff --git a/codex-ui/src/styles/z-axis.pcss b/codex-ui/src/styles/z-axis.pcss deleted file mode 100644 index 19998842..00000000 --- a/codex-ui/src/styles/z-axis.pcss +++ /dev/null @@ -1,4 +0,0 @@ -:root { - --z-popover: 3; - --z-alert: calc(var(--z-popover) + 1) -} diff --git a/codex-ui/src/vue/components/alert/AlertTransition.vue b/codex-ui/src/vue/components/alert/AlertTransition.vue deleted file mode 100644 index 151ae191..00000000 --- a/codex-ui/src/vue/components/alert/AlertTransition.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - From d104aa9b70f5779bb74021a8344f59a769c793a0 Mon Sep 17 00:00:00 2001 From: Gabriel Eronini Odinaka Date: Wed, 9 Jul 2025 09:01:08 +0100 Subject: [PATCH 44/45] changes based on comment --- .../vue/components/alert/AlertTransition.vue | 18 ++- .../ui/src/vue/components/alert/useAlert.ts | 110 ++++++++++++------ 2 files changed, 87 insertions(+), 41 deletions(-) diff --git a/@codexteam/ui/src/vue/components/alert/AlertTransition.vue b/@codexteam/ui/src/vue/components/alert/AlertTransition.vue index 2c81bd38..08b6d13c 100644 --- a/@codexteam/ui/src/vue/components/alert/AlertTransition.vue +++ b/@codexteam/ui/src/vue/components/alert/AlertTransition.vue @@ -16,12 +16,18 @@ /* Enter/Leave transitions */ .alert-enter-active { transition: all 0.3s ease-out; + position: relative; + z-index: 1; } .alert-leave-active { - transition: all 0.4s ease-in; - position: absolute; - width: 100%; + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); + position: relative; + z-index: 0; + height: 0; + margin: 0; + padding: 0; + overflow: hidden; } .alert-enter-from { @@ -36,12 +42,14 @@ .alert-leave-to { opacity: 0; - transform: translateX(-100%); + transform: translateY(-10px); + margin: 0; + padding: 0; } /* Move other items smoothly when one is removed */ .alert-move { - transition: transform 0.4s ease; + transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1); } .alert-container { diff --git a/@codexteam/ui/src/vue/components/alert/useAlert.ts b/@codexteam/ui/src/vue/components/alert/useAlert.ts index bba33c1d..e02304d4 100644 --- a/@codexteam/ui/src/vue/components/alert/useAlert.ts +++ b/@codexteam/ui/src/vue/components/alert/useAlert.ts @@ -1,7 +1,7 @@ import type { Ref } from 'vue'; import { onUnmounted, ref } from 'vue'; import { createSharedComposable } from '@vueuse/core'; -import type { AlertOptions, AlertType } from './Alert.types'; +import type { AlertOptions } from './Alert.types'; /** * Return values of useAlert composable @@ -52,22 +52,51 @@ export const useAlert = createSharedComposable((): UseAlertComposableState => { const maxAlerts = 10; // Default maximum number of alerts const alerts = ref([]); const animationFrameIds = new Map(); + const ANIMATION_DELAY = 50; // ms delay for smooth animations + // Batch removal of expired alerts to prevent layout thrashing function removeExpiredAlerts(): void { const currentTime = new Date().getTime(); - - alerts.value = alerts.value.filter(alert => alert.timeout > currentTime); + // Check if any alerts have expired by comparing their timeout + // timestamps to the current time. If any have expired, we'll + // need to remove them from the list of visible alerts. + const hasExpiredAlerts = alerts.value.some( + alert => alert.timeout <= currentTime + ); + + if (hasExpiredAlerts) { + // Use requestAnimationFrame to batch DOM updates + requestAnimationFrame(() => { + alerts.value = alerts.value.filter(alert => alert.timeout > currentTime); + }); + } } function scheduleRemoval(alertId: number, timeout: number): void { const startTime = performance.now(); + let lastFrameTime = startTime; + const FRAME_TIME_MS = 16.67; // ~60fps + const removalThreshold = FRAME_TIME_MS * 2; // ~2 frames at 60fps const checkExpiry = (timestamp: number): void => { - const elpased = timestamp - startTime; + // Skip frames if we're calling too frequently + if (timestamp - lastFrameTime < removalThreshold) { + const frameId = requestAnimationFrame(checkExpiry); + + animationFrameIds.set(alertId, frameId); + + return; + } + lastFrameTime = timestamp; + + const elapsed = timestamp - startTime; - if (elpased >= timeout) { - removeExpiredAlerts(); - animationFrameIds.delete(alertId); + if (elapsed >= timeout) { + // Use a slight delay to ensure smooth animation + setTimeout(() => { + removeExpiredAlerts(); + animationFrameIds.delete(alertId); + }, ANIMATION_DELAY); } else { const frameId = requestAnimationFrame(checkExpiry); @@ -82,10 +111,9 @@ export const useAlert = createSharedComposable((): UseAlertComposableState => { /** * Trigger alert component - * @param type alert type (success, error, warning, info and default) - * @param opt alert optiontimeout, message and icon) + * @param opt alert options */ - function triggerAlert(type: AlertType, opt: AlertOptions): void { + function triggerAlert(opt: AlertOptions): void { if (opt.timeout === Infinity) { return; } @@ -93,30 +121,35 @@ export const useAlert = createSharedComposable((): UseAlertComposableState => { const currentTime = new Date().getTime(); const currentTimeout = currentTime + opt.timeout; - if (alerts.value.length >= maxAlerts) { - // Find and remove the oldest alert (smallest ID) - const oldestAlert = alerts.value.reduce((prev, current) => { - if (prev?.id === undefined || current.id === undefined) { - return prev; - } - - return (prev.id < current.id) ? prev : current; - }); - - alerts.value = alerts.value.filter(alert => alert.id !== oldestAlert?.id); - } + // Use requestAnimationFrame to batch DOM updates + requestAnimationFrame(() => { + if (alerts.value.length >= maxAlerts) { + // Find and remove the oldest alert (smallest ID) + const oldestAlert = alerts.value.reduce((prev, current) => { + if (prev?.id === undefined || current.id === undefined) { + return current; + } + + return (prev.id < current.id) ? prev : current; + }); + + // Remove the oldest alert + alerts.value = alerts.value.filter(alert => alert.id !== oldestAlert?.id); + } - const newAlert = { - ...opt, - id: counter.value++, - type, - timeout: currentTimeout, - }; + const newAlert = { + ...opt, + id: counter.value++, + timeout: currentTimeout, + }; - alerts.value = [newAlert, ...alerts.value]; + // Add new alert at the beginning of the array + alerts.value = [newAlert, ...alerts.value]; - requestAnimationFrame(() => { - scheduleRemoval(Number(newAlert.id), opt.timeout); + // Schedule removal with a small delay to ensure smooth animation + setTimeout(() => { + scheduleRemoval(Number(newAlert.id), opt.timeout); + }, ANIMATION_DELAY); }); } @@ -130,10 +163,15 @@ export const useAlert = createSharedComposable((): UseAlertComposableState => { return { alerts, - success: (opt: Omit) => triggerAlert('success', opt), - error: (opt: Omit) => triggerAlert('error', opt), - warning: (opt: Omit) => triggerAlert('warning', opt), - info: (opt: Omit) => triggerAlert('info', opt), - alert: (opt: Omit) => triggerAlert('default', opt), + success: (opt: Omit) => triggerAlert({ ...opt, + type: 'success' }), + error: (opt: Omit) => triggerAlert({ ...opt, + type: 'error' }), + warning: (opt: Omit) => triggerAlert({ ...opt, + type: 'warning' }), + info: (opt: Omit) => triggerAlert({ ...opt, + type: 'info' }), + alert: (opt: Omit) => triggerAlert({ ...opt, + type: 'default' }), }; }); From 92a4841be0e4b387ca052658e04e73bfee470f4c Mon Sep 17 00:00:00 2001 From: Gabriel Eronini Odinaka Date: Wed, 24 Sep 2025 03:31:14 +0100 Subject: [PATCH 45/45] comment review change --- .../ui/src/vue/components/alert/Alert.vue | 1 - .../vue/components/alert/AlertContainer.vue | 3 ++ .../vue/components/alert/AlertTransition.vue | 41 +++++++++++-------- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/@codexteam/ui/src/vue/components/alert/Alert.vue b/@codexteam/ui/src/vue/components/alert/Alert.vue index 7e7d3822..a29cc982 100644 --- a/@codexteam/ui/src/vue/components/alert/Alert.vue +++ b/@codexteam/ui/src/vue/components/alert/Alert.vue @@ -80,7 +80,6 @@ const computedTheme = computed((): AlertTheme => { border-radius: var(--radius-field); color: var(--base--text-solid-foreground); overflow-wrap: anywhere; - transform: translateY(10%); &--success { background-color: var(--base--solid); diff --git a/@codexteam/ui/src/vue/components/alert/AlertContainer.vue b/@codexteam/ui/src/vue/components/alert/AlertContainer.vue index fe4d0bf2..9ef0d730 100644 --- a/@codexteam/ui/src/vue/components/alert/AlertContainer.vue +++ b/@codexteam/ui/src/vue/components/alert/AlertContainer.vue @@ -36,6 +36,9 @@ const { alerts } = useAlert(); left: 50%; transform: translateX(-50%); bottom: var(--spacing-l); + width: auto; + min-width: auto; + max-width: auto; } } diff --git a/@codexteam/ui/src/vue/components/alert/AlertTransition.vue b/@codexteam/ui/src/vue/components/alert/AlertTransition.vue index 08b6d13c..9fb475fc 100644 --- a/@codexteam/ui/src/vue/components/alert/AlertTransition.vue +++ b/@codexteam/ui/src/vue/components/alert/AlertTransition.vue @@ -13,43 +13,51 @@