diff --git a/packages/console/app/src/routes/changelog.json.ts b/packages/console/app/src/routes/changelog.json.ts index b668229f81..a23f205032 100644 --- a/packages/console/app/src/routes/changelog.json.ts +++ b/packages/console/app/src/routes/changelog.json.ts @@ -6,21 +6,22 @@ type Release = { html_url: string } -type Highlight = { - source: string +type HighlightMedia = { type: "video"; src: string } | { type: "image"; src: string; width: string; height: string } + +type HighlightItem = { title: string description: string shortDescription?: string - image?: { - src: string - width: string - height: string - } - video?: string + media: HighlightMedia } -function parseHighlights(body: string): Highlight[] { - const highlights: Highlight[] = [] +type HighlightGroup = { + source: string + items: HighlightItem[] +} + +function parseHighlights(body: string): HighlightGroup[] { + const groups = new Map() const regex = /([\s\S]*?)<\/highlight>/g let match @@ -30,29 +31,32 @@ function parseHighlights(body: string): Highlight[] { const titleMatch = content.match(/

([^<]+)<\/h2>/) const pMatch = content.match(/([^<]+)<\/p>/) - const imgMatch = content.match(/ ({ source, items })) } function parseMarkdown(body: string) { diff --git a/packages/console/app/src/routes/changelog/index.css b/packages/console/app/src/routes/changelog/index.css index a06fb00554..233d85cc0e 100644 --- a/packages/console/app/src/routes/changelog/index.css +++ b/packages/console/app/src/routes/changelog/index.css @@ -367,11 +367,18 @@ display: flex; flex-direction: column; gap: 4px; + position: sticky; + top: 80px; + align-self: start; + background: var(--color-background); + padding: 8px 0; @media (max-width: 50rem) { + position: static; flex-direction: row; align-items: center; gap: 12px; + padding: 0; } [data-slot="version"] { @@ -402,24 +409,26 @@ [data-component="section"] { h3 { - font-size: 14px; + font-size: 13px; font-weight: 600; color: var(--color-text-strong); - margin-bottom: 8px; + margin-bottom: 6px; } ul { list-style: none; padding: 0; margin: 0; + padding-left: 16px; display: flex; flex-direction: column; - gap: 6px; + gap: 4px; li { color: var(--color-text); + font-size: 13px; line-height: 1.5; - padding-left: 16px; + padding-left: 12px; position: relative; &::before { @@ -431,7 +440,7 @@ [data-slot="author"] { color: var(--color-text-weak); - font-size: 13px; + font-size: 12px; margin-left: 4px; text-decoration: none; @@ -473,6 +482,72 @@ margin-bottom: 1.5rem; } + [data-component="collapsible-sections"] { + display: flex; + flex-direction: column; + gap: 0; + } + + [data-component="collapsible-section"] { + [data-slot="toggle"] { + display: flex; + align-items: center; + gap: 6px; + background: none; + border: none; + padding: 6px 0; + cursor: pointer; + font-family: inherit; + font-size: 13px; + font-weight: 600; + color: var(--color-text-weak); + + &:hover { + color: var(--color-text); + } + + [data-slot="icon"] { + font-size: 10px; + } + } + + ul { + list-style: none; + padding: 0; + margin: 0; + padding-left: 16px; + padding-bottom: 8px; + + li { + color: var(--color-text); + font-size: 13px; + line-height: 1.5; + padding-left: 12px; + position: relative; + + &::before { + content: "-"; + position: absolute; + left: 0; + color: var(--color-text-weak); + } + + [data-slot="author"] { + color: var(--color-text-weak); + font-size: 12px; + margin-left: 4px; + text-decoration: none; + + &:hover { + text-decoration: underline; + text-underline-offset: 2px; + text-decoration-thickness: 1px; + } + } + } + } + } + [data-component="highlight"] { h4 { font-size: 14px; @@ -481,16 +556,29 @@ margin-bottom: 8px; } - p[data-slot="title"] { - font-weight: 500; - color: var(--color-text-strong); - margin-bottom: 4px; + hr { + border: none; + border-top: 1px solid var(--color-border-weak); + margin-bottom: 16px; } - p { - color: var(--color-text); - line-height: 1.5; - margin-bottom: 12px; + [data-slot="highlight-item"] { + margin-bottom: 24px; + + &:last-child { + margin-bottom: 0; + } + + p[data-slot="title"] { + font-weight: 600; + font-size: 16px; + margin-bottom: 4px; + } + + p { + font-size: 14px; + margin-bottom: 12px; + } } img, diff --git a/packages/console/app/src/routes/changelog/index.tsx b/packages/console/app/src/routes/changelog/index.tsx index 34fd5f83b7..87e021ec88 100644 --- a/packages/console/app/src/routes/changelog/index.tsx +++ b/packages/console/app/src/routes/changelog/index.tsx @@ -5,7 +5,7 @@ import { Header } from "~/component/header" import { Footer } from "~/component/footer" import { Legal } from "~/component/legal" import { config } from "~/config" -import { For, Show } from "solid-js" +import { For, Show, createSignal } from "solid-js" type Release = { tag_name: string @@ -40,21 +40,22 @@ function formatDate(dateString: string) { }) } -type Highlight = { - source: string +type HighlightMedia = { type: "video"; src: string } | { type: "image"; src: string; width: string; height: string } + +type HighlightItem = { title: string description: string shortDescription?: string - image?: { - src: string - width: string - height: string - } - video?: string + media: HighlightMedia } -function parseHighlights(body: string): Highlight[] { - const highlights: Highlight[] = [] +type HighlightGroup = { + source: string + items: HighlightItem[] +} + +function parseHighlights(body: string): HighlightGroup[] { + const groups = new Map() const regex = /([\s\S]*?)<\/highlight>/g let match @@ -64,33 +65,32 @@ function parseHighlights(body: string): Highlight[] { const titleMatch = content.match(/

([^<]+)<\/h2>/) const pMatch = content.match(/([^<]+)<\/p>/) - const imgMatch = content.match(/ ({ source, items })) } function parseMarkdown(body: string) { @@ -142,27 +142,60 @@ function ReleaseItem(props: { item: string }) { ) } -function HighlightCard(props: { highlight: Highlight }) { +function HighlightSection(props: { group: HighlightGroup }) { return (
-

{props.highlight.source}

-

{props.highlight.title}

-

{props.highlight.description}

- - - - {props.highlight.title} +

{props.group.source}

+
+ + {(item) => ( +
+

{item.title}

+

{item.description}

+ + + + {item.title} + +
+ )} +
+
+ ) +} + +function CollapsibleSection(props: { section: { title: string; items: string[] } }) { + const [open, setOpen] = createSignal(false) + + return ( +
+ + +
    + {(item) => } +
) } +function CollapsibleSections(props: { sections: { title: string; items: string[] }[] }) { + return ( +
+ {(section) => } +
+ ) +} + export default function Changelog() { const releases = createAsync(() => getReleases()) @@ -198,19 +231,24 @@ export default function Changelog() {
0}>
- {(highlight) => } + {(group) => }
- - {(section) => ( -
-

{section.title}

-
    - {(item) => } -
-
- )} -
+ 0 && parsed().sections.length > 0}> + + + + + {(section) => ( +
+

{section.title}

+
    + {(item) => } +
+
+ )} +
+
)