feat(docs): add documentation for new input components, activity log features, theming, and expand DeesAppui docs
This commit is contained in:
12
changelog.md
12
changelog.md
@@ -1,5 +1,17 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-01-03 - 3.29.0 - feat(docs)
|
||||||
|
add documentation for new input components, activity log features, theming, and expand DeesAppui docs
|
||||||
|
|
||||||
|
- Updated top-level README to reflect component count increase (75+ → 80+) and added many new component docs
|
||||||
|
- Added documentation and examples for DeesInputList (sortable list input) and DeesInputProfilepicture (cropping, upload, processing)
|
||||||
|
- Introduced DeesTheme documentation with usage examples and CSS custom property overrides
|
||||||
|
- Expanded DeesAppui readme with architecture overview, activity log panel docs, activity entry types, and navigation/secondary menu guidance
|
||||||
|
- Documented activity log APIs and controls (activityLog.add, addMany, clear, getEntries, filter, search) and new control API helpers (setActivityLogVisible, toggleActivityLog, getActivityLogVisible)
|
||||||
|
- Updated Appbar examples to include activity log toggle properties (.showActivityLogToggle, .activityLogCount, .activityLogActive) and @activity-toggle event
|
||||||
|
- Added interface docs (IViewDefinition, IActivityEntry) and updated menu/secondary menu type references
|
||||||
|
- Changes are documentation-focused (README/element readmes); no source code logic changes shown in this diff
|
||||||
|
|
||||||
## 2026-01-03 - 3.28.1 - fix(appui)
|
## 2026-01-03 - 3.28.1 - fix(appui)
|
||||||
adjust layout and spacing in app UI components: fix activity log overflow, contain main content overscroll, and refine secondary menu padding/transition
|
adjust layout and spacing in app UI components: fix activity log overflow, contain main content overscroll, and refine secondary menu padding/transition
|
||||||
|
|
||||||
|
|||||||
159
readme.md
159
readme.md
@@ -1,6 +1,6 @@
|
|||||||
# @design.estate/dees-catalog
|
# @design.estate/dees-catalog
|
||||||
|
|
||||||
A comprehensive web components library built with TypeScript and LitElement, providing **75+ UI components** for building modern web applications with consistent design and behavior. 🚀
|
A comprehensive web components library built with TypeScript and LitElement, providing **80+ production-ready UI components** for building modern web applications with consistent design and behavior. 🚀
|
||||||
|
|
||||||
[](https://www.typescriptlang.org/)
|
[](https://www.typescriptlang.org/)
|
||||||
[](https://lit.dev/)
|
[](https://lit.dev/)
|
||||||
@@ -53,13 +53,14 @@ For developers working on this library, please refer to the [UI Components Playb
|
|||||||
| Category | Components |
|
| Category | Components |
|
||||||
|----------|------------|
|
|----------|------------|
|
||||||
| **Core UI** | [`DeesButton`](#deesbutton), [`DeesButtonExit`](#deesbuttonexit), [`DeesButtonGroup`](#deesbuttongroup), [`DeesBadge`](#deesbadge), [`DeesChips`](#deeschips), [`DeesHeading`](#deesheading), [`DeesHint`](#deeshint), [`DeesIcon`](#deesicon), [`DeesLabel`](#deeslabel), [`DeesPanel`](#deespanel), [`DeesSearchbar`](#deessearchbar), [`DeesSpinner`](#deesspinner), [`DeesToast`](#deestoast), [`DeesWindowcontrols`](#deeswindowcontrols) |
|
| **Core UI** | [`DeesButton`](#deesbutton), [`DeesButtonExit`](#deesbuttonexit), [`DeesButtonGroup`](#deesbuttongroup), [`DeesBadge`](#deesbadge), [`DeesChips`](#deeschips), [`DeesHeading`](#deesheading), [`DeesHint`](#deeshint), [`DeesIcon`](#deesicon), [`DeesLabel`](#deeslabel), [`DeesPanel`](#deespanel), [`DeesSearchbar`](#deessearchbar), [`DeesSpinner`](#deesspinner), [`DeesToast`](#deestoast), [`DeesWindowcontrols`](#deeswindowcontrols) |
|
||||||
| **Forms** | [`DeesForm`](#deesform), [`DeesInputText`](#deesinputtext), [`DeesInputCheckbox`](#deesinputcheckbox), [`DeesInputDropdown`](#deesinputdropdown), [`DeesInputRadiogroup`](#deesinputradiogroup), [`DeesInputFileupload`](#deesinputfileupload), [`DeesInputIban`](#deesinputiban), [`DeesInputPhone`](#deesinputphone), [`DeesInputQuantitySelector`](#deesinputquantityselector), [`DeesInputMultitoggle`](#deesinputmultitoggle), [`DeesInputTags`](#deesinputtags), [`DeesInputTypelist`](#deesinputtypelist), [`DeesInputRichtext`](#deesinputrichtext), [`DeesInputWysiwyg`](#deesinputwysiwyg), [`DeesInputDatepicker`](#deesinputdatepicker), [`DeesInputSearchselect`](#deesinputsearchselect), [`DeesFormSubmit`](#deesformsubmit) |
|
| **Forms** | [`DeesForm`](#deesform), [`DeesInputText`](#deesinputtext), [`DeesInputCheckbox`](#deesinputcheckbox), [`DeesInputDropdown`](#deesinputdropdown), [`DeesInputRadiogroup`](#deesinputradiogroup), [`DeesInputFileupload`](#deesinputfileupload), [`DeesInputIban`](#deesinputiban), [`DeesInputPhone`](#deesinputphone), [`DeesInputQuantitySelector`](#deesinputquantityselector), [`DeesInputMultitoggle`](#deesinputmultitoggle), [`DeesInputTags`](#deesinputtags), [`DeesInputTypelist`](#deesinputtypelist), [`DeesInputList`](#deesinputlist), [`DeesInputProfilepicture`](#deesinputprofilepicture), [`DeesInputRichtext`](#deesinputrichtext), [`DeesInputWysiwyg`](#deesinputwysiwyg), [`DeesInputDatepicker`](#deesinputdatepicker), [`DeesInputSearchselect`](#deesinputsearchselect), [`DeesFormSubmit`](#deesformsubmit) |
|
||||||
| **Layout** | [`DeesAppui`](#deesappui), [`DeesAppuiMainmenu`](#deesappuimainmenu), [`DeesAppuiSecondarymenu`](#deesappuisecondarymenu), [`DeesAppuiMaincontent`](#deesappuimaincontent), [`DeesAppuiAppbar`](#deesappuiappbar), [`DeesAppuiActivitylog`](#deesappuiactivitylog), [`DeesAppuiProfiledropdown`](#deesappuiprofiledropdown), [`DeesAppuiTabs`](#deesappuitabs), [`DeesMobileNavigation`](#deesmobilenavigation), [`DeesDashboardGrid`](#deesdashboardgrid) |
|
| **Layout** | [`DeesAppui`](#deesappui), [`DeesAppuiMainmenu`](#deesappuimainmenu), [`DeesAppuiSecondarymenu`](#deesappuisecondarymenu), [`DeesAppuiMaincontent`](#deesappuimaincontent), [`DeesAppuiAppbar`](#deesappuiappbar), [`DeesAppuiActivitylog`](#deesappuiactivitylog), [`DeesAppuiProfiledropdown`](#deesappuiprofiledropdown), [`DeesAppuiTabs`](#deesappuitabs), [`DeesMobileNavigation`](#deesmobilenavigation), [`DeesDashboardGrid`](#deesdashboardgrid) |
|
||||||
| **Data Display** | [`DeesTable`](#deestable), [`DeesDataviewCodebox`](#deesdataviewcodebox), [`DeesDataviewStatusobject`](#deesdataviewstatusobject), [`DeesPdf`](#deespdf), [`DeesStatsGrid`](#deesstatsgrid), [`DeesPagination`](#deespagination) |
|
| **Data Display** | [`DeesTable`](#deestable), [`DeesDataviewCodebox`](#deesdataviewcodebox), [`DeesDataviewStatusobject`](#deesdataviewstatusobject), [`DeesPdf`](#deespdf), [`DeesStatsGrid`](#deesstatsgrid), [`DeesPagination`](#deespagination) |
|
||||||
| **Visualization** | [`DeesChartArea`](#deeschartarea), [`DeesChartLog`](#deeschartlog) |
|
| **Visualization** | [`DeesChartArea`](#deeschartarea), [`DeesChartLog`](#deeschartlog) |
|
||||||
| **Dialogs & Overlays** | [`DeesModal`](#deesmodal), [`DeesContextmenu`](#deescontextmenu), [`DeesSpeechbubble`](#deesspeechbubble), [`DeesWindowlayer`](#deeswindowlayer) |
|
| **Dialogs & Overlays** | [`DeesModal`](#deesmodal), [`DeesContextmenu`](#deescontextmenu), [`DeesSpeechbubble`](#deesspeechbubble), [`DeesWindowlayer`](#deeswindowlayer) |
|
||||||
| **Navigation** | [`DeesStepper`](#deesstepper), [`DeesProgressbar`](#deesprogressbar) |
|
| **Navigation** | [`DeesStepper`](#deesstepper), [`DeesProgressbar`](#deesprogressbar) |
|
||||||
| **Development** | [`DeesEditor`](#deeseditor), [`DeesEditorMarkdown`](#deeseditormarkdown), [`DeesEditorMarkdownoutlet`](#deeseditormarkdownoutlet), [`DeesTerminal`](#deesterminal), [`DeesUpdater`](#deesupdater) |
|
| **Development** | [`DeesEditor`](#deeseditor), [`DeesEditorMarkdown`](#deeseditormarkdown), [`DeesEditorMarkdownoutlet`](#deeseditormarkdownoutlet), [`DeesTerminal`](#deesterminal), [`DeesUpdater`](#deesupdater) |
|
||||||
|
| **Theming** | [`DeesTheme`](#deestheme) |
|
||||||
| **Auth & Utilities** | [`DeesSimpleAppdash`](#deessimpleappdash), [`DeesSimpleLogin`](#deessimplelogin) |
|
| **Auth & Utilities** | [`DeesSimpleAppdash`](#deessimpleappdash), [`DeesSimpleLogin`](#deessimplelogin) |
|
||||||
| **Shopping** | [`DeesShoppingProductcard`](#deesshoppingproductcard) |
|
| **Shopping** | [`DeesShoppingProductcard`](#deesshoppingproductcard) |
|
||||||
|
|
||||||
@@ -482,6 +483,62 @@ Dynamic list input for managing arrays of typed values.
|
|||||||
></dees-input-typelist>
|
></dees-input-typelist>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `DeesInputList`
|
||||||
|
Advanced list input with drag-and-drop reordering, inline editing, and validation.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
<dees-input-list
|
||||||
|
key="items"
|
||||||
|
label="List Items"
|
||||||
|
placeholder="Add new item..."
|
||||||
|
.value=${['Item 1', 'Item 2', 'Item 3']}
|
||||||
|
maxItems={10} // Optional: maximum items
|
||||||
|
minItems={1} // Optional: minimum items
|
||||||
|
allowDuplicates={false} // Optional: allow duplicate values
|
||||||
|
sortable={true} // Optional: enable drag-and-drop reordering
|
||||||
|
confirmDelete={true} // Optional: confirm before deletion
|
||||||
|
@change=${handleListChange}
|
||||||
|
></dees-input-list>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- Add, edit, and remove items inline
|
||||||
|
- Drag-and-drop reordering with visual feedback
|
||||||
|
- Optional duplicate prevention
|
||||||
|
- Min/max item constraints
|
||||||
|
- Delete confirmation dialog
|
||||||
|
- Full keyboard support
|
||||||
|
- Form validation integration
|
||||||
|
|
||||||
|
#### `DeesInputProfilepicture`
|
||||||
|
Profile picture input with cropping, zoom, and image processing.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
<dees-input-profilepicture
|
||||||
|
key="avatar"
|
||||||
|
label="Profile Picture"
|
||||||
|
shape="round" // Options: round, square
|
||||||
|
size={120} // Display size in pixels
|
||||||
|
.value=${imageBase64} // Base64 encoded image or URL
|
||||||
|
allowUpload={true} // Enable upload button
|
||||||
|
allowDelete={true} // Enable delete button
|
||||||
|
maxFileSize={5242880} // Max file size in bytes (5MB)
|
||||||
|
.acceptedFormats=${['image/jpeg', 'image/png', 'image/webp']}
|
||||||
|
outputSize={800} // Output resolution in pixels
|
||||||
|
outputQuality={0.95} // JPEG quality (0-1)
|
||||||
|
@change=${handleAvatarChange}
|
||||||
|
></dees-input-profilepicture>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- Interactive cropping modal with zoom and pan
|
||||||
|
- Drag-and-drop file upload
|
||||||
|
- Round or square output shapes
|
||||||
|
- Configurable output size and quality
|
||||||
|
- File size and format validation
|
||||||
|
- Delete functionality
|
||||||
|
- Preview on hover
|
||||||
|
|
||||||
#### `DeesInputDatepicker`
|
#### `DeesInputDatepicker`
|
||||||
Date and time picker component with calendar interface and manual typing support.
|
Date and time picker component with calendar interface and manual typing support.
|
||||||
|
|
||||||
@@ -661,6 +718,7 @@ class MyApp extends DeesElement {
|
|||||||
- **Hash-based Routing**: Automatic URL synchronization with view navigation
|
- **Hash-based Routing**: Automatic URL synchronization with view navigation
|
||||||
- **RxJS Observables**: `viewChanged$` and `viewLifecycle$` for reactive programming
|
- **RxJS Observables**: `viewChanged$` and `viewLifecycle$` for reactive programming
|
||||||
- **TypeScript-first**: Typed `IViewActivationContext` passed to views on activation
|
- **TypeScript-first**: Typed `IViewActivationContext` passed to views on activation
|
||||||
|
- **Activity Log Toggle**: Built-in appbar button to show/hide activity panel with entry count badge
|
||||||
|
|
||||||
**Programmatic APIs include:**
|
**Programmatic APIs include:**
|
||||||
- `navigateToView(viewId, params?)` - Navigate between views
|
- `navigateToView(viewId, params?)` - Navigate between views
|
||||||
@@ -670,6 +728,7 @@ class MyApp extends DeesElement {
|
|||||||
- `setSecondaryMenu()`, `setSecondaryMenuCollapsed()`, `setSecondaryMenuVisible()` - Control secondary menu
|
- `setSecondaryMenu()`, `setSecondaryMenuCollapsed()`, `setSecondaryMenuVisible()` - Control secondary menu
|
||||||
- `setContentTabs()`, `setContentTabsVisible()` - Control view-specific UI
|
- `setContentTabs()`, `setContentTabsVisible()` - Control view-specific UI
|
||||||
- `activityLog.add()`, `activityLog.addMany()`, `activityLog.clear()` - Manage activity entries
|
- `activityLog.add()`, `activityLog.addMany()`, `activityLog.clear()` - Manage activity entries
|
||||||
|
- `setActivityLogVisible()`, `toggleActivityLog()`, `getActivityLogVisible()` - Control activity panel
|
||||||
|
|
||||||
**View Visibility Control:**
|
**View Visibility Control:**
|
||||||
```typescript
|
```typescript
|
||||||
@@ -740,7 +799,7 @@ Main content area with tab management support.
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### `DeesAppuiAppbar`
|
#### `DeesAppuiAppbar`
|
||||||
Professional application bar component with hierarchical menus, breadcrumb navigation, and user account management.
|
Professional application bar component with hierarchical menus, breadcrumb navigation, user account management, and activity log toggle.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
<dees-appui-appbar
|
<dees-appui-appbar
|
||||||
@@ -775,6 +834,9 @@ Professional application bar component with hierarchical menus, breadcrumb navig
|
|||||||
.breadcrumbs=${'Project > src > components'}
|
.breadcrumbs=${'Project > src > components'}
|
||||||
.showWindowControls=${true}
|
.showWindowControls=${true}
|
||||||
.showSearch=${true}
|
.showSearch=${true}
|
||||||
|
.showActivityLogToggle=${true}
|
||||||
|
.activityLogCount=${5}
|
||||||
|
.activityLogActive=${false}
|
||||||
.user=${{
|
.user=${{
|
||||||
name: 'John Doe',
|
name: 'John Doe',
|
||||||
avatar: '/path/to/avatar.jpg',
|
avatar: '/path/to/avatar.jpg',
|
||||||
@@ -782,6 +844,7 @@ Professional application bar component with hierarchical menus, breadcrumb navig
|
|||||||
}}
|
}}
|
||||||
@menu-select=${(e) => handleMenuSelect(e.detail.item)}
|
@menu-select=${(e) => handleMenuSelect(e.detail.item)}
|
||||||
@breadcrumb-navigate=${(e) => handleBreadcrumbClick(e.detail)}
|
@breadcrumb-navigate=${(e) => handleBreadcrumbClick(e.detail)}
|
||||||
|
@activity-toggle=${() => handleActivityToggle()}
|
||||||
></dees-appui-appbar>
|
></dees-appui-appbar>
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -789,9 +852,40 @@ Professional application bar component with hierarchical menus, breadcrumb navig
|
|||||||
- **Hierarchical Menu System** - Top-level menus with dropdown submenus, icons, and keyboard shortcuts
|
- **Hierarchical Menu System** - Top-level menus with dropdown submenus, icons, and keyboard shortcuts
|
||||||
- **Keyboard Navigation** - Full keyboard support (Tab, Arrow keys, Enter, Escape)
|
- **Keyboard Navigation** - Full keyboard support (Tab, Arrow keys, Enter, Escape)
|
||||||
- **Breadcrumb Navigation** - Customizable breadcrumb trail with click events
|
- **Breadcrumb Navigation** - Customizable breadcrumb trail with click events
|
||||||
- **User Account Section** - Avatar with status indicator
|
- **User Account Section** - Avatar with status indicator and profile dropdown
|
||||||
|
- **Activity Log Toggle** - Button with badge count to show/hide activity panel
|
||||||
- **Accessibility** - Full ARIA support with menubar roles
|
- **Accessibility** - Full ARIA support with menubar roles
|
||||||
|
|
||||||
|
#### `DeesAppuiActivitylog`
|
||||||
|
Real-time activity log panel for displaying user actions and system events.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
<dees-appui-activitylog></dees-appui-activitylog>
|
||||||
|
|
||||||
|
// Programmatic API
|
||||||
|
activityLog.add({
|
||||||
|
type: 'update', // Options: login, logout, view, create, update, delete, custom
|
||||||
|
user: 'John Doe',
|
||||||
|
message: 'Updated project settings',
|
||||||
|
iconName: 'lucide:settings' // Optional: custom icon
|
||||||
|
});
|
||||||
|
|
||||||
|
activityLog.addMany(entries); // Add multiple entries
|
||||||
|
activityLog.clear(); // Clear all entries
|
||||||
|
activityLog.getEntries(); // Get all entries
|
||||||
|
activityLog.filter({ user: 'John' }); // Filter by user/type
|
||||||
|
activityLog.search('settings'); // Search by message
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- Stacked entry layout with icon, user, timestamp, and message
|
||||||
|
- Date grouping (Today, Yesterday, etc.)
|
||||||
|
- Search and filter functionality
|
||||||
|
- Context menu for entry actions
|
||||||
|
- Live streaming indicator
|
||||||
|
- Animated slide-in/out panel
|
||||||
|
- Theme-aware styling
|
||||||
|
|
||||||
#### `DeesAppuiTabs`
|
#### `DeesAppuiTabs`
|
||||||
Reusable tab component with horizontal/vertical layout support.
|
Reusable tab component with horizontal/vertical layout support.
|
||||||
|
|
||||||
@@ -1089,6 +1183,40 @@ Progress indicator component for tracking completion status.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### Theming Components
|
||||||
|
|
||||||
|
#### `DeesTheme`
|
||||||
|
Theme provider component that wraps children and provides CSS custom properties for consistent theming.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Basic usage - wrap your app
|
||||||
|
<dees-theme>
|
||||||
|
<my-app></my-app>
|
||||||
|
</dees-theme>
|
||||||
|
|
||||||
|
// With custom overrides
|
||||||
|
<dees-theme
|
||||||
|
.customColors=${{
|
||||||
|
primary: '#007bff',
|
||||||
|
success: '#28a745'
|
||||||
|
}}
|
||||||
|
.customSpacing=${{
|
||||||
|
lg: '24px',
|
||||||
|
xl: '32px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<my-section></my-section>
|
||||||
|
</dees-theme>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- Provides CSS custom properties for colors, spacing, radius, shadows, and transitions
|
||||||
|
- Can be nested for section-specific theming
|
||||||
|
- Works with dark/light mode
|
||||||
|
- Overrides cascade to all child components
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Development Components
|
### Development Components
|
||||||
|
|
||||||
#### `DeesEditor`
|
#### `DeesEditor`
|
||||||
@@ -1241,6 +1369,29 @@ interface IMenuGroup {
|
|||||||
collapsed?: boolean;
|
collapsed?: boolean;
|
||||||
iconName?: string;
|
iconName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// View definition for app navigation
|
||||||
|
interface IViewDefinition {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
iconName?: string;
|
||||||
|
content: string | HTMLElement | (() => TemplateResult);
|
||||||
|
secondaryMenu?: ISecondaryMenuGroup[];
|
||||||
|
contentTabs?: IMenuItem[];
|
||||||
|
route?: string;
|
||||||
|
badge?: string | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activity log entry
|
||||||
|
interface IActivityEntry {
|
||||||
|
id?: string;
|
||||||
|
timestamp?: Date;
|
||||||
|
type: 'login' | 'logout' | 'view' | 'create' | 'update' | 'delete' | 'custom';
|
||||||
|
user: string;
|
||||||
|
message: string;
|
||||||
|
iconName?: string;
|
||||||
|
data?: Record<string, unknown>;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@design.estate/dees-catalog',
|
name: '@design.estate/dees-catalog',
|
||||||
version: '3.28.1',
|
version: '3.29.0',
|
||||||
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
|
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# DeesAppui
|
# DeesAppui
|
||||||
|
|
||||||
A comprehensive application shell component providing a complete UI framework with navigation, menus, activity logging, and view management.
|
A comprehensive application shell component providing a complete UI framework with navigation, menus, activity logging, and view management. 🚀
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
@@ -35,6 +35,34 @@ class MyApp extends DeesElement {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Architecture Overview
|
||||||
|
|
||||||
|
The DeesAppui shell consists of several interconnected components:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ AppBar (dees-appui-appbar) │
|
||||||
|
│ ├── Menus (File, Edit, View...) │
|
||||||
|
│ ├── Breadcrumbs │
|
||||||
|
│ ├── User Profile + Dropdown │
|
||||||
|
│ └── Activity Log Toggle │
|
||||||
|
├─────────────┬───────────────────────────────────┬───────────────────┤
|
||||||
|
│ Main Menu │ Content Area │ Activity Log │
|
||||||
|
│ (collapsed/ │ ├── Content Tabs │ (slide panel) │
|
||||||
|
│ expanded) │ │ (closable, from tables/lists)│ │
|
||||||
|
│ │ └── View Container │ │
|
||||||
|
│ ┌─────────┐ │ └── Active View │ │
|
||||||
|
│ │ 🏠 Home │ ├─────────────────────────────────┐ │ │
|
||||||
|
│ │ 📁 Files│ │ Secondary Menu │ │ │
|
||||||
|
│ │ ⚙ Settings ├── Collapsible Groups │ │ │
|
||||||
|
│ │ │ │ ├── Item 1 │ │ │
|
||||||
|
│ └─────────┘ │ ├── Item 2 (with badge) │ │ │
|
||||||
|
│ │ └── Item 3 │ │ │
|
||||||
|
└─────────────┴─────────────────────────────────┴───────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Configuration API
|
## Configuration API
|
||||||
|
|
||||||
### `configure(config: IAppConfig)`
|
### `configure(config: IAppConfig)`
|
||||||
@@ -155,74 +183,289 @@ appui.removeMainMenuItem('Main', 'tasks');
|
|||||||
|
|
||||||
// Selection
|
// Selection
|
||||||
appui.setMainMenuSelection('dashboard');
|
appui.setMainMenuSelection('dashboard');
|
||||||
appui.setMainMenuCollapsed(true);
|
|
||||||
|
// Visibility control
|
||||||
|
appui.setMainMenuCollapsed(true); // Collapse to icon-only sidebar
|
||||||
|
appui.setMainMenuVisible(false); // Hide completely
|
||||||
|
|
||||||
// Badges
|
// Badges
|
||||||
appui.setMainMenuBadge('inbox', 12);
|
appui.setMainMenuBadge('inbox', 12);
|
||||||
appui.clearMainMenuBadge('inbox');
|
appui.clearMainMenuBadge('inbox');
|
||||||
```
|
```
|
||||||
|
|
||||||
### Secondary Menu API
|
---
|
||||||
|
|
||||||
Views can control the secondary (contextual) menu.
|
## Secondary Menu API 📋
|
||||||
|
|
||||||
|
The secondary menu is a contextual sidebar that appears next to the main content area. It supports **collapsible groups** with icons and badges, making it perfect for:
|
||||||
|
|
||||||
|
- **Settings pages** (grouped settings categories)
|
||||||
|
- **File browsers** (folder trees)
|
||||||
|
- **Project navigation** (grouped by category)
|
||||||
|
- **Documentation** (chapters/sections)
|
||||||
|
|
||||||
|
### Collapsible Groups
|
||||||
|
|
||||||
|
Groups can be collapsed/expanded by clicking the group header. The state is visually indicated with an icon rotation.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// Set menu
|
// Set secondary menu with collapsible groups
|
||||||
appui.setSecondaryMenu({
|
appui.setSecondaryMenu({
|
||||||
heading: 'Settings',
|
heading: 'Settings',
|
||||||
groups: [
|
groups: [
|
||||||
{
|
{
|
||||||
name: 'Account',
|
name: 'Account',
|
||||||
|
iconName: 'lucide:user', // Group icon
|
||||||
|
collapsed: false, // Initial state (default: false)
|
||||||
items: [
|
items: [
|
||||||
{ key: 'profile', iconName: 'lucide:user', action: () => {} },
|
{ key: 'profile', iconName: 'lucide:user', action: () => showProfile() },
|
||||||
{ key: 'security', iconName: 'lucide:shield', action: () => {} },
|
{ key: 'security', iconName: 'lucide:shield', badge: '!', badgeVariant: 'warning', action: () => showSecurity() },
|
||||||
|
{ key: 'billing', iconName: 'lucide:credit-card', action: () => showBilling() }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Preferences',
|
||||||
|
iconName: 'lucide:settings',
|
||||||
|
collapsed: true, // Start collapsed
|
||||||
|
items: [
|
||||||
|
{ key: 'notifications', iconName: 'lucide:bell', action: () => {} },
|
||||||
|
{ key: 'appearance', iconName: 'lucide:palette', action: () => {} },
|
||||||
|
{ key: 'language', iconName: 'lucide:globe', action: () => {} }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
```
|
||||||
|
|
||||||
// Update group
|
### Secondary Menu Item Properties
|
||||||
appui.updateSecondaryMenuGroup('Account', { items: newItems });
|
|
||||||
|
|
||||||
// Add item
|
```typescript
|
||||||
appui.addSecondaryMenuItem('Account', {
|
interface ISecondaryMenuItem {
|
||||||
key: 'notifications',
|
key: string; // Unique identifier
|
||||||
iconName: 'lucide:bell',
|
iconName?: string; // Icon (e.g., 'lucide:user')
|
||||||
action: () => {}
|
action: () => void; // Click handler
|
||||||
|
badge?: string | number; // Badge text/count
|
||||||
|
badgeVariant?: 'default' | 'success' | 'warning' | 'error';
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISecondaryMenuGroup {
|
||||||
|
name: string; // Group name (shown in header)
|
||||||
|
iconName?: string; // Group icon
|
||||||
|
collapsed?: boolean; // Initial collapsed state
|
||||||
|
items: ISecondaryMenuItem[]; // Items in this group
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Updating Secondary Menu
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Update a specific group
|
||||||
|
appui.updateSecondaryMenuGroup('Account', {
|
||||||
|
items: [...newItems]
|
||||||
});
|
});
|
||||||
|
|
||||||
// Selection
|
// Add item to a group
|
||||||
|
appui.addSecondaryMenuItem('Account', {
|
||||||
|
key: 'api-keys',
|
||||||
|
iconName: 'lucide:key',
|
||||||
|
action: () => showApiKeys()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Selection (highlights the item)
|
||||||
appui.setSecondaryMenuSelection('profile');
|
appui.setSecondaryMenuSelection('profile');
|
||||||
|
|
||||||
|
// Visibility control
|
||||||
|
appui.setSecondaryMenuCollapsed(true); // Collapse panel
|
||||||
|
appui.setSecondaryMenuVisible(false); // Hide completely
|
||||||
|
|
||||||
// Clear
|
// Clear
|
||||||
appui.clearSecondaryMenu();
|
appui.clearSecondaryMenu();
|
||||||
```
|
```
|
||||||
|
|
||||||
### Content Tabs API
|
### View-Specific Secondary Menus
|
||||||
|
|
||||||
Control tabs in the main content area.
|
Each view can define its own secondary menu that appears when the view is activated:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// Set tabs
|
// In view definition
|
||||||
appui.setContentTabs([
|
{
|
||||||
{ key: 'code', iconName: 'lucide:code', action: () => {} },
|
id: 'settings',
|
||||||
{ key: 'preview', iconName: 'lucide:eye', action: () => {} }
|
name: 'Settings',
|
||||||
]);
|
content: 'my-settings-view',
|
||||||
|
secondaryMenu: [
|
||||||
|
{
|
||||||
|
name: 'General',
|
||||||
|
items: [
|
||||||
|
{ key: 'account', iconName: 'lucide:user', action: () => {} },
|
||||||
|
{ key: 'security', iconName: 'lucide:shield', action: () => {} }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
// Add/remove
|
// Or set dynamically in view's onActivate hook
|
||||||
appui.addContentTab({ key: 'debug', iconName: 'lucide:bug', action: () => {} });
|
onActivate(context: IViewActivationContext) {
|
||||||
appui.removeContentTab('debug');
|
context.appui.setSecondaryMenu({
|
||||||
|
heading: 'Project Files',
|
||||||
// Select
|
groups: [...]
|
||||||
appui.selectContentTab('preview');
|
});
|
||||||
|
}
|
||||||
// Get current
|
|
||||||
const current = appui.getSelectedContentTab();
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Activity Log API
|
---
|
||||||
|
|
||||||
Add activity entries to the right-side activity log.
|
## Content Tabs API 📑
|
||||||
|
|
||||||
|
Content tabs appear above the main view content. They're designed for **opening multiple items** from tables, lists, or other data sources—similar to browser tabs or IDE editor tabs.
|
||||||
|
|
||||||
|
### Common Use Cases
|
||||||
|
|
||||||
|
- **Table row details** - Click a row to open it as a tab
|
||||||
|
- **Document editing** - Open multiple documents
|
||||||
|
- **Entity inspection** - View customer, order, product details
|
||||||
|
- **Multi-file editing** - Edit multiple configuration files
|
||||||
|
|
||||||
|
### Closable Tabs
|
||||||
|
|
||||||
|
Tabs can be closable, allowing users to open items, work with them, and close when done:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Set initial tabs
|
||||||
|
appui.setContentTabs([
|
||||||
|
{ key: 'overview', iconName: 'lucide:home', action: () => showOverview() },
|
||||||
|
{ key: 'activity', iconName: 'lucide:activity', action: () => showActivity() }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Add a closable tab when user clicks a table row
|
||||||
|
table.addEventListener('row-click', (e) => {
|
||||||
|
const item = e.detail.item;
|
||||||
|
|
||||||
|
appui.addContentTab({
|
||||||
|
key: `item-${item.id}`,
|
||||||
|
label: item.name, // Display label
|
||||||
|
iconName: 'lucide:file',
|
||||||
|
closable: true, // Allow closing
|
||||||
|
action: () => showItemDetails(item)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Select the new tab
|
||||||
|
appui.selectContentTab(`item-${item.id}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle tab close
|
||||||
|
appui.addEventListener('tab-close', (e) => {
|
||||||
|
const tabKey = e.detail.key;
|
||||||
|
// Cleanup resources if needed
|
||||||
|
console.log(`Tab ${tabKey} closed`);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tab Management
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Add/remove tabs
|
||||||
|
appui.addContentTab({
|
||||||
|
key: 'debug',
|
||||||
|
iconName: 'lucide:bug',
|
||||||
|
closable: true,
|
||||||
|
action: () => {}
|
||||||
|
});
|
||||||
|
appui.removeContentTab('debug');
|
||||||
|
|
||||||
|
// Select tab
|
||||||
|
appui.selectContentTab('preview');
|
||||||
|
|
||||||
|
// Get current tab
|
||||||
|
const current = appui.getSelectedContentTab();
|
||||||
|
|
||||||
|
// Visibility control
|
||||||
|
appui.setContentTabsVisible(false); // Hide tab bar
|
||||||
|
|
||||||
|
// Auto-hide when only one tab
|
||||||
|
appui.setContentTabsAutoHide(true, 1); // Hide when ≤ 1 tab
|
||||||
|
```
|
||||||
|
|
||||||
|
### Opening Items from Tables/Lists
|
||||||
|
|
||||||
|
A common pattern is opening table rows as closable tabs:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@customElement('my-customers-view')
|
||||||
|
class MyCustomersView extends DeesElement {
|
||||||
|
private appui: DeesAppui;
|
||||||
|
|
||||||
|
onActivate(context: IViewActivationContext) {
|
||||||
|
this.appui = context.appui;
|
||||||
|
|
||||||
|
// Set base tabs
|
||||||
|
this.appui.setContentTabs([
|
||||||
|
{ key: 'list', label: 'All Customers', iconName: 'lucide:users', action: () => this.showList() }
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return html`
|
||||||
|
<dees-table
|
||||||
|
.data=${this.customers}
|
||||||
|
@row-dblclick=${this.openCustomerTab}
|
||||||
|
></dees-table>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
openCustomerTab(e: CustomEvent) {
|
||||||
|
const customer = e.detail.item;
|
||||||
|
const tabKey = `customer-${customer.id}`;
|
||||||
|
|
||||||
|
// Check if tab already exists
|
||||||
|
const existingTab = this.appui.getSelectedContentTab();
|
||||||
|
if (existingTab?.key === tabKey) {
|
||||||
|
return; // Already viewing this customer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new closable tab
|
||||||
|
this.appui.addContentTab({
|
||||||
|
key: tabKey,
|
||||||
|
label: customer.name,
|
||||||
|
iconName: 'lucide:user',
|
||||||
|
closable: true,
|
||||||
|
action: () => this.showCustomerDetails(customer)
|
||||||
|
});
|
||||||
|
|
||||||
|
this.appui.selectContentTab(tabKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
showCustomerDetails(customer: Customer) {
|
||||||
|
// Render customer details
|
||||||
|
this.currentView = html`<customer-details .customer=${customer}></customer-details>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
showList() {
|
||||||
|
this.currentView = html`<dees-table ...></dees-table>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Activity Log API 📊
|
||||||
|
|
||||||
|
The activity log is a slide-out panel on the right side showing user actions and system events.
|
||||||
|
|
||||||
|
### Activity Log Toggle
|
||||||
|
|
||||||
|
The appbar includes a toggle button with a badge showing the entry count:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Control visibility
|
||||||
|
appui.setActivityLogVisible(true); // Show panel
|
||||||
|
appui.toggleActivityLog(); // Toggle state
|
||||||
|
const isVisible = appui.getActivityLogVisible();
|
||||||
|
|
||||||
|
// The toggle button automatically shows entry count
|
||||||
|
// Add entries and the badge updates automatically
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding Entries
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// Add single entry
|
// Add single entry
|
||||||
@@ -234,19 +477,35 @@ appui.activityLog.add({
|
|||||||
data: { invoiceId: '123' } // Optional metadata
|
data: { invoiceId: '123' } // Optional metadata
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add multiple
|
// Add multiple entries (e.g., from backend)
|
||||||
appui.activityLog.addMany([...entries]);
|
appui.activityLog.addMany([...entries]);
|
||||||
|
|
||||||
// Clear
|
// Clear all entries
|
||||||
appui.activityLog.clear();
|
appui.activityLog.clear();
|
||||||
|
|
||||||
// Query
|
// Query entries
|
||||||
const entries = appui.activityLog.getEntries();
|
const entries = appui.activityLog.getEntries();
|
||||||
const filtered = appui.activityLog.filter({ user: 'John', type: 'create' });
|
const filtered = appui.activityLog.filter({ user: 'John', type: 'create' });
|
||||||
const searched = appui.activityLog.search('invoice');
|
const searched = appui.activityLog.search('invoice');
|
||||||
```
|
```
|
||||||
|
|
||||||
### Navigation API
|
### Activity Entry Types
|
||||||
|
|
||||||
|
Each type has a default icon that can be overridden:
|
||||||
|
|
||||||
|
| Type | Default Icon | Use Case |
|
||||||
|
|------|--------------|----------|
|
||||||
|
| `login` | `lucide:log-in` | User sign-in |
|
||||||
|
| `logout` | `lucide:log-out` | User sign-out |
|
||||||
|
| `view` | `lucide:eye` | Page/item viewed |
|
||||||
|
| `create` | `lucide:plus` | New item created |
|
||||||
|
| `update` | `lucide:pencil` | Item modified |
|
||||||
|
| `delete` | `lucide:trash` | Item deleted |
|
||||||
|
| `custom` | `lucide:activity` | Custom events |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Navigation API
|
||||||
|
|
||||||
Navigate between views programmatically.
|
Navigate between views programmatically.
|
||||||
|
|
||||||
@@ -512,6 +771,7 @@ class CrmSettings extends DeesElement {
|
|||||||
groups: [
|
groups: [
|
||||||
{
|
{
|
||||||
name: 'Account',
|
name: 'Account',
|
||||||
|
iconName: 'lucide:user',
|
||||||
items: [
|
items: [
|
||||||
{ key: 'profile', iconName: 'lucide:user', action: () => this.showSection('profile') },
|
{ key: 'profile', iconName: 'lucide:user', action: () => this.showSection('profile') },
|
||||||
{ key: 'security', iconName: 'lucide:shield', action: () => this.showSection('security') }
|
{ key: 'security', iconName: 'lucide:shield', action: () => this.showSection('security') }
|
||||||
@@ -519,6 +779,8 @@ class CrmSettings extends DeesElement {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Preferences',
|
name: 'Preferences',
|
||||||
|
iconName: 'lucide:settings',
|
||||||
|
collapsed: true,
|
||||||
items: [
|
items: [
|
||||||
{ key: 'notifications', iconName: 'lucide:bell', action: () => this.showSection('notifications') }
|
{ key: 'notifications', iconName: 'lucide:bell', action: () => this.showSection('notifications') }
|
||||||
]
|
]
|
||||||
@@ -557,4 +819,5 @@ All interfaces are exported from `@design.estate/dees-catalog`:
|
|||||||
- `IAppBarMenuItem` - App bar menu item
|
- `IAppBarMenuItem` - App bar menu item
|
||||||
- `IMainMenuConfig` - Main menu configuration
|
- `IMainMenuConfig` - Main menu configuration
|
||||||
- `ISecondaryMenuGroup` - Secondary menu group
|
- `ISecondaryMenuGroup` - Secondary menu group
|
||||||
- `ITab` - Tab definition
|
- `ISecondaryMenuItem` - Secondary menu item
|
||||||
|
- `IMenuItem` - Tab/menu item definition
|
||||||
|
|||||||
Reference in New Issue
Block a user