@rimelight/ui 0.0.25 → 0.0.26

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rimelight/ui",
3
- "version": "0.0.25",
3
+ "version": "0.0.26",
4
4
  "private": false,
5
5
  "description": "Rimelight Entertainment UI Library.",
6
6
  "keywords": [
@@ -2,13 +2,13 @@
2
2
  import RLAButton from "./astro/RLAButton.astro";
3
3
 
4
4
  export interface ThemeToggleProps {
5
- class?: string;
6
5
  size?: "sm" | "md" | "lg";
6
+ class?: any;
7
7
  }
8
8
 
9
9
  type Props = ThemeToggleProps;
10
10
 
11
- const { class: className, size = "md" } = Astro.props as Props
11
+ const { size = "md", class: className } = Astro.props as Props
12
12
  ---
13
13
 
14
14
  <RLAButton
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  import { scv, cx } from "css-variants"
3
3
  import { useUi, resolveClasses } from "../../utils"
4
- import type { ComponentVariants } from "../../types"
4
+ import type { ComponentVariants, ComponentSlots } from "../../types"
5
5
  import buttonTheme from "../../themes/button.theme"
6
6
 
7
7
  const button = scv(buttonTheme)
@@ -21,8 +21,8 @@ export interface RLAButtonProps {
21
21
  active?: boolean;
22
22
  activeColor?: ButtonVariants['color'];
23
23
  activeVariant?: ButtonVariants['variant'];
24
- ui?: Partial<Record<string, string>>;
25
- class?: string;
24
+ ui?: ComponentSlots<typeof buttonTheme>;
25
+ class?: any;
26
26
  [key: string]: unknown;
27
27
  }
28
28
 
@@ -30,8 +30,6 @@ const {
30
30
  variant = "solid",
31
31
  color = "primary",
32
32
  size = "md",
33
- class: className,
34
- ui: uiProp,
35
33
  href,
36
34
  label,
37
35
  leadingIcon,
@@ -42,6 +40,8 @@ const {
42
40
  active = false,
43
41
  activeColor,
44
42
  activeVariant,
43
+ ui: uiProp,
44
+ class: className,
45
45
  ...rest
46
46
  } = Astro.props as RLAButtonProps
47
47
 
@@ -75,7 +75,7 @@ const Tag = href ? "a" : "button";
75
75
  ---
76
76
  <Tag
77
77
  class={classes.root}
78
- data-slot="rla-button"
78
+ data-slot="root"
79
79
  {...(Tag === "a" ? { href } : {})}
80
80
  {...rest}
81
81
  >
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  import { scv } from "css-variants"
3
3
  import { useUi, resolveClasses } from "../../utils"
4
- import type { ComponentVariants } from "../../types"
4
+ import type { ComponentVariants, ComponentSlots } from "../../types"
5
5
  import footerTheme from "../../themes/footer.theme"
6
6
 
7
7
  const footer = scv(footerTheme)
@@ -9,15 +9,15 @@ type FooterVariants = ComponentVariants<typeof footerTheme>
9
9
 
10
10
  export interface RLAFooterProps {
11
11
  contain?: FooterVariants['contain'];
12
- ui?: Partial<Record<string, string>>;
13
- class?: string;
12
+ ui?: ComponentSlots<typeof footerTheme>;
13
+ class?: any;
14
14
  [key: string]: unknown;
15
15
  }
16
16
 
17
17
  const {
18
18
  contain = false,
19
- class: className,
20
19
  ui: uiProp,
20
+ class: className,
21
21
  ...rest
22
22
  } = Astro.props as RLAFooterProps
23
23
 
@@ -26,17 +26,17 @@ const classes = resolveClasses(footer, { contain }, useUi("footer", uiProp), cla
26
26
 
27
27
  <footer
28
28
  class:list={[classes.root]}
29
- data-slot="rla-footer"
29
+ data-slot="root"
30
30
  {...rest}
31
31
  >
32
32
  <div class:list={[classes.container]}>
33
- <div class:list={[classes.left]} data-slot="footer-left">
33
+ <div class:list={[classes.left]} data-slot="left">
34
34
  <slot name="left" />
35
35
  </div>
36
- <div class:list={[classes.center]} data-slot="footer-center">
36
+ <div class:list={[classes.center]} data-slot="center">
37
37
  <slot name="center" />
38
38
  </div>
39
- <div class:list={[classes.right]} data-slot="footer-right">
39
+ <div class:list={[classes.right]} data-slot="right">
40
40
  <slot name="right" />
41
41
  </div>
42
42
  </div>
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  import { scv } from "css-variants"
3
3
  import { useUi, resolveClasses } from "../../utils"
4
- import type { ComponentVariants } from "../../types"
4
+ import type { ComponentVariants, ComponentSlots } from "../../types"
5
5
  import headerTheme from "../../themes/header.theme"
6
6
 
7
7
  const header = scv(headerTheme)
@@ -13,8 +13,8 @@ export interface RLAHeaderProps {
13
13
  fixed?: HeaderVariants['fixed'];
14
14
  stackIndex?: number;
15
15
  hideOnScroll?: boolean;
16
- ui?: Partial<Record<string, string>>;
17
- class?: string;
16
+ ui?: ComponentSlots<typeof headerTheme>;
17
+ class?: any;
18
18
  [key: string]: unknown;
19
19
  }
20
20
 
@@ -24,8 +24,8 @@ const {
24
24
  fixed = false,
25
25
  stackIndex = 0,
26
26
  hideOnScroll = false,
27
- class: className,
28
27
  ui: uiProp,
28
+ class: className,
29
29
  ...rest
30
30
  } = Astro.props as RLAHeaderProps;
31
31
 
@@ -41,6 +41,7 @@ const zIndex = 100 - stackIndex;
41
41
 
42
42
  <header
43
43
  id={headerId}
44
+ data-slot="root"
44
45
  class:list={[classes.root]}
45
46
  data-rla-header={fixed ? "true" : undefined}
46
47
  data-stack-index={stackIndex}
@@ -50,13 +51,13 @@ const zIndex = 100 - stackIndex;
50
51
  >
51
52
  <div class:list={[classes.content]} data-header-content>
52
53
  <div class:list={[classes.container]}>
53
- <div class:list={[classes.left]} data-slot="header-left">
54
+ <div class:list={[classes.left]} data-slot="left">
54
55
  <slot name="left" />
55
56
  </div>
56
- <div class:list={[classes.center]} data-slot="header-center">
57
+ <div class:list={[classes.center]} data-slot="center">
57
58
  <slot name="center" />
58
59
  </div>
59
- <div class:list={[classes.right]} data-slot="header-right">
60
+ <div class:list={[classes.right]} data-slot="right">
60
61
  <slot name="right" />
61
62
  </div>
62
63
  </div>
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  import { scv } from "css-variants"
3
3
  import { useUi, resolveClasses } from "../../utils"
4
- import type { ComponentVariants } from "../../types"
4
+ import type { ComponentVariants, ComponentSlots } from "../../types"
5
5
  import iconTheme from "../../themes/icon.theme"
6
6
 
7
7
  const icon = scv(iconTheme)
@@ -10,16 +10,16 @@ type IconVariants = ComponentVariants<typeof iconTheme>
10
10
  export interface RLAIconProps {
11
11
  name: string
12
12
  size?: IconVariants['size']
13
- class?: string
14
- ui?: Partial<Record<string, string>>
13
+ ui?: ComponentSlots<typeof iconTheme>
14
+ class?: any
15
15
  [key: string]: unknown
16
16
  }
17
17
 
18
18
  const {
19
19
  name,
20
20
  size = "md",
21
- class: className,
22
21
  ui: uiProp,
22
+ class: className,
23
23
  ...rest
24
24
  } = Astro.props as RLAIconProps
25
25
 
@@ -28,7 +28,7 @@ const classes = resolveClasses(icon, { size }, useUi("icon", uiProp), className)
28
28
 
29
29
  <span
30
30
  class={classes.root}
31
- data-slot="rla-icon"
31
+ data-slot="root"
32
32
  aria-hidden="true"
33
33
  {...rest}
34
34
  >
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  import { scv } from "css-variants"
3
3
  import { useUi, resolveClasses } from "../../utils"
4
+ import type { ComponentSlots } from "../../types"
4
5
  import logoTheme from "../../themes/logo.theme"
5
6
  import { getUIConfig } from "virtual:rimelight-ui"
6
7
 
@@ -10,9 +11,9 @@ export interface RLALogoProps {
10
11
  variant?: string;
11
12
  mode?: "color" | "white" | "black";
12
13
  href?: string;
13
- ui?: Partial<Record<string, string>>;
14
- class?: string;
15
14
  alt?: string;
15
+ ui?: ComponentSlots<typeof logoTheme>;
16
+ class?: any;
16
17
  [key: string]: unknown;
17
18
  }
18
19
 
@@ -20,9 +21,9 @@ const {
20
21
  variant = "logomark",
21
22
  mode,
22
23
  href = "/",
23
- class: className,
24
- ui: uiProp,
25
24
  alt,
25
+ ui: uiProp,
26
+ class: className,
26
27
  ...rest
27
28
  } = Astro.props as RLALogoProps;
28
29
 
@@ -50,7 +51,7 @@ const isIcon = logoSrc && (logoSrc.includes(":") || logoSrc.startsWith("i-"));
50
51
  class={classes.root}
51
52
  href={href}
52
53
  aria-label={alt || variant}
53
- data-slot="rla-logo"
54
+ data-slot="root"
54
55
  {...rest}
55
56
  >
56
57
  {logoSrc ? (
@@ -1,19 +1,20 @@
1
1
  ---
2
2
  import { scv } from "css-variants"
3
3
  import { useUi, resolveClasses } from "../../utils"
4
+ import type { ComponentSlots } from "../../types"
4
5
  import placeholderTheme from "../../themes/placeholder.theme"
5
6
 
6
7
  const placeholder = scv(placeholderTheme)
7
8
 
8
9
  export interface RLAPlaceholderProps {
9
- ui?: Partial<Record<string, string>>
10
- class?: string
10
+ ui?: ComponentSlots<typeof placeholderTheme>
11
+ class?: any
11
12
  [key: string]: unknown
12
13
  }
13
14
 
14
15
  const {
15
- class: className,
16
16
  ui: uiProp,
17
+ class: className,
17
18
  ...rest
18
19
  } = Astro.props as RLAPlaceholderProps
19
20
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  import { scv } from "css-variants"
3
3
  import { useUi, resolveClasses } from "../../utils"
4
- import type { ComponentVariants } from "../../types"
4
+ import type { ComponentVariants, ComponentSlots } from "../../types"
5
5
  import scrollToTopTheme from "../../themes/scroll-to-top.theme"
6
6
 
7
7
  const scrollToTop = scv(scrollToTopTheme)
@@ -13,8 +13,8 @@ export interface RLAScrollToTopProps {
13
13
  duration?: number;
14
14
  threshold?: number;
15
15
  showProgress?: boolean;
16
- ui?: Partial<Record<string, string>>;
17
- class?: string;
16
+ ui?: ComponentSlots<typeof scrollToTopTheme>;
17
+ class?: any;
18
18
  [key: string]: unknown;
19
19
  }
20
20
 
@@ -1,181 +1,210 @@
1
- ---
2
- import { scv } from "css-variants"
3
- import { useUi, resolveClasses } from "../../utils"
4
- import type { ComponentVariants } from "../../types"
5
- import sectionTheme from "../../themes/section.theme"
6
-
7
- const section = scv(sectionTheme)
8
- type SectionVariants = ComponentVariants<typeof sectionTheme>
9
-
10
- export interface RLASectionProps {
11
- as?: string;
12
- variant?: SectionVariants['variant'];
13
- headline?: string;
14
- icon?: string;
15
- title?: string;
16
- description?: string;
17
- orientation?: SectionVariants['orientation'];
18
- reverse?: boolean;
19
- ctaVariant?: SectionVariants['ctaVariant'];
20
- ui?: Partial<Record<string, string>>;
21
- class?: string;
22
- [key: string]: unknown;
23
- }
24
-
25
- const {
26
- as = "section",
27
- variant = "default",
28
- orientation = "vertical",
29
- reverse = false,
30
- ctaVariant = "outline",
31
- class: className,
32
- ui: uiProp,
33
- ...rest
34
- } = Astro.props as RLASectionProps;
35
-
36
- const classes = resolveClasses(section, {
37
- variant,
38
- orientation,
39
- reverse,
40
- ...(variant === "cta" && { ctaVariant }),
41
- headline: Astro.slots.has("headline") || Astro.props.headline,
42
- title: Astro.slots.has("title") || Astro.props.title,
43
- description: Astro.slots.has("description") || Astro.props.description,
44
- body: Astro.slots.has("body") || Astro.slots.has("features")
45
- }, useUi("section", uiProp), className);
46
-
47
- const Tag = as;
48
- ---
49
-
50
- <Tag
51
- data-orientation={orientation}
52
- data-slot="rla-section"
53
- class:list={[classes.root]}
54
- {...rest}
55
- >
56
- <slot name="background">
57
- {Astro.slots.has("background") && (
58
- <div class:list={[classes.background]} data-slot="background">
59
- <slot name="background" />
60
- </div>
61
- )}
62
- </slot>
63
-
64
- <slot name="top" />
65
-
66
- <div
67
- data-slot="container"
68
- class:list={[classes.container]}
69
- >
70
- {(Astro.slots.has("header") || Astro.props.icon || Astro.props.headline || Astro.props.title || Astro.props.description || Astro.slots.has("body") || Astro.slots.has("footer") || Astro.slots.has("links") || Astro.slots.has("features")) && (
71
- <div
72
- data-slot="wrapper"
73
- class:list={[classes.wrapper]}
74
- >
75
- {(Astro.slots.has("header") || Astro.props.icon || Astro.props.headline || Astro.props.title || Astro.props.description) && (
76
- <div
77
- data-slot="header"
78
- class:list={[classes.header]}
79
- >
80
- <slot name="header">
81
- {(Astro.props.icon || Astro.slots.has("leading")) && (
82
- <div
83
- data-slot="leading"
84
- class:list={[classes.leading]}
85
- >
86
- <slot name="leading" {...{ ui: classes }}>
87
- {Astro.props.icon && (
88
- <span
89
- class:list={[classes.leadingIcon]}
90
- data-slot="leading-icon"
91
- >
92
- <span class={Astro.props.icon} aria-hidden="true" />
93
- </span>
94
- )}
95
- </slot>
96
- </div>
97
- )}
98
-
99
- {(Astro.props.headline || Astro.slots.has("headline")) && (
100
- <div
101
- data-slot="headline"
102
- class:list={[classes.headline]}
103
- >
104
- <slot name="headline">
105
- {Astro.props.headline}
106
- </slot>
107
- </div>
108
- )}
109
-
110
- {(Astro.props.title || Astro.slots.has("title")) && (
111
- <component
112
- is={variant === "hero" ? "h1" : "h2"}
113
- data-slot="title"
114
- class:list={[classes.title]}
115
- >
116
- <slot name="title">
117
- {Astro.props.title}
118
- </slot>
119
- </component>
120
- )}
121
-
122
- {(Astro.props.description || Astro.slots.has("description")) && (
123
- <div
124
- data-slot="description"
125
- class:list={[classes.description]}
126
- >
127
- <slot name="description">
128
- {Astro.props.description}
129
- </slot>
130
- </div>
131
- )}
132
- </slot>
133
- </div>
134
- )}
135
-
136
- {(Astro.slots.has("body") || Astro.slots.has("features")) && (
137
- <div
138
- data-slot="body"
139
- class:list={[classes.body]}
140
- >
141
- <slot name="body">
142
- {Astro.slots.has("features") && (
143
- <ul
144
- data-slot="features"
145
- class:list={[classes.features]}
146
- >
147
- <slot name="features" />
148
- </ul>
149
- )}
150
- </slot>
151
- </div>
152
- )}
153
-
154
- {(Astro.slots.has("footer") || Astro.slots.has("links")) && (
155
- <div
156
- data-slot="footer"
157
- class:list={[classes.footer]}
158
- >
159
- <slot name="footer">
160
- {Astro.slots.has("links") && (
161
- <div
162
- data-slot="links"
163
- class:list={[classes.links]}
164
- >
165
- <slot name="links" />
166
- </div>
167
- )}
168
- </slot>
169
- </div>
170
- )}
171
- </div>
172
- )}
173
-
174
- <slot />
175
- {orientation === "horizontal" && (
176
- <div class="hidden lg:block" />
177
- )}
178
- </div>
179
-
180
- <slot name="bottom" />
181
- </Tag>
1
+ ---
2
+ import { scv } from "css-variants"
3
+ import { useUi, resolveClasses } from "../../utils"
4
+ import type { ComponentVariants, ComponentSlots } from "../../types"
5
+ import sectionTheme from "../../themes/section.theme"
6
+ import type { RLAIconProps } from "./RLAIcon.astro"
7
+ import type { RLAButtonProps } from "./RLAButton.astro"
8
+ import RLAIcon from "./RLAIcon.astro"
9
+ import RLAButton from "./RLAButton.astro"
10
+
11
+ const section = scv(sectionTheme)
12
+ type SectionVariants = ComponentVariants<typeof sectionTheme>
13
+
14
+ export interface RLASectionProps {
15
+ /**
16
+ * The element or component this component should render as.
17
+ * @default 'section'
18
+ */
19
+ as?: any;
20
+ /**
21
+ * The variant of the section.
22
+ * @default 'default'
23
+ */
24
+ variant?: SectionVariants['variant'];
25
+ /** The variant of the section when it's a CTA.
26
+ * @default 'solid'
27
+ */
28
+ ctaVariant?: SectionVariants['ctaVariant'];
29
+ /**
30
+ * The headline displayed above the title.
31
+ */
32
+ headline?: string;
33
+ /**
34
+ * The icon displayed above the title.
35
+ */
36
+ icon?: RLAIconProps["name"];
37
+ /**
38
+ * The section's title, displayed as a <h1> for the hero variant or <h2> otherwise.
39
+ */
40
+ title?: string;
41
+ /**
42
+ * The section's description, displayed under the title.
43
+ */
44
+ description?: string;
45
+ /**
46
+ * Display a list of buttons under the description.
47
+ */
48
+ links?: RLAButtonProps[]
49
+ /**
50
+ * The orientation of the section.
51
+ * @default 'vertical'
52
+ */
53
+ orientation?: SectionVariants['orientation'];
54
+ /**
55
+ * Reverse the order of the default slot.
56
+ * @default false
57
+ */
58
+ reverse?: boolean;
59
+ ui?: ComponentSlots<typeof sectionTheme>;
60
+ class?: any;
61
+ [key: string]: unknown;
62
+ }
63
+
64
+ const {
65
+ as = "section",
66
+ variant = "default",
67
+ orientation = "vertical",
68
+ reverse = false,
69
+ ctaVariant = "solid",
70
+ ui: uiProp,
71
+ class: className,
72
+ ...rest
73
+ } = Astro.props as RLASectionProps;
74
+
75
+ const classes = resolveClasses(section, {
76
+ variant,
77
+ orientation,
78
+ reverse,
79
+ ...(variant === "cta" && { ctaVariant }),
80
+ headline: !!(Astro.slots.has("headline") || Astro.props.headline),
81
+ title: !!(Astro.slots.has("title") || Astro.props.title),
82
+ description: !!(Astro.slots.has("description") || Astro.props.description),
83
+ body: Astro.slots.has("body")
84
+ }, useUi("section", uiProp), className);
85
+
86
+ const hasDefaultSlot = Astro.slots.has("default");
87
+
88
+ const Tag = as;
89
+ const TitleTag = variant === "hero" ? "h1" : "h2";
90
+ ---
91
+
92
+ <Tag
93
+ data-orientation={orientation}
94
+ data-slot="root"
95
+ class:list={[classes.root]}
96
+ {...rest}
97
+ >
98
+ {Astro.slots.has("background") && (
99
+ <div class:list={[classes.background]} data-slot="background">
100
+ <slot name="background" />
101
+ </div>
102
+ )}
103
+
104
+ <slot name="top" />
105
+
106
+ <div
107
+ data-slot="container"
108
+ class:list={[classes.container]}
109
+ >
110
+ {(Astro.slots.has("header") || Astro.props.icon || Astro.props.headline || Astro.props.title || Astro.props.description || Astro.slots.has("body") || Astro.slots.has("footer") || Astro.slots.has("links") || Astro.props.links?.length) && (
111
+ <div
112
+ data-slot="wrapper"
113
+ class:list={[classes.wrapper]}
114
+ >
115
+ {(Astro.slots.has("header") || Astro.props.icon || Astro.props.headline || Astro.props.title || Astro.props.description) && (
116
+ <div
117
+ data-slot="header"
118
+ class:list={[classes.header]}
119
+ >
120
+ <slot name="header">
121
+ {(Astro.props.icon || Astro.slots.has("leading")) && (
122
+ <div
123
+ data-slot="leading"
124
+ class:list={[classes.leading]}
125
+ >
126
+ <slot name="leading" {...{ ui: classes }}>
127
+ {Astro.props.icon && (
128
+ <RLAIcon name={Astro.props.icon} size="md" ui={{ root: classes.leadingIcon }} />
129
+ )}
130
+ </slot>
131
+ </div>
132
+ )}
133
+
134
+ {(Astro.props.headline || Astro.slots.has("headline")) && (
135
+ <div
136
+ data-slot="headline"
137
+ class:list={[classes.headline]}
138
+ >
139
+ <slot name="headline">
140
+ {Astro.props.headline}
141
+ </slot>
142
+ </div>
143
+ )}
144
+
145
+ {(Astro.props.title || Astro.slots.has("title")) && (
146
+ <TitleTag
147
+ data-slot="title"
148
+ class:list={[classes.title]}
149
+ >
150
+ <slot name="title">
151
+ {Astro.props.title}
152
+ </slot>
153
+ </TitleTag>
154
+ )}
155
+
156
+ {(Astro.props.description || Astro.slots.has("description")) && (
157
+ <div
158
+ data-slot="description"
159
+ class:list={[classes.description]}
160
+ >
161
+ <slot name="description">
162
+ {Astro.props.description}
163
+ </slot>
164
+ </div>
165
+ )}
166
+ </slot>
167
+ </div>
168
+ )}
169
+
170
+ {Astro.slots.has("body") && (
171
+ <div
172
+ data-slot="body"
173
+ class:list={[classes.body]}
174
+ >
175
+ <slot name="body" />
176
+ </div>
177
+ )}
178
+
179
+ {(Astro.slots.has("footer") || Astro.slots.has("links") || Astro.props.links?.length) && (
180
+ <div
181
+ data-slot="footer"
182
+ class:list={[classes.footer]}
183
+ >
184
+ <slot name="footer">
185
+ {(Astro.props.links?.length || Astro.slots.has("links")) && (
186
+ <div
187
+ data-slot="links"
188
+ class:list={[classes.links]}
189
+ >
190
+ {Astro.props.links?.map((link) => (
191
+ <RLAButton size="lg" {...link} />
192
+ ))}
193
+ <slot name="links" />
194
+ </div>
195
+ )}
196
+ </slot>
197
+ </div>
198
+ )}
199
+ </div>
200
+ )}
201
+
202
+ {hasDefaultSlot ? (
203
+ <slot />
204
+ ) : orientation === "horizontal" ? (
205
+ <div class="hidden lg:block" />
206
+ ) : null}
207
+ </div>
208
+
209
+ <slot name="bottom" />
210
+ </Tag>
@@ -2,7 +2,7 @@
2
2
  import { computed, useSlots } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
- import type { ComponentVariants } from "../../types"
5
+ import type { ComponentVariants, ComponentSlots } from "../../types"
6
6
  import buttonTheme from "../../themes/button.theme"
7
7
 
8
8
  const button = scv(buttonTheme)
@@ -64,8 +64,8 @@ export interface RLVButtonProps {
64
64
  /**
65
65
  * Component-specific CSS class overrides
66
66
  */
67
- ui?: Partial<Record<string, string>>
68
- class?: string
67
+ ui?: ComponentSlots<typeof buttonTheme>
68
+ class?: any
69
69
  [key: string]: unknown
70
70
  }
71
71
 
@@ -73,8 +73,6 @@ const {
73
73
  variant = "solid",
74
74
  color = "primary",
75
75
  size = "md",
76
- class: className,
77
- ui: uiProp,
78
76
  href,
79
77
  label,
80
78
  leadingIcon,
@@ -84,7 +82,9 @@ const {
84
82
  block = false,
85
83
  active = false,
86
84
  activeColor,
87
- activeVariant
85
+ activeVariant,
86
+ ui: uiProp,
87
+ class: className
88
88
  } = defineProps<RLVButtonProps>()
89
89
 
90
90
  const slots = useSlots()
@@ -141,13 +141,7 @@ const Tag = href ? "a" : "button"
141
141
  </script>
142
142
 
143
143
  <template>
144
- <component
145
- v-bind="$attrs"
146
- :is="Tag"
147
- :href="href"
148
- :class="resolvedClasses.root"
149
- data-slot="rlv-button"
150
- >
144
+ <component v-bind="$attrs" :is="Tag" :href="href" :class="resolvedClasses.root" data-slot="root">
151
145
  <slot name="leading" :ui="resolvedClasses">
152
146
  <span v-if="isLeading" :class="resolvedClasses.leadingIcon" data-slot="leading-icon">
153
147
  <span :class="[showLeadingIcon, leadingIconClass]" aria-hidden="true" />
@@ -2,7 +2,7 @@
2
2
  import { computed } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
- import type { ComponentVariants } from "../../types"
5
+ import type { ComponentVariants, ComponentSlots } from "../../types"
6
6
  import footerTheme from "../../themes/footer.theme"
7
7
 
8
8
  const footer = scv(footerTheme)
@@ -10,11 +10,11 @@ type FooterVariants = ComponentVariants<typeof footerTheme>
10
10
 
11
11
  export interface RLVFooterProps {
12
12
  contain?: FooterVariants["contain"]
13
- ui?: Partial<Record<string, string>>
14
- class?: string
13
+ ui?: ComponentSlots<typeof footerTheme>
14
+ class?: any
15
15
  }
16
16
 
17
- const { contain = false, class: className, ui: uiProp } = defineProps<RLVFooterProps>()
17
+ const { contain = false, ui: uiProp, class: className } = defineProps<RLVFooterProps>()
18
18
 
19
19
  defineSlots<{
20
20
  left(props: {}): any
@@ -28,15 +28,15 @@ const resolvedClasses = computed(() =>
28
28
  </script>
29
29
 
30
30
  <template>
31
- <footer :class="[resolvedClasses.root]" data-slot="rlv-footer" v-bind="$attrs">
31
+ <footer :class="[resolvedClasses.root]" data-slot="root" v-bind="$attrs">
32
32
  <div :class="resolvedClasses.container">
33
- <div :class="resolvedClasses.left" data-slot="footer-left">
33
+ <div :class="resolvedClasses.left" data-slot="left">
34
34
  <slot name="left" />
35
35
  </div>
36
- <div :class="resolvedClasses.center" data-slot="footer-center">
36
+ <div :class="resolvedClasses.center" data-slot="center">
37
37
  <slot name="center" />
38
38
  </div>
39
- <div :class="resolvedClasses.right" data-slot="footer-right">
39
+ <div :class="resolvedClasses.right" data-slot="right">
40
40
  <slot name="right" />
41
41
  </div>
42
42
  </div>
@@ -2,7 +2,7 @@
2
2
  import { computed, onMounted, onUnmounted, ref } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
- import type { ComponentVariants } from "../../types"
5
+ import type { ComponentVariants, ComponentSlots } from "../../types"
6
6
  import headerTheme from "../../themes/header.theme"
7
7
  import { getHeaderStack } from "../../utils/headerStack"
8
8
 
@@ -15,8 +15,8 @@ export interface RLVHeaderProps {
15
15
  fixed?: HeaderVariants["fixed"]
16
16
  stackIndex?: number
17
17
  hideOnScroll?: boolean
18
- ui?: Partial<Record<string, string>>
19
- class?: string
18
+ ui?: ComponentSlots<typeof headerTheme>
19
+ class?: any
20
20
  }
21
21
 
22
22
  const {
@@ -25,8 +25,8 @@ const {
25
25
  fixed = false,
26
26
  stackIndex = 0,
27
27
  hideOnScroll = false,
28
- class: className,
29
- ui: uiProp
28
+ ui: uiProp,
29
+ class: className
30
30
  } = defineProps<RLVHeaderProps>()
31
31
 
32
32
  defineSlots<{
@@ -112,18 +112,18 @@ onUnmounted(() => {
112
112
  :id="id"
113
113
  :class="[resolvedClasses.root]"
114
114
  :style="fixedStyle"
115
- data-slot="rlv-header"
115
+ data-slot="root"
116
116
  v-bind="$attrs"
117
117
  >
118
118
  <div ref="contentRef" :class="resolvedClasses.content">
119
119
  <div :class="resolvedClasses.container">
120
- <div :class="resolvedClasses.left" data-slot="header-left">
120
+ <div :class="resolvedClasses.left" data-slot="left">
121
121
  <slot name="left" />
122
122
  </div>
123
- <div :class="resolvedClasses.center" data-slot="header-center">
123
+ <div :class="resolvedClasses.center" data-slot="center">
124
124
  <slot name="center" />
125
125
  </div>
126
- <div :class="resolvedClasses.right" data-slot="header-right">
126
+ <div :class="resolvedClasses.right" data-slot="right">
127
127
  <slot name="right" />
128
128
  </div>
129
129
  </div>
@@ -2,7 +2,7 @@
2
2
  import { computed } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
- import type { ComponentVariants } from "../../types"
5
+ import type { ComponentVariants, ComponentSlots } from "../../types"
6
6
  import iconTheme from "../../themes/icon.theme"
7
7
 
8
8
  const icon = scv(iconTheme)
@@ -11,11 +11,11 @@ type IconVariants = ComponentVariants<typeof iconTheme>
11
11
  export interface RLVIconProps {
12
12
  name: string
13
13
  size?: IconVariants["size"]
14
- class?: string
15
- ui?: Partial<Record<string, string>>
14
+ ui?: ComponentSlots<typeof iconTheme>
15
+ class?: any
16
16
  }
17
17
 
18
- const { name, size = "md", class: className, ui: uiProp } = defineProps<RLVIconProps>()
18
+ const { name, size = "md", ui: uiProp, class: className } = defineProps<RLVIconProps>()
19
19
 
20
20
  const resolvedClasses = computed(() =>
21
21
  resolveClasses(icon, { size }, useUi("icon", uiProp), className)
@@ -27,12 +27,7 @@ defineSlots<{
27
27
  </script>
28
28
 
29
29
  <template>
30
- <span
31
- v-bind="$attrs"
32
- :class="[resolvedClasses.root, name]"
33
- data-slot="rlv-icon"
34
- aria-hidden="true"
35
- >
30
+ <span v-bind="$attrs" :class="[resolvedClasses.root, name]" data-slot="root" aria-hidden="true">
36
31
  <slot />
37
32
  </span>
38
33
  </template>
@@ -2,6 +2,7 @@
2
2
  import { computed } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
+ import type { ComponentSlots } from "../../types"
5
6
  import logoTheme from "../../themes/logo.theme"
6
7
  import { getUIConfig } from "virtual:rimelight-ui"
7
8
 
@@ -11,9 +12,9 @@ export interface RLVLogoProps {
11
12
  variant?: string
12
13
  mode?: "color" | "white" | "black"
13
14
  href?: string
14
- ui?: Partial<Record<string, string>>
15
- class?: string
16
15
  alt?: string
16
+ ui?: ComponentSlots<typeof logoTheme>
17
+ class?: any
17
18
  [key: string]: unknown
18
19
  }
19
20
 
@@ -64,7 +65,7 @@ const Tag = computed(() => (props.href ? "a" : "div"))
64
65
  :href="Tag === 'a' ? href : undefined"
65
66
  :aria-label="alt || variant"
66
67
  :class="resolvedClasses.root"
67
- data-slot="rlv-logo"
68
+ data-slot="root"
68
69
  >
69
70
  <template v-if="logoSrc">
70
71
  <span v-if="isIcon" :class="[logoSrc, 'size-full block shrink-0']" aria-hidden="true" />
@@ -2,17 +2,18 @@
2
2
  import { computed } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
+ import type { ComponentSlots } from "../../types"
5
6
  import placeholderTheme from "../../themes/placeholder.theme"
6
7
 
7
8
  const placeholder = scv(placeholderTheme)
8
9
 
9
10
  export interface RLVPlaceholderProps {
10
- ui?: Partial<Record<string, string>>
11
- class?: string
11
+ ui?: ComponentSlots<typeof placeholderTheme>
12
+ class?: any
12
13
  [key: string]: unknown
13
14
  }
14
15
 
15
- const { class: className, ui: uiProp } = defineProps<RLVPlaceholderProps>()
16
+ const { ui: uiProp, class: className } = defineProps<RLVPlaceholderProps>()
16
17
 
17
18
  defineSlots<{
18
19
  /**
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { scv } from "css-variants"
3
3
  import { useUi, resolveClasses } from "../../utils"
4
- import type { ComponentVariants } from "../../types"
4
+ import type { ComponentVariants, ComponentSlots } from "../../types"
5
5
  import scrollToTopTheme from "../../themes/scroll-to-top.theme"
6
6
  import { useScrollToTop } from "../../composables/useScrollToTop"
7
7
  import { computed } from "vue"
@@ -15,8 +15,8 @@ export interface RLVScrollToTopProps {
15
15
  duration?: number
16
16
  threshold?: number
17
17
  showProgress?: boolean
18
- ui?: Partial<Record<string, string>>
19
- class?: string
18
+ ui?: ComponentSlots<typeof scrollToTopTheme>
19
+ class?: any
20
20
  }
21
21
 
22
22
  const {
@@ -1,35 +1,47 @@
1
1
  <script setup lang="ts">
2
- import { computed } from "vue"
2
+ import { computed, useSlots } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
- import type { ComponentVariants } from "../../types"
5
+ import type { ComponentVariants, ComponentSlots } from "../../types"
6
6
  import sectionTheme from "../../themes/section.theme"
7
+ import type { RLVButtonProps } from "./RLVButton.vue"
8
+ import RLVIcon from "./RLVIcon.vue"
9
+ import RLVButton from "./RLVButton.vue"
7
10
 
8
11
  const section = scv(sectionTheme)
9
12
  type SectionVariants = ComponentVariants<typeof sectionTheme>
10
13
 
11
14
  export interface RLVSectionProps {
15
+ as?: any
12
16
  variant?: SectionVariants["variant"]
13
17
  headline?: string
14
18
  icon?: string
15
19
  title?: string
16
20
  description?: string
21
+ links?: RLVButtonProps[]
17
22
  orientation?: SectionVariants["orientation"]
18
23
  reverse?: boolean
19
24
  ctaVariant?: SectionVariants["ctaVariant"]
20
- ui?: Partial<Record<string, string>>
21
- class?: string
25
+ ui?: ComponentSlots<typeof sectionTheme>
26
+ class?: any
22
27
  }
23
28
 
24
29
  const {
30
+ as = "div",
25
31
  variant = "default",
26
32
  orientation = "vertical",
27
33
  reverse = false,
28
- ctaVariant = "outline",
34
+ ctaVariant = "solid",
35
+ ui: uiProp,
29
36
  class: className,
30
- ui: uiProp
37
+ headline,
38
+ title,
39
+ description,
40
+ links
31
41
  } = defineProps<RLVSectionProps>()
32
42
 
43
+ const slots = useSlots()
44
+
33
45
  const resolvedClasses = computed(() =>
34
46
  resolveClasses(
35
47
  section,
@@ -38,10 +50,10 @@ const resolvedClasses = computed(() =>
38
50
  orientation,
39
51
  reverse,
40
52
  ...(variant === "cta" && { ctaVariant }),
41
- headline: false,
42
- title: false,
43
- description: false,
44
- body: false
53
+ headline: !!(slots.headline || headline),
54
+ title: !!(slots.title || title),
55
+ description: !!(slots.description || description),
56
+ body: !!slots.body
45
57
  },
46
58
  useUi("section", uiProp),
47
59
  className
@@ -50,8 +62,14 @@ const resolvedClasses = computed(() =>
50
62
  </script>
51
63
 
52
64
  <template>
53
- <div data-slot="rlv-section" :class="[resolvedClasses.root]" v-bind="$attrs">
54
- <slot name="background">
65
+ <component
66
+ :is="as"
67
+ data-slot="root"
68
+ :data-orientation="orientation"
69
+ :class="[resolvedClasses.root]"
70
+ v-bind="$attrs"
71
+ >
72
+ <slot v-if="$slots.background" name="background">
55
73
  <div :class="resolvedClasses.background" data-slot="background">
56
74
  <slot name="background" />
57
75
  </div>
@@ -59,40 +77,90 @@ const resolvedClasses = computed(() =>
59
77
 
60
78
  <slot name="top" />
61
79
 
62
- <div :class="resolvedClasses.container">
63
- <div :class="resolvedClasses.wrapper">
64
- <div :class="resolvedClasses.header">
65
- <slot name="leading">
66
- <span v-if="icon" :class="resolvedClasses.leadingIcon" data-slot="leading-icon">
67
- <span :class="icon" aria-hidden="true" />
68
- </span>
69
- </slot>
80
+ <div data-slot="container" :class="resolvedClasses.container">
81
+ <div
82
+ v-if="
83
+ $slots.header ||
84
+ icon ||
85
+ headline ||
86
+ title ||
87
+ description ||
88
+ $slots.body ||
89
+ $slots.footer ||
90
+ $slots.links ||
91
+ links?.length
92
+ "
93
+ data-slot="wrapper"
94
+ :class="resolvedClasses.wrapper"
95
+ >
96
+ <div
97
+ v-if="$slots.header || icon || headline || title || description"
98
+ data-slot="header"
99
+ :class="resolvedClasses.header"
100
+ >
101
+ <slot name="header">
102
+ <div v-if="icon || $slots.leading" data-slot="leading" :class="resolvedClasses.leading">
103
+ <slot name="leading" :ui="resolvedClasses">
104
+ <RLVIcon
105
+ v-if="icon"
106
+ :name="icon"
107
+ size="md"
108
+ :ui="{ root: resolvedClasses.leadingIcon }"
109
+ />
110
+ </slot>
111
+ </div>
70
112
 
71
- <div v-if="headline" :class="resolvedClasses.headline">
72
- {{ headline }}
73
- </div>
113
+ <div v-if="headline" data-slot="headline" :class="resolvedClasses.headline">
114
+ <slot name="headline">
115
+ {{ headline }}
116
+ </slot>
117
+ </div>
74
118
 
75
- <h2 v-if="title" :class="resolvedClasses.title">
76
- {{ title }}
77
- </h2>
119
+ <component
120
+ :is="variant === 'hero' ? 'h1' : 'h2'"
121
+ v-if="title"
122
+ data-slot="title"
123
+ :class="resolvedClasses.title"
124
+ >
125
+ <slot name="title">
126
+ {{ title }}
127
+ </slot>
128
+ </component>
78
129
 
79
- <div v-if="description" :class="resolvedClasses.description">
80
- {{ description }}
81
- </div>
130
+ <div v-if="description" data-slot="description" :class="resolvedClasses.description">
131
+ <slot name="description">
132
+ {{ description }}
133
+ </slot>
134
+ </div>
135
+ </slot>
82
136
  </div>
83
137
 
84
- <div :class="resolvedClasses.body">
138
+ <div v-if="$slots.body" data-slot="body" :class="resolvedClasses.body">
85
139
  <slot name="body" />
86
140
  </div>
87
141
 
88
- <div :class="resolvedClasses.footer">
89
- <slot name="links" />
142
+ <div
143
+ v-if="$slots.footer || $slots.links || links?.length"
144
+ data-slot="footer"
145
+ :class="resolvedClasses.footer"
146
+ >
147
+ <slot name="footer">
148
+ <div
149
+ v-if="links?.length || $slots.links"
150
+ data-slot="links"
151
+ :class="resolvedClasses.links"
152
+ >
153
+ <RLVButton v-for="(link, index) in links" :key="index" size="lg" v-bind="link" />
154
+ <slot name="links" />
155
+ </div>
156
+ </slot>
90
157
  </div>
91
158
  </div>
92
159
 
93
- <slot />
160
+ <slot v-if="$slots.default" />
161
+ <div v-else-if="orientation === 'horizontal'" class="hidden lg:block" />
94
162
  </div>
95
163
 
96
164
  <slot name="bottom" />
97
- </div>
165
+ </component>
98
166
  </template>
@@ -13,70 +13,53 @@ export default defineTheme({
13
13
  "title",
14
14
  "description",
15
15
  "body",
16
- "features",
17
16
  "footer",
18
17
  "links"
19
18
  ],
20
19
  base: {
21
20
  root: "relative isolate",
22
21
  background: "absolute inset-0 -z-1 overflow-hidden",
23
- container: "flex flex-col lg:grid gap-8 sm:gap-16",
22
+ container: "flex flex-col lg:grid",
24
23
  wrapper: "",
25
24
  header: "",
26
25
  leading: "flex items-center mb-6",
27
26
  leadingIcon: "size-10 shrink-0 text-primary",
28
- headline: "mb-3",
27
+ headline: "",
29
28
  title: "text-pretty tracking-tight font-bold text-highlighted",
30
29
  description: "text-muted",
31
- body: "mt-8",
32
- features: "grid gap-8",
33
- footer: "mt-8",
34
- links: "flex flex-wrap gap-x-6 gap-y-3"
30
+ body: "",
31
+ footer: "",
32
+ links: "flex flex-wrap"
35
33
  },
36
34
  variants: {
37
35
  variant: {
38
36
  default: {
39
- container: "py-16 sm:py-24 lg:py-32",
37
+ container: "py-16 sm:py-24 lg:py-32 gap-8 sm:gap-16",
38
+ headline: "mb-3",
40
39
  title: "text-3xl sm:text-4xl lg:text-5xl",
41
40
  description: "text-base sm:text-lg",
42
- features: "sm:grid-cols-2 lg:grid-cols-3"
41
+ body: "mt-8",
42
+ footer: "mt-8",
43
+ links: "gap-x-6 gap-y-3"
43
44
  },
44
45
  hero: {
45
46
  container: "py-24 sm:py-32 lg:py-40 gap-16 sm:gap-y-24",
47
+ headline: "mb-4",
46
48
  title: "text-5xl sm:text-7xl",
47
49
  description: "text-lg sm:text-xl/8",
48
- headline: "mb-4",
49
50
  leading: "mb-6",
50
51
  body: "mt-10",
51
52
  footer: "mt-10",
52
- links: "mt-10"
53
+ links: "gap-x-6 gap-y-3"
53
54
  },
54
55
  cta: {
55
56
  root: "rounded-xl overflow-hidden",
56
- container: "px-6 py-12 sm:px-12 sm:py-24 lg:px-16 lg:py-24 gap-8 sm:gap-16",
57
+ container: "lg:grid px-6 py-12 sm:px-12 sm:py-24 lg:px-16 lg:py-24 gap-8 sm:gap-16",
57
58
  title: "text-3xl sm:text-4xl",
58
- description: "text-base sm:text-lg"
59
- }
60
- },
61
- orientation: {
62
- horizontal: {
63
- container: "lg:grid-cols-2 lg:items-center",
64
- description: "text-pretty",
65
- features: "gap-4"
66
- },
67
- vertical: {
68
- container: "",
69
- headline: "justify-center",
70
- leading: "justify-center",
71
- title: "text-center",
72
- description: "text-center text-balance",
73
- links: "justify-center",
74
- features: ""
75
- }
76
- },
77
- reverse: {
78
- true: {
79
- wrapper: "order-last"
59
+ description: "text-base sm:text-lg text-muted",
60
+ body: "mt-8",
61
+ footer: "mt-8",
62
+ links: "gap-x-6 gap-y-3"
80
63
  }
81
64
  },
82
65
  ctaVariant: {
@@ -101,6 +84,25 @@ export default defineTheme({
101
84
  description: "text-muted"
102
85
  }
103
86
  },
87
+ orientation: {
88
+ horizontal: {
89
+ container: "lg:grid-cols-2 lg:items-center",
90
+ description: "text-pretty"
91
+ },
92
+ vertical: {
93
+ container: "",
94
+ headline: "justify-center",
95
+ leading: "justify-center",
96
+ title: "text-center",
97
+ description: "text-center text-balance",
98
+ links: "justify-center"
99
+ }
100
+ },
101
+ reverse: {
102
+ true: {
103
+ wrapper: "order-last"
104
+ }
105
+ },
104
106
  headline: {
105
107
  true: {
106
108
  headline: "font-semibold text-primary flex items-center gap-1.5"
@@ -180,6 +182,6 @@ export default defineTheme({
180
182
  defaultVariants: {
181
183
  variant: "default",
182
184
  orientation: "vertical",
183
- ctaVariant: "outline"
185
+ ctaVariant: "solid"
184
186
  }
185
187
  })
@@ -8,3 +8,7 @@ export type ComponentVariants<T extends { variants?: Record<string, Record<strin
8
8
  : keyof T["variants"][K]
9
9
  }
10
10
  : never
11
+
12
+ export type ComponentSlots<T extends { slots: readonly string[] }> = Partial<
13
+ Record<T["slots"][number], string>
14
+ >