The Trans Directory
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: flex component, document higher-order layout components

+153 -33
+62
docs/layout-components.md
··· 1 + --- 2 + title: Higher-Order Layout Components 3 + --- 4 + 5 + Quartz provides several higher-order components that help with layout composition and responsive design. These components wrap other components to add additional functionality or modify their behavior. 6 + 7 + ## `Flex` Component 8 + 9 + The `Flex` component creates a [flexible box layout](https://developer.mozilla.org/en-US/docs/Web/CSS/flex) that can arrange child components in various ways. It's particularly useful for creating responsive layouts and organizing components in rows or columns. 10 + 11 + ```typescript 12 + type FlexConfig = { 13 + components: { 14 + Component: QuartzComponent 15 + grow?: boolean // whether component should grow to fill space 16 + shrink?: boolean // whether component should shrink if needed 17 + basis?: string // initial main size of the component 18 + order?: number // order in flex container 19 + align?: "start" | "end" | "center" | "stretch" // cross-axis alignment 20 + justify?: "start" | "end" | "center" | "between" | "around" // main-axis alignment 21 + }[] 22 + direction?: "row" | "row-reverse" | "column" | "column-reverse" 23 + wrap?: "nowrap" | "wrap" | "wrap-reverse" 24 + gap?: string 25 + } 26 + ``` 27 + 28 + ### Example Usage 29 + 30 + ```typescript 31 + Component.Flex({ 32 + components: [ 33 + { 34 + Component: Component.Search(), 35 + grow: true, // Search will grow to fill available space 36 + }, 37 + { Component: Component.Darkmode() }, // Darkmode keeps its natural size 38 + ], 39 + direction: "row", 40 + gap: "1rem", 41 + }) 42 + ``` 43 + 44 + ## `MobileOnly` Component 45 + 46 + The `MobileOnly` component is a wrapper that makes its child component only visible on mobile devices. This is useful for creating responsive layouts where certain components should only appear on smaller screens. 47 + 48 + ### Example Usage 49 + 50 + ```typescript 51 + Component.MobileOnly(Component.Spacer()) 52 + ``` 53 + 54 + ## `DesktopOnly` Component 55 + 56 + The `DesktopOnly` component is the counterpart to `MobileOnly`. It makes its child component only visible on desktop devices. This helps create responsive layouts where certain components should only appear on larger screens. 57 + 58 + ### Example Usage 59 + 60 + ```typescript 61 + Component.DesktopOnly(Component.TableOfContents()) 62 + ```
+3 -1
docs/layout.md
··· 35 35 36 36 Quartz **components**, like plugins, can take in additional properties as configuration options. If you're familiar with React terminology, you can think of them as Higher-order Components. 37 37 38 - See [a list of all the components](component.md) for all available components along with their configuration options. You can also checkout the guide on [[creating components]] if you're interested in further customizing the behaviour of Quartz. 38 + See [a list of all the components](component.md) for all available components along with their configuration options. Additionally, Quartz provides several built-in higher-order components for layout composition - see [[layout-components]] for more details. 39 + 40 + You can also checkout the guide on [[creating components]] if you're interested in further customizing the behaviour of Quartz. 39 41 40 42 ### Layout breakpoints 41 43
+9 -2
quartz.layout.ts
··· 25 25 left: [ 26 26 Component.PageTitle(), 27 27 Component.MobileOnly(Component.Spacer()), 28 - Component.Search(), 29 - Component.Darkmode(), 28 + Component.Flex({ 29 + components: [ 30 + { 31 + Component: Component.Search(), 32 + grow: true, 33 + }, 34 + { Component: Component.Darkmode() }, 35 + ], 36 + }), 30 37 Component.Explorer(), 31 38 ], 32 39 right: [
+11 -15
quartz/components/DesktopOnly.tsx
··· 1 1 import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types" 2 2 3 - export default ((component?: QuartzComponent) => { 4 - if (component) { 5 - const Component = component 6 - const DesktopOnly: QuartzComponent = (props: QuartzComponentProps) => { 7 - return <Component displayClass="desktop-only" {...props} /> 8 - } 9 - 10 - DesktopOnly.displayName = component.displayName 11 - DesktopOnly.afterDOMLoaded = component?.afterDOMLoaded 12 - DesktopOnly.beforeDOMLoaded = component?.beforeDOMLoaded 13 - DesktopOnly.css = component?.css 14 - return DesktopOnly 15 - } else { 16 - return () => <></> 3 + export default ((component: QuartzComponent) => { 4 + const Component = component 5 + const DesktopOnly: QuartzComponent = (props: QuartzComponentProps) => { 6 + return <Component displayClass="desktop-only" {...props} /> 17 7 } 18 - }) satisfies QuartzComponentConstructor 8 + 9 + DesktopOnly.displayName = component.displayName 10 + DesktopOnly.afterDOMLoaded = component?.afterDOMLoaded 11 + DesktopOnly.beforeDOMLoaded = component?.beforeDOMLoaded 12 + DesktopOnly.css = component?.css 13 + return DesktopOnly 14 + }) satisfies QuartzComponentConstructor<QuartzComponent>
+55
quartz/components/Flex.tsx
··· 1 + import { concatenateResources } from "../util/resources" 2 + import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types" 3 + 4 + type FlexConfig = { 5 + components: { 6 + Component: QuartzComponent 7 + grow?: boolean 8 + shrink?: boolean 9 + basis?: string 10 + order?: number 11 + align?: "start" | "end" | "center" | "stretch" 12 + justify?: "start" | "end" | "center" | "between" | "around" 13 + }[] 14 + direction?: "row" | "row-reverse" | "column" | "column-reverse" 15 + wrap?: "nowrap" | "wrap" | "wrap-reverse" 16 + gap?: string 17 + } 18 + 19 + export default ((config: FlexConfig) => { 20 + const Flex: QuartzComponent = (props: QuartzComponentProps) => { 21 + const direction = config.direction ?? "row" 22 + const wrap = config.wrap ?? "nowrap" 23 + const gap = config.gap ?? "1rem" 24 + 25 + return ( 26 + <div style={`display: flex; flex-direction: ${direction}; flex-wrap: ${wrap}; gap: ${gap};`}> 27 + {config.components.map((c) => { 28 + const grow = c.grow ? 1 : 0 29 + const shrink = (c.shrink ?? true) ? 1 : 0 30 + const basis = c.basis ?? "auto" 31 + const order = c.order ?? 0 32 + const align = c.align ?? "center" 33 + const justify = c.justify ?? "center" 34 + 35 + return ( 36 + <div 37 + style={`flex-grow: ${grow}; flex-shrink: ${shrink}; flex-basis: ${basis}; order: ${order}; align-self: ${align}; justify-self: ${justify};`} 38 + > 39 + <c.Component {...props} /> 40 + </div> 41 + ) 42 + })} 43 + </div> 44 + ) 45 + } 46 + 47 + Flex.afterDOMLoaded = concatenateResources( 48 + ...config.components.map((c) => c.Component.afterDOMLoaded), 49 + ) 50 + Flex.beforeDOMLoaded = concatenateResources( 51 + ...config.components.map((c) => c.Component.beforeDOMLoaded), 52 + ) 53 + Flex.css = concatenateResources(...config.components.map((c) => c.Component.css)) 54 + return Flex 55 + }) satisfies QuartzComponentConstructor<FlexConfig>
+11 -15
quartz/components/MobileOnly.tsx
··· 1 1 import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types" 2 2 3 - export default ((component?: QuartzComponent) => { 4 - if (component) { 5 - const Component = component 6 - const MobileOnly: QuartzComponent = (props: QuartzComponentProps) => { 7 - return <Component displayClass="mobile-only" {...props} /> 8 - } 9 - 10 - MobileOnly.displayName = component.displayName 11 - MobileOnly.afterDOMLoaded = component?.afterDOMLoaded 12 - MobileOnly.beforeDOMLoaded = component?.beforeDOMLoaded 13 - MobileOnly.css = component?.css 14 - return MobileOnly 15 - } else { 16 - return () => <></> 3 + export default ((component: QuartzComponent) => { 4 + const Component = component 5 + const MobileOnly: QuartzComponent = (props: QuartzComponentProps) => { 6 + return <Component displayClass="mobile-only" {...props} /> 17 7 } 18 - }) satisfies QuartzComponentConstructor 8 + 9 + MobileOnly.displayName = component.displayName 10 + MobileOnly.afterDOMLoaded = component?.afterDOMLoaded 11 + MobileOnly.beforeDOMLoaded = component?.beforeDOMLoaded 12 + MobileOnly.css = component?.css 13 + return MobileOnly 14 + }) satisfies QuartzComponentConstructor<QuartzComponent>
+2
quartz/components/index.ts
··· 20 20 import RecentNotes from "./RecentNotes" 21 21 import Breadcrumbs from "./Breadcrumbs" 22 22 import Comments from "./Comments" 23 + import Flex from "./Flex" 23 24 24 25 export { 25 26 ArticleTitle, ··· 44 45 NotFound, 45 46 Breadcrumbs, 46 47 Comments, 48 + Flex, 47 49 }