Skip to main content
Glama
Inline.vue5.88 kB
/* General "inline" component, which helps arrange a horizontal row of components with even spacing between them, wrapping to the next line if necessary NOTE - also converted to functional component to make HMR work and improve perf */ <script lang="ts"> import { h, VNode, PropType } from "vue"; import { BreakpointNamesWithoutSmallest, HorizontalAlignmentValues, responsiveAlignProps, responsiveSpacingProps, responsiveVerticalAlignProps, } from "../utils/size_utils"; import { FunctionalComponentContextArg, FunctionalComponentPropsType, getSlotChildren, } from "../../utils/vue_utils"; const propsDefinition = { ...responsiveSpacingProps("xs"), ...responsiveAlignProps, ...responsiveVerticalAlignProps, collapseBelow: { type: String as PropType<BreakpointNamesWithoutSmallest> }, tagName: { type: String as PropType<"div" | "section" | "ol" | "ul" | "li">, default: "div", }, reverse: { type: Boolean, default: false, }, noWrap: Boolean, fullWidth: Boolean, } as const; function flipAlignIfReversed( reverse: boolean | undefined, alignValue?: HorizontalAlignmentValues, ) { if (!reverse) return alignValue; if (alignValue === "left") return "right"; if (alignValue === "right") return "left"; return alignValue; } const Inline = ( props: FunctionalComponentPropsType<typeof propsDefinition>, context: FunctionalComponentContextArg, ): VNode => { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const isList = ["ol", "ul"].includes(props.tagName!); const classes = { "ui-inline": true, [`--spacing-${props.spacing}`]: true, [`--spacing-${props.spacingMobile}-mobile-only`]: !!props.spacingMobile, [`--spacing-${props.spacingTablet}-tablet`]: !!props.spacingTablet, [`--spacing-${props.spacingDesktop}-desktop`]: !!props.spacingDesktop, [`--spacing-${props.spacingWide}-wide`]: !!props.spacingWide, [`--spacing-${props.spacingHuge}-huge`]: !!props.spacingHuge, // need to flip the alignment option if reversed option is being used [`--align-${flipAlignIfReversed(props.reverse, props.align)}`]: true, [`--align-${flipAlignIfReversed( props.reverse, props.alignMobile, )}-mobile-only`]: !!props.alignMobile, [`--align-${flipAlignIfReversed(props.reverse, props.alignTablet)}-tablet`]: !!props.alignTablet, [`--align-${flipAlignIfReversed( props.reverse, props.alignDesktop, )}-desktop`]: !!props.alignDesktop, [`--align-${flipAlignIfReversed(props.reverse, props.alignWide)}-wide`]: !!props.alignWide, [`--align-${flipAlignIfReversed(props.reverse, props.alignHuge)}-huge`]: !!props.alignHuge, [`--aligny-${props.alignY}`]: true, [`--aligny-${props.alignYMobile}-mobile-only`]: !!props.alignYMobile, [`--aligny-${props.alignYTablet}-tablet`]: !!props.alignYTablet, [`--aligny-${props.alignYDesktop}-desktop`]: !!props.alignYDesktop, [`--aligny-${props.alignYWide}-wide`]: !!props.alignYWide, [`--aligny-${props.alignYHuge}-huge`]: !!props.alignYHuge, "--reverse": props.reverse, ...(props.collapseBelow && { [`--collapse-below-${props.collapseBelow}`]: true, }), "--no-wrap": props.noWrap, "--full-width": props.fullWidth, }; const wrappedChildren = [] as VNode[]; const children = getSlotChildren(context.slots.default); for (let i = 0; i < children.length; i++) { const item = h( isList ? "li" : "div", { class: "inline__item" }, children[i], ); // item.children = []; wrappedChildren.push(item); } return h( props.tagName || "div", { class: classes, }, wrappedChildren, ); }; Inline.props = propsDefinition; export default Inline; </script> <style lang="less"> // avoiding the class name "inline" to not conflict with tailwind .ui-inline { display: flex; flex-direction: row; flex-wrap: wrap; gap: @spacing-rem[xs]; // could set this up to only be there if tagname is ol/ul, but doesn't hurt anything list-style: none; margin: 0; padding: 0; &.--full-width { > .inline__item { flex-grow: 1; display: flex; flex-direction: column; > .vbutton { flex-grow: 1; } } } &.--reverse { flex-direction: row-reverse; } &.--no-wrap { flex-wrap: nowrap; } each(@spacing-rem, .(@size-px, @size-name){ &.--spacing-@{size-name} { gap: @size-px; } }) each(@horizontal-align-options, .(@flex-value, @option-name){ &.--align-@{option-name} { justify-content: @flex-value; } }) each(@vertical-align-options, .(@flex-value, @option-name){ &.--aligny-@{option-name} { align-items: @flex-value; } }) each(@breakpoints, .(@bp-name){ @mq-var-name: ~'mq-@{bp-name}'; @media @@mq-var-name { each(@spacing-rem, .(@size-px, @size-name){ &.--spacing-@{size-name}-@{bp-name} { gap: @size-px; } }) each(@horizontal-align-options, .(@flex-value, @option-name){ &.--align-@{option-name}-@{bp-name} { justify-content: @flex-value; } }) each(@vertical-align-options, .(@flex-value, @option-name){ &.--aligny-@{option-name}-@{bp-name} { align-items: @flex-value; } }) } }) each(@breakpoints-without-smallest, .(@bp-name){ @mq-var-name: ~'mq-below-@{bp-name}'; @media @@mq-var-name { &.--collapse-below-@{bp-name} { flex-direction: column; &.--reverse { flex-direction: column-reverse; } } } }); > .inline__item { &:empty { display: none; } } } // TODO: add hacky good enough fix for no flex gap support :( // see https://ppuzio.medium.com/flexbox-gap-workaround-for-safari-on-ios-14-13-and-lower-ffcae589eb69 </style>

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server