Compare commits
6 Commits
ios-contac
...
dialog-not
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e588e223bc | ||
|
|
02eead5609 | ||
| 1e203da9bb | |||
|
|
df49c80199 | ||
|
|
4d89042997 | ||
|
|
8f5111d100 |
69
doc/z-index-guide.md
Normal file
69
doc/z-index-guide.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# Z-Index Guide — TimeSafari
|
||||||
|
|
||||||
|
**Author**: Development Team
|
||||||
|
**Date**: 2025-08-25T19:38:09-08:00
|
||||||
|
**Status**: 🎯 **ACTIVE** - Z-index layering standards
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
Establish consistent z-index values across the TimeSafari application to ensure proper layering of UI elements.
|
||||||
|
|
||||||
|
## Result
|
||||||
|
This document defines the z-index hierarchy for all UI components.
|
||||||
|
|
||||||
|
## Use/Run
|
||||||
|
Reference these values when implementing new components or modifying existing ones to maintain consistent layering.
|
||||||
|
|
||||||
|
## Z-Index Hierarchy
|
||||||
|
|
||||||
|
| Component | Z-Index | Usage |
|
||||||
|
|-----------|---------|-------|
|
||||||
|
| **Map** | `40` | Base map layer and map-related overlays |
|
||||||
|
| **QuickNav** | `50` | Quick navigation bottom bar |
|
||||||
|
| **Dialogs and Modals** | `100` | Modal dialogs, popups, and overlay content |
|
||||||
|
| **Notifications and Toasts** | `120` | System notifications, alerts, and toast messages |
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Never exceed 120** - Keep the highest z-index reserved for critical notifications
|
||||||
|
2. **Use increments of 10** - Leave room for future additions between layers
|
||||||
|
3. **Document exceptions** - If you need a z-index outside this range, document the reason
|
||||||
|
4. **Test layering** - Verify z-index behavior across different screen sizes and devices
|
||||||
|
|
||||||
|
## Common Pitfalls
|
||||||
|
|
||||||
|
- **Avoid arbitrary values** - Don't use random z-index numbers
|
||||||
|
- **Don't nest high z-index** - Keep child elements within their parent's z-index range
|
||||||
|
- **Consider stacking context** - Remember that `position: relative` creates new stacking contexts
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
| Owner | Task | Exit Criteria | Target Date |
|
||||||
|
|-------|------|---------------|-------------|
|
||||||
|
| Dev Team | Apply z-index classes to existing components | All components use defined z-index values | 2025-09-01 |
|
||||||
|
|
||||||
|
## Competence Hooks
|
||||||
|
|
||||||
|
- **Why this works**: Creates predictable layering hierarchy that prevents UI conflicts
|
||||||
|
- **Common pitfalls**: Using arbitrary z-index values or exceeding the defined range
|
||||||
|
- **Next skill unlock**: Learn about CSS stacking contexts and their impact on z-index
|
||||||
|
- **Teach-back**: Explain the z-index hierarchy to a team member without referencing this guide
|
||||||
|
|
||||||
|
## Collaboration Hooks
|
||||||
|
|
||||||
|
- **Reviewers**: Frontend team, UI/UX designers
|
||||||
|
- **Sign-off checklist**:
|
||||||
|
- [ ] All new components follow z-index guidelines
|
||||||
|
- [ ] Existing components updated to use defined values
|
||||||
|
- [ ] Cross-browser testing completed
|
||||||
|
- [ ] Mobile responsiveness verified
|
||||||
|
|
||||||
|
## Assumptions & Limits
|
||||||
|
|
||||||
|
- Assumes modern browser support for z-index
|
||||||
|
- Limited to 4 defined layers (expandable if needed)
|
||||||
|
- Requires team discipline to maintain consistency
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [MDN Z-Index Documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/z-index)
|
||||||
|
- [CSS Stacking Context Guide](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context)
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<!-- Messages in the upper-right - https://github.com/emmanuelsw/notiwind -->
|
<!-- Messages in the upper-right - https://github.com/emmanuelsw/notiwind -->
|
||||||
<NotificationGroup group="alert">
|
<NotificationGroup group="alert">
|
||||||
<div
|
<div
|
||||||
class="fixed z-[90] top-[max(1rem,env(safe-area-inset-top))] right-4 left-4 sm:left-auto sm:w-full sm:max-w-sm flex flex-col items-start justify-end"
|
class="fixed z-[120] top-[max(1rem,env(safe-area-inset-top))] right-4 left-4 sm:left-auto sm:w-full sm:max-w-sm flex flex-col items-start justify-end"
|
||||||
>
|
>
|
||||||
<Notification
|
<Notification
|
||||||
v-slot="{ notifications, close }"
|
v-slot="{ notifications, close }"
|
||||||
|
|||||||
@@ -14,4 +14,12 @@
|
|||||||
transform: translateX(100%);
|
transform: translateX(100%);
|
||||||
background-color: #FFF !important;
|
background-color: #FFF !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dialog-overlay {
|
||||||
|
@apply z-[100] fixed inset-0 bg-black/50 flex justify-center items-center p-6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog {
|
||||||
|
@apply bg-white p-4 rounded-lg w-full max-w-lg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<!-- similar to UserNameDialog -->
|
<!-- similar to UserNameDialog -->
|
||||||
<template>
|
<template>
|
||||||
<div v-if="visible" :class="overlayClasses">
|
<div v-if="visible" class="dialog-overlay">
|
||||||
<div :class="dialogClasses">
|
<div class="dialog">
|
||||||
<h1 :class="titleClasses">{{ title }}</h1>
|
<h1 :class="titleClasses">{{ title }}</h1>
|
||||||
{{ message }}
|
{{ message }}
|
||||||
Note that their name is only stored on this device.
|
Note that their name is only stored on this device.
|
||||||
@@ -61,20 +61,6 @@ export default class ContactNameDialog extends Vue {
|
|||||||
title = "Contact Name";
|
title = "Contact Name";
|
||||||
visible = false;
|
visible = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* CSS classes for the modal overlay backdrop
|
|
||||||
*/
|
|
||||||
get overlayClasses(): string {
|
|
||||||
return "z-index-50 fixed top-0 left-0 right-0 bottom-0 bg-black/50 flex justify-center items-center p-6";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CSS classes for the modal dialog container
|
|
||||||
*/
|
|
||||||
get dialogClasses(): string {
|
|
||||||
return "bg-white p-4 rounded-lg w-full max-w-[500px]";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CSS classes for the dialog title
|
* CSS classes for the dialog title
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -212,30 +212,7 @@ export default class FeedFilters extends Vue {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.dialog-overlay {
|
|
||||||
z-index: 50;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#dialogFeedFilters.dialog-overlay {
|
#dialogFeedFilters.dialog-overlay {
|
||||||
z-index: 100;
|
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog {
|
|
||||||
background-color: white;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 500px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -665,27 +665,3 @@ export default class GiftedDialog extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
.dialog-overlay {
|
|
||||||
z-index: 50;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog {
|
|
||||||
background-color: white;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 500px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -291,27 +291,3 @@ export default class GivenPrompts extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
.dialog-overlay {
|
|
||||||
z-index: 50;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog {
|
|
||||||
background-color: white;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 500px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div v-if="isOpen" class="dialog-overlay">
|
||||||
v-if="isOpen"
|
<div class="dialog">
|
||||||
class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"
|
|
||||||
>
|
|
||||||
<div class="bg-white rounded-lg p-6 max-w-2xl w-full mx-4">
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="flex justify-between items-center mb-4">
|
<div class="flex justify-between items-center mb-4">
|
||||||
<h2 class="text-xl font-bold capitalize">{{ roleName }} Details</h2>
|
<h2 class="text-xl font-bold capitalize">{{ roleName }} Details</h2>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="visible" class="dialog-overlay z-[60]">
|
<div v-if="visible" class="dialog-overlay">
|
||||||
<div class="dialog relative">
|
<div class="dialog relative">
|
||||||
<div class="text-lg text-center font-bold relative">
|
<div class="text-lg text-center font-bold relative">
|
||||||
<h1 id="ViewHeading" class="text-center font-bold">
|
<h1 id="ViewHeading" class="text-center font-bold">
|
||||||
@@ -931,32 +931,6 @@ export default class ImageMethodDialog extends Vue {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.dialog-overlay {
|
|
||||||
z-index: 50;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog {
|
|
||||||
background-color: white;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 700px;
|
|
||||||
max-height: 90vh;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add styles for diagnostic panel */
|
/* Add styles for diagnostic panel */
|
||||||
.diagnostic-panel {
|
.diagnostic-panel {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
|
|||||||
@@ -93,27 +93,3 @@ export default class InviteDialog extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
.dialog-overlay {
|
|
||||||
z-index: 50;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog {
|
|
||||||
background-color: white;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 500px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -312,28 +312,3 @@ export default class OfferDialog extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.dialog-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: rgba(0, 0, 0, 0.5);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
z-index: 50;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog {
|
|
||||||
background: white;
|
|
||||||
padding: 1.5rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
max-width: 500px;
|
|
||||||
width: 90%;
|
|
||||||
max-height: 90vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -307,27 +307,3 @@ export default class OnboardingDialog extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
.dialog-overlay {
|
|
||||||
z-index: 40;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog {
|
|
||||||
background-color: white;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 500px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Comprehensive error handling * * @author Matthew Raymer * @version 1.0.0 * @file
|
|||||||
PhotoDialog.vue */
|
PhotoDialog.vue */
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="visible" class="dialog-overlay z-[60]">
|
<div v-if="visible" class="dialog-overlay>
|
||||||
<div class="dialog relative">
|
<div class="dialog relative">
|
||||||
<div class="text-lg text-center font-light relative z-50">
|
<div class="text-lg text-center font-light relative z-50">
|
||||||
<div id="ViewHeading" :class="headingClasses">
|
<div id="ViewHeading" :class="headingClasses">
|
||||||
@@ -628,34 +628,6 @@ export default class PhotoDialog extends Vue {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* Dialog overlay styling */
|
|
||||||
.dialog-overlay {
|
|
||||||
z-index: 60;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dialog container styling */
|
|
||||||
.dialog {
|
|
||||||
background-color: white;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 700px;
|
|
||||||
max-height: 90vh;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Camera preview styling */
|
/* Camera preview styling */
|
||||||
.camera-preview {
|
.camera-preview {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|||||||
@@ -134,27 +134,3 @@ export default class UserNameDialog extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
.dialog-overlay {
|
|
||||||
z-index: 50;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog {
|
|
||||||
background-color: white;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 500px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -831,26 +831,3 @@ export default class DIDView extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
.dialog-overlay {
|
|
||||||
z-index: 50;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 1.5rem;
|
|
||||||
}
|
|
||||||
.dialog {
|
|
||||||
background-color: white;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 500px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user