diff --git a/Assets/Resources/UIToolkit/Modal/UTKAlert.uss b/Assets/Resources/UIToolkit/Modal/UTKAlert.uss
index 32c006b4..1c63b144 100644
--- a/Assets/Resources/UIToolkit/Modal/UTKAlert.uss
+++ b/Assets/Resources/UIToolkit/Modal/UTKAlert.uss
@@ -43,7 +43,7 @@
.utk-alert__content {
flex-direction: column;
- align-items: center;
+ align-items: stretch;
flex-grow: 1;
margin-top: var(--space-xxl);
margin-bottom: var(--space-xxl);
@@ -56,7 +56,7 @@
.utk-alert__message {
font-size: var(--font-size-body2);
color: var(--color-text-secondary);
- -unity-text-align: middle-center;
+ -unity-text-align: middle-left;
white-space: normal;
}
@@ -66,7 +66,7 @@
.utk-alert__buttons {
flex-direction: row;
- justify-content: center;
+ justify-content: flex-end;
}
.utk-alert__btn {
diff --git a/Assets/Resources/UIToolkit/Modal/UTKModal.uss b/Assets/Resources/UIToolkit/Modal/UTKModal.uss
index 5acbced5..d5282c65 100644
--- a/Assets/Resources/UIToolkit/Modal/UTKModal.uss
+++ b/Assets/Resources/UIToolkit/Modal/UTKModal.uss
@@ -98,6 +98,11 @@
overflow: scroll;
}
+.utk-modal__content {
+ color: var(--color-text-primary);
+ font-size: var(--font-size-body1);
+}
+
/* ===================================
Footer
=================================== */
diff --git a/Assets/Resources/UIToolkit/Sample/Modal/UTKModalSample.uxml b/Assets/Resources/UIToolkit/Sample/Modal/UTKModalSample.uxml
new file mode 100644
index 00000000..d9c37522
--- /dev/null
+++ b/Assets/Resources/UIToolkit/Sample/Modal/UTKModalSample.uxml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Assets/Resources/UIToolkit/Sample/Modal/UTKModalSample.uxml.meta b/Assets/Resources/UIToolkit/Sample/Modal/UTKModalSample.uxml.meta
new file mode 100644
index 00000000..e7cdacd2
--- /dev/null
+++ b/Assets/Resources/UIToolkit/Sample/Modal/UTKModalSample.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 0cf3905be994d1247b02ebefc1beb32f
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
diff --git a/Assets/Resources/UIToolkit/Sample/Modal/UTKNotificationSample.uxml b/Assets/Resources/UIToolkit/Sample/Modal/UTKNotificationSample.uxml
new file mode 100644
index 00000000..56c482c1
--- /dev/null
+++ b/Assets/Resources/UIToolkit/Sample/Modal/UTKNotificationSample.uxml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Assets/Resources/UIToolkit/Sample/Modal/UTKNotificationSample.uxml.meta b/Assets/Resources/UIToolkit/Sample/Modal/UTKNotificationSample.uxml.meta
new file mode 100644
index 00000000..e8cc5d8c
--- /dev/null
+++ b/Assets/Resources/UIToolkit/Sample/Modal/UTKNotificationSample.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: ee2d341bdf4a1e24890200aae4cc279a
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
diff --git a/Assets/Resources/UIToolkit/Window/UTKPropertyListWindow.uxml b/Assets/Resources/UIToolkit/Window/UTKPropertyListWindow.uxml
index f763d570..498dfc34 100644
--- a/Assets/Resources/UIToolkit/Window/UTKPropertyListWindow.uxml
+++ b/Assets/Resources/UIToolkit/Window/UTKPropertyListWindow.uxml
@@ -3,7 +3,7 @@
diff --git a/Assets/Resources/UIToolkit/Window/UTKPropertyTabListWindow.uxml b/Assets/Resources/UIToolkit/Window/UTKPropertyTabListWindow.uxml
index 90e264aa..5cfa5844 100644
--- a/Assets/Resources/UIToolkit/Window/UTKPropertyTabListWindow.uxml
+++ b/Assets/Resources/UIToolkit/Window/UTKPropertyTabListWindow.uxml
@@ -18,7 +18,7 @@
diff --git a/Assets/Sample/UIToolkit/UTKColorPickerSample.cs b/Assets/Sample/UIToolkit/UTKColorPickerSample.cs
index 87c8f025..a0c0cd22 100644
--- a/Assets/Sample/UIToolkit/UTKColorPickerSample.cs
+++ b/Assets/Sample/UIToolkit/UTKColorPickerSample.cs
@@ -57,6 +57,7 @@ namespace UVC.Sample.UIToolkit
};
_root = _uiDocument.rootVisualElement;
+ UTKColorPicker.SetRoot(_root);
CreateSampleUI();
}
@@ -243,7 +244,7 @@ namespace UVC.Sample.UIToolkit
bool useAlpha = _useAlphaToggle?.value ?? false;
- _currentPicker = UTKColorPicker.Show(_root, _currentColor, "Select Color", useAlpha);
+ _currentPicker = UTKColorPicker.Show(_currentColor, "Select Color", useAlpha);
_currentPicker.OnColorChanged += OnColorChanged;
_currentPicker.OnColorSelected += OnColorSelected;
@@ -257,7 +258,7 @@ namespace UVC.Sample.UIToolkit
if (_root == null || _currentPicker != null) return;
// useAlpha = true로 명시적 호출
- _currentPicker = UTKColorPicker.Show(_root, _currentColor, "Select Color (Alpha ON)", useAlpha: true);
+ _currentPicker = UTKColorPicker.Show(_currentColor, "Select Color (Alpha ON)", useAlpha: true);
_currentPicker.OnColorChanged += OnColorChanged;
_currentPicker.OnColorSelected += OnColorSelected;
@@ -273,7 +274,7 @@ namespace UVC.Sample.UIToolkit
if (_root == null || _currentPicker != null) return;
// useAlpha = false로 명시적 호출
- _currentPicker = UTKColorPicker.Show(_root, _currentColor, "Select Color (Alpha OFF)", useAlpha: false);
+ _currentPicker = UTKColorPicker.Show(_currentColor, "Select Color (Alpha OFF)", useAlpha: false);
_currentPicker.OnColorChanged += OnColorChanged;
_currentPicker.OnColorSelected += OnColorSelected;
@@ -309,7 +310,7 @@ namespace UVC.Sample.UIToolkit
// ShowAsync를 사용하여 색상 선택 대기
// OK 클릭 시 선택된 색상 반환, 취소/닫기 시 _currentColor 반환
- Color selectedColor = await UTKColorPicker.ShowAsync(_root, _currentColor, "Select Color (Async)", useAlpha);
+ Color selectedColor = await UTKColorPicker.ShowAsync(_currentColor, "Select Color (Async)", useAlpha);
// 결과 처리
_currentColor = selectedColor;
diff --git a/Assets/Sample/UIToolkit/UTKDatePickerSample.cs b/Assets/Sample/UIToolkit/UTKDatePickerSample.cs
index 203fff03..33a0c2f0 100644
--- a/Assets/Sample/UIToolkit/UTKDatePickerSample.cs
+++ b/Assets/Sample/UIToolkit/UTKDatePickerSample.cs
@@ -64,6 +64,7 @@ namespace UVC.Sample.UIToolkit
Debug.Log($"LocalizationManager: LoadDefaultLocalizationData success: {success}");
_root = _uiDocument.rootVisualElement;
+ UTKDatePicker.SetRoot(_root);
CreateSampleUI();
}
@@ -227,7 +228,6 @@ namespace UVC.Sample.UIToolkit
if (_root == null || _currentPicker != null) return;
_currentPicker = UTKDatePicker.Show(
- _root,
_selectedDate,
UTKDatePicker.PickerMode.DateOnly,
"Select Date"
@@ -242,7 +242,6 @@ namespace UVC.Sample.UIToolkit
if (_root == null || _currentPicker != null) return;
_currentPicker = UTKDatePicker.Show(
- _root,
_selectedDateTime,
UTKDatePicker.PickerMode.DateAndTime,
"Select Date & Time"
@@ -259,7 +258,6 @@ namespace UVC.Sample.UIToolkit
// ShowAsync를 사용하여 날짜 선택 대기
// OK 클릭 시 선택된 날짜 반환, 취소/닫기 시 null 반환
DateTime? result = await UTKDatePicker.ShowAsync(
- _root,
_selectedDate,
UTKDatePicker.PickerMode.DateOnly,
"Select Date (Async)"
@@ -350,7 +348,6 @@ namespace UVC.Sample.UIToolkit
if (_root == null || _currentPicker != null) return;
_currentPicker = UTKDatePicker.ShowRange(
- _root,
_rangeStartDate,
_rangeEndDate,
false,
@@ -368,7 +365,6 @@ namespace UVC.Sample.UIToolkit
// ShowRangeAsync를 사용하여 날짜 범위 선택 대기
// OK 클릭 시 선택된 범위 반환, 취소/닫기 시 null 반환
var result = await UTKDatePicker.ShowRangeAsync(
- _root,
_rangeStartDate,
_rangeEndDate,
false,
diff --git a/Assets/Sample/UIToolkit/UTKPropertyListWindowSample.cs b/Assets/Sample/UIToolkit/UTKPropertyListWindowSample.cs
index 48b68f90..232e2893 100644
--- a/Assets/Sample/UIToolkit/UTKPropertyListWindowSample.cs
+++ b/Assets/Sample/UIToolkit/UTKPropertyListWindowSample.cs
@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
+using UVC.Locale;
using UVC.UIToolkit;
namespace UVC.Sample.UIToolkit
@@ -26,6 +27,10 @@ namespace UVC.Sample.UIToolkit
private void Start()
{
+
+ bool success = LocalizationManager.Instance.LoadDefaultLocalizationData("KO");
+ Debug.Log($"LocalizationManager: LoadDefaultLocalizationData success: {success}");
+
// UIDocument 참조 확인
var doc = GetComponent();
if (doc == null)
diff --git a/Assets/Sample/UIToolkit/UTKStyleGuideSample.Modal.cs b/Assets/Sample/UIToolkit/UTKStyleGuideSample.Modal.cs
index 88568678..5c157189 100644
--- a/Assets/Sample/UIToolkit/UTKStyleGuideSample.Modal.cs
+++ b/Assets/Sample/UIToolkit/UTKStyleGuideSample.Modal.cs
@@ -203,14 +203,14 @@ var currentTab = tabView.SelectedIndex;",
var btnCallback = root.Q("btn-callback");
btnCallback?.RegisterCallback(_ =>
{
- UTKAlert.ShowInfo(_root, "Callback Style", "This uses callback instead of async.",
+ UTKAlert.ShowInfo("Callback Style", "This uses callback instead of async.",
onClose: () => Debug.Log("Alert closed via callback"));
});
var btnConfirmCallback = root.Q("btn-confirm-callback");
btnConfirmCallback?.RegisterCallback(_ =>
{
- UTKAlert.ShowConfirm(_root, "Confirm", "Do you want to proceed?",
+ UTKAlert.ShowConfirm("Confirm", "Do you want to proceed?",
onConfirm: () => Debug.Log("Confirmed via callback!"),
onCancel: () => Debug.Log("Cancelled via callback!"));
});
@@ -262,11 +262,11 @@ await UTKAlert.ShowInfoAsync(""정보"", ""배경을 클릭해도 닫힙니다."
// ========================================
// Info with Callback
-UTKAlert.ShowInfo(rootVisualElement, ""정보"", ""콜백 방식입니다."",
+UTKAlert.ShowInfo(""정보"", ""콜백 방식입니다."",
onClose: () => Debug.Log(""Alert가 닫혔습니다.""));
// Confirm with Callback
-UTKAlert.ShowConfirm(rootVisualElement, ""확인"", ""진행하시겠습니까?"",
+UTKAlert.ShowConfirm(""확인"", ""진행하시겠습니까?"",
onConfirm: () => Debug.Log(""확인 클릭!""),
onCancel: () => Debug.Log(""취소 클릭!""));");
}
@@ -405,12 +405,383 @@ for (int i = 0; i < buttons.Length; i++)
#endregion
+ #region Modal Initializers (UTKModal)
+
+ private void InitializeModalSample(VisualElement root)
+ {
+ if (_root == null) return;
+
+ UTKModal.SetRoot(_root);
+
+ // Modal Sizes
+ var btnSmall = root.Q("btn-modal-small");
+ btnSmall?.RegisterCallback(_ => ShowModalWithSize(UTKModal.ModalSize.Small));
+
+ var btnMedium = root.Q("btn-modal-medium");
+ btnMedium?.RegisterCallback(_ => ShowModalWithSize(UTKModal.ModalSize.Medium));
+
+ var btnLarge = root.Q("btn-modal-large");
+ btnLarge?.RegisterCallback(_ => ShowModalWithSize(UTKModal.ModalSize.Large));
+
+ var btnFullScreen = root.Q("btn-modal-fullscreen");
+ btnFullScreen?.RegisterCallback(_ => ShowModalWithSize(UTKModal.ModalSize.FullScreen));
+
+ // Options
+ var btnFooter = root.Q("btn-modal-footer");
+ btnFooter?.RegisterCallback(_ =>
+ {
+ var modal = UTKModal.Show("푸터 버튼 모달", UTKModal.ModalSize.Medium);
+ modal.Add(new Label("확인 또는 취소를 선택하세요."));
+
+ var confirmBtn = new UTKButton("확인") { Variant = UTKButton.ButtonVariant.Primary };
+ confirmBtn.RegisterCallback(_ =>
+ {
+ Debug.Log("Modal confirmed");
+ modal.Close();
+ });
+
+ var cancelBtn = new UTKButton("취소") { Variant = UTKButton.ButtonVariant.Normal };
+ cancelBtn.RegisterCallback(_ =>
+ {
+ Debug.Log("Modal cancelled");
+ modal.Close();
+ });
+
+ modal.AddToFooter(cancelBtn);
+ modal.AddToFooter(confirmBtn);
+ });
+
+ var btnNoClose = root.Q("btn-modal-no-close");
+ btnNoClose?.RegisterCallback(_ =>
+ {
+ var modal = UTKModal.Show("닫기 버튼 없음", UTKModal.ModalSize.Small);
+ modal.ShowCloseButton = false;
+ modal.Add(new Label("닫기 버튼이 없습니다.\n배경을 클릭하면 닫힙니다."));
+ });
+
+ var btnNoBackdrop = root.Q("btn-modal-no-backdrop");
+ btnNoBackdrop?.RegisterCallback(_ =>
+ {
+ var modal = UTKModal.Show("배경 클릭 비활성화", UTKModal.ModalSize.Small);
+ modal.CloseOnBackdropClick = false;
+ modal.Add(new Label("배경을 클릭해도 닫히지 않습니다.\nX 버튼으로만 닫을 수 있습니다."));
+ });
+
+ // Custom Content - Form Modal
+ var btnForm = root.Q("btn-modal-form");
+ btnForm?.RegisterCallback(_ =>
+ {
+ var modal = UTKModal.Show("사용자 정보 입력", UTKModal.ModalSize.Medium);
+
+ var nameField = new UTKInputField("이름");
+ var emailField = new UTKInputField("이메일");
+ modal.Add(nameField);
+ modal.Add(emailField);
+
+ var submitBtn = new UTKButton("제출") { Variant = UTKButton.ButtonVariant.Primary };
+ submitBtn.RegisterCallback(_ =>
+ {
+ Debug.Log($"Name: {nameField.value}, Email: {emailField.value}");
+ modal.Close();
+ });
+
+ var cancelBtn = new UTKButton("취소") { Variant = UTKButton.ButtonVariant.Normal };
+ cancelBtn.RegisterCallback(_ => modal.Close());
+
+ modal.AddToFooter(cancelBtn);
+ modal.AddToFooter(submitBtn);
+ });
+
+ SetCodeSamples(root,
+ csharpCode: @"// Root 설정 (한 번만)
+UTKModal.SetRoot(rootVisualElement);
+
+// ========================================
+// 1. 기본 모달 표시
+// ========================================
+
+var modal = UTKModal.Show(""제목"", UTKModal.ModalSize.Medium);
+modal.Add(new Label(""모달 내용""));
+
+// 닫힘 이벤트
+modal.OnClosed += () => Debug.Log(""모달 닫힘"");
+
+// ========================================
+// 2. 모달 크기
+// ========================================
+
+// Small
+UTKModal.Show(""Small"", UTKModal.ModalSize.Small);
+
+// Medium (기본)
+UTKModal.Show(""Medium"", UTKModal.ModalSize.Medium);
+
+// Large
+UTKModal.Show(""Large"", UTKModal.ModalSize.Large);
+
+// FullScreen
+UTKModal.Show(""FullScreen"", UTKModal.ModalSize.FullScreen);
+
+// ========================================
+// 3. 옵션 설정
+// ========================================
+
+var modal = UTKModal.Show(""설정"");
+
+// 닫기 버튼 숨기기
+modal.ShowCloseButton = false;
+
+// 배경 클릭 시 닫기 비활성화
+modal.CloseOnBackdropClick = false;
+
+// 푸터 숨기기
+modal.SetFooterVisible(false);
+
+// ========================================
+// 4. 푸터 버튼 추가
+// ========================================
+
+var modal = UTKModal.Show(""확인 모달"");
+modal.Add(new Label(""정말 삭제하시겠습니까?""));
+
+var confirmBtn = new UTKButton(""삭제"") { Variant = UTKButton.ButtonVariant.Danger };
+confirmBtn.RegisterCallback(_ =>
+{
+ Debug.Log(""삭제 실행"");
+ modal.Close();
+});
+
+var cancelBtn = new UTKButton(""취소"") { Variant = UTKButton.ButtonVariant.Normal };
+cancelBtn.RegisterCallback(_ => modal.Close());
+
+modal.AddToFooter(cancelBtn);
+modal.AddToFooter(confirmBtn);
+
+// ========================================
+// 5. 폼 모달
+// ========================================
+
+var modal = UTKModal.Show(""사용자 정보"");
+
+var nameField = new UTKInputField(""이름"");
+var emailField = new UTKInputField(""이메일"");
+modal.Add(nameField);
+modal.Add(emailField);
+
+var submitBtn = new UTKButton(""제출"") { Variant = UTKButton.ButtonVariant.Primary };
+submitBtn.RegisterCallback(_ =>
+{
+ Debug.Log($""Name: {nameField.value}, Email: {emailField.value}"");
+ modal.Close();
+});
+modal.AddToFooter(submitBtn);
+
+// ========================================
+// 6. 프로그래밍 방식 닫기
+// ========================================
+
+var modal = UTKModal.Show(""타이머 모달"");
+modal.Add(new Label(""3초 후 자동으로 닫힙니다.""));
+modal.ShowCloseButton = false;
+modal.CloseOnBackdropClick = false;
+
+// 3초 후 닫기
+modal.schedule.Execute(() => modal.Close()).StartingIn(3000);",
+ uxmlCode: @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+");
+ }
+
+ private void ShowModalWithSize(UTKModal.ModalSize size)
+ {
+ if (_root == null) return;
+
+ var modal = UTKModal.Show($"{size} Modal", size);
+ modal.Add(new Label($"이것은 {size} 크기의 모달입니다."));
+ modal.OnClosed += () => Debug.Log($"{size} modal closed");
+ }
+
+ #endregion
+
+ #region Notification Initializers
+
+ private void InitializeNotificationSample(VisualElement root)
+ {
+ if (_root == null) return;
+
+ UTKNotification.SetRoot(_root);
+
+ // Notification Types
+ var btnInfo = root.Q("btn-noti-info");
+ btnInfo?.RegisterCallback(_ =>
+ UTKNotification.ShowInfo("정보", "이것은 정보 알림입니다."));
+
+ var btnSuccess = root.Q("btn-noti-success");
+ btnSuccess?.RegisterCallback(_ =>
+ UTKNotification.ShowSuccess("성공", "작업이 성공적으로 완료되었습니다!"));
+
+ var btnWarning = root.Q("btn-noti-warning");
+ btnWarning?.RegisterCallback(_ =>
+ UTKNotification.ShowWarning("경고", "주의가 필요한 상황입니다."));
+
+ var btnError = root.Q("btn-noti-error");
+ btnError?.RegisterCallback(_ =>
+ UTKNotification.ShowError("오류", "오류가 발생했습니다!"));
+
+ // Position
+ var btnTopLeft = root.Q("btn-noti-top-left");
+ btnTopLeft?.RegisterCallback(_ =>
+ UTKNotification.Show("Top Left", "TopLeft 위치 알림",
+ UTKNotification.NotificationType.Info, UTKNotification.NotificationPosition.TopLeft));
+
+ var btnTopRight = root.Q("btn-noti-top-right");
+ btnTopRight?.RegisterCallback(_ =>
+ UTKNotification.Show("Top Right", "TopRight 위치 알림",
+ UTKNotification.NotificationType.Info, UTKNotification.NotificationPosition.TopRight));
+
+ var btnBottomLeft = root.Q("btn-noti-bottom-left");
+ btnBottomLeft?.RegisterCallback(_ =>
+ UTKNotification.Show("Bottom Left", "BottomLeft 위치 알림",
+ UTKNotification.NotificationType.Info, UTKNotification.NotificationPosition.BottomLeft));
+
+ var btnBottomRight = root.Q("btn-noti-bottom-right");
+ btnBottomRight?.RegisterCallback(_ =>
+ UTKNotification.Show("Bottom Right", "BottomRight 위치 알림",
+ UTKNotification.NotificationType.Info, UTKNotification.NotificationPosition.BottomRight));
+
+ // With Actions
+ var btnAction = root.Q("btn-noti-action");
+ btnAction?.RegisterCallback(_ =>
+ {
+ var notification = UTKNotification.Show("업데이트 가능",
+ "새로운 버전이 있습니다. 업데이트하시겠습니까?",
+ UTKNotification.NotificationType.Info, UTKNotification.NotificationPosition.TopRight);
+ notification.AddAction("업데이트", "update");
+ notification.AddAction("나중에", "later");
+ notification.OnActionClicked += (actionId) =>
+ {
+ Debug.Log($"Action clicked: {actionId}");
+ };
+ });
+
+ var btnPersistent = root.Q("btn-noti-persistent");
+ btnPersistent?.RegisterCallback(_ =>
+ {
+ var notification = UTKNotification.Show("수동 닫기",
+ "이 알림은 자동으로 닫히지 않습니다. X 버튼을 눌러 닫아주세요.",
+ UTKNotification.NotificationType.Warning, UTKNotification.NotificationPosition.TopRight,
+ duration: 0);
+ notification.OnClosed += () => Debug.Log("Persistent notification closed");
+ });
+
+ SetCodeSamples(root,
+ csharpCode: @"// Root 설정 (한 번만)
+UTKNotification.SetRoot(rootVisualElement);
+
+// ========================================
+// 1. 기본 알림 타입
+// ========================================
+
+// Info
+UTKNotification.ShowInfo(""정보"", ""이것은 정보 알림입니다."");
+
+// Success
+UTKNotification.ShowSuccess(""성공"", ""작업이 완료되었습니다!"");
+
+// Warning
+UTKNotification.ShowWarning(""경고"", ""주의가 필요합니다."");
+
+// Error
+UTKNotification.ShowError(""오류"", ""오류가 발생했습니다!"");
+
+// ========================================
+// 2. 위치 지정
+// ========================================
+
+UTKNotification.Show(""제목"", ""메시지"",
+ UTKNotification.NotificationType.Info,
+ UTKNotification.NotificationPosition.TopRight); // 기본값
+
+UTKNotification.Show(""제목"", ""메시지"",
+ UTKNotification.NotificationType.Success,
+ UTKNotification.NotificationPosition.BottomLeft);
+
+// ========================================
+// 3. 지속 시간 설정
+// ========================================
+
+// 기본 5초
+UTKNotification.ShowInfo(""정보"", ""5초 후 자동 닫힘"");
+
+// 10초
+UTKNotification.ShowInfo(""정보"", ""10초 후 자동 닫힘"", duration: 10000);
+
+// 수동 닫기 (자동 닫힘 없음)
+UTKNotification.ShowWarning(""경고"", ""수동으로 닫아주세요."", duration: 0);
+
+// ========================================
+// 4. 액션 버튼 추가
+// ========================================
+
+var notification = UTKNotification.Show(
+ ""업데이트 가능"", ""새로운 버전이 있습니다."",
+ UTKNotification.NotificationType.Info,
+ UTKNotification.NotificationPosition.TopRight);
+
+notification.AddAction(""업데이트"", ""update"");
+notification.AddAction(""나중에"", ""later"");
+
+notification.OnActionClicked += (actionId) =>
+{
+ if (actionId == ""update"")
+ Debug.Log(""업데이트 시작"");
+ else
+ Debug.Log(""나중에 업데이트"");
+};
+
+// ========================================
+// 5. 닫힘 이벤트
+// ========================================
+
+var noti = UTKNotification.ShowInfo(""알림"", ""메시지"");
+noti.OnClosed += () => Debug.Log(""알림이 닫혔습니다."");
+
+// ========================================
+// 6. 인스턴스 직접 생성
+// ========================================
+
+var custom = new UTKNotification(""제목"", ""메시지"", UTKNotification.NotificationType.Success);
+custom.Duration = 0;
+custom.AddAction(""확인"", ""confirm"");
+rootVisualElement.Add(custom);");
+ }
+
+ #endregion
+
#region Picker Initializers
private void InitializeColorPickerSample(VisualElement root)
{
if (_root == null) return;
+ UTKColorPicker.SetRoot(_root);
+
_colorPreviewBox = root.Q("color-preview-box");
_colorHexLabel = root.Q