@chrryai/chrry 1.1.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/About.module.scss +112 -0
- package/Account.module.scss +159 -0
- package/AddToHomeScreen.module.scss +126 -0
- package/Affiliate.module.scss +245 -0
- package/AffiliateDashboard.module.scss +269 -0
- package/Agent.module.scss +197 -0
- package/AnimatedWrapper.module.scss +0 -0
- package/App.module.scss +283 -0
- package/Bookmark.module.scss +15 -0
- package/Calendar.module.scss +824 -0
- package/CharacterProfiles.module.scss +29 -0
- package/Chat.module.scss +932 -0
- package/Checkbox.module.scss +67 -0
- package/Chrry.module.scss +69 -0
- package/Collaborate.module.scss +22 -0
- package/CollaborationStatus.module.scss +17 -0
- package/CollaborationTooltip.module.scss +257 -0
- package/ColorScheme.module.scss +24 -0
- package/EditThread.module.scss +51 -0
- package/EmptyStateTips.module.scss +52 -0
- package/EnableNotifications.module.scss +20 -0
- package/EventModal.module.scss +277 -0
- package/Img.module.scss +48 -0
- package/Instructions.module.scss +333 -0
- package/LICENSE +664 -0
- package/LanguageSwitcher.module.scss +21 -0
- package/Loading.module.scss +32 -0
- package/MarkdownContent.module.scss +161 -0
- package/MemoryConsent.module.scss +41 -0
- package/Menu.module.scss +272 -0
- package/Message.module.scss +470 -0
- package/Messages.module.scss +86 -0
- package/Modal.module.scss +118 -0
- package/README.md +112 -0
- package/Search.module.scss +26 -0
- package/Select.module.scss +32 -0
- package/Share.module.scss +84 -0
- package/Sidebar.module.scss +69 -0
- package/SignIn.module.scss +129 -0
- package/Skeleton.module.scss +232 -0
- package/SplashScreen.module.scss +189 -0
- package/Star.module.scss +15 -0
- package/Store.module.scss +240 -0
- package/Subscribe.module.scss +219 -0
- package/Testimonials.module.scss +33 -0
- package/Thread.module.scss +111 -0
- package/Threads.module.scss +105 -0
- package/TypingIndicator.module.scss +93 -0
- package/Users.module.scss +98 -0
- package/Version.module.scss +22 -0
- package/Weather.module.scss +31 -0
- package/Why.module.scss +79 -0
- package/__tests__/README.md +126 -0
- package/__tests__/TestComponent.module.scss +236 -0
- package/animations.scss +163 -0
- package/breakpoints.scss +8 -0
- package/context/AppContext.module.scss +22 -0
- package/context/providers/README.md +329 -0
- package/dist/About.module-RPTFOKG6.scss +112 -0
- package/dist/Account.module-AA2NOD5S.scss +159 -0
- package/dist/AddToHomeScreen.module-P6HAQ4QD.scss +126 -0
- package/dist/Affiliate.module-YM7MG54E.scss +245 -0
- package/dist/AffiliateDashboard.module-SZQJJBME.scss +269 -0
- package/dist/Agent.module-66YIBDMM.scss +197 -0
- package/dist/App.module-TOWYJFPB.scss +283 -0
- package/dist/Bookmark.module-UVMQ4TED.scss +15 -0
- package/dist/Calendar.module-HHEIXJEA.scss +824 -0
- package/dist/CharacterProfiles.module-KABR34TV.scss +29 -0
- package/dist/Chat.module-Y4TGJLBQ.scss +932 -0
- package/dist/Checkbox.module-RNW2YOC5.scss +67 -0
- package/dist/Chrry.module-SLPTRY52.scss +69 -0
- package/dist/Collaborate.module-MLRE23FZ.scss +22 -0
- package/dist/CollaborationStatus.module-CRGOOW56.scss +17 -0
- package/dist/ColorScheme.module-N7SJ5N52.scss +24 -0
- package/dist/EditThread.module-L3HOEGS3.scss +51 -0
- package/dist/EmptyStateTips.module-JLNPQ4OO.scss +52 -0
- package/dist/EnableNotifications.module-C4MYQTUA.scss +20 -0
- package/dist/EventModal.module-K7VNKTCE.scss +277 -0
- package/dist/Instructions.module-JMFWEXAP.scss +333 -0
- package/dist/LanguageSwitcher.module-MT2SIZ4L.scss +21 -0
- package/dist/Loading.module-OU42QILE.scss +32 -0
- package/dist/MarkdownContent.module-64GHE3YP.scss +161 -0
- package/dist/MemoryConsent.module-FZL3REH4.scss +41 -0
- package/dist/Menu.module-RVXPXILR.scss +272 -0
- package/dist/Message.module-5UUYCVY2.scss +470 -0
- package/dist/Messages.module-GBPUAPAI.scss +86 -0
- package/dist/Modal.module-TOU4YLFQ.scss +118 -0
- package/dist/Search.module-GU3BRADG.scss +26 -0
- package/dist/Select.module-R7QM256C.scss +32 -0
- package/dist/Share.module-VQBCBSA5.scss +84 -0
- package/dist/Sidebar.module-AUSDVTCY.scss +69 -0
- package/dist/SignIn.module-53SOSG63.scss +129 -0
- package/dist/Skeleton.module-REMEBLDY.scss +232 -0
- package/dist/Store.module-NP6776GY.scss +240 -0
- package/dist/Subscribe.module-NVGQ57RA.scss +219 -0
- package/dist/Thread.module-QAJI6KOQ.scss +111 -0
- package/dist/Threads.module-J54DFQQZ.scss +105 -0
- package/dist/Users.module-ZRHCY63D.scss +98 -0
- package/dist/Version.module-MLMD7GW5.scss +22 -0
- package/dist/Weather.module-NT6XFKA7.scss +31 -0
- package/dist/Why.module-UVZJCJF7.scss +79 -0
- package/dist/index.d.mts +1408 -0
- package/dist/index.d.ts +1408 -0
- package/dist/index.js +44600 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +44575 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react-tooltip.min-LLVNRY3Z.css +1 -0
- package/globals.css +91 -0
- package/globals.scss +585 -0
- package/icons/README.md +150 -0
- package/package.json +118 -0
- package/styles/view-transitions.css +207 -0
- package/toRem.scss +6 -0
- package/utils.module.scss +116 -0
- package/utils.scss +88 -0
package/icons/README.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Platform-Aware Icon System
|
|
2
|
+
|
|
3
|
+
1. Smart Meeting Scheduler 🗓️
|
|
4
|
+
Ask: "Schedule a team standup meeting tomorrow at 10 AM for 30 minutes with the title 'Daily Sync' and invite emma.brown@google.com"
|
|
5
|
+
|
|
6
|
+
Why it's impressive: Shows AI understanding multiple parameters (time, duration, title, attendees) and creating a complete calendar event in one command.
|
|
7
|
+
|
|
8
|
+
2. Conflict Detector ⚠️
|
|
9
|
+
Ask: "Do I have any meetings between 2 PM and 5 PM today? If yes, can you reschedule my 3 PM call to tomorrow same time?"
|
|
10
|
+
|
|
11
|
+
Why it's impressive: Demonstrates AI reading calendar, detecting conflicts, and proactively suggesting/making changes.
|
|
12
|
+
|
|
13
|
+
3. Weekly Overview 📊
|
|
14
|
+
Ask: "What's my schedule for this week? Highlight any back-to-back meetings and suggest breaks I should add."
|
|
15
|
+
|
|
16
|
+
Why it's impressive: Shows AI analyzing patterns, providing insights, and making smart recommendations for work-life balance.
|
|
17
|
+
|
|
18
|
+
4. Natural Language Event Creation 🎯
|
|
19
|
+
Ask: "Block my calendar every Friday afternoon from 2-5 PM for the next month as 'Focus Time - No Meetings' and mark it as busy"
|
|
20
|
+
|
|
21
|
+
Why it's impressive: Demonstrates recurring event creation, natural language understanding, and calendar blocking strategy - perfect for productivity.
|
|
22
|
+
|
|
23
|
+
Pro tip for video: Start with #4 (most impressive), then show #1 (practical), then #3 (analytical), and end with #2 (problem-solving). This creates a compelling narrative from "wow" to "useful" to "intelligent."
|
|
24
|
+
|
|
25
|
+
This directory contains a platform-aware icon system that automatically uses the correct icon library based on the execution environment.
|
|
26
|
+
|
|
27
|
+
## 🎯 Features
|
|
28
|
+
|
|
29
|
+
- **Automatic Platform Detection**: Uses `lucide-react` for web and `lucide-react-native` for native
|
|
30
|
+
- **Single Import Path**: Import from `chrry/icons` regardless of platform
|
|
31
|
+
- **Type-Safe**: Full TypeScript support with `IconProps`
|
|
32
|
+
- **Zero Configuration**: React Native Metro and Next.js handle it automatically
|
|
33
|
+
|
|
34
|
+
## 📦 Usage
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { Star, Heart, Settings, Menu } from 'chrry/icons'
|
|
38
|
+
|
|
39
|
+
function MyComponent() {
|
|
40
|
+
return (
|
|
41
|
+
<div>
|
|
42
|
+
<Star size={24} color="gold" />
|
|
43
|
+
<Heart size={24} color="red" />
|
|
44
|
+
<Settings size={24} />
|
|
45
|
+
</div>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 🔧 How It Works
|
|
51
|
+
|
|
52
|
+
The system uses platform-specific file extensions that bundlers automatically resolve:
|
|
53
|
+
|
|
54
|
+
### File Structure
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
icons/
|
|
58
|
+
├── index.tsx # Default (web) - used by Next.js
|
|
59
|
+
├── index.web.tsx # Web-specific exports (lucide-react)
|
|
60
|
+
└── index.native.tsx # Native-specific exports (lucide-react-native)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Platform Resolution
|
|
64
|
+
|
|
65
|
+
- **Next.js**: Uses `index.tsx` → `index.web.tsx` → `lucide-react`
|
|
66
|
+
- **React Native Metro**: Uses `index.native.tsx` → `lucide-react-native`
|
|
67
|
+
|
|
68
|
+
This approach ensures:
|
|
69
|
+
|
|
70
|
+
- ✅ No React Native dependencies in web builds
|
|
71
|
+
- ✅ Proper native icons on ios/Android
|
|
72
|
+
- ✅ Single import path for all platforms
|
|
73
|
+
|
|
74
|
+
## 🎨 Available Icons
|
|
75
|
+
|
|
76
|
+
All Lucide icons are available with consistent naming:
|
|
77
|
+
|
|
78
|
+
- `Star`, `Heart`, `Menu`, `Settings`
|
|
79
|
+
- `CircleX` (mapped from `X`)
|
|
80
|
+
- `CircleArrowLeft` (mapped from `ArrowLeft`)
|
|
81
|
+
- `ImageIcon` (mapped from `Image`)
|
|
82
|
+
- `VideoIcon` (mapped from `Video`)
|
|
83
|
+
- `FileIcon` (mapped from `File`)
|
|
84
|
+
- `TextIcon` (mapped from `Text`)
|
|
85
|
+
- And 100+ more...
|
|
86
|
+
|
|
87
|
+
## 🔄 Migration from Tamagui
|
|
88
|
+
|
|
89
|
+
If you're migrating from `@tamagui/lucide-icons`:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
// Before
|
|
93
|
+
import { Star, Heart } from "@tamagui/lucide-icons"
|
|
94
|
+
|
|
95
|
+
// After
|
|
96
|
+
import { Star, Heart } from "./icons"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Run the replacement script:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
cd packages/ui
|
|
103
|
+
chmod +x replace-icons.sh
|
|
104
|
+
./replace-icons.sh
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## 🚀 Benefits
|
|
108
|
+
|
|
109
|
+
1. **No React Native Dependencies on Web**: Avoids `react-native-svg` build errors in Next.js
|
|
110
|
+
2. **True Cross-Platform**: Works seamlessly on web, ios, Android, and browser extensions
|
|
111
|
+
3. **Automatic Resolution**: Bundlers handle platform detection at build time
|
|
112
|
+
4. **Type Safety**: Full TypeScript support with proper types for each platform
|
|
113
|
+
|
|
114
|
+
## 📝 Adding New Icons
|
|
115
|
+
|
|
116
|
+
All Lucide icons are automatically available via `export *`. Just import and use:
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
import { NewIcon } from 'chrry/icons'
|
|
120
|
+
|
|
121
|
+
// Works immediately if the icon exists in lucide-react/lucide-react-native
|
|
122
|
+
<NewIcon size={24} />
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
No manual exports needed!
|
|
126
|
+
|
|
127
|
+
## 🐛 Troubleshooting
|
|
128
|
+
|
|
129
|
+
### TypeScript errors about missing icons
|
|
130
|
+
|
|
131
|
+
- Make sure both `lucide-react` and `lucide-react-native` are installed
|
|
132
|
+
- Run `npm install` in the `packages/ui` directory
|
|
133
|
+
|
|
134
|
+
### Icons not rendering on web
|
|
135
|
+
|
|
136
|
+
- Verify the icon exists in `lucide-react`
|
|
137
|
+
- Check the import path: `from 'chrry/icons'`
|
|
138
|
+
- Clear Next.js cache: `rm -rf .next && npm run dev`
|
|
139
|
+
|
|
140
|
+
### Icons not rendering on native
|
|
141
|
+
|
|
142
|
+
- Verify the icon exists in `lucide-react-native`
|
|
143
|
+
- Check that Metro bundler is resolving `index.native.tsx`
|
|
144
|
+
- Clear Metro cache: `npm start -- --reset-cache`
|
|
145
|
+
|
|
146
|
+
### Build errors about react-native-svg
|
|
147
|
+
|
|
148
|
+
- This should not happen with the new structure
|
|
149
|
+
- Verify `index.tsx` exports from `./index.web` (not direct lucide-react-native import)
|
|
150
|
+
- Ensure Next.js is not trying to bundle native files
|
package/package.json
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@chrryai/chrry",
|
|
3
|
+
"version": "1.1.78",
|
|
4
|
+
"description": "A modern, cross-platform UI library for React, React Native, and Next.js",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./*": "./*"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"**/*.css",
|
|
19
|
+
"**/*.scss",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"private": false,
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/chrryai/chrry.git"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"react",
|
|
32
|
+
"react-native",
|
|
33
|
+
"nextjs",
|
|
34
|
+
"ui",
|
|
35
|
+
"components",
|
|
36
|
+
"cross-platform",
|
|
37
|
+
"typescript"
|
|
38
|
+
],
|
|
39
|
+
"author": "Iliyan Velinov",
|
|
40
|
+
"license": "AGPL-3.0",
|
|
41
|
+
"bugs": {
|
|
42
|
+
"url": "https://github.com/chrryai/chrry/issues"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://chrry.dev",
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "tsup",
|
|
47
|
+
"dev": "tsup --watch",
|
|
48
|
+
"lint": "eslint . --max-warnings 1500",
|
|
49
|
+
"generate:component": "turbo gen react-component",
|
|
50
|
+
"check-types": "tsc --noEmit",
|
|
51
|
+
"prepublishOnly": "npm run build"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@repo/eslint-config": "*",
|
|
55
|
+
"@repo/typescript-config": "*",
|
|
56
|
+
"@types/node": "^22.15.3",
|
|
57
|
+
"@types/react": "19.1.12",
|
|
58
|
+
"eslint": "^9.34.0",
|
|
59
|
+
"tsup": "^8.0.0",
|
|
60
|
+
"typescript": "5.8.2"
|
|
61
|
+
},
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
64
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
65
|
+
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"@hookform/resolvers": "^5.2.2",
|
|
68
|
+
"@lobehub/icons": "^2.23.0",
|
|
69
|
+
"@react-native-community/netinfo": "^11.4.1",
|
|
70
|
+
"@react-spring/native": "^10.0.3",
|
|
71
|
+
"@react-spring/web": "^10.0.3",
|
|
72
|
+
"@stripe/stripe-js": "^7.7.0",
|
|
73
|
+
"@tanstack/react-query": "^5.83.0",
|
|
74
|
+
"@types/chrome": "^0.1.1",
|
|
75
|
+
"@types/nprogress": "^0.2.3",
|
|
76
|
+
"@types/react-dom": "19.1.1",
|
|
77
|
+
"@types/react-syntax-highlighter": "^15.5.13",
|
|
78
|
+
"@types/sanitize-html": "^2.16.0",
|
|
79
|
+
"@uidotdev/usehooks": "^2.4.1",
|
|
80
|
+
"ai": "^5.0.0",
|
|
81
|
+
"antd": "^5.26.7",
|
|
82
|
+
"clsx": "^2.1.1",
|
|
83
|
+
"date-fns": "^4.1.0",
|
|
84
|
+
"emoji-picker-react": "^4.14.0",
|
|
85
|
+
"i18next": "^25.3.4",
|
|
86
|
+
"javascript-time-ago": "^2.5.11",
|
|
87
|
+
"lucide-react": "^0.534.0",
|
|
88
|
+
"lucide-react-native": "^0.462.0",
|
|
89
|
+
"markdown-to-jsx": "^7.7.13",
|
|
90
|
+
"next-auth": "^4.24.11",
|
|
91
|
+
"next-themes": "^0.4.6",
|
|
92
|
+
"nextjs-toploader": "^3.8.16",
|
|
93
|
+
"nprogress": "^0.2.0",
|
|
94
|
+
"react": "^19.1.1",
|
|
95
|
+
"react-audio-play": "^1.0.4",
|
|
96
|
+
"react-big-calendar": "^1.19.4",
|
|
97
|
+
"react-dnd": "^16.0.1",
|
|
98
|
+
"react-dnd-html5-backend": "^16.0.1",
|
|
99
|
+
"react-dom": "^19.1.1",
|
|
100
|
+
"react-hook-form": "^7.63.0",
|
|
101
|
+
"react-hot-toast": "^2.5.2",
|
|
102
|
+
"react-i18next": "^15.6.1",
|
|
103
|
+
"react-icons": "^5.5.0",
|
|
104
|
+
"react-intersection-observer": "^9.16.0",
|
|
105
|
+
"react-markdown": "^10.1.0",
|
|
106
|
+
"react-native-reanimated": "^4.1.3",
|
|
107
|
+
"react-select": "^5.10.2",
|
|
108
|
+
"react-syntax-highlighter": "^15.6.1",
|
|
109
|
+
"react-use-cookie": "^1.6.1",
|
|
110
|
+
"remark-gfm": "^4.0.1",
|
|
111
|
+
"sanitize-html": "^2.17.0",
|
|
112
|
+
"sass": "^1.90.0",
|
|
113
|
+
"superjson": "^2.2.2",
|
|
114
|
+
"use-debounce": "^10.0.5",
|
|
115
|
+
"usehooks-ts": "^3.1.1",
|
|
116
|
+
"zod": "^4.1.11"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/* View Transitions API - Optimized for in-page transitions */
|
|
2
|
+
|
|
3
|
+
/* ============================================
|
|
4
|
+
DEFAULT: Smooth page transitions
|
|
5
|
+
Desktop: Slide up/down
|
|
6
|
+
Mobile: Slide left/right
|
|
7
|
+
============================================ */
|
|
8
|
+
|
|
9
|
+
/* Desktop: Smooth slide-up animation for page changes */
|
|
10
|
+
::view-transition-old(root),
|
|
11
|
+
::view-transition-new(root) {
|
|
12
|
+
animation-duration: 0.3s;
|
|
13
|
+
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
::view-transition-old(root) {
|
|
17
|
+
animation-name: slide-down;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
::view-transition-new(root) {
|
|
21
|
+
animation-name: slide-up;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Mobile: Slide aside (left/right) for more natural mobile feel */
|
|
25
|
+
@media (max-width: 768px) {
|
|
26
|
+
::view-transition-old(root) {
|
|
27
|
+
animation-name: slide-to-left;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
::view-transition-new(root) {
|
|
31
|
+
animation-name: slide-from-right;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* ============================================
|
|
36
|
+
KEYFRAMES - Reusable animations
|
|
37
|
+
============================================ */
|
|
38
|
+
|
|
39
|
+
@keyframes fade-out {
|
|
40
|
+
to {
|
|
41
|
+
opacity: 0;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@keyframes fade-in {
|
|
46
|
+
from {
|
|
47
|
+
opacity: 0;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@keyframes scale-up {
|
|
52
|
+
from {
|
|
53
|
+
transform: scale(0.9);
|
|
54
|
+
opacity: 0;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@keyframes scale-down {
|
|
59
|
+
to {
|
|
60
|
+
transform: scale(0.9);
|
|
61
|
+
opacity: 0;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@keyframes slide-up {
|
|
66
|
+
from {
|
|
67
|
+
transform: translateY(10px);
|
|
68
|
+
opacity: 0;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@keyframes slide-down {
|
|
73
|
+
to {
|
|
74
|
+
transform: translateY(10px);
|
|
75
|
+
opacity: 0;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@keyframes slide-to-left {
|
|
80
|
+
to {
|
|
81
|
+
transform: translateX(-100%);
|
|
82
|
+
opacity: 0;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@keyframes slide-from-right {
|
|
87
|
+
from {
|
|
88
|
+
transform: translateX(100%);
|
|
89
|
+
opacity: 0;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* ============================================
|
|
94
|
+
IN-PAGE TRANSITIONS (Always enabled)
|
|
95
|
+
============================================ */
|
|
96
|
+
|
|
97
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
98
|
+
/* App image - smooth morph transition */
|
|
99
|
+
::view-transition-old(app-image),
|
|
100
|
+
::view-transition-new(app-image) {
|
|
101
|
+
animation-duration: 0.4s;
|
|
102
|
+
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
103
|
+
overflow: clip;
|
|
104
|
+
mix-blend-mode: normal;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
::view-transition-old(app-image) {
|
|
108
|
+
animation-name: scale-down;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
::view-transition-new(app-image) {
|
|
112
|
+
animation-name: scale-up;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/* App title - smooth slide and fade */
|
|
116
|
+
::view-transition-old(app-title),
|
|
117
|
+
::view-transition-new(app-title) {
|
|
118
|
+
animation-duration: 0.35s;
|
|
119
|
+
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
::view-transition-old(app-title) {
|
|
123
|
+
animation-name: slide-down;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
::view-transition-new(app-title) {
|
|
127
|
+
animation-name: slide-up;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/* Image enlargement - smooth scale transition */
|
|
131
|
+
::view-transition-old(image-enlarge),
|
|
132
|
+
::view-transition-new(image-enlarge) {
|
|
133
|
+
animation-duration: 0.3s;
|
|
134
|
+
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
135
|
+
overflow: clip;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
::view-transition-old(image-enlarge) {
|
|
139
|
+
animation-name: scale-down;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
::view-transition-new(image-enlarge) {
|
|
143
|
+
animation-name: scale-up;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* Modal/Dialog transitions */
|
|
147
|
+
::view-transition-old(modal),
|
|
148
|
+
::view-transition-new(modal) {
|
|
149
|
+
animation-duration: 0.25s;
|
|
150
|
+
animation-timing-function: ease-in-out;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
::view-transition-old(modal) {
|
|
154
|
+
animation-name: fade-out;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
::view-transition-new(modal) {
|
|
158
|
+
animation-name: scale-up;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/* Content sections - subtle fade */
|
|
162
|
+
::view-transition-old(content-section),
|
|
163
|
+
::view-transition-new(content-section) {
|
|
164
|
+
animation-duration: 0.2s;
|
|
165
|
+
animation-timing-function: ease-in-out;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
::view-transition-old(content-section) {
|
|
169
|
+
animation-name: fade-out;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
::view-transition-new(content-section) {
|
|
173
|
+
animation-name: fade-in;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* ============================================
|
|
178
|
+
OPTIONAL: Enable full-page transitions
|
|
179
|
+
Add .page-transitions class to <html> or <body>
|
|
180
|
+
============================================ */
|
|
181
|
+
|
|
182
|
+
.page-transitions {
|
|
183
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
184
|
+
::view-transition-old(root),
|
|
185
|
+
::view-transition-new(root) {
|
|
186
|
+
animation-duration: 0.2s;
|
|
187
|
+
animation-timing-function: ease-in-out;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
::view-transition-old(root) {
|
|
191
|
+
animation-name: fade-out;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
::view-transition-new(root) {
|
|
195
|
+
animation-name: fade-in;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/* Main content with page transitions enabled */
|
|
199
|
+
::view-transition-old(main-content) {
|
|
200
|
+
animation: fade-out 0.15s ease-out;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
::view-transition-new(main-content) {
|
|
204
|
+
animation: fade-in 0.2s ease-in;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
package/toRem.scss
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
@use "./toRem.scss";
|
|
2
|
+
|
|
3
|
+
// Utility classes for cross-platform styling
|
|
4
|
+
.button {
|
|
5
|
+
padding: toRem.toRem(8) toRem.toRem(12);
|
|
6
|
+
background-color: var(--link-color);
|
|
7
|
+
color: #fff;
|
|
8
|
+
display: inline-flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
gap: toRem.toRem(5);
|
|
11
|
+
border: none;
|
|
12
|
+
border-radius: var(--radius);
|
|
13
|
+
cursor: pointer;
|
|
14
|
+
box-shadow: var(--shadow);
|
|
15
|
+
font-size: toRem.toRem(14);
|
|
16
|
+
line-height: 1.15;
|
|
17
|
+
|
|
18
|
+
&:hover {
|
|
19
|
+
background-color: var(--accent-5);
|
|
20
|
+
color: #fff;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&:active {
|
|
24
|
+
transform: translateY(toRem.toRem(1.2));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&:disabled {
|
|
28
|
+
cursor: default;
|
|
29
|
+
background-color: var(--background);
|
|
30
|
+
color: var(--foreground);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.link {
|
|
35
|
+
text-decoration: none;
|
|
36
|
+
color: var(--accent-6);
|
|
37
|
+
cursor: pointer;
|
|
38
|
+
background-color: transparent;
|
|
39
|
+
box-shadow: none;
|
|
40
|
+
padding: 0;
|
|
41
|
+
margin: 0;
|
|
42
|
+
display: inline-flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
gap: toRem.toRem(5);
|
|
45
|
+
|
|
46
|
+
&:hover {
|
|
47
|
+
text-decoration: none;
|
|
48
|
+
color: var(--accent-5);
|
|
49
|
+
background-color: transparent;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
&:active {
|
|
53
|
+
transform: translateY(toRem.toRem(1.2));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.small {
|
|
58
|
+
padding: toRem.toRem(5.6) toRem.toRem(8.8);
|
|
59
|
+
font-size: toRem.toRem(14);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.xSmall {
|
|
63
|
+
padding: toRem.toRem(4) toRem.toRem(7.2);
|
|
64
|
+
font-size: toRem.toRem(12);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.large {
|
|
68
|
+
padding: toRem.toRem(8) toRem.toRem(20);
|
|
69
|
+
font-size: toRem.toRem(16);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.transparent {
|
|
73
|
+
background-color: var(--background);
|
|
74
|
+
color: var(--foreground);
|
|
75
|
+
border: toRem.toRem(1) solid var(--shade-2);
|
|
76
|
+
box-shadow: none;
|
|
77
|
+
|
|
78
|
+
&:hover {
|
|
79
|
+
background-color: var(--shade-1);
|
|
80
|
+
color: var(--foreground);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.inverted {
|
|
85
|
+
background-color: var(--foreground);
|
|
86
|
+
color: var(--background);
|
|
87
|
+
border: toRem.toRem(1) solid var(--shade-2);
|
|
88
|
+
box-shadow: none;
|
|
89
|
+
|
|
90
|
+
&:hover {
|
|
91
|
+
background-color: var(--shade-7);
|
|
92
|
+
color: var(--background);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.row {
|
|
97
|
+
display: flex;
|
|
98
|
+
flex-direction: row;
|
|
99
|
+
align-items: center;
|
|
100
|
+
gap: toRem.toRem(5);
|
|
101
|
+
flex-wrap: wrap;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.column {
|
|
105
|
+
display: flex;
|
|
106
|
+
flex-direction: column;
|
|
107
|
+
gap: toRem.toRem(5);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.left {
|
|
111
|
+
margin-right: auto;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.right {
|
|
115
|
+
margin-left: auto;
|
|
116
|
+
}
|
package/utils.scss
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
@use "./toRem.scss";
|
|
2
|
+
|
|
3
|
+
@function toRem($value) {
|
|
4
|
+
$remValue: math.div($value, 16) + rem;
|
|
5
|
+
@return $remValue;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
@mixin respect-reduced-motion {
|
|
9
|
+
@media (prefers-reduced-motion: reduce) {
|
|
10
|
+
animation: none !important;
|
|
11
|
+
transition: none !important;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@keyframes slideLeft {
|
|
16
|
+
from {
|
|
17
|
+
opacity: 0;
|
|
18
|
+
transform: translateX(toRem.toRem(-20)); /* Start slightly left */
|
|
19
|
+
}
|
|
20
|
+
to {
|
|
21
|
+
opacity: 1;
|
|
22
|
+
transform: translateX(0); /* End at original position */
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@keyframes slideRight {
|
|
27
|
+
from {
|
|
28
|
+
opacity: 0;
|
|
29
|
+
transform: translateX(toRem.toRem(20)); /* Start slightly right */
|
|
30
|
+
}
|
|
31
|
+
to {
|
|
32
|
+
opacity: 1;
|
|
33
|
+
transform: translateX(0); /* End at original position */
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
@keyframes slideUp {
|
|
37
|
+
from {
|
|
38
|
+
opacity: 0;
|
|
39
|
+
transform: translateY(toRem.toRem(20)); /* Start slightly below */
|
|
40
|
+
}
|
|
41
|
+
to {
|
|
42
|
+
opacity: 1;
|
|
43
|
+
transform: translateY(0); /* End at original position */
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@keyframes blink {
|
|
48
|
+
0%,
|
|
49
|
+
100% {
|
|
50
|
+
opacity: 1;
|
|
51
|
+
}
|
|
52
|
+
50% {
|
|
53
|
+
opacity: 0;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@keyframes pulse {
|
|
58
|
+
0% {
|
|
59
|
+
transform: scale(0.9);
|
|
60
|
+
opacity: 0.7;
|
|
61
|
+
}
|
|
62
|
+
50% {
|
|
63
|
+
transform: scale(1.1);
|
|
64
|
+
opacity: 1;
|
|
65
|
+
}
|
|
66
|
+
100% {
|
|
67
|
+
transform: scale(0.9);
|
|
68
|
+
opacity: 0.7;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
@keyframes float {
|
|
72
|
+
0%,
|
|
73
|
+
100% {
|
|
74
|
+
transform: translateY(0);
|
|
75
|
+
}
|
|
76
|
+
50% {
|
|
77
|
+
transform: translateY(-5px);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
@keyframes wiggle {
|
|
81
|
+
0%,
|
|
82
|
+
100% {
|
|
83
|
+
transform: rotate(-5deg);
|
|
84
|
+
}
|
|
85
|
+
50% {
|
|
86
|
+
transform: rotate(5deg);
|
|
87
|
+
}
|
|
88
|
+
}
|