@proyecto-viviana/ui 0.4.0 → 0.5.0
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/dist/styles.css +0 -3
- package/dist/vite.d.ts +1 -0
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +9 -1
- package/dist/vite.js.map +1 -1
- package/dist/vite.jsx +9 -1
- package/dist/vite.jsx.map +1 -1
- package/dist/viviana-tokens.css +240 -171
- package/package.json +3 -57
- package/src/vite.ts +13 -1
- package/src/viviana-tokens.css +240 -171
- package/dist/CalendarCard.d.ts +0 -2
- package/dist/CalendarCard.d.ts.map +0 -1
- package/dist/CalendarCard.js +0 -97
- package/dist/CalendarCard.js.map +0 -1
- package/dist/CalendarCard.jsx +0 -51
- package/dist/CalendarCard.jsx.map +0 -1
- package/dist/Chip.d.ts +0 -2
- package/dist/Chip.d.ts.map +0 -1
- package/dist/Chip.js +0 -2
- package/dist/Chip.jsx +0 -2
- package/dist/Conversation.d.ts +0 -2
- package/dist/Conversation.d.ts.map +0 -1
- package/dist/Conversation.js +0 -177
- package/dist/Conversation.js.map +0 -1
- package/dist/Conversation.jsx +0 -107
- package/dist/Conversation.jsx.map +0 -1
- package/dist/EventCard.d.ts +0 -2
- package/dist/EventCard.d.ts.map +0 -1
- package/dist/EventCard.js +0 -173
- package/dist/EventCard.js.map +0 -1
- package/dist/EventCard.jsx +0 -96
- package/dist/EventCard.jsx.map +0 -1
- package/dist/Logo.d.ts +0 -2
- package/dist/Logo.d.ts.map +0 -1
- package/dist/Logo.js +0 -116
- package/dist/Logo.js.map +0 -1
- package/dist/Logo.jsx +0 -101
- package/dist/Logo.jsx.map +0 -1
- package/dist/PageLayout.d.ts +0 -2
- package/dist/PageLayout.d.ts.map +0 -1
- package/dist/PageLayout.js +0 -31
- package/dist/PageLayout.js.map +0 -1
- package/dist/PageLayout.jsx +0 -23
- package/dist/PageLayout.jsx.map +0 -1
- package/dist/ProfileCard.d.ts +0 -2
- package/dist/ProfileCard.d.ts.map +0 -1
- package/dist/ProfileCard.js +0 -78
- package/dist/ProfileCard.js.map +0 -1
- package/dist/ProfileCard.jsx +0 -53
- package/dist/ProfileCard.jsx.map +0 -1
- package/dist/ProjectCard.d.ts +0 -2
- package/dist/ProjectCard.d.ts.map +0 -1
- package/dist/ProjectCard.js +0 -164
- package/dist/ProjectCard.js.map +0 -1
- package/dist/ProjectCard.jsx +0 -133
- package/dist/ProjectCard.jsx.map +0 -1
- package/dist/TimelineItem.d.ts +0 -2
- package/dist/TimelineItem.d.ts.map +0 -1
- package/dist/TimelineItem.js +0 -137
- package/dist/TimelineItem.js.map +0 -1
- package/dist/TimelineItem.jsx +0 -70
- package/dist/TimelineItem.jsx.map +0 -1
- package/dist/chip2.js +0 -82
- package/dist/chip2.js.map +0 -1
- package/dist/chip2.jsx +0 -68
- package/dist/chip2.jsx.map +0 -1
- package/dist/custom/calendar-card/index.d.ts +0 -12
- package/dist/custom/calendar-card/index.d.ts.map +0 -1
- package/dist/custom/chip/index.d.ts +0 -16
- package/dist/custom/chip/index.d.ts.map +0 -1
- package/dist/custom/conversation/index.d.ts +0 -32
- package/dist/custom/conversation/index.d.ts.map +0 -1
- package/dist/custom/event-card/index.d.ts +0 -30
- package/dist/custom/event-card/index.d.ts.map +0 -1
- package/dist/custom/header/index.d.ts +0 -12
- package/dist/custom/header/index.d.ts.map +0 -1
- package/dist/custom/lateral-nav/index.d.ts +0 -32
- package/dist/custom/lateral-nav/index.d.ts.map +0 -1
- package/dist/custom/logo/index.d.ts +0 -11
- package/dist/custom/logo/index.d.ts.map +0 -1
- package/dist/custom/nav-header/index.d.ts +0 -13
- package/dist/custom/nav-header/index.d.ts.map +0 -1
- package/dist/custom/page-layout/index.d.ts +0 -7
- package/dist/custom/page-layout/index.d.ts.map +0 -1
- package/dist/custom/profile-card/index.d.ts +0 -16
- package/dist/custom/profile-card/index.d.ts.map +0 -1
- package/dist/custom/project-card/index.d.ts +0 -13
- package/dist/custom/project-card/index.d.ts.map +0 -1
- package/dist/custom/timeline-item/index.d.ts +0 -28
- package/dist/custom/timeline-item/index.d.ts.map +0 -1
- package/src/CalendarCard.ts +0 -1
- package/src/Chip.ts +0 -1
- package/src/Conversation.ts +0 -1
- package/src/EventCard.ts +0 -1
- package/src/Logo.ts +0 -1
- package/src/PageLayout.ts +0 -1
- package/src/ProfileCard.ts +0 -1
- package/src/ProjectCard.ts +0 -1
- package/src/TimelineItem.ts +0 -1
- package/src/custom/calendar-card/index.tsx +0 -115
- package/src/custom/chip/index.tsx +0 -78
- package/src/custom/conversation/index.tsx +0 -199
- package/src/custom/event-card/index.tsx +0 -232
- package/src/custom/header/index.tsx +0 -64
- package/src/custom/lateral-nav/index.tsx +0 -134
- package/src/custom/logo/index.tsx +0 -53
- package/src/custom/nav-header/index.tsx +0 -98
- package/src/custom/page-layout/index.tsx +0 -33
- package/src/custom/profile-card/index.tsx +0 -114
- package/src/custom/project-card/index.tsx +0 -76
- package/src/custom/timeline-item/index.tsx +0 -140
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import { Show, For } from "solid-js";
|
|
2
|
-
import { Avatar } from "@proyecto-viviana/solid-spectrum";
|
|
3
|
-
import { Button as HeadlessButton } from "@proyecto-viviana/solidaria-components";
|
|
4
|
-
// Styled via the S2 style() macro through viviana's own seam (../../style →
|
|
5
|
-
// src/style.ts). A conversation preview row, message bubbles, and a thread
|
|
6
|
-
// list, on the S2 spacing/radius ramps in Silapse colors.
|
|
7
|
-
import { style } from "../../style" with { type: "macro" };
|
|
8
|
-
|
|
9
|
-
export interface Message {
|
|
10
|
-
id: string;
|
|
11
|
-
content: string;
|
|
12
|
-
sender: "user" | "other";
|
|
13
|
-
timestamp?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface ConversationPreviewProps {
|
|
17
|
-
user: {
|
|
18
|
-
name: string;
|
|
19
|
-
avatar?: string;
|
|
20
|
-
online?: boolean;
|
|
21
|
-
};
|
|
22
|
-
lastMessage?: string;
|
|
23
|
-
unreadCount?: number;
|
|
24
|
-
timestamp?: string;
|
|
25
|
-
onClick?: () => void;
|
|
26
|
-
class?: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const preview = style({
|
|
30
|
-
display: "flex",
|
|
31
|
-
alignItems: "center",
|
|
32
|
-
gap: 12,
|
|
33
|
-
width: "full",
|
|
34
|
-
padding: 12,
|
|
35
|
-
borderRadius: "lg",
|
|
36
|
-
textAlign: "start",
|
|
37
|
-
cursor: "pointer",
|
|
38
|
-
backgroundColor: "transparent",
|
|
39
|
-
borderStyle: "none",
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const previewBody = style({
|
|
43
|
-
display: "flex",
|
|
44
|
-
flexDirection: "column",
|
|
45
|
-
gap: 2,
|
|
46
|
-
flexGrow: 1,
|
|
47
|
-
minWidth: 0,
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
const previewTop = style({
|
|
51
|
-
display: "flex",
|
|
52
|
-
alignItems: "center",
|
|
53
|
-
justifyContent: "space-between",
|
|
54
|
-
gap: 8,
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
const previewName = style({
|
|
58
|
-
font: "ui",
|
|
59
|
-
fontWeight: "bold",
|
|
60
|
-
color: "[var(--color-primary-100)]",
|
|
61
|
-
overflow: "hidden",
|
|
62
|
-
textOverflow: "ellipsis",
|
|
63
|
-
whiteSpace: "nowrap",
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
const previewTime = style({
|
|
67
|
-
font: "detail-sm",
|
|
68
|
-
color: "[var(--color-text-muted)]",
|
|
69
|
-
flexShrink: 0,
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
const previewMessage = style({
|
|
73
|
-
font: "ui-sm",
|
|
74
|
-
color: "[var(--color-text-secondary)]",
|
|
75
|
-
overflow: "hidden",
|
|
76
|
-
textOverflow: "ellipsis",
|
|
77
|
-
whiteSpace: "nowrap",
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
const unread = style({
|
|
81
|
-
display: "flex",
|
|
82
|
-
alignItems: "center",
|
|
83
|
-
justifyContent: "center",
|
|
84
|
-
flexShrink: 0,
|
|
85
|
-
width: 20,
|
|
86
|
-
height: 20,
|
|
87
|
-
borderRadius: "full",
|
|
88
|
-
font: "detail-sm",
|
|
89
|
-
fontWeight: "bold",
|
|
90
|
-
backgroundColor: "[var(--color-accent)]",
|
|
91
|
-
color: "[var(--color-bg-400)]",
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
export function ConversationPreview(props: ConversationPreviewProps) {
|
|
95
|
-
return (
|
|
96
|
-
<HeadlessButton
|
|
97
|
-
type="button"
|
|
98
|
-
class={`${preview} ${props.class ?? ""}`}
|
|
99
|
-
onPress={() => props.onClick?.()}
|
|
100
|
-
>
|
|
101
|
-
<Avatar src={props.user.avatar} alt={props.user.name} online={props.user.online} size="md" />
|
|
102
|
-
<div class={previewBody}>
|
|
103
|
-
<div class={previewTop}>
|
|
104
|
-
<span class={previewName}>{props.user.name}</span>
|
|
105
|
-
<Show when={props.timestamp}>
|
|
106
|
-
<span class={previewTime}>{props.timestamp}</span>
|
|
107
|
-
</Show>
|
|
108
|
-
</div>
|
|
109
|
-
<Show when={props.lastMessage}>
|
|
110
|
-
<p class={previewMessage}>{props.lastMessage}</p>
|
|
111
|
-
</Show>
|
|
112
|
-
</div>
|
|
113
|
-
<Show when={props.unreadCount && props.unreadCount > 0}>
|
|
114
|
-
<span class={unread}>{props.unreadCount}</span>
|
|
115
|
-
</Show>
|
|
116
|
-
</HeadlessButton>
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export interface ConversationBubbleProps {
|
|
121
|
-
content: string;
|
|
122
|
-
sender: "user" | "other";
|
|
123
|
-
timestamp?: string;
|
|
124
|
-
class?: string;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const bubbleRow = style<{ isUser: boolean }>({
|
|
128
|
-
display: "flex",
|
|
129
|
-
justifyContent: { default: "start", isUser: "end" },
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
const bubble = style<{ isUser: boolean }>({
|
|
133
|
-
display: "flex",
|
|
134
|
-
flexDirection: "column",
|
|
135
|
-
gap: 2,
|
|
136
|
-
maxWidth: "[70%]",
|
|
137
|
-
paddingX: 16,
|
|
138
|
-
paddingY: 8,
|
|
139
|
-
borderRadius: "lg",
|
|
140
|
-
backgroundColor: {
|
|
141
|
-
default: "[var(--color-bg-300)]",
|
|
142
|
-
isUser: "[var(--color-accent)]",
|
|
143
|
-
},
|
|
144
|
-
color: {
|
|
145
|
-
default: "[var(--color-primary-100)]",
|
|
146
|
-
isUser: "[var(--color-bg-400)]",
|
|
147
|
-
},
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
const bubbleTime = style<{ isUser: boolean }>({
|
|
151
|
-
font: "detail-sm",
|
|
152
|
-
color: {
|
|
153
|
-
default: "[var(--color-text-muted)]",
|
|
154
|
-
isUser: "[var(--color-bg-300)]",
|
|
155
|
-
},
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
export function ConversationBubble(props: ConversationBubbleProps) {
|
|
159
|
-
const isUser = () => props.sender === "user";
|
|
160
|
-
|
|
161
|
-
return (
|
|
162
|
-
<div class={`${bubbleRow({ isUser: isUser() })} ${props.class ?? ""}`}>
|
|
163
|
-
<div class={bubble({ isUser: isUser() })}>
|
|
164
|
-
<p>{props.content}</p>
|
|
165
|
-
<Show when={props.timestamp}>
|
|
166
|
-
<span class={bubbleTime({ isUser: isUser() })}>{props.timestamp}</span>
|
|
167
|
-
</Show>
|
|
168
|
-
</div>
|
|
169
|
-
</div>
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
export interface ConversationProps {
|
|
174
|
-
messages: Message[];
|
|
175
|
-
class?: string;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const thread = style({
|
|
179
|
-
display: "flex",
|
|
180
|
-
flexDirection: "column",
|
|
181
|
-
gap: 8,
|
|
182
|
-
padding: 16,
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
export function Conversation(props: ConversationProps) {
|
|
186
|
-
return (
|
|
187
|
-
<div class={`${thread} ${props.class ?? ""}`}>
|
|
188
|
-
<For each={props.messages}>
|
|
189
|
-
{(message) => (
|
|
190
|
-
<ConversationBubble
|
|
191
|
-
content={message.content}
|
|
192
|
-
sender={message.sender}
|
|
193
|
-
timestamp={message.timestamp}
|
|
194
|
-
/>
|
|
195
|
-
)}
|
|
196
|
-
</For>
|
|
197
|
-
</div>
|
|
198
|
-
);
|
|
199
|
-
}
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
import type { JSX } from "solid-js";
|
|
2
|
-
import { Show, For } from "solid-js";
|
|
3
|
-
import { Avatar } from "@proyecto-viviana/solid-spectrum";
|
|
4
|
-
import { Button as HeadlessButton } from "@proyecto-viviana/solidaria-components";
|
|
5
|
-
// Styled via the S2 style() macro through viviana's own seam (../../style →
|
|
6
|
-
// src/style.ts). An event summary card (S2 Card shape: preview + content +
|
|
7
|
-
// footer) plus a compact list-item variant, on the S2 ramps in Silapse colors.
|
|
8
|
-
import { style } from "../../style" with { type: "macro" };
|
|
9
|
-
|
|
10
|
-
export interface EventCardProps {
|
|
11
|
-
title: string;
|
|
12
|
-
image?: string;
|
|
13
|
-
date?: string;
|
|
14
|
-
author?: string;
|
|
15
|
-
authorAvatar?: string;
|
|
16
|
-
attendees?: { avatar?: string; name: string }[];
|
|
17
|
-
attendeeCount?: number;
|
|
18
|
-
decorationImage?: string;
|
|
19
|
-
/**
|
|
20
|
-
* Actions to display below the event.
|
|
21
|
-
* Use a function returning JSX for SSR compatibility: `actions={() => <Button>...</Button>}`
|
|
22
|
-
*/
|
|
23
|
-
actions?: JSX.Element | (() => JSX.Element);
|
|
24
|
-
class?: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const card = style({
|
|
28
|
-
position: "relative",
|
|
29
|
-
display: "flex",
|
|
30
|
-
flexDirection: "column",
|
|
31
|
-
overflow: "hidden",
|
|
32
|
-
borderRadius: "xl",
|
|
33
|
-
backgroundColor: "[var(--color-bg-200)]",
|
|
34
|
-
boxShadow: "elevated",
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
const decoration = style({
|
|
38
|
-
position: "absolute",
|
|
39
|
-
top: 8,
|
|
40
|
-
insetEnd: 8,
|
|
41
|
-
width: 32,
|
|
42
|
-
height: 32,
|
|
43
|
-
objectFit: "contain",
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
const preview = style({
|
|
47
|
-
width: "full",
|
|
48
|
-
aspectRatio: "16/9",
|
|
49
|
-
objectFit: "cover",
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const body = style({
|
|
53
|
-
display: "flex",
|
|
54
|
-
flexDirection: "column",
|
|
55
|
-
gap: 12,
|
|
56
|
-
padding: 16,
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const title = style({
|
|
60
|
-
font: "heading",
|
|
61
|
-
color: "[var(--color-accent)]",
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
const meta = style({
|
|
65
|
-
display: "flex",
|
|
66
|
-
alignItems: "center",
|
|
67
|
-
gap: 16,
|
|
68
|
-
font: "ui-sm",
|
|
69
|
-
color: "[var(--color-text-secondary)]",
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
const metaItem = style({
|
|
73
|
-
display: "flex",
|
|
74
|
-
alignItems: "center",
|
|
75
|
-
gap: 4,
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
const metaIcon = style({
|
|
79
|
-
color: "[var(--color-accent)]",
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
const attendeesRow = style({
|
|
83
|
-
display: "flex",
|
|
84
|
-
alignItems: "center",
|
|
85
|
-
gap: 8,
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
const avatars = style({
|
|
89
|
-
display: "flex",
|
|
90
|
-
alignItems: "center",
|
|
91
|
-
gap: 4,
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
const more = style({
|
|
95
|
-
font: "ui-sm",
|
|
96
|
-
color: "[var(--color-text-secondary)]",
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
const actionRow = style({
|
|
100
|
-
display: "flex",
|
|
101
|
-
gap: 8,
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
export function EventCard(props: EventCardProps) {
|
|
105
|
-
const displayedAttendees = () => props.attendees?.slice(0, 3) ?? [];
|
|
106
|
-
const remainingCount = () => {
|
|
107
|
-
const total = props.attendeeCount ?? props.attendees?.length ?? 0;
|
|
108
|
-
const displayed = displayedAttendees().length;
|
|
109
|
-
return total - displayed;
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
<div class={`${card} ${props.class ?? ""}`}>
|
|
114
|
-
<Show when={props.decorationImage}>
|
|
115
|
-
<img class={decoration} src={props.decorationImage} alt="" />
|
|
116
|
-
</Show>
|
|
117
|
-
|
|
118
|
-
<Show when={props.image}>
|
|
119
|
-
<img class={preview} src={props.image} alt={props.title} />
|
|
120
|
-
</Show>
|
|
121
|
-
|
|
122
|
-
<div class={body}>
|
|
123
|
-
<h3 class={title}>{props.title}</h3>
|
|
124
|
-
|
|
125
|
-
<Show when={props.date || props.author}>
|
|
126
|
-
<div class={meta}>
|
|
127
|
-
<Show when={props.author}>
|
|
128
|
-
<div class={metaItem}>
|
|
129
|
-
<span class={metaIcon}>@</span>
|
|
130
|
-
<span>{props.author}</span>
|
|
131
|
-
</div>
|
|
132
|
-
</Show>
|
|
133
|
-
<Show when={props.date}>
|
|
134
|
-
<div class={metaItem}>
|
|
135
|
-
<span class={metaIcon}>⏱</span>
|
|
136
|
-
<span>{props.date}</span>
|
|
137
|
-
</div>
|
|
138
|
-
</Show>
|
|
139
|
-
</div>
|
|
140
|
-
</Show>
|
|
141
|
-
|
|
142
|
-
<Show when={displayedAttendees().length > 0}>
|
|
143
|
-
<div class={attendeesRow}>
|
|
144
|
-
<div class={avatars}>
|
|
145
|
-
<For each={displayedAttendees()}>
|
|
146
|
-
{(attendee) => <Avatar src={attendee.avatar} alt={attendee.name} size="sm" />}
|
|
147
|
-
</For>
|
|
148
|
-
</div>
|
|
149
|
-
<Show when={remainingCount() > 0}>
|
|
150
|
-
<span class={more}>+{remainingCount()} más</span>
|
|
151
|
-
</Show>
|
|
152
|
-
</div>
|
|
153
|
-
</Show>
|
|
154
|
-
|
|
155
|
-
<Show when={props.actions}>
|
|
156
|
-
<div class={actionRow}>
|
|
157
|
-
{typeof props.actions === "function" ? props.actions() : props.actions}
|
|
158
|
-
</div>
|
|
159
|
-
</Show>
|
|
160
|
-
</div>
|
|
161
|
-
</div>
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export interface EventListItemProps {
|
|
166
|
-
title: string;
|
|
167
|
-
image?: string;
|
|
168
|
-
subtitle?: string;
|
|
169
|
-
onClick?: () => void;
|
|
170
|
-
class?: string;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const listItem = style({
|
|
174
|
-
display: "flex",
|
|
175
|
-
alignItems: "center",
|
|
176
|
-
gap: 12,
|
|
177
|
-
width: "full",
|
|
178
|
-
padding: 8,
|
|
179
|
-
borderRadius: "lg",
|
|
180
|
-
textAlign: "start",
|
|
181
|
-
cursor: "pointer",
|
|
182
|
-
backgroundColor: "transparent",
|
|
183
|
-
borderStyle: "none",
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
const thumb = style({
|
|
187
|
-
width: 48,
|
|
188
|
-
height: 48,
|
|
189
|
-
flexShrink: 0,
|
|
190
|
-
borderRadius: "default",
|
|
191
|
-
objectFit: "cover",
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
const listBody = style({
|
|
195
|
-
display: "flex",
|
|
196
|
-
flexDirection: "column",
|
|
197
|
-
flexGrow: 1,
|
|
198
|
-
minWidth: 0,
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
const listTitle = style({
|
|
202
|
-
font: "ui",
|
|
203
|
-
fontWeight: "medium",
|
|
204
|
-
color: "[var(--color-primary-100)]",
|
|
205
|
-
overflow: "hidden",
|
|
206
|
-
textOverflow: "ellipsis",
|
|
207
|
-
whiteSpace: "nowrap",
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
const listSubtitle = style({
|
|
211
|
-
font: "ui-sm",
|
|
212
|
-
color: "[var(--color-text-secondary)]",
|
|
213
|
-
overflow: "hidden",
|
|
214
|
-
textOverflow: "ellipsis",
|
|
215
|
-
whiteSpace: "nowrap",
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
export function EventListItem(props: EventListItemProps) {
|
|
219
|
-
return (
|
|
220
|
-
<HeadlessButton class={`${listItem} ${props.class ?? ""}`} onPress={() => props.onClick?.()}>
|
|
221
|
-
<Show when={props.image}>
|
|
222
|
-
<img class={thumb} src={props.image} alt={props.title} />
|
|
223
|
-
</Show>
|
|
224
|
-
<div class={listBody}>
|
|
225
|
-
<h4 class={listTitle}>{props.title}</h4>
|
|
226
|
-
<Show when={props.subtitle}>
|
|
227
|
-
<p class={listSubtitle}>{props.subtitle}</p>
|
|
228
|
-
</Show>
|
|
229
|
-
</div>
|
|
230
|
-
</HeadlessButton>
|
|
231
|
-
);
|
|
232
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import type { JSX } from "solid-js";
|
|
2
|
-
import { Logo, type LogoProps } from "../logo";
|
|
3
|
-
// Styled via the S2 style() macro through viviana's own seam (../../style →
|
|
4
|
-
// src/style.ts). A top app-bar: centered max-width row with a logo group and
|
|
5
|
-
// a nav slot, on the S2 ramps in Silapse colors.
|
|
6
|
-
import { style } from "../../style" with { type: "macro" };
|
|
7
|
-
|
|
8
|
-
export interface HeaderProps {
|
|
9
|
-
logoImage?: JSX.Element;
|
|
10
|
-
/** Props to pass to the Logo component (firstWord, secondWord, size, inverted). Pass null to hide the text logo. */
|
|
11
|
-
logoProps?: LogoProps | null;
|
|
12
|
-
logo?: JSX.Element;
|
|
13
|
-
children?: JSX.Element;
|
|
14
|
-
class?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const bar = style({
|
|
18
|
-
display: "flex",
|
|
19
|
-
alignItems: "center",
|
|
20
|
-
justifyContent: "center",
|
|
21
|
-
width: "full",
|
|
22
|
-
backgroundColor: "[var(--color-header-bg)]",
|
|
23
|
-
borderBottomWidth: 1,
|
|
24
|
-
borderStyle: "solid",
|
|
25
|
-
borderColor: "[var(--color-border)]",
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const inner = style({
|
|
29
|
-
display: "flex",
|
|
30
|
-
alignItems: "center",
|
|
31
|
-
justifyContent: "space-between",
|
|
32
|
-
width: "full",
|
|
33
|
-
maxWidth: 1152,
|
|
34
|
-
paddingX: 24,
|
|
35
|
-
paddingY: 12,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
const logoGroup = style({
|
|
39
|
-
display: "flex",
|
|
40
|
-
alignItems: "center",
|
|
41
|
-
gap: 12,
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
const nav = style({
|
|
45
|
-
display: "flex",
|
|
46
|
-
alignItems: "center",
|
|
47
|
-
gap: 16,
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
export function Header(props: HeaderProps) {
|
|
51
|
-
const showTextLogo = () => props.logo !== undefined || props.logoProps !== null;
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<header class={`${bar} ${props.class ?? ""}`}>
|
|
55
|
-
<div class={inner}>
|
|
56
|
-
<div class={logoGroup}>
|
|
57
|
-
{props.logoImage}
|
|
58
|
-
{showTextLogo() && (props.logo ?? <Logo size="lg" {...(props.logoProps ?? {})} />)}
|
|
59
|
-
</div>
|
|
60
|
-
<nav class={nav}>{props.children}</nav>
|
|
61
|
-
</div>
|
|
62
|
-
</header>
|
|
63
|
-
);
|
|
64
|
-
}
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import type { JSX } from "solid-js";
|
|
2
|
-
import { Show, For } from "solid-js";
|
|
3
|
-
// Styled via the S2 style() macro through viviana's own seam (../../style →
|
|
4
|
-
// src/style.ts). A sidebar nav (sections with an accent rail + links) on the
|
|
5
|
-
// S2 spacing/type ramps in Silapse colors.
|
|
6
|
-
import { style } from "../../style" with { type: "macro" };
|
|
7
|
-
|
|
8
|
-
export interface NavItemProps {
|
|
9
|
-
title: string;
|
|
10
|
-
children?: JSX.Element;
|
|
11
|
-
class?: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const item = style({
|
|
15
|
-
display: "flex",
|
|
16
|
-
alignItems: "center",
|
|
17
|
-
font: "heading-sm",
|
|
18
|
-
color: "[var(--color-primary-200)]",
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
export function NavItem(props: NavItemProps) {
|
|
22
|
-
return (
|
|
23
|
-
<li class={`${item} ${props.class ?? ""}`}>
|
|
24
|
-
<span>{props.title}</span>
|
|
25
|
-
{props.children}
|
|
26
|
-
</li>
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface NavLinkProps {
|
|
31
|
-
href: string;
|
|
32
|
-
children: JSX.Element;
|
|
33
|
-
active?: boolean;
|
|
34
|
-
class?: string;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const link = style<{ isActive: boolean }>({
|
|
38
|
-
font: "ui",
|
|
39
|
-
textDecoration: { default: "none", isActive: "underline" },
|
|
40
|
-
fontWeight: { default: "normal", isActive: "medium" },
|
|
41
|
-
color: {
|
|
42
|
-
default: "[var(--color-text-secondary)]",
|
|
43
|
-
isActive: "[var(--color-primary-300)]",
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
export function NavLink(props: NavLinkProps) {
|
|
48
|
-
return (
|
|
49
|
-
<a
|
|
50
|
-
href={props.href}
|
|
51
|
-
class={`${link({ isActive: props.active ?? false })} ${props.class ?? ""}`}
|
|
52
|
-
>
|
|
53
|
-
{props.children}
|
|
54
|
-
</a>
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface NavSectionProps {
|
|
59
|
-
title: string;
|
|
60
|
-
links?: { href: string; label: string; active?: boolean }[];
|
|
61
|
-
children?: JSX.Element;
|
|
62
|
-
class?: string;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const sectionRow = style({
|
|
66
|
-
display: "flex",
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
const accentRail = style({
|
|
70
|
-
flexShrink: 0,
|
|
71
|
-
width: 4,
|
|
72
|
-
height: 20,
|
|
73
|
-
backgroundColor: "[var(--color-accent-300)]",
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const list = style({
|
|
77
|
-
display: "flex",
|
|
78
|
-
flexDirection: "column",
|
|
79
|
-
flexGrow: 1,
|
|
80
|
-
gap: 4,
|
|
81
|
-
paddingStart: 16,
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
export function NavSection(props: NavSectionProps) {
|
|
85
|
-
return (
|
|
86
|
-
<div class={props.class ?? ""}>
|
|
87
|
-
<NavItem title={props.title} />
|
|
88
|
-
<div class={sectionRow}>
|
|
89
|
-
<div class={accentRail} />
|
|
90
|
-
<ul class={list}>
|
|
91
|
-
<Show when={props.links}>
|
|
92
|
-
<For each={props.links}>
|
|
93
|
-
{(navLink) => (
|
|
94
|
-
<li>
|
|
95
|
-
<NavLink href={navLink.href} active={navLink.active}>
|
|
96
|
-
{navLink.label}
|
|
97
|
-
</NavLink>
|
|
98
|
-
</li>
|
|
99
|
-
)}
|
|
100
|
-
</For>
|
|
101
|
-
</Show>
|
|
102
|
-
{props.children}
|
|
103
|
-
</ul>
|
|
104
|
-
</div>
|
|
105
|
-
</div>
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export interface LateralNavProps {
|
|
110
|
-
transparent?: boolean;
|
|
111
|
-
children?: JSX.Element;
|
|
112
|
-
class?: string;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const nav = style<{ isTransparent: boolean }>({
|
|
116
|
-
width: 300,
|
|
117
|
-
margin: 0,
|
|
118
|
-
padding: 12,
|
|
119
|
-
borderEndWidth: 1,
|
|
120
|
-
borderStyle: "solid",
|
|
121
|
-
borderColor: "[var(--color-primary-600)]",
|
|
122
|
-
backgroundColor: {
|
|
123
|
-
default: "[var(--color-bg-200)]",
|
|
124
|
-
isTransparent: "transparent",
|
|
125
|
-
},
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
export function LateralNav(props: LateralNavProps) {
|
|
129
|
-
return (
|
|
130
|
-
<div class={`${nav({ isTransparent: props.transparent ?? false })} ${props.class ?? ""}`}>
|
|
131
|
-
{props.children}
|
|
132
|
-
</div>
|
|
133
|
-
);
|
|
134
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import type { JSX } from "solid-js";
|
|
2
|
-
// Styled via the S2 style() macro through viviana's own seam (../../style →
|
|
3
|
-
// src/style.ts). A clean two-word wordmark: the S2 title ramp sizes it; Silapse
|
|
4
|
-
// colors paint it (primary + accent). `inverted` swaps which word takes accent.
|
|
5
|
-
import { style } from "../../style" with { type: "macro" };
|
|
6
|
-
|
|
7
|
-
export type LogoSize = "sm" | "md" | "lg" | "xl";
|
|
8
|
-
|
|
9
|
-
export interface LogoProps {
|
|
10
|
-
firstWord?: string;
|
|
11
|
-
secondWord?: string;
|
|
12
|
-
size?: LogoSize;
|
|
13
|
-
inverted?: boolean;
|
|
14
|
-
class?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const wordmark = style<{ size: LogoSize }>({
|
|
18
|
-
display: "inline-flex",
|
|
19
|
-
alignItems: "baseline",
|
|
20
|
-
columnGap: 8,
|
|
21
|
-
whiteSpace: "nowrap",
|
|
22
|
-
font: {
|
|
23
|
-
size: {
|
|
24
|
-
sm: "title-sm",
|
|
25
|
-
md: "title",
|
|
26
|
-
lg: "title-xl",
|
|
27
|
-
xl: "title-3xl",
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
fontWeight: "black",
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
const word = style<{ tone: "primary" | "accent" }>({
|
|
34
|
-
color: {
|
|
35
|
-
tone: {
|
|
36
|
-
primary: "[var(--color-primary-100)]",
|
|
37
|
-
accent: "[var(--color-accent)]",
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
export function Logo(props: LogoProps): JSX.Element {
|
|
43
|
-
const firstWord = () => props.firstWord ?? "Proyecto";
|
|
44
|
-
const secondWord = () => props.secondWord ?? "Viviana";
|
|
45
|
-
const inverted = () => props.inverted ?? false;
|
|
46
|
-
|
|
47
|
-
return (
|
|
48
|
-
<span class={`${wordmark({ size: props.size ?? "md" })} ${props.class ?? ""}`}>
|
|
49
|
-
<span class={word({ tone: inverted() ? "accent" : "primary" })}>{firstWord()}</span>
|
|
50
|
-
<span class={word({ tone: inverted() ? "primary" : "accent" })}>{secondWord()}</span>
|
|
51
|
-
</span>
|
|
52
|
-
);
|
|
53
|
-
}
|