418 lines
13 KiB
Markdown
418 lines
13 KiB
Markdown
|
|
# @design.estate/dees-catalog-mobile
|
|||
|
|
|
|||
|
|
A mobile-optimized web component catalog for building cross-platform business applications with touch-first UI components. Built on Lit and designed for PWAs, native app wrappers, and mobile web.
|
|||
|
|
|
|||
|
|
## Issue Reporting and Security
|
|||
|
|
|
|||
|
|
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
|
|||
|
|
|
|||
|
|
## Install
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
npm install @design.estate/dees-catalog-mobile
|
|||
|
|
# or
|
|||
|
|
pnpm add @design.estate/dees-catalog-mobile
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 📱 Features
|
|||
|
|
|
|||
|
|
- **Touch-First Design** – 44px minimum touch targets, tap feedback, and gesture-friendly interactions
|
|||
|
|
- **Dark/Light Theme Support** – Automatic theme adaptation using `cssManager.bdTheme()`
|
|||
|
|
- **iOS Safe Area Support** – Proper handling of notches and home indicators
|
|||
|
|
- **iOS Keyboard Detection** – Automatic layout adjustments when soft keyboard appears
|
|||
|
|
- **Smooth Animations** – Native-feeling slide transitions for view navigation
|
|||
|
|
- **TypeScript Native** – Full type definitions and excellent IDE support
|
|||
|
|
- **Lucide Icons** – 1000+ icons with intelligent caching
|
|||
|
|
|
|||
|
|
## 🧩 Components
|
|||
|
|
|
|||
|
|
### UI Components
|
|||
|
|
|
|||
|
|
#### `<dees-mobile-button>`
|
|||
|
|
|
|||
|
|
Versatile button with multiple variants and sizes.
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<dees-mobile-button variant="primary" size="md">Click Me</dees-mobile-button>
|
|||
|
|
<dees-mobile-button variant="destructive" loading>Processing...</dees-mobile-button>
|
|||
|
|
<dees-mobile-button variant="ghost" icon><dees-mobile-icon icon="menu"></dees-mobile-icon></dees-mobile-button>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
| Property | Type | Default | Description |
|
|||
|
|
|----------|------|---------|-------------|
|
|||
|
|
| `variant` | `'default' \| 'primary' \| 'secondary' \| 'outline' \| 'ghost' \| 'destructive' \| 'link'` | `'default'` | Button style variant |
|
|||
|
|
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Button size |
|
|||
|
|
| `disabled` | `boolean` | `false` | Disable the button |
|
|||
|
|
| `loading` | `boolean` | `false` | Show loading spinner |
|
|||
|
|
| `icon` | `boolean` | `false` | Icon-only mode (square button) |
|
|||
|
|
| `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | HTML button type |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### `<dees-mobile-icon>`
|
|||
|
|
|
|||
|
|
Lucide icon integration with smart caching.
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<dees-mobile-icon icon="home" size="24" color="#3b82f6"></dees-mobile-icon>
|
|||
|
|
<dees-mobile-icon icon="settings" size="32"></dees-mobile-icon>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
| Property | Type | Default | Description |
|
|||
|
|
|----------|------|---------|-------------|
|
|||
|
|
| `icon` | `string` | `''` | Lucide icon name (e.g., `'home'`, `'settings'`, `'user'`) |
|
|||
|
|
| `size` | `string \| number` | `'24'` | Icon size in pixels |
|
|||
|
|
| `color` | `string` | `'currentColor'` | Icon color |
|
|||
|
|
| `strokeWidth` | `string \| number` | `'2'` | Stroke width |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### `<dees-mobile-header>`
|
|||
|
|
|
|||
|
|
App header with flexible slot-based layout.
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<dees-mobile-header title="My App" subtitle="Dashboard">
|
|||
|
|
<dees-mobile-button slot="left-action" icon variant="ghost">
|
|||
|
|
<dees-mobile-icon icon="menu"></dees-mobile-icon>
|
|||
|
|
</dees-mobile-button>
|
|||
|
|
<dees-mobile-button slot="actions" icon variant="ghost">
|
|||
|
|
<dees-mobile-icon icon="search"></dees-mobile-icon>
|
|||
|
|
</dees-mobile-button>
|
|||
|
|
</dees-mobile-header>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
| Property | Type | Default | Description |
|
|||
|
|
|----------|------|---------|-------------|
|
|||
|
|
| `title` | `string` | `''` | Header title |
|
|||
|
|
| `subtitle` | `string` | `''` | Optional subtitle |
|
|||
|
|
|
|||
|
|
**Slots:** `left-action`, `content`, `middle`, `actions`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### `<dees-mobile-modal>`
|
|||
|
|
|
|||
|
|
Centered modal dialog with backdrop.
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<dees-mobile-modal .open=${this.showModal} title="Confirm Action" @close=${() => this.showModal = false}>
|
|||
|
|
<p>Are you sure you want to proceed?</p>
|
|||
|
|
<div slot="footer">
|
|||
|
|
<dees-mobile-button variant="outline" @click=${() => this.showModal = false}>Cancel</dees-mobile-button>
|
|||
|
|
<dees-mobile-button variant="primary" @click=${this.confirm}>Confirm</dees-mobile-button>
|
|||
|
|
</div>
|
|||
|
|
</dees-mobile-modal>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
| Property | Type | Default | Description |
|
|||
|
|
|----------|------|---------|-------------|
|
|||
|
|
| `open` | `boolean` | `false` | Controls visibility |
|
|||
|
|
| `title` | `string` | `''` | Modal title |
|
|||
|
|
| `showCloseButton` | `boolean` | `true` | Show close button in header |
|
|||
|
|
|
|||
|
|
**Events:** `close`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### `<dees-mobile-actionsheet>`
|
|||
|
|
|
|||
|
|
iOS-style bottom action sheet.
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<dees-mobile-actionsheet
|
|||
|
|
title="Choose an action"
|
|||
|
|
.options=${[
|
|||
|
|
{ id: 'edit', icon: 'pencil', title: 'Edit', subtitle: 'Modify this item' },
|
|||
|
|
{ id: 'share', icon: 'share', title: 'Share' },
|
|||
|
|
{ id: 'delete', icon: 'trash-2', iconColor: '#dc2626', title: 'Delete' }
|
|||
|
|
]}
|
|||
|
|
@select=${(e) => console.log('Selected:', e.detail.id)}
|
|||
|
|
@close=${() => this.hideActionSheet()}
|
|||
|
|
></dees-mobile-actionsheet>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
| Property | Type | Default | Description |
|
|||
|
|
|----------|------|---------|-------------|
|
|||
|
|
| `title` | `string` | `''` | Sheet title |
|
|||
|
|
| `options` | `IActionSheetOption[]` | `[]` | Action options |
|
|||
|
|
| `cancelText` | `string` | `'Cancel'` | Cancel button text |
|
|||
|
|
|
|||
|
|
**Events:** `select`, `close`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### `<dees-mobile-toast>`
|
|||
|
|
|
|||
|
|
Toast notification system.
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<dees-mobile-toast
|
|||
|
|
.open=${this.showToast}
|
|||
|
|
message="Item saved successfully!"
|
|||
|
|
type="success"
|
|||
|
|
duration="3000"
|
|||
|
|
></dees-mobile-toast>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Layout Components
|
|||
|
|
|
|||
|
|
#### `<dees-mobile-navigation>`
|
|||
|
|
|
|||
|
|
Bottom tab navigation bar with badge support.
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<dees-mobile-navigation
|
|||
|
|
.activeTab=${'home'}
|
|||
|
|
.tabs=${[
|
|||
|
|
{ id: 'home', icon: 'home', label: 'Home' },
|
|||
|
|
{ id: 'search', icon: 'search', label: 'Search' },
|
|||
|
|
{ id: 'notifications', icon: 'bell', label: 'Alerts', badge: 5 },
|
|||
|
|
{ id: 'profile', icon: 'user', label: 'Profile' }
|
|||
|
|
]}
|
|||
|
|
@tab-change=${(e) => this.activeTab = e.detail.tab}
|
|||
|
|
></dees-mobile-navigation>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
| Property | Type | Default | Description |
|
|||
|
|
|----------|------|---------|-------------|
|
|||
|
|
| `activeTab` | `string` | `''` | Currently active tab ID |
|
|||
|
|
| `tabs` | `INavigationTab[]` | `[]` | Array of tab definitions |
|
|||
|
|
|
|||
|
|
**Events:** `tab-change`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### `<dees-mobile-applayout>`
|
|||
|
|
|
|||
|
|
Full-screen app layout with iOS keyboard handling.
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<dees-mobile-applayout>
|
|||
|
|
<dees-mobile-header slot="header" title="My App"></dees-mobile-header>
|
|||
|
|
|
|||
|
|
<div slot="content">
|
|||
|
|
<!-- Your app content here -->
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<dees-mobile-navigation slot="navigation" .tabs=${this.tabs}></dees-mobile-navigation>
|
|||
|
|
</dees-mobile-applayout>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Slots:** `header`, `content`, `navigation`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### `<dees-mobile-viewstack>` + `<dees-mobile-view>`
|
|||
|
|
|
|||
|
|
Stack-based navigation with smooth slide transitions. Perfect for drill-down interfaces (lists → detail → sub-detail).
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<dees-mobile-viewstack initial-view="lists" @view-changed=${this.handleViewChange}>
|
|||
|
|
<dees-mobile-view view-id="lists">
|
|||
|
|
<my-lists-view @item-click=${(e) => this.viewstack.pushView('detail')}></my-lists-view>
|
|||
|
|
</dees-mobile-view>
|
|||
|
|
|
|||
|
|
<dees-mobile-view view-id="detail">
|
|||
|
|
<my-detail-view @back=${() => this.viewstack.popView()}></my-detail-view>
|
|||
|
|
</dees-mobile-view>
|
|||
|
|
|
|||
|
|
<dees-mobile-view view-id="subdetail">
|
|||
|
|
<my-subdetail-view></my-subdetail-view>
|
|||
|
|
</dees-mobile-view>
|
|||
|
|
</dees-mobile-viewstack>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Viewstack API:**
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
const viewstack = document.querySelector('dees-mobile-viewstack');
|
|||
|
|
|
|||
|
|
// Navigate forward (slides in from right)
|
|||
|
|
await viewstack.pushView('detail');
|
|||
|
|
|
|||
|
|
// Navigate back (slides out to right)
|
|||
|
|
await viewstack.popView();
|
|||
|
|
|
|||
|
|
// Replace current view (no animation)
|
|||
|
|
viewstack.replaceView('other');
|
|||
|
|
|
|||
|
|
// Go back to root view
|
|||
|
|
await viewstack.goToRoot(true); // animated
|
|||
|
|
viewstack.goToRoot(false); // instant
|
|||
|
|
|
|||
|
|
// Properties
|
|||
|
|
viewstack.currentView; // Current view ID
|
|||
|
|
viewstack.stackDepth; // Number of views in stack
|
|||
|
|
viewstack.canGoBack; // true if stack depth > 1
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Events:** `view-changed`, `transition-start`, `transition-end`, `navigate-back`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Input Components
|
|||
|
|
|
|||
|
|
#### `<dees-mobile-input>`
|
|||
|
|
|
|||
|
|
Form input with label, validation, and iOS zoom prevention.
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<dees-mobile-input
|
|||
|
|
label="Email Address"
|
|||
|
|
type="email"
|
|||
|
|
placeholder="you@example.com"
|
|||
|
|
required
|
|||
|
|
autocomplete="email"
|
|||
|
|
@input=${(e) => console.log(e.detail.value)}
|
|||
|
|
></dees-mobile-input>
|
|||
|
|
|
|||
|
|
<dees-mobile-input
|
|||
|
|
label="Password"
|
|||
|
|
type="password"
|
|||
|
|
error="Password must be at least 8 characters"
|
|||
|
|
></dees-mobile-input>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
| Property | Type | Default | Description |
|
|||
|
|
|----------|------|---------|-------------|
|
|||
|
|
| `type` | `'text' \| 'email' \| 'password' \| 'number' \| 'tel' \| 'url' \| 'search'` | `'text'` | Input type |
|
|||
|
|
| `label` | `string` | `''` | Label text |
|
|||
|
|
| `placeholder` | `string` | `''` | Placeholder text |
|
|||
|
|
| `value` | `string` | `''` | Input value |
|
|||
|
|
| `disabled` | `boolean` | `false` | Disable input |
|
|||
|
|
| `required` | `boolean` | `false` | Mark as required |
|
|||
|
|
| `error` | `string` | `''` | Error message |
|
|||
|
|
| `autocomplete` | `string` | `''` | Autocomplete hint |
|
|||
|
|
|
|||
|
|
**Events:** `input`, `change`, `input-focus`, `input-blur`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎨 Theming
|
|||
|
|
|
|||
|
|
Components automatically adapt to dark/light themes. Theme switching is handled via CSS variables and `cssManager.bdTheme()`:
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// In your component styles
|
|||
|
|
css`
|
|||
|
|
.my-element {
|
|||
|
|
background: ${cssManager.bdTheme('#ffffff', '#09090b')};
|
|||
|
|
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
|
|||
|
|
border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
|
|||
|
|
}
|
|||
|
|
`
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### CSS Variables
|
|||
|
|
|
|||
|
|
Components use these CSS custom properties:
|
|||
|
|
|
|||
|
|
```css
|
|||
|
|
:root {
|
|||
|
|
--dees-primary: #3b82f6;
|
|||
|
|
--dees-background: #ffffff;
|
|||
|
|
--dees-foreground: #09090b;
|
|||
|
|
--dees-muted-foreground: #71717a;
|
|||
|
|
--dees-border: #e4e4e7;
|
|||
|
|
--dees-ring: #3b82f6;
|
|||
|
|
--dees-danger: #dc2626;
|
|||
|
|
--dees-radius: 0.5rem;
|
|||
|
|
--dees-radius-lg: 0.75rem;
|
|||
|
|
--dees-transition-fast: 150ms;
|
|||
|
|
--safe-area-inset-bottom: env(safe-area-inset-bottom, 0px);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📦 Full Example
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import {
|
|||
|
|
DeesMobileButton,
|
|||
|
|
DeesMobileHeader,
|
|||
|
|
DeesMobileNavigation,
|
|||
|
|
DeesMobileViewstack,
|
|||
|
|
DeesMobileView,
|
|||
|
|
DeesMobileInput,
|
|||
|
|
} from '@design.estate/dees-catalog-mobile';
|
|||
|
|
|
|||
|
|
// All components auto-register. Just use them in your templates:
|
|||
|
|
const template = html`
|
|||
|
|
<dees-mobile-applayout>
|
|||
|
|
<dees-mobile-header slot="header" title="My App"></dees-mobile-header>
|
|||
|
|
|
|||
|
|
<dees-mobile-viewstack slot="content" initial-view="home">
|
|||
|
|
<dees-mobile-view view-id="home">
|
|||
|
|
<div class="home-content">
|
|||
|
|
<h1>Welcome!</h1>
|
|||
|
|
<dees-mobile-button variant="primary" @click=${() => viewstack.pushView('settings')}>
|
|||
|
|
Go to Settings
|
|||
|
|
</dees-mobile-button>
|
|||
|
|
</div>
|
|||
|
|
</dees-mobile-view>
|
|||
|
|
|
|||
|
|
<dees-mobile-view view-id="settings">
|
|||
|
|
<div class="settings-content">
|
|||
|
|
<dees-mobile-input label="Username" placeholder="Enter username"></dees-mobile-input>
|
|||
|
|
<dees-mobile-button @click=${() => viewstack.popView()}>Back</dees-mobile-button>
|
|||
|
|
</div>
|
|||
|
|
</dees-mobile-view>
|
|||
|
|
</dees-mobile-viewstack>
|
|||
|
|
|
|||
|
|
<dees-mobile-navigation
|
|||
|
|
slot="navigation"
|
|||
|
|
.activeTab=${'home'}
|
|||
|
|
.tabs=${[
|
|||
|
|
{ id: 'home', icon: 'home', label: 'Home' },
|
|||
|
|
{ id: 'settings', icon: 'settings', label: 'Settings' },
|
|||
|
|
]}
|
|||
|
|
></dees-mobile-navigation>
|
|||
|
|
</dees-mobile-applayout>
|
|||
|
|
`;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🛠️ Development
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Install dependencies
|
|||
|
|
pnpm install
|
|||
|
|
|
|||
|
|
# Start development server with wcctools
|
|||
|
|
pnpm run watch
|
|||
|
|
|
|||
|
|
# Build for production
|
|||
|
|
pnpm run build
|
|||
|
|
|
|||
|
|
# Run tests
|
|||
|
|
pnpm test
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## License and Legal Information
|
|||
|
|
|
|||
|
|
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](./license) file.
|
|||
|
|
|
|||
|
|
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
|||
|
|
|
|||
|
|
### Trademarks
|
|||
|
|
|
|||
|
|
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
|
|||
|
|
|
|||
|
|
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
|
|||
|
|
|
|||
|
|
### Company Information
|
|||
|
|
|
|||
|
|
Task Venture Capital GmbH
|
|||
|
|
Registered at District Court Bremen HRB 35230 HB, Germany
|
|||
|
|
|
|||
|
|
For any legal inquiries or further information, please contact us via email at hello@task.vc.
|
|||
|
|
|
|||
|
|
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|