@uxfront/layer-docs 0.4.1 → 0.6.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.
Files changed (100) hide show
  1. package/README.md +42 -213
  2. package/app/app.config.ts +8 -92
  3. package/app/components/app/AppHeaderLeft.vue +84 -0
  4. package/app/components/content/FrameworkSwitcher.vue +66 -40
  5. package/app/components/docs/DocsAsideLeftTop.vue +9 -15
  6. package/app/components/docs/DocsFrameworkSelect.vue +4 -7
  7. package/app/composables/useFramework.ts +43 -38
  8. package/nuxt.config.ts +16 -170
  9. package/package.json +11 -77
  10. package/CHANGELOG.md +0 -192
  11. package/LICENSE +0 -21
  12. package/app/app.vue +0 -138
  13. package/app/assets/css/main.css +0 -15
  14. package/app/components/IconMenuToggle.vue +0 -92
  15. package/app/components/LanguageSelect.vue +0 -73
  16. package/app/components/MorphingGradientBackground.vue +0 -261
  17. package/app/components/OgImage/OgImageDocs.satori.vue +0 -40
  18. package/app/components/OgImage/OgImageLanding.satori.vue +0 -41
  19. package/app/components/app/AppFooter.vue +0 -13
  20. package/app/components/app/AppFooterCenter.vue +0 -17
  21. package/app/components/app/AppFooterLeft.vue +0 -21
  22. package/app/components/app/AppFooterRight.vue +0 -33
  23. package/app/components/app/AppHeader.vue +0 -123
  24. package/app/components/app/AppHeaderAttribution.vue +0 -45
  25. package/app/components/app/AppHeaderBody.vue +0 -14
  26. package/app/components/app/AppHeaderCTA.vue +0 -31
  27. package/app/components/app/AppHeaderCenter.vue +0 -10
  28. package/app/components/app/AppHeaderLogo.vue +0 -16
  29. package/app/components/app/AppOgDecoration.vue +0 -27
  30. package/app/components/app/AppOgLogo.vue +0 -19
  31. package/app/components/app/AppSearch.vue +0 -59
  32. package/app/components/app/AppSubHeader.vue +0 -21
  33. package/app/components/content/BrowserFrame.vue +0 -28
  34. package/app/components/content/GradientPageHero.vue +0 -35
  35. package/app/components/content/StorybookEmbed.vue +0 -160
  36. package/app/components/content/Video.vue +0 -103
  37. package/app/components/docs/DocsAsideLeftBody.vue +0 -20
  38. package/app/components/docs/DocsAsideRightBottom.vue +0 -15
  39. package/app/components/docs/DocsPageHeaderLinks.vue +0 -75
  40. package/app/composables/useDocsSections.ts +0 -57
  41. package/app/composables/useDocusI18n.ts +0 -49
  42. package/app/constants/sections.ts +0 -25
  43. package/app/error.vue +0 -140
  44. package/app/layouts/default.vue +0 -24
  45. package/app/pages/[[lang]]/[...slug].vue +0 -58
  46. package/app/pages/[[lang]]/docs/[section]/[...slug].vue +0 -180
  47. package/app/plugins/i18n.ts +0 -21
  48. package/app/plugins/posthog.client.ts +0 -56
  49. package/app/types/non-route-categories.ts +0 -12
  50. package/app/utils/flattenNavigation.ts +0 -22
  51. package/app/utils/foldNonRouteCategories.ts +0 -47
  52. package/app/utils/prerender.ts +0 -9
  53. package/app/utils/storybookEmbed.test.ts +0 -98
  54. package/app/utils/storybookEmbed.ts +0 -93
  55. package/i18n/locales/ar.json +0 -24
  56. package/i18n/locales/be.json +0 -24
  57. package/i18n/locales/bn.json +0 -24
  58. package/i18n/locales/ca.json +0 -24
  59. package/i18n/locales/ckb.json +0 -24
  60. package/i18n/locales/cs.json +0 -24
  61. package/i18n/locales/da.json +0 -24
  62. package/i18n/locales/de.json +0 -24
  63. package/i18n/locales/el.json +0 -24
  64. package/i18n/locales/en.json +0 -24
  65. package/i18n/locales/et.json +0 -24
  66. package/i18n/locales/fr.json +0 -24
  67. package/i18n/locales/he.json +0 -24
  68. package/i18n/locales/hi.json +0 -24
  69. package/i18n/locales/hy.json +0 -24
  70. package/i18n/locales/it.json +0 -24
  71. package/i18n/locales/ja.json +0 -24
  72. package/i18n/locales/kk.json +0 -24
  73. package/i18n/locales/km.json +0 -24
  74. package/i18n/locales/ko.json +0 -24
  75. package/i18n/locales/ky.json +0 -24
  76. package/i18n/locales/lb.json +0 -24
  77. package/i18n/locales/ms.json +0 -24
  78. package/i18n/locales/nb.json +0 -24
  79. package/i18n/locales/pl.json +0 -24
  80. package/i18n/locales/ru.json +0 -24
  81. package/i18n/locales/sl.json +0 -24
  82. package/i18n/locales/sv.json +0 -24
  83. package/i18n/locales/uk.json +0 -24
  84. package/i18n/locales/ur.json +0 -24
  85. package/i18n/locales/vi.json +0 -24
  86. package/modules/config.ts +0 -144
  87. package/modules/optimizeDeps.ts +0 -45
  88. package/modules/routing.ts +0 -20
  89. package/nuxt.schema.ts +0 -374
  90. package/server/plugins/llms-redirect.ts +0 -60
  91. package/server/routes/raw/[...slug].md.get.ts +0 -74
  92. package/storybook/index.test.ts +0 -110
  93. package/storybook/index.ts +0 -362
  94. package/test/brand-palette.ts +0 -235
  95. package/test/no-brand-leakage.test.ts +0 -124
  96. package/tsconfig.json +0 -17
  97. package/utils/accent.ts +0 -80
  98. package/utils/content.ts +0 -193
  99. package/utils/git.ts +0 -114
  100. package/utils/meta.ts +0 -28
package/app/app.vue DELETED
@@ -1,138 +0,0 @@
1
- <script setup lang="ts">
2
- import type { ContentNavigationItem, PageCollections } from "@nuxt/content";
3
- import * as nuxtUiLocales from "@nuxt/ui/locale";
4
-
5
- const appConfig = useAppConfig();
6
- const { seo } = appConfig;
7
- const site = useSiteConfig();
8
- const { locale, locales, isEnabled, switchLocalePath } = useDocusI18n();
9
-
10
- const lang = computed(
11
- () => nuxtUiLocales[locale.value as keyof typeof nuxtUiLocales]?.code || "en",
12
- );
13
- const dir = computed(() => nuxtUiLocales[locale.value as keyof typeof nuxtUiLocales]?.dir || "ltr");
14
-
15
- const getCollectionName = (key: string) =>
16
- (isEnabled.value ? `docs_${key}_${locale.value}` : `docs_${key}`) as keyof PageCollections;
17
-
18
- useHead({
19
- meta: [{ name: "viewport", content: "width=device-width, initial-scale=1" }],
20
- link: [{ rel: "icon", href: "/favicon.ico" }],
21
- htmlAttrs: {
22
- lang,
23
- dir,
24
- },
25
- });
26
-
27
- useSeoMeta({
28
- titleTemplate: seo?.titleTemplate,
29
- title: seo?.title,
30
- description: seo?.description,
31
- ogSiteName: site.name,
32
- twitterCard: "summary_large_image",
33
- });
34
-
35
- if (isEnabled.value) {
36
- const route = useRoute();
37
- const defaultLocale = (useRuntimeConfig().public.i18n as { defaultLocale: string }).defaultLocale;
38
- onMounted(() => {
39
- const currentLocale = route.path.split("/")[1];
40
- if (!locales.some((locale) => locale.code === currentLocale)) {
41
- return navigateTo(switchLocalePath(defaultLocale) as string);
42
- }
43
- });
44
- }
45
-
46
- const { data: navigation } = await useAsyncData(
47
- () => `navigation_${locale.value}`,
48
- async () => {
49
- const results = await Promise.all(
50
- DOCS_SECTIONS.map(async (section) => {
51
- const collectionName = getCollectionName(section.key);
52
- const data = await queryCollectionNavigation(collectionName);
53
- const rootResult =
54
- data.find((item) => item.path === `/docs/${section.slug}`)?.children ||
55
- data.find((item) => item.path === "/docs")?.children ||
56
- data ||
57
- [];
58
- const localeResult =
59
- rootResult.find((item) => item.path === `/${locale.value}`)?.children || rootResult;
60
- const sectionPath = `/docs/${section.slug}`;
61
- let result: ContentNavigationItem[];
62
- if (Array.isArray(section.folder)) {
63
- const rootIdx = "rootFolder" in section ? (section.rootFolder as number) : -1;
64
- const rootWrapper =
65
- localeResult.length === 1 && localeResult[0]?.path === sectionPath
66
- ? localeResult[0]
67
- : null;
68
- const allItems = rootWrapper ? (rootWrapper.children ?? []) : localeResult;
69
-
70
- if (rootIdx >= 0) {
71
- const nonRootPaths = new Set(
72
- section.folder
73
- .filter((_: string, i: number) => i !== rootIdx)
74
- .map((f: string) => `${sectionPath}/${f.replace(/^\d+\./, "")}`),
75
- );
76
- const items: ContentNavigationItem[] = [];
77
- for (let i = 0; i < section.folder.length; i++) {
78
- if (i === rootIdx) {
79
- items.push({
80
- ...rootWrapper,
81
- title: rootWrapper?.title ?? section.label,
82
- path: sectionPath,
83
- children: allItems.filter((item) => !nonRootPaths.has(item.path)),
84
- } as ContentNavigationItem);
85
- } else {
86
- const found = allItems.find(
87
- (item) =>
88
- item.path === `${sectionPath}/${section.folder[i]?.replace(/^\d+\./, "")}`,
89
- );
90
- if (found) items.push(found);
91
- }
92
- }
93
- result = items;
94
- } else {
95
- result = section.folder
96
- .map((folder: string) =>
97
- allItems.find(
98
- (item) => item.path === `${sectionPath}/${folder.replace(/^\d+\./, "")}`,
99
- ),
100
- )
101
- .filter((item): item is ContentNavigationItem => item !== undefined);
102
- }
103
- } else {
104
- result = localeResult;
105
- }
106
- return [
107
- section.key,
108
- foldNonRouteCategories(flattenNavigation(result), appConfig.nonRouteCategories ?? {}),
109
- ] as const;
110
- }),
111
- );
112
- return Object.fromEntries(results) as Record<string, ContentNavigationItem[]>;
113
- },
114
- {
115
- watch: [locale],
116
- },
117
- );
118
-
119
- const flatNavigation = computed(() =>
120
- navigation.value ? Object.values(navigation.value).flat() : [],
121
- );
122
-
123
- provide("navigation", navigation);
124
- </script>
125
-
126
- <template>
127
- <UApp :locale="nuxtUiLocales[locale as keyof typeof nuxtUiLocales]">
128
- <NuxtLoadingIndicator color="var(--ui-primary)" />
129
-
130
- <NuxtLayout>
131
- <NuxtPage />
132
- </NuxtLayout>
133
-
134
- <ClientOnly>
135
- <AppSearch :navigation="flatNavigation" />
136
- </ClientOnly>
137
- </UApp>
138
- </template>
@@ -1,15 +0,0 @@
1
- @import "tailwindcss";
2
- @import "@nuxt/ui";
3
-
4
- @source "../../../content/**/*";
5
- @source "../../../layers/**/*";
6
- @source "../../app.config.ts";
7
-
8
- /*
9
- * Neutral shell styling only. The brand palette (the `--color-*` scale and the
10
- * `--ui-primary` mapping) is consumer-supplied — each consuming app defines its
11
- * own `@theme` in its CSS entrypoint, layered over this neutral base.
12
- */
13
- .prose-container {
14
- --ui-container: 760px;
15
- }
@@ -1,92 +0,0 @@
1
- <script setup lang="ts">
2
- import { motion } from "motion-v";
3
- import type { VariantType } from "motion-v";
4
- import { useLocale } from "@nuxt/ui/composables/useLocale";
5
-
6
- const props = defineProps<{
7
- open: boolean;
8
- }>();
9
-
10
- // Same strings Nuxt UI's default `UHeader` toggle uses, so the accessible name
11
- // stays in sync with the app's locale instead of being hardcoded here.
12
- const { t } = useLocale();
13
-
14
- const variants: {
15
- [k: string]: VariantType | ((custom: unknown) => VariantType);
16
- } = {
17
- normal: {
18
- rotate: 0,
19
- y: 0,
20
- opacity: 1,
21
- },
22
- close: (custom: unknown) => {
23
- const c = custom as number;
24
- return {
25
- rotate: c === 1 ? 45 : c === 3 ? -45 : 0,
26
- y: c === 1 ? 6 : c === 3 ? -6 : 0,
27
- opacity: c === 2 ? 0 : 1,
28
- transition: {
29
- type: "spring",
30
- stiffness: 260,
31
- damping: 20,
32
- },
33
- };
34
- },
35
- };
36
-
37
- const state = computed(() => (props.open ? "close" : "normal"));
38
- </script>
39
-
40
- <template>
41
- <UButton
42
- size="sm"
43
- variant="ghost"
44
- color="neutral"
45
- class="-me-1.5"
46
- square
47
- :aria-label="open ? t('header.close') : t('header.open')"
48
- >
49
- <svg
50
- xmlns="http://www.w3.org/2000/svg"
51
- class="size-5"
52
- viewBox="0 0 24 24"
53
- fill="none"
54
- stroke="currentColor"
55
- stroke-width="2"
56
- stroke-linecap="round"
57
- stroke-linejoin="round"
58
- aria-hidden="true"
59
- >
60
- <motion.line
61
- x1="4"
62
- y1="6"
63
- x2="20"
64
- y2="6"
65
- :variants="variants"
66
- :animate="state"
67
- :custom="1"
68
- class="outline-none"
69
- />
70
- <motion.line
71
- x1="4"
72
- y1="12"
73
- x2="20"
74
- y2="12"
75
- :variants="variants"
76
- :animate="state"
77
- :custom="2"
78
- class="outline-none"
79
- />
80
- <motion.line
81
- x1="4"
82
- y1="18"
83
- x2="20"
84
- y2="18"
85
- :variants="variants"
86
- :animate="state"
87
- :custom="3"
88
- class="outline-none"
89
- />
90
- </svg>
91
- </UButton>
92
- </template>
@@ -1,73 +0,0 @@
1
- <script setup lang="ts">
2
- const { locale, locales, switchLocalePath } = useDocusI18n();
3
-
4
- function getEmojiFlag(locale: string): string {
5
- const languageToCountry: Record<string, string> = {
6
- ar: "sa", // Arabic -> Saudi Arabia
7
- bn: "bd", // Bengali -> Bangladesh
8
- ca: "es", // Catalan -> Spain
9
- ckb: "iq", // Central Kurdish -> Iraq
10
- cs: "cz", // Czech -> Czech Republic (note: modern country code is actually 'cz')
11
- da: "dk", // Danish -> Denmark
12
- el: "gr", // Greek -> Greece
13
- en: "gb", // English -> Great Britain
14
- et: "ee", // Estonian -> Estonia
15
- he: "il", // Hebrew -> Israel
16
- hi: "in", // Hindi -> India
17
- hy: "am", // Armenian -> Armenia
18
- ja: "jp", // Japanese -> Japan
19
- kk: "kz", // Kazakh -> Kazakhstan
20
- km: "kh", // Khmer -> Cambodia
21
- ko: "kr", // Korean -> South Korea
22
- ky: "kg", // Kyrgyz -> Kyrgyzstan
23
- lb: "lu", // Luxembourgish -> Luxembourg
24
- ms: "my", // Malay -> Malaysia
25
- nb: "no", // Norwegian Bokmål -> Norway
26
- sl: "si", // Slovenian -> Slovenia
27
- sv: "se", // Swedish -> Sweden
28
- uk: "ua", // Ukrainian -> Ukraine
29
- ur: "pk", // Urdu -> Pakistan
30
- vi: "vn", // Vietnamese -> Vietnam
31
- };
32
-
33
- const baseLanguage = locale.split("-")[0]?.toLowerCase() || locale;
34
- const countryCode = languageToCountry[baseLanguage] || locale.replace(/^.*-/, "").slice(0, 2);
35
-
36
- return countryCode
37
- .toUpperCase()
38
- .split("")
39
- .map((char) => String.fromCodePoint(0x1f1a5 + char.charCodeAt(0)))
40
- .join("");
41
- }
42
- </script>
43
-
44
- <template>
45
- <UPopover mode="hover" :content="{ align: 'end' }">
46
- <UButton color="neutral" variant="ghost" class="size-8">
47
- <template #trailing>
48
- <span class="text-lg">
49
- {{ getEmojiFlag(locale) }}
50
- </span>
51
- </template>
52
- </UButton>
53
-
54
- <template #content>
55
- <ul class="flex flex-col">
56
- <li v-for="localeItem in locales" :key="localeItem.code">
57
- <NuxtLink
58
- class="flex justify-between py-1.5 px-2 gap-1 hover:bg-muted"
59
- :to="switchLocalePath(localeItem.code) as string"
60
- :aria-label="localeItem.name"
61
- >
62
- <span class="text-sm">
63
- {{ localeItem.name }}
64
- </span>
65
- <span class="size-5 text-center">
66
- {{ getEmojiFlag(localeItem.code) }}
67
- </span>
68
- </NuxtLink>
69
- </li>
70
- </ul>
71
- </template>
72
- </UPopover>
73
- </template>
@@ -1,261 +0,0 @@
1
- <script setup lang="ts">
2
- import { onBeforeUnmount, onMounted, ref } from "vue";
3
-
4
- const currentX = ref(0);
5
- const currentY = ref(0);
6
- const mouseX = ref(0);
7
- const mouseY = ref(0);
8
-
9
- let animationId: number | null = null;
10
-
11
- const interactiveBubbleStyle = computed(() => {
12
- return {
13
- transform: `translate(${Math.round(currentX.value)}px, ${Math.round(currentY.value)}px)`,
14
- };
15
- });
16
-
17
- function move() {
18
- currentX.value += (mouseX.value - currentX.value) / 20;
19
- currentY.value += (mouseY.value - currentY.value) / 20;
20
- animationId = requestAnimationFrame(move);
21
- }
22
-
23
- function handleMouseMove(event: MouseEvent) {
24
- mouseX.value = event.clientX;
25
- mouseY.value = event.clientY;
26
- }
27
-
28
- onMounted(() => {
29
- move();
30
- });
31
-
32
- onBeforeUnmount(() => {
33
- if (animationId) {
34
- cancelAnimationFrame(animationId);
35
- }
36
- });
37
- </script>
38
-
39
- <template>
40
- <div class="morphing-gradient-background">
41
- <svg xmlns="http://www.w3.org/2000/svg">
42
- <defs>
43
- <filter id="goo">
44
- <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
45
- <feBlend in="SourceGraphic" in2="goo" />
46
- </filter>
47
- </defs>
48
- </svg>
49
- <div class="gradients-container">
50
- <div class="g1"></div>
51
- <div class="g2"></div>
52
- <div class="g3"></div>
53
- <div class="g4"></div>
54
- <div class="g5"></div>
55
- <div class="interactive" :style="interactiveBubbleStyle"></div>
56
- </div>
57
- <slot :onMousemove="handleMouseMove" />
58
- </div>
59
- </template>
60
-
61
- <style scoped>
62
- @keyframes moveInCircle {
63
- 0% {
64
- transform: rotate(0deg);
65
- }
66
- 50% {
67
- transform: rotate(180deg);
68
- }
69
- 100% {
70
- transform: rotate(360deg);
71
- }
72
- }
73
-
74
- @keyframes moveVertical {
75
- 0% {
76
- transform: translateY(-50%);
77
- }
78
- 50% {
79
- transform: translateY(50%);
80
- }
81
- 100% {
82
- transform: translateY(-50%);
83
- }
84
- }
85
-
86
- @keyframes moveHorizontal {
87
- 0% {
88
- transform: translateX(-50%) translateY(-10%);
89
- }
90
- 50% {
91
- transform: translateX(50%) translateY(10%);
92
- }
93
- 100% {
94
- transform: translateX(-50%) translateY(-10%);
95
- }
96
- }
97
-
98
- .morphing-gradient-background {
99
- --color-bg1: var(--ui-bg);
100
- --color-bg2: var(--ui-bg);
101
- --color1: 18, 113, 255;
102
- --color2: 221, 74, 255;
103
- --color3: 100, 220, 255;
104
- --color4: 200, 50, 50;
105
- --color5: 180, 180, 50;
106
- --color-interactive: 140, 100, 255;
107
- --circle-size: 80%;
108
- --blending: hard-light;
109
- --intensity: 0.2;
110
-
111
- position: relative;
112
- background: linear-gradient(40deg, var(--color-bg1), var(--color-bg2));
113
- overflow: hidden;
114
- min-height: 100%;
115
- width: 100%;
116
-
117
- .gradients-container {
118
- filter: url(#goo) blur(40px);
119
- width: 100%;
120
- height: 100%;
121
- position: absolute;
122
- top: 0;
123
- left: 0;
124
- right: 0;
125
- bottom: 0;
126
- overflow: hidden;
127
- pointer-events: none;
128
- }
129
-
130
- svg {
131
- position: absolute;
132
- top: 0;
133
- left: 0;
134
- width: 0;
135
- height: 0;
136
- }
137
-
138
- .g1 {
139
- position: absolute;
140
- background: radial-gradient(
141
- circle at center,
142
- rgba(var(--color1), var(--intensity)) 0,
143
- rgba(var(--color1), 0) 50%
144
- )
145
- no-repeat;
146
- mix-blend-mode: var(--blending);
147
-
148
- width: var(--circle-size);
149
- height: var(--circle-size);
150
- top: calc(50% - var(--circle-size) / 2);
151
- left: calc(50% - var(--circle-size) / 2);
152
-
153
- transform-origin: center center;
154
- animation: moveVertical 30s ease infinite;
155
-
156
- opacity: 1;
157
- }
158
-
159
- .g2 {
160
- position: absolute;
161
- background: radial-gradient(
162
- circle at center,
163
- rgba(var(--color2), var(--intensity)) 0,
164
- rgba(var(--color2), 0) 50%
165
- )
166
- no-repeat;
167
- mix-blend-mode: var(--blending);
168
-
169
- width: var(--circle-size);
170
- height: var(--circle-size);
171
- top: calc(50% - var(--circle-size) / 2);
172
- left: calc(50% - var(--circle-size) / 2);
173
-
174
- transform-origin: calc(50% - 400px);
175
- animation: moveInCircle 20s reverse infinite;
176
-
177
- opacity: 1;
178
- }
179
-
180
- .g3 {
181
- position: absolute;
182
- background: radial-gradient(
183
- circle at center,
184
- rgba(var(--color3), var(--intensity)) 0,
185
- rgba(var(--color3), 0) 50%
186
- )
187
- no-repeat;
188
- mix-blend-mode: var(--blending);
189
-
190
- width: var(--circle-size);
191
- height: var(--circle-size);
192
- top: calc(50% - var(--circle-size) / 2 + 200px);
193
- left: calc(50% - var(--circle-size) / 2 - 500px);
194
-
195
- transform-origin: calc(50% + 400px);
196
- animation: moveInCircle 40s linear infinite;
197
-
198
- opacity: 1;
199
- }
200
-
201
- .g4 {
202
- position: absolute;
203
- background: radial-gradient(
204
- circle at center,
205
- rgba(var(--color4), var(--intensity)) 0,
206
- rgba(var(--color4), 0) 50%
207
- )
208
- no-repeat;
209
- mix-blend-mode: var(--blending);
210
-
211
- width: var(--circle-size);
212
- height: var(--circle-size);
213
- top: calc(50% - var(--circle-size) / 2);
214
- left: calc(50% - var(--circle-size) / 2);
215
-
216
- transform-origin: calc(50% - 200px);
217
- animation: moveHorizontal 40s ease infinite;
218
-
219
- opacity: 0.7;
220
- }
221
-
222
- .g5 {
223
- position: absolute;
224
- background: radial-gradient(
225
- circle at center,
226
- rgba(var(--color5), var(--intensity)) 0,
227
- rgba(var(--color5), 0) 50%
228
- )
229
- no-repeat;
230
- mix-blend-mode: var(--blending);
231
-
232
- width: calc(var(--circle-size) * 2);
233
- height: calc(var(--circle-size) * 2);
234
- top: calc(50% - var(--circle-size));
235
- left: calc(50% - var(--circle-size));
236
-
237
- transform-origin: calc(50% - 800px) calc(50% + 200px);
238
- animation: moveInCircle 20s ease infinite;
239
-
240
- opacity: 1;
241
- }
242
-
243
- .interactive {
244
- position: absolute;
245
- background: radial-gradient(
246
- circle at center,
247
- rgba(var(--color-interactive), var(--intensity)) 0,
248
- rgba(var(--color-interactive), 0) 50%
249
- )
250
- no-repeat;
251
- mix-blend-mode: var(--blending);
252
-
253
- width: 100%;
254
- height: 100%;
255
- top: -50%;
256
- left: -50%;
257
-
258
- opacity: 0.7;
259
- }
260
- }
261
- </style>
@@ -1,40 +0,0 @@
1
- <script lang="ts" setup>
2
- /**
3
- * Default OG card for docs, changelog and landing pages — `defineOgImage("DocsSatori", ...)`.
4
- *
5
- * Brandable without touching this package: the accent comes from the consumer's
6
- * own `--ui-primary` token (resolved in `modules/config.ts`), and both the
7
- * decoration and the wordmark are components a consumer can shadow. See
8
- * README § OG images.
9
- */
10
- withDefaults(defineProps<{ title?: string; description?: string; headline?: string }>(), {
11
- title: "",
12
- description: "",
13
- headline: "",
14
- });
15
-
16
- const appConfig = useAppConfig();
17
- const accent = computed(() => appConfig.ogImage?.accent);
18
- </script>
19
-
20
- <template>
21
- <div class="w-full h-full flex flex-col justify-center bg-neutral-900">
22
- <AppOgDecoration />
23
-
24
- <div class="pl-[100px]">
25
- <p
26
- v-if="headline"
27
- class="uppercase text-[24px] mb-4 font-semibold"
28
- :style="{ color: accent }"
29
- >
30
- {{ headline }}
31
- </p>
32
- <h1 v-if="title" class="m-0 text-[75px] font-semibold mb-4 text-white flex items-center">
33
- <span>{{ title.slice(0, 60) }}</span>
34
- </h1>
35
- <p v-if="description" class="text-[32px] text-neutral-300 leading-tight w-[700px]">
36
- {{ description.slice(0, 200) }}
37
- </p>
38
- </div>
39
- </div>
40
- </template>
@@ -1,41 +0,0 @@
1
- <script lang="ts" setup>
2
- /**
3
- * Centred OG card variant for landing pages — `defineOgImage("LandingSatori", ...)`.
4
- *
5
- * Same brand contract as {@link OgImageDocs}: accent from the consumer's token,
6
- * decoration and wordmark as overridable components.
7
- */
8
- withDefaults(defineProps<{ title?: string; description?: string; headline?: string }>(), {
9
- title: "",
10
- description: "",
11
- headline: "",
12
- });
13
-
14
- const appConfig = useAppConfig();
15
- const accent = computed(() => appConfig.ogImage?.accent);
16
- </script>
17
-
18
- <template>
19
- <div class="w-full h-full flex items-center justify-center bg-neutral-900">
20
- <AppOgDecoration />
21
-
22
- <div class="flex flex-col justify-center p-8">
23
- <div class="flex justify-center mb-8">
24
- <AppOgLogo />
25
- </div>
26
- <p
27
- v-if="headline"
28
- class="flex justify-center uppercase text-[24px] mb-4 font-semibold"
29
- :style="{ color: accent }"
30
- >
31
- {{ headline }}
32
- </p>
33
- <h1 v-if="title" class="flex justify-center m-0 text-5xl font-semibold mb-4 text-white">
34
- <span>{{ title.slice(0, 60) }}</span>
35
- </h1>
36
- <p v-if="description" class="text-center text-2xl text-neutral-300 leading-tight">
37
- {{ description.slice(0, 200) }}
38
- </p>
39
- </div>
40
- </div>
41
- </template>
@@ -1,13 +0,0 @@
1
- <template>
2
- <UFooter>
3
- <template #left>
4
- <AppFooterLeft />
5
- </template>
6
-
7
- <AppFooterCenter />
8
-
9
- <template #right>
10
- <AppFooterRight />
11
- </template>
12
- </UFooter>
13
- </template>
@@ -1,17 +0,0 @@
1
- <script lang="ts" setup>
2
- import type { NavigationMenuItem } from "@nuxt/ui";
3
-
4
- /**
5
- * Footer link row. Brand/legal links (Privacy, Terms, ...) are consumer data,
6
- * read from `footer.links` in `app.config.ts`. This layer ships none.
7
- */
8
- const appConfig = useAppConfig();
9
-
10
- const links = computed<NavigationMenuItem[]>(
11
- () => (appConfig.footer?.links as NavigationMenuItem[] | undefined) ?? [],
12
- );
13
- </script>
14
-
15
- <template>
16
- <UNavigationMenu v-if="links.length" orientation="horizontal" :items="links" />
17
- </template>