@aiaiai-pt/design-system 0.25.0 → 0.26.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.
@@ -0,0 +1,37 @@
1
+ export default Steps;
2
+ type Steps = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ /**
7
+ * Steps
8
+ *
9
+ * A numbered "how it works" explainer — an ordered list of steps, each a number
10
+ * badge, a heading and a short description. Distinct from `ServiceFlow`/`Stepper`
11
+ * (which drive a live multi-step form): this is presentational marketing content
12
+ * that explains a process. The numbers come from the list order (decorative
13
+ * badges, `aria-hidden`) so screen readers get the native `<ol>` sequence.
14
+ *
15
+ * @example
16
+ * <Steps
17
+ * heading="Como funciona"
18
+ * steps={[
19
+ * { title: "Proponha", text: "Submeta a sua ideia até 31 de março." },
20
+ * { title: "Análise", text: "A comissão verifica a elegibilidade." },
21
+ * { title: "Votação", text: "Os cidadãos votam nas finalistas." },
22
+ * { title: "Execução", text: "As propostas vencedoras são executadas." },
23
+ * ]}
24
+ * />
25
+ */
26
+ declare const Steps: import("svelte").Component<{
27
+ heading?: string;
28
+ headingLevel?: number;
29
+ steps?: any[];
30
+ class?: string;
31
+ } & Record<string, any>, {}, "">;
32
+ type $$ComponentProps = {
33
+ heading?: string;
34
+ headingLevel?: number;
35
+ steps?: any[];
36
+ class?: string;
37
+ } & Record<string, any>;
@@ -0,0 +1,161 @@
1
+ <!--
2
+ @component Testimonial
3
+
4
+ A quote / testimonial band — one prominent pull-quote, or a small grid of
5
+ them. Semantic `<figure>` + `<blockquote>` + `<figcaption>` so the attribution
6
+ is correctly associated with the quote. Presentational: the quotes (text +
7
+ author + role + optional avatar) are DATA.
8
+
9
+ @example Single quote
10
+ <Testimonial quote="Finalmente a minha rua tem iluminação nova." author="Maria S." role="Junta de Freguesia" />
11
+
12
+ @example A grid of quotes
13
+ <Testimonial
14
+ heading="O que dizem os cidadãos"
15
+ items={[
16
+ { quote: "Simples e rápido.", author: "João P." },
17
+ { quote: "A minha proposta foi executada!", author: "Ana R.", role: "Valongo" },
18
+ ]}
19
+ />
20
+ -->
21
+ <script>
22
+ let {
23
+ /** @type {string} Optional band heading (for the grid form). */
24
+ heading = "",
25
+ /** @type {2 | 3} Heading level for `heading`. */
26
+ headingLevel = 2,
27
+ /** @type {string} Single-quote text (when `items` is empty). */
28
+ quote = "",
29
+ /** @type {string} */
30
+ author = "",
31
+ /** @type {string} */
32
+ role = "",
33
+ /** @type {string | undefined} Avatar image URL. */
34
+ avatar = undefined,
35
+ /**
36
+ * @type {Array<{ quote?: string, author?: string, role?: string, avatar?: string }>}
37
+ * Multiple testimonials (renders a grid). Overrides the single-quote props.
38
+ */
39
+ items = [],
40
+ /** @type {string} */
41
+ class: className = "",
42
+ ...rest
43
+ } = $props();
44
+
45
+ const list = $derived(
46
+ items.length > 0
47
+ ? items
48
+ : quote
49
+ ? [{ quote, author, role, avatar }]
50
+ : [],
51
+ );
52
+ </script>
53
+
54
+ <section class="testimonial {className}" {...rest}>
55
+ {#if heading}
56
+ <svelte:element this={`h${headingLevel}`} class="testimonial-heading"
57
+ >{heading}</svelte:element
58
+ >
59
+ {/if}
60
+ <div class="testimonial-grid" class:testimonial-grid-multi={list.length > 1}>
61
+ {#each list as item (item.quote)}
62
+ <figure class="testimonial-item">
63
+ <blockquote class="testimonial-quote">{item.quote}</blockquote>
64
+ {#if item.author || item.role}
65
+ <figcaption class="testimonial-cite">
66
+ {#if item.avatar}
67
+ <img class="testimonial-avatar" src={item.avatar} alt="" loading="lazy" />
68
+ {/if}
69
+ <span class="testimonial-attrib">
70
+ {#if item.author}<span class="testimonial-author">{item.author}</span>{/if}
71
+ {#if item.role}<span class="testimonial-role">{item.role}</span>{/if}
72
+ </span>
73
+ </figcaption>
74
+ {/if}
75
+ </figure>
76
+ {/each}
77
+ </div>
78
+ </section>
79
+
80
+ <style>
81
+ .testimonial {
82
+ display: flex;
83
+ flex-direction: column;
84
+ gap: var(--space-xl);
85
+ overflow-wrap: break-word;
86
+ }
87
+
88
+ .testimonial-heading {
89
+ margin: 0;
90
+ font-family: var(--type-heading-font);
91
+ font-size: var(--type-heading-size);
92
+ line-height: var(--type-heading-leading);
93
+ color: var(--color-text);
94
+ }
95
+
96
+ .testimonial-grid {
97
+ display: grid;
98
+ grid-template-columns: 1fr;
99
+ gap: var(--space-lg);
100
+ }
101
+
102
+ @media (min-width: 768px) {
103
+ .testimonial-grid-multi {
104
+ grid-template-columns: repeat(2, 1fr);
105
+ }
106
+ }
107
+
108
+ .testimonial-item {
109
+ margin: 0;
110
+ display: flex;
111
+ flex-direction: column;
112
+ gap: var(--space-md);
113
+ padding: var(--space-xl);
114
+ background: var(--color-surface-secondary);
115
+ border-left: 3px solid var(--color-accent);
116
+ border-radius: var(--card-radius);
117
+ /* Grid child: shrink so a long quote/name wraps instead of overflowing. */
118
+ min-width: 0;
119
+ }
120
+
121
+ .testimonial-quote {
122
+ margin: 0;
123
+ font-family: var(--type-heading-sm-font);
124
+ font-size: var(--type-heading-sm-size);
125
+ line-height: var(--type-heading-sm-leading);
126
+ color: var(--color-text);
127
+ }
128
+
129
+ .testimonial-cite {
130
+ display: flex;
131
+ align-items: center;
132
+ gap: var(--space-sm);
133
+ font-style: normal;
134
+ }
135
+
136
+ .testimonial-avatar {
137
+ width: 2.5rem;
138
+ height: 2.5rem;
139
+ border-radius: 50%;
140
+ object-fit: cover;
141
+ }
142
+
143
+ .testimonial-attrib {
144
+ display: flex;
145
+ flex-direction: column;
146
+ min-width: 0;
147
+ }
148
+
149
+ .testimonial-author {
150
+ font-family: var(--type-label-font);
151
+ font-size: var(--type-body-sm-size);
152
+ font-weight: 600;
153
+ color: var(--color-text);
154
+ }
155
+
156
+ .testimonial-role {
157
+ font-family: var(--type-caption-font);
158
+ font-size: var(--type-caption-size);
159
+ color: var(--color-text-muted);
160
+ }
161
+ </style>
@@ -0,0 +1,45 @@
1
+ export default Testimonial;
2
+ type Testimonial = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ /**
7
+ * Testimonial
8
+ *
9
+ * A quote / testimonial band — one prominent pull-quote, or a small grid of
10
+ * them. Semantic `<figure>` + `<blockquote>` + `<figcaption>` so the attribution
11
+ * is correctly associated with the quote. Presentational: the quotes (text +
12
+ * author + role + optional avatar) are DATA.
13
+ *
14
+ * @example Single quote
15
+ * <Testimonial quote="Finalmente a minha rua tem iluminação nova." author="Maria S." role="Junta de Freguesia" />
16
+ *
17
+ * @example A grid of quotes
18
+ * <Testimonial
19
+ * heading="O que dizem os cidadãos"
20
+ * items={[
21
+ * { quote: "Simples e rápido.", author: "João P." },
22
+ * { quote: "A minha proposta foi executada!", author: "Ana R.", role: "Valongo" },
23
+ * ]}
24
+ * />
25
+ */
26
+ declare const Testimonial: import("svelte").Component<{
27
+ heading?: string;
28
+ headingLevel?: number;
29
+ quote?: string;
30
+ author?: string;
31
+ role?: string;
32
+ avatar?: any;
33
+ items?: any[];
34
+ class?: string;
35
+ } & Record<string, any>, {}, "">;
36
+ type $$ComponentProps = {
37
+ heading?: string;
38
+ headingLevel?: number;
39
+ quote?: string;
40
+ author?: string;
41
+ role?: string;
42
+ avatar?: any;
43
+ items?: any[];
44
+ class?: string;
45
+ } & Record<string, any>;
@@ -31,6 +31,14 @@ export { default as ContentBlock } from "./ContentBlock.svelte";
31
31
  export { default as StatusTimeline } from "./StatusTimeline.svelte";
32
32
  export { default as WidgetGrid } from "./WidgetGrid.svelte";
33
33
  export { default as VotingWidget } from "./VotingWidget.svelte";
34
+ export { default as FeatureGrid } from "./FeatureGrid.svelte";
35
+ export { default as CallToAction } from "./CallToAction.svelte";
36
+ export { default as MediaText } from "./MediaText.svelte";
37
+ export { default as Steps } from "./Steps.svelte";
38
+ export { default as Testimonial } from "./Testimonial.svelte";
39
+ export { default as FaqList } from "./FaqList.svelte";
40
+ export { default as LogoStrip } from "./LogoStrip.svelte";
41
+ export { default as MediaGallery } from "./MediaGallery.svelte";
34
42
  export { default as Card } from "./Card.svelte";
35
43
  export { default as Panel } from "./Panel.svelte";
36
44
  export { default as Modal } from "./Modal.svelte";
@@ -53,6 +61,14 @@ export { default as TabPanel } from "./TabPanel.svelte";
53
61
  export { default as FeedView } from "./FeedView.svelte";
54
62
  export { default as ActionPanel } from "./ActionPanel.svelte";
55
63
  export { default as RecordList } from "./RecordList.svelte";
64
+ export { default as PhaseTimeline } from "./PhaseTimeline.svelte";
65
+ export { default as RankingBoard } from "./RankingBoard.svelte";
66
+ export { default as ResultsChart } from "./ResultsChart.svelte";
67
+ export { default as NotificationPrefs } from "./NotificationPrefs.svelte";
68
+ export { default as ConsentManager } from "./ConsentManager.svelte";
69
+ export { default as ServiceFlow } from "./ServiceFlow.svelte";
70
+ export { default as CheckAnswers } from "./CheckAnswers.svelte";
71
+ export { default as Confirmation } from "./Confirmation.svelte";
56
72
  export { default as Alert } from "./Alert.svelte";
57
73
  export { default as Toast } from "./Toast.svelte";
58
74
  export { default as ToastManager } from "./ToastManager.svelte";
@@ -49,6 +49,18 @@ export { default as StatusTimeline } from "./StatusTimeline.svelte";
49
49
  export { default as WidgetGrid } from "./WidgetGrid.svelte";
50
50
  export { default as VotingWidget } from "./VotingWidget.svelte";
51
51
 
52
+ // Landing & content surface (#105 Phase 7) — presentational, marketing-grade,
53
+ // config-driven sections for landing / campaign / about / faq / contact pages.
54
+ // Each renders purely from props (zero fetch); copy + media are tenant DATA.
55
+ export { default as FeatureGrid } from "./FeatureGrid.svelte";
56
+ export { default as CallToAction } from "./CallToAction.svelte";
57
+ export { default as MediaText } from "./MediaText.svelte";
58
+ export { default as Steps } from "./Steps.svelte";
59
+ export { default as Testimonial } from "./Testimonial.svelte";
60
+ export { default as FaqList } from "./FaqList.svelte";
61
+ export { default as LogoStrip } from "./LogoStrip.svelte";
62
+ export { default as MediaGallery } from "./MediaGallery.svelte";
63
+
52
64
  // Containers
53
65
  export { default as Card } from "./Card.svelte";
54
66
  export { default as Panel } from "./Panel.svelte";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiaiai-pt/design-system",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "description": "Design system tokens and Svelte components for aiaiai products",
5
5
  "license": "MIT",
6
6
  "type": "module",